Skip to content

jeedomAutoload() charge un mauvais chemin de classe (casse incohérente dossier/fichier) #3459

Description

@Petitblue92

Description

Bug report — jeedomAutoload() charge un mauvais chemin de classe (casse incohérente dossier/fichier)
Résumé
La fonction jeedomAutoload() (core/php/core.inc.php) génère une erreur répétée dans les logs :
[ERROR] Fichier introuvable : /var/www/html/core/php/../../plugins/Nut/core/class/Nut.class.php
alors que le plugin est correctement installé dans /var/www/html/plugins/nut/ (minuscule). Le plugin fonctionne normalement (la tuile équipement remonte bien les données), le bug est donc sans impact fonctionnel visible mais pollue les logs en continu.
Environnement
Plugin concerné : Nut (gestion onduleur / NUT)
Le même mécanisme peut affecter n'importe quel plugin dont l'id est référencé par une classe PHP compagnon se terminant par Cmd ou Real (ex : NutCmd)
Cause
Dans jeedomAutoload($_classname) (core/php/core.inc.php) :
} else if (strpos($_classname, '\') === false && strpos($classname, '/') === false) {
/* autoload for plugins : no namespace */
$classname = str_replace(array('Real', 'Cmd'), '', $classname);
$plugin_active = config::byKey('active', $classname, null);
if (($plugin_active === null || $plugin_active == '' || $plugin_active == 0) && strpos($classname, '
') !== false) {
$classname = explode('
', $classname)[0];
$plugin_active = config::byKey('active', $classname, null);
}
if ($plugin_active == 1) {
try {
include_file('core', $classname, 'class', $classname);
} catch (Throwable $e) {
log::add('plugin', 'error', $e->getMessage());
}
}
}

Quand une classe non encore chargée type NutCmd doit être autoloadée :
str_replace(['Real', 'Cmd'], '', 'NutCmd') donne Nut (casse dérivée du nom de classe PHP, qui est en ucfirst).
config::byKey('active', 'Nut', null) retourne bien 1, car la comparaison MariaDB (collation par défaut utf8_general_ci) est insensible à la casse — Nut matche la ligne plugin = 'nut' en base.
include_file('core', $classname, 'class', $classname) est alors appelée avec $classname = 'Nut' utilisé à la fois comme nom de fichier et comme nom de dossier plugin.
Dans include_file() (core/php/utils.inc.php, ligne ~76), le chemin final est construit ainsi :
if ($_plugin != '') {
$_folder = 'plugins/' . $_plugin . '/' . $_folder;
}
$path = DIR . '/../../' . $_folder . '/' . $_fn;
if (!file_exists($path) && $type == 'php') {
throw new Exception(__('Fichier introuvable :', FILE) . ' ' . secureXSS($path), 35486);
}

Le dossier plugin sur le système de fichiers est en minuscule (plugins/nut/, Linux est sensible à la casse), donc le chemin construit avec Nut (majuscule) échoue systématiquement : plugins/Nut/core/class/Nut.class.php n'existe pas.
L'exception est attrapée et logguée dans jeedomAutoload() :
catch (Throwable $e) {
log::add('plugin', 'error', $e->getMessage());
}
D'où l'entrée de log observée.

Type de matériel / Hardware type

VM

Version de Jeedom / Jeedom Version

4.6.1

Navigateur / Browser

Chrome

Étapes pour reproduire / Steps to reproduce

Reproduction
Avoir un plugin installé dont l'id est en minuscule (convention standard, ex. nut) et actif (config.plugin = 'nut', key = 'active', value = '1').
Déclencher, avant que la classe principale du plugin ne soit chargée par un autre mécanisme, l'autoload d'une classe compagnon nommée Cmd ou Real (ex. NutCmd).
jeedomAutoload() tente de charger plugins//core/class/.class.php au lieu de plugins//core/class/.class.php.
Erreur "Fichier introuvable" logguée en catégorie plugin.
Vérifications effectuées côté utilisateur (excluant les autres causes possibles)
Table cron : aucune entrée avec class = 'Nut'.
Table config : aucune entrée avec clé contenant "Nut", et la ligne active du plugin est bien plugin = 'nut' (minuscule).
Table eqLogic : eqType_name = 'nut' (minuscule) pour l'équipement concerné.
plugin_info/info.json du plugin : "id": "nut" (minuscule).
Code du plugin Nut : aucune référence en dur à "Nut" ni ucfirst() suspect ; les seules occurrences de CLASS (dans getCmdPython3(CLASS)) ne sont pas en cause ici (chemin venv Python non emprunté sur cette install, OS < Debian 12).

Le problème vient donc bien du cœur (core/php/core.inc.php), pas du plugin ni d'une donnée corrompue.
Impact
Aucun impact fonctionnel constaté (le plugin et ses équipements fonctionnent normalement).
Pollution récurrente des logs (catégorie plugin, niveau ERROR).
Piste de correction suggérée
Dans jeedomAutoload(), ne pas réutiliser la même variable $classname (dérivée par ucfirst) pour le paramètre $_plugin de include_file(). Le nom du dossier plugin doit correspondre à l'id du plugin tel que stocké/normalisé (minuscule), par exemple :
include_file('core', $classname, 'class', strtolower($classname));
ou en récupérant l'id réel du plugin via plugin::byId()/la valeur de configuration plutôt qu'en dérivant depuis le nom de classe.

Logs

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions