views:

28

answers:

2

I am trying to make a script that lists only folders within a folder. The thing is that I have users who can create folders within their folders so basically what I'm trying to do is to have a way for users to manage their folders and storing files... My problem is that I want to make php "think" that the root folder is their home directory and they cannot go upper than their home directory. Currently my php function doesn't do that, it only shows the content of the directory...and if the user goes one level up and again one level up ...and so on....he could browse the entire hard drive.

function directoryList($path) {
    $dirStruct = array();
    if(is_dir($path)) {
        $handle = opendir($path);
        while(($file = readdir($handle)) !== false) {
            if(@opendir($path.$file)) {
                chdir($path.$file);
                $absolutepath = getcwd();
                $dirStruct[] = array('path' => $absolutepath.'\\', 'name'=>$file);
            }
        }
    }
    return $dirStruct;
}
+2  A: 

Instead of giving the user an absolute path, only allow them to specify paths which are relative to a given base path. Next, write a function which removes any "/../" for the relative path and you're safe (as long as users can't create links on the server ...).

If you want to be nice, you can match the ".." with the element before that (so "a/../b" would become "b", i.e. the ".." remove the "a") or ignore the ".." if there is no path element before it.

Aaron Digulla
i am assuming that the "a/../b" would be a regex. is it?
No, ".." is the parent directory.
Aaron Digulla
A: 

Here is a little something to expand on:

function listFolders($folderPath, $homeFolder)
{
    $folderPath = realpath($folderPath);
    $homeFolder = realpath($homeFolder);
    if(strpos($folderPath, $homeFolder) === 0) {
        return glob("$folderPath/*", GLOB_ONLYDIR);
    }
}

$dirs = listFolders('/home/gordon/code/php', '/home/gordon');
print_r($dirs);

For $folderPath you pass in the folder you want to list the directories from. For $homeFolder pass in the folder you want to be the top most folder. By realpathing both paths you make sure they are resolved to absolute paths. If the $folderPath is below the $homeFolder, then the $folderPath string will start with and contain the entire $homeFolder string. If this is the case, we just glob all directories in the $folderPath and return their absolute pathes in an array.


To get the relative path of the $folderPath from the $homeFolder, just do

ltrim(str_replace('/home/gordon/', './', '/home/gordon/code/php/'), '/');

which would return ./code/php/.


If you want to do this with OOP, you might be interested in the SPL DirectoryIterator.

Gordon