scan listage descendant à partir d'un répertoire donné

Mammouth du PHP | 737 Messages

26 mars 2009, 01:09

Hi !

Le temps me manque et non l'envie (loin de là) et d'autres développeurs m'ont souvent dit qu'il ne fallait pas réinventer la roue...

Je cherche un moyen à partir d'un dossier de scanner tout son contenu (fichiers et sous-dossiers) que je puisse descendre jusqu'au dernier point sans jamais pouvoir remonter au dessus de mon point de départ, vous voyez le rendu. Une sorte de ftp phpïsé :)

Exemple : http://ludivine.gouel.free.fr/site/

pouvoir descendre mais pas remonter à l'accueil.

J'ai bien ceci :
      <?php 
	  $dos = "mon_dossier/";
      if ($handle = opendir($dos)) {
          while (false !== ($file = readdir($handle))) {
              if ($file != "." && $file != "..") {
                  echo "<a href='".$dos.$file."'>$file</a>\n";
              }
          }
          closedir($handle);
      }

	  ?>
Je ne demande pas qu'on m'envoie chier, ni d'aller regarder sur le net, les anciens me connaissent, je cherche juste à gagner un peu de temps car ce script est à ma portée...mais comme beaucoup je dois gérer 36 000 trucs à la fois.

Merci à vous, à toi Ryle et à la PHPfrance team :)

Mega
;)

ViPHP
ViPHP | 3300 Messages

26 mars 2009, 04:26

la réponse est fonction récursive, comme je suis de bonne humeur et que je m'ennuie, voilou
<?php

function scanrec($dir='root', $debug=false) {
    $result = array();
    if($dir == 'root') {
        $dir = dirname(__FILE__);
    }
    $dir = trim($dir);
    if(DIRECTORY_SEPARATOR == '/') {
        $dir = str_replace('\\', DIRECTORY_SEPARATOR, $dir);
    } else {
        $dir = str_replace('/', DIRECTORY_SEPARATOR, $dir);
    }
    $dir = str_replace(DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR, $dir);
    if($debug) {
        echo 'Requested: "' . $dir . '"'."\n";
    }
    $dir = realpath($dir);
    if(is_dir($dir)) {
        if($dir[strlen($dir - 1)] != DIRECTORY_SEPARATOR) {
            $dir .= DIRECTORY_SEPARATOR;
        }
        if($debug) {
            echo 'Scanning: "' . $dir . '"' . "\n";
        }
        $curlist = glob($dir . '*');
        for($i=0; $i<count($curlist); $i++) {
            array_push($result, $curlist[$i]);
            if(is_dir($curlist[$i])) {
                $curcontent = scanrec($curlist[$i], $debug);
                for($j=0; $j<count($curcontent); $j++) {
                    array_push($result, $curcontent[$j]);
                }
            }
        }
    }
    return $result;
}

echo '<pre>';
print_r(scanrec('\\\\home\\\\logan                   ', true));
echo '</pre>';

Fait du php depuis que ca existe ou presque :)

ViPHP
ViPHP | 3300 Messages

26 mars 2009, 06:00

Bah j'ai relu, et ensuite je me suis dit que j'avais pas compris la question ceci dit tu pourrais utiliser mon premier script et faire un truc en javascript tout mignon, dans le cas contraire tu pourrais utiliser ça:

<?php

function listcurdir($root='root', $dir='root', $debug=false) {
    $result = array();
    if($dir == 'root' || is_null($dir)) {
        if($root != 'root') {
            $dir = $root;
        } else {
            $dir = dirname(__FILE__);
        }
    } else {
        $dir = base64_decode(urldecode($dir));
    }
    if($root == 'root' || is_null($root)) {
        $root = dirname(__FILE__);
    }
    if(!preg_match('`^'.$root.'`', $dir)) {
        if($debug) {
            echo 'Error: ' . $dir . ' isnt in '. $root . '!' . "\n";
        }
        return $result;
    }
    $dir = trim($dir);
    $root = trim($root);
    if(DIRECTORY_SEPARATOR == '/') {
        $dir = str_replace('\\', DIRECTORY_SEPARATOR, $dir);
        $root = str_replace('\\', DIRECTORY_SEPARATOR, $root);
    } else {
        $dir = str_replace('/', DIRECTORY_SEPARATOR, $dir);
        $root = str_replace('/', DIRECTORY_SEPARATOR, $root);
    }
    $dir = str_replace(DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR, $dir);
    $root = str_replace(DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR, $root);
    if($debug) {
        echo 'Requested: "' . $dir . '"'."\n";
    }
    $dir = realpath($dir);
    $root = realpath($root);
    $tmp = explode(DIRECTORY_SEPARATOR, $dir);
    array_pop($tmp);
    $prevdir = implode(DIRECTORY_SEPARATOR, $tmp);
    if($dir[strlen($dir - 1)] != DIRECTORY_SEPARATOR) {
        $dir .= DIRECTORY_SEPARATOR;
    }
    if($root[strlen($root - 1)] != DIRECTORY_SEPARATOR) {
        $root .= DIRECTORY_SEPARATOR;
    }
    if($prevdir[strlen($prevdir - 1)] != DIRECTORY_SEPARATOR) {
        $prevdir .= DIRECTORY_SEPARATOR;
    }
    if($debug) {
        echo 'Scanning: "' . $dir . '"' . "\n";
    }
    if($root == $prevdir || preg_match('`^'.$root.'`', $prevdir)) {
        array_push($result, array('link'=>urlencode(base64_encode($prevdir)), 'type'=>'D', 'name'=>'..'));
    }
    $curlist = glob($dir . '*');
    for($i=0; $i<count($curlist); $i++) {
        $type = 'U';
        if(is_dir($curlist[$i])) {$type = 'D';}
        if(is_file($curlist[$i])) {$type = 'F';}
        if(is_link($curlist[$i])) {$type = 'L';}
        array_push($result, array('link'=>urlencode(base64_encode($curlist[$i])), 'type'=>$type, 'name'=>str_replace($dir, '', $curlist[$i])));
    }
    return $result;
}

if(isset($_GET['dir'])) {
    $dir = $_GET['dir'];
} else {
    $dir = null;
}

$list = listcurdir('/home/logan', $dir);

function cmp($a, $b){
    if($b['name'] == '..') return +1;
    if ($a['type'] == $b['type']) {
        if(strtolower($a['name']) == strtolower($b['name'])) {
            return 0;
        } else {
            return (strtolower($a['name']) > strtolower($b['name'])) ? +1 : -1;
        }
    }
    return ($a['type']=='D' && ($b['type'] == 'F' || $b['type'] == 'L')) ? -1 : +1;
}

usort($list, "cmp");

echo '<ul>' . "\n";
foreach($list as $file) {
    if($file['type'] == 'D') {
        $text = '<a href="'.$_SERVER['PHP_SELF'].'?dir=' . $file['link'] . '">'.$file['name'].'</a>';
    } else {
        $text = $file['name'];
    }
    echo '<li>('.$file['type'].')&nbsp;' . $text . '</li>' . "\n";
}
echo '</ul>' . "\n";


Fait du php depuis que ca existe ou presque :)

ViPHP
ViPHP | 3300 Messages

26 mars 2009, 06:12

Donc pour commenter un peu les principaux points sont:

-les données passées en url doivent être protégée (urlencode base64_encode)
-la fonction te renvoit pour chaque fichier un array contenant le type (Dossier, Fichier, Link)
-Les résultats sont ordonnés classiquement (répertoire d'abord, fichiers ensuite, chacun ordonnés alphabétiquement et case insensitivement les uns par rapport aux autres)
-l'appel de fonction comprend un root et un dir, le root c'est le répertoire le plus haut qu'on peut browser, le dir c'est le répertoire de départ, ca devrait être assez souple pour que tu puisse faire un peu ce que tu veux
-pour chaque résultat, le premier fichier est le répertoire parent (sauf si on est dans le root) on peut s'amuser à taper l'argument nécessaire pour browser au dessus du root mais la fonction va pondre un tableau vide, à toi de faire la gestion d'erreur qui te convient
-les balises utilisées sont des ul, li, c'est assez facile à customizer pour faire ressembler le tout à un vrai répertoire

Voilou, en tout cas tu m'as occupé dans mon insomnie :)
Fait du php depuis que ca existe ou presque :)

Mammouth du PHP | 737 Messages

26 mars 2009, 14:36

Salut, content d'avoir pu te rendre service lol

En tout cas un grand MERCI Nagol, je pense que tu m'as fait gagné quelques précieuses heures.

Musicalement,

Mega
;)

ViPHP
ViPHP | 3300 Messages

28 mars 2009, 18:21

y'a pas de quoi

oublie pas le résolu si c'est résolu :)
Fait du php depuis que ca existe ou presque :)

Mammouth du PHP | 737 Messages

29 mars 2009, 14:53

Exact, j'avais bidouillé un script de mon côté qui obligeait à mettre un fichier index différent à chaque "sous-étage", moins pratique que le tien mais très fonctionnel :)