What is the best way to resolve a relative path (like realpath) for non-existing files?

后端 未结 4 1982
Happy的楠姐
Happy的楠姐 2020-12-30 01:43

I\'m trying to enforce a root directory in a filesystem abstraction. The problem I\'m encountering is the following:

The API lets you read and write files, not only

4条回答
  •  -上瘾入骨i
    2020-12-30 02:10

    /**
     * Remove '.' and '..' path parts and make path absolute without
     * resolving symlinks.
     *
     * Examples:
     *
     *   resolvePath("test/./me/../now/", false);
     *   => test/now
     *   
     *   resolvePath("test///.///me///../now/", true);
     *   => /home/example/test/now
     *   
     *   resolvePath("test/./me/../now/", "/www/example.com");
     *   => /www/example.com/test/now
     *   
     *   resolvePath("/test/./me/../now/", "/www/example.com");
     *   => /test/now
     *
     * @access public
     * @param string $path
     * @param mixed $basePath resolve paths realtively to this path. Params:
     *                        STRING: prefix with this path;
     *                        TRUE: use current dir;
     *                        FALSE: keep relative (default)
     * @return string resolved path
     */
    function resolvePath($path, $basePath=false) {
        // Make absolute path
        if (substr($path, 0, 1) !== DIRECTORY_SEPARATOR) {
            if ($basePath === true) {
                // Get PWD first to avoid getcwd() resolving symlinks if in symlinked folder
                $path=(getenv('PWD') ?: getcwd()).DIRECTORY_SEPARATOR.$path;
            } elseif (strlen($basePath)) {
                $path=$basePath.DIRECTORY_SEPARATOR.$path;
            }
        }
    
        // Resolve '.' and '..'
        $components=array();
        foreach(explode(DIRECTORY_SEPARATOR, rtrim($path, DIRECTORY_SEPARATOR)) as $name) {
            if ($name === '..') {
                array_pop($components);
            } elseif ($name !== '.' && !(count($components) && $name === '')) {
                // … && !(count($components) && $name === '') - we want to keep initial '/' for abs paths
                $components[]=$name;
            }
        }
    
        return implode(DIRECTORY_SEPARATOR, $components);
    }
    

提交回复
热议问题