phpabsolute-pathdirectory-browsing

Absolute path without symlink resolution / Keep user in home directory


Is there a way in PHP how to determine an absolute path given a relative path without actually resolving symlinks? Something like the realpath function but without symlink resolution.

Or alternatively, is there some easy way to check whether user (who uses my browsing PHP script to view files) did not accidentally step out of Apache virtual host's home directory? (or disallow him to use the nasty . and .. in paths)

Thanks!


Solution

  • I don't know PHP native solution for this, but here's one nice absolute path implementation from a comment in the PHP docs:

    Because realpath() does not work on files that do not exist, I wrote a function that does. It replaces (consecutive) occurences of / and \ with whatever is in DIRECTORY_SEPARATOR, and processes /. and /.. fine. Paths returned by get_absolute_path() contain no (back)slash at position 0 (beginning of the string) or position -1 (ending).

    function get_absolute_path($path) {
       $path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path);
       $parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen');
       $absolutes = array();
       foreach ($parts as $part) {
           if ('.' == $part) continue;
           if ('..' == $part) {
               array_pop($absolutes);
           } else {
               $absolutes[] = $part;
           }
       }
       return implode(DIRECTORY_SEPARATOR, $absolutes);
    }
    

    A test:

    var_dump(get_absolute_path('this/is/../a/./test/.///is'));
    

    Returns:

    string(14) "this/a/test/is"
    

    As you can see, it also produces Yoda-speak. :)

    (edited for formatting & typos)