domotruc / jMQTT

Jeedom plugin to interface as a client with an MQTT broker.
16 stars 8 forks source link

erreur "call to undefined function mb_check_encoding" #47

Closed domotruc closed 6 years ago

domotruc commented 6 years ago

Suite message de meute sur le forum:

Hello, pour info depuis la mise à jour aujourd'hui j'ai cette erreur :

Erreur sur jMQTT::daemon() : Error Object ( [message:protected] => Call to undefined function mb_check_encoding() [string:Error:private] => [code:protected] => 0 [file:protected] => /var/www/html/plugins/jMQTT/core/class/jMQTT.class.php [line:protected] => 410 [trace:Error:private] => Array ( [0] => Array ( [function] => mosquittoMessage [class] => jMQTT [type] => :: [args] => Array ( [0] => Mosquitto\Message Object ( [mid] => 0 [topic] => ebusd/bai/WPPWMPower [payload] => { "percent0": {"value": 0}} [qos] => 0 [retain] => ) ) ) [1] => Array ( [file] => /var/www/html/plugins/jMQTT/core/class/jMQTT.class.php [line] => 319 [function] => loopForever [class] => Mosquitto\Client [type] => -> [args] => Array ( ) ) [2] => Array ( [file] => /var/www/html/core/php/jeeCron.php [line] => 72 [function] => daemon [class] => jMQTT [type] => :: [args] => Array ( ) ) ) [previous:Error:private] => )

PS, Je suis en stable donc le problème a été introduit sur une des deux betas vu que je l'avais pas juste avant avec la version du 2018-04-29.

L'erreur revient exactement toutes les 5 minutes, peut-être synchrone avec un de mes poolings, il faut que je vérifie ...

domotruc commented 6 years ago

L'utilisation de la fonction mb_check_encoding est bien nouvelle (depuis version 2018-05-10). Elle est présente depuis les versions PHP 4 >= 4.4.3, PHP 5 >= 5.1.3, PHP 7. Quelle version de PHP utilises tu?

Pour te dépanner en attendant la correction, tu peux commenter les lignes comme suit dans le code jMQTT/core/class/jMQTT.class.php:

// Return in case of invalid topic
if(!ctype_print($msgTopic) || empty($topicContent)) {
//    if (!mb_check_encoding($msgTopic, 'ASCII'))
//  $msgTopic = strtoupper(bin2hex($msgTopic));
    log::add('jMQTT', 'warning', 'Message skipped: "' . $msgTopic . '" is not a valid topic');
    return;
}

// Return in case of invalid payload (only ascii payload are supported) - fix issue #46
//if (!mb_check_encoding($msgValue, 'ASCII')) {
//    log::add('jMQTT', 'warning', 'Message skipped: payload ' . strtoupper(bin2hex($msgValue)) . ' is not //valid for topic ' . $msgTopic);
//    return;
//}
meute commented 6 years ago

pour PHP je suis en 7.0.27-0+deb9u1 donc ca doit pas être ça.

domotruc commented 6 years ago

Pourtant c'est ce que dis le message d'erreur: Call to undefined function mb_check_encoding()

As tu la possibilité de tester le contournement indiqué précédemment pour vérifier?

meute commented 6 years ago

Je suis occupé de modifier la class, je retrouve 2 fois la fonction mb_check_encoding dans le code, je commente les deux ?

meute commented 6 years ago

Ok, j'ai commenté que la deuxième occurrence, la première on y passe pas tant qu'on a pas un topic invalide, je vérifie ce que ça donne.

domotruc commented 6 years ago

Effectivement, 2 occurrences à commenter (voir message corrigé ci-dessus), même si tu as raison, la première n'est pas exécutée si le topic est valide.

domotruc commented 6 years ago

Donc le "seul problème" est que la fonction mb_check_encoding n'est pas présente sur ton système. J'ai exactement la même version de PHP que toi et n'ai pas de soucis. Je cherche...

meute commented 6 years ago

Oui il me semble, le reste fonctionne actuellement.

domotruc commented 6 years ago

J'ai trouvé, la fonction mb_check_encoding vient de la librairie mbstring qui n'est pas une librairie installée par défaut. Je vais chercher à utiliser une autre fonction.

domotruc commented 6 years ago

La fonction mb_check_encoding est utilisée pour filtrer une payload corrompue entraînant la perte totale de configuration de la commande (voir bug #46). La payload qui a révélé ce bug est une chaîne de caractère non ASCII : 02 02 d3 00 03 03 f7 00 0f 0b 67.

En poursuivant l'investigation, on trouve que la perte de configuration se produit lorsque la payload est enregistrée, via le code suivant de la classe jMQTTCmd qui étend la classe cmd:

$this->setConfiguration('value', $value);

Pour le mettre en évidence, le code suivant:

log::add('jMQTT', 'debug', '$this->configuration);
$this->setConfiguration('value', $value);
log::add('jMQTT', 'debug', '$this->configuration);

donne les traces:

[2018-05-11 10:23:59][DEBUG] : {"topic":"Loic74\/HauteurEau\/TaillanderieBas","parseJson":0,"value":"{\"battery_voltage\": 2.51, \"distance\": 1030.68, \"node_id\": 723}"}
[2018-05-11 10:23:59][DEBUG] : 

L'analyse du core Jeedom montre que le problème se produit dans la fonction utils::setJsonAttr où la payload est encodée JSON via json_encode($attr, JSON_UNESCAPED_UNICODE).

Donc la solution pour vérifier qu'une payload est valide est de s'assurer qu'elle peut être encodée JSON, ce qui donne la fonction suivante ajoutée dans la classe jMQTTCmd:

public static function isConfigurationValid($value) {
   return (json_encode(array('v' => $value), JSON_UNESCAPED_UNICODE) !== FALSE);
}