[spip-dev] Bug sur is_dir()

Remarqué sur SPIP 2.0.6, sur : find_in_path('../tmp/couteau-suisse/1ac2e6ce1759c835f172f0d220fb4128.html')

La fonction find_in_path() (inc/utils.php) utilise un is_dir() sans précaution.
Sous free, voici les répertoires parcourus, presque tous OK :

../plugins/auto/enluminures_typographiques_v3/../tmp/couteau-suisse/
../plugins/auto/autorite/../tmp/couteau-suisse/
(...)
../plugins/auto/cfg/../tmp/couteau-suisse/
../../tmp/couteau-suisse/

ICI ERREUR : Warning: is_dir() [function.is-dir]: Unable to access ../../tmp/couteau-suisse/ in /mnt/139/sdc/8/7/bachant/ecrire/inc/utils.php on line 698

Je pense que free n'aime pas trop ../../

Je propose de remplacer dans SPIP :
  $dirs[$a] = (is_dir($a) || !$a) ;
par :
  $dirs[$a] = (@is_dir($a) || !$a) ;

(patch joint)

Pat

patch_utils.patch (420 Bytes)

La fonction find_in_path() (inc/utils.php) utilise un is_dir() sans
précaution.
Sous free, voici les répertoires parcourus, presque tous OK :

../plugins/auto/enluminures_typographiques_v3/../tmp/couteau-suisse/
../plugins/auto/autorite/../tmp/couteau-suisse/
(...)
../plugins/auto/cfg/../tmp/couteau-suisse/
../../tmp/couteau-suisse/

Ca ne va pas, tu proposes de masquer le bug plutôt que de le corriger...

-- Fil

OK, je pensais de toute façon que si le dir est rejeté par le système, c'est qu'il n'existe pas.
Bon, je te laisse voir ce qu'il en est alors.
Pat

Fil a écrit :

Bon, je te laisse voir ce qu'il en est alors.

ben attends t'y es presque, abandonne pas

-- Fil

hmm... nan je seche... il me faut un pro lol

Que j'essaie is_readable() ou file_exists(), le warning apparait, free rejete le test.

Le bug n'est ni dans le find_in_path ni dans le is_dir, mais conceptuellement dans l'appel :
../tmp/...
est une aberration car ne pouvant jamais se raporter au path. find_in_path doit trouver quelque chose *dans* le chemin, alors qu'en faisant ../ tu cherches *en dehors* du chemin.

Si patch il devait y avoir, cela serait un rejet pur et simple de tout appel à find_in_path dont le fichier commence par '../'

Si tu as besoin de chercher un fichier dans tmp/ cela devrait être simplement
find_in_path('tmp/truc.html')
puisque la racine est dans le chemin...

Cédric

Bon,
C'est vrai que le "../" retourné par creer_chemin() est aberrant.
Mais je ne sais pas d'où il vient...
Un recuperer_fond() peut-être qui n'a pas vu qu'il était appelé en privé?
En plus là vraiment, je dois aller bosser.
Et si tu vois la soluce, n'hésite pas.. Je n'ai pas encore installé Eclipse !!
Pat

Fil a écrit :

Oui, c'est très clair ce que tu dis.
Mais en privé, dans 'ecrire/', le find_in_path('../tmp/') semble valide pourtant...
find_in_path() va se promener dans le niveau supérieur, alors qu'il ne devrait pas...
Le fichier en question est fabriqué comme ceci :
  define('_DIR_CS_TMP', sous_repertoire(_DIR_TMP, "couteau-suisse"));
  $fond = _DIR_CS_TMP . md5($code);
Pat

cedric.morin@yterium.com a écrit :

Mais en privé, dans 'ecrire/', le find_in_path('../tmp/') semble valide
pourtant...

Non car tu n'as pas à "chercher" _DIR_TMP, vu que _DIR_TMP est une
constante qui indique où se trouve ce répertoire.

-- Fil

C'est pas moi c'est lui !
Non lol, je voulais dire que je ne cherche moi-même pas ce fichier en dur.
J'utilise seulement les fonctions :
  ecrire_fichier() et inclure_page()
Voici le code de la fonction en question :

/**
  * recupere le resultat du calcul d'une compilation de code de squelette (marcimat)
  * $coucou = $this->recuperer_code('[(#AUTORISER{ok}|oui)coucou]');
  */
function cs_recuperer_code(&$code) {//, $contexte=array(), $options = array(), $connect=''){
  $fond = _DIR_CS_TMP . md5($code);
  $base = $fond . '.html';
  if (!file_exists($base) OR $GLOBALS['var_mode']=='recalcul')
    ecrire_fichier($base, $code);
  include_spip('public/assembler');
  return recuperer_fond($fond, array('fond'=>$fond));
// $f = inclure_page($fond, array('fond'=>$fond));
// return $f['texte'];
}

Pat

Fil a écrit :

oui mais c'est à toi de construire mieux ton chemin vers ton fond...
En particulier à en virer le ../ qui vient de ton _DIR_CS_TMP et qui n'est la que pour aller directement au répertoire depuis là ou on est (dans ecrire), et n'a rien à faire dans le chemin "relatif au path" donné pour vers le squelette.
Cédric

Mais quoi de mieux que :
     define('_DIR_CS_TMP', sous_repertoire(_DIR_TMP, "couteau-suisse"));
?
Je dois le passer en absolu, c'est ca ?
J'y peux rien moi si chemin() va voir systématiquement en '../' !
Pat

cedric.morin@yterium.com a écrit :

define('_DIR_CS_TMP', sous_repertoire(_DIR_TMP, "couteau-suisse"));
?
Je dois le passer en absolu, c'est ca ?

$fond = _DIR_CS_TMP . md5($code);

essaie avec
$fond = str_replace('../', '', _DIR_CS_TMP) . md5($code);

Il faut voir ce que ça donne en mutualisation aussi :slight_smile:

-- Fil

Non, c'est une erreur bloquante cette fois :
vérifier les droits d'écriture. Le système a rencontré une erreur lors de l'écriture du fichier tmp/couteau-suisse/1ac2e6ce1759c835f172f0d220fb4128.html. Veuillez, en tant qu'administrateur du site, vérifier les droits d'écriture sur le répertoire ecrire/tmp/couteau-suisse.

Pat

Fil a écrit :

Non, c'est une erreur bloquante cette fois :
vérifier les droits d'écriture. Le système a rencontré une erreur lors de
l'écriture du fichier
tmp/couteau-suisse/1ac2e6ce1759c835f172f0d220fb4128.html. Veuillez, en tant

euh ma modif n'est censée concerner que la lecture de ce fichier :
c'est bien $fond qu'il faut changer, pas _DIR_CS_TMP

-- Fil

Excuse-moi je dois être trop simplet, je sèche complètement...
Nous sommes dans ecrire/ et le fond est '../tmp/couteau-suisse/1ac2e6ce1759c835f172f0d220fb4128.html'
Tout me parait bien normal...
Le truc à éviter peut-être, c'est que creer_chemin() aille voir dans '../' lorsqu'un fichier est déjà en ../ et qu'on est dans ecrire/
C'est bien cette fonction qui remonte trop haut dans l'arborescence, non?
Bon, ça lui ferait quelques de conditions à tester... J'admets que mon '@' réglait brutalement le pb...
C'est vrai aussi que tous les serveurs ne sont pas aussi susceptibles et ne renvoient pas tous de warning à ce sujet...
Pat

Fil a écrit :

Non
../ n'a *rien* à faire dans le chemin vers un fond :

../tmp... est un chemin relatif au repertoire d'execution de ton script (ecrire/ en l'occurence)
Alors que les fonds demandent un fichier contenu *dans* un répertoire du chemin
(d'où le *in* dans le nom de la fonction find_in_path.... -> trouver *dans* le chemin)

../tmp/ n'est pas un dossier contenu *dans* ecrire/
mais tmp/ est bien un dossier contenu *dans* la racine

Le bug est définitivement dans le pré(fixe) de ton nom de fichier.
Cédric

Nous sommes dans ecrire/ et le fond est
'../tmp/couteau-suisse/1ac2e6ce1759c835f172f0d220fb4128.html'
Tout me parait bien normal...

non le fond devrait être
'tmp/couteau-suisse/1ac2e6ce1759c835f172f0d220fb4128.html' car même
dans l'espac eprivé le compilo ira le chercher à la racine.

-- Fil

Eh oui, suis allé trop vite moi aussi!
Voici la correction, c'était tout simple effectivement :
return recuperer_fond(str_replace('../','',$fond),array('fond'=>$fond));

Fil et Cédric, merci de vos réponses.
Pat, désolé pour le bruit.

Fil a écrit :