4

I have a php script that reads a directory and lists all the files/directories in link form, and it works, except I'm trying to get it to be recursive so that when I choose another directory it once again uses the script to display the files inside. Right now when I select a directory it just goes to the default apache listing....any help is appreciated.

Script:

    <?php
$dirname = '/drives/Storage/AppsOSs/';
$webdirname = '/AppsOSs'; // what the directory appears as from the web browser's point of view

$dir = opendir($dirname);
$file_list = '';

while(($file = readdir($dir)) != false) {
if(($file != '.') && ($file != '..')) {
$file_list .= "<a href=\"$webdirname/$file\">$file</a><br/>";
}
}

closedir($dir);
?>

<p>
<?=$file_list?>
</p>
jz3
  • 521
  • 3
  • 13
  • 21
  • 1
    You could use $dirname as $dirname = $_GET['dirname']; and $file_list as $file_list .= "$file
    "; but this would bring you to a new level of problems such as people trying to send commands like "rm -rf *" to your $_GET and such so you would need to escape and sanitize all the incoming data so you don't run into problems but there is probably a better solution
    – Prix Jul 08 '10 at 14:22
  • hmm, yea i would rather not use GET, i try to stay away from that for the most part... The problem is when I click on a directory, right now its linking to the direct path, and since it is a directory, not a file it goes to the apache directory. What I basically want to do is have it only actually point to a direct path if the item is a file (that way it can be downloaded) but if its a directory, I really just want to retrieve the files/directories inside of that and list them similarly to how I do now w/ my script....I'm honestly not the best w/ php so I'm having a bit of trouble – jz3 Jul 08 '10 at 14:38
  • Joe - there's no getting around using GET Unless you use POST - you have to update the script wit the new directory to traverse and display or you will continually get the Apache default directory because it's no longer pointed to the script but to the physical directory. – Marco Ceppi Jul 08 '10 at 14:43
  • @Prix - passing "rm -rf *" would not be an issue in this case - the script does nothing but read only commands and does not employ shell_exec, or the like. When "rm -rf *" would come into "opendir" that function will throw a warning and fail. Though the real issue is people trying to Pry into directories they might not be allowed to see. – Marco Ceppi Jul 08 '10 at 14:47
  • @Marco Then that is a fine approch to it if you can be sure it won't be injected by anything... I am not sure myself so i will just say it is not safe :P – Prix Jul 08 '10 at 15:00

3 Answers3

3

Take a look at the Directory Iterator and the Recursive Iterator

http://php.net/manual/en/class.directoryiterator.php

or even the Recursive Directory Iterator

http://www.php.net/manual/en/class.recursivedirectoryiterator.php

Lizard
  • 43,732
  • 39
  • 106
  • 167
  • I've added more extensive recusrive diretory traversing examples with those classes in another answer: http://stackoverflow.com/a/12233983/367456 – hakre Sep 02 '12 at 08:36
2

First of all your code structure looks horrid - not sure if that was a copy and paste thing or what. But as it stands you're creating a link to the directory rather than calling the script again. Try this:

<?php
$dirname = ( isset($_GET['dir']) ) ? $_GET['dir'] : '/drives/Storage/AppsOSs/';

if( !$dir = opendir($dirname) )
{
    die("Unable to open $dirname");
}

$file_list = "";

while( ($file = readdir($dir)) !== false)
{
    if( ($file != '.') && ($file != '..') )
    {
        if( is_dir($dirname . $file) )
        {
            $file_list .= "<a href=\"" . $_SERVER['PHP_SELF'] . "?dir=" . $dirname . $file . "\">" . $file . "</a><br/>";
        }
        else
        {
            $file_list .= "<a href=\"$dirname/$file\">$file</a><br/>";
        }
    }
}

closedir($dir);
?>

<p>
<?= $file_list; ?>
</p>

You may need to tweak it slightly to work with your system. However the idea is: If it's a file it loads the File path directly into the browser, if it's a directory call the script again with the new dirname. You could elaborate further with something like this:

<?php
$dirname = ( isset($_GET['dir']) ) ? $_GET['dir'] : '/drives/Storage/AppsOSs/';

if( !$dir = opendir($dirname) )
{
    die("Unable to open $dirname");
}

$dir_arr = array();
$file_arr = array();

while( ($file = readdir($dir)) !== false)
{
    if( ($file != '.') && ($file != '..') )
    {
        if( is_dir($dirname . $file) )
        {
            $dir_arr[] = "<a href=\"" . $_SERVER['PHP_SELF'] . "?dir=" . $dirname . $file . "\">" . $file . "</a>";
        }
        else
        {
            $file_arr[] = "<a href=\"$dirname/$file\">$file</a>";
        }
    }
}

closedir($dir);

$dir_list = implode("<br/>", $dir_arr);
$file_list = implode("<br/>", $file_arr);
?>

<p>
<?= "<h1>Directories</h1>" . $dir_list . "<h1>Files</h1>" . $file_list; ?>
</p>

With this setup all directories will be listed first - rather than mixed alphabetically like in the first example.

Marco Ceppi
  • 7,163
  • 5
  • 31
  • 43
  • thanks for the help marco, yea that looks like exactly what I am trying to do. The only part I see where it might run into trouble is the files/folders I am trying to access are outside my DocumentRoot so it will display everything fine for the hardcoded directory, but when it tries to concatenate the path in the browser when I choose a link, it is going to have the wrong path because it will try to tack it on after my documentRoot – jz3 Jul 08 '10 at 14:58
  • I've been trying to get it to work on my system, and it seems to almost work. The script runs fine, and categorizes them into files/directories but it only works for the initial load. If I click on a directory, it navigates into that directory, but then it doesn't run the script again, and lists everything as a file. When I first choose a directory it does it w/ a ?dir="path" statement. But once I go into a directory, and try to select another directory, or download a file, it no longer uses the script, but just tries to link directly to it. – jz3 Jul 08 '10 at 15:29
  • hi Joe - sorry I don't have a Mac, but I do run Linux. So what you're saying is when you generate the page on first load you get the list. When you click on the link for a directory what does that link look like? – Marco Ceppi Jul 09 '10 at 12:34
0

Try the RecursiveIterator-Class and the DirectoryIterator which are delivered by the SPL (Standard PHP Library). It comes with PHP, so you can view the documentation on php.net.

See this link:

Fidi
  • 5,754
  • 1
  • 18
  • 25