Php 无符号链接解析的绝对路径/将用户保留在主目录中

Php 无符号链接解析的绝对路径/将用户保留在主目录中,php,absolute-path,directory-browsing,Php,Absolute Path,Directory Browsing,在PHP中,有没有一种方法可以在不解析符号链接的情况下确定给定相对路径的绝对路径?类似于realpath函数,但没有符号链接解析 或者,是否有一些简单的方法来检查用户(使用我的浏览PHP脚本查看文件的用户)是否无意中跳出了Apache虚拟主机的主目录?(或者不允许他在小路上使用肮脏的东西) 谢谢 您可以使用设置ini php.ini或在虚拟主机声明中(作为php\u admin\u value指令)。我不知道php本机解决方案,但这里有一个很好的绝对路径实现:这是我模仿原始realpath()的

在PHP中,有没有一种方法可以在不解析符号链接的情况下确定给定相对路径的绝对路径?类似于
realpath
函数,但没有符号链接解析

或者,是否有一些简单的方法来检查用户(使用我的浏览PHP脚本查看文件的用户)是否无意中跳出了Apache虚拟主机的主目录?(或者不允许他在小路上使用肮脏的东西)


谢谢

您可以使用设置ini php.ini或在虚拟主机声明中(作为php\u admin\u value指令)。

我不知道php本机解决方案,但这里有一个很好的绝对路径实现:

这是我模仿原始
realpath()
的方法,它还:

  • 添加/删除Windows驱动器号,如
    c:
    所示
  • 删除尾部斜杠
  • 将当前工作目录前置到相对路径
  • (可选)检查文件是否存在。如果文件不存在,A)不执行任何操作,B)返回假值或C)抛出错误
  • 可以选择跟随符号链接
  • 注意:这种方法使用正则表达式,这是众所周知的CPU开销,所以我喜欢使用数组的方法


    这是如何避免符号链接解析的?@MikePretzlaw与
    realpath
    不同,此函数在文件系统级别上不做任何事情,因为它只对字符串修改有效。这就是重点!:-)
    // Set constants for when a file does not exist.
    // 0: Check file existence, set FALSE when file not exists.
    define('FILE_EXISTENCE_CHECK', 0);
    // 1: Require file existence, throw error when file not exists.
    define('FILE_EXISTENCE_CHECK_REQUIRE_FILE', 1);
    // 2: Do not check file existence.
    define('FILE_EXISTENCE_CHECK_SKIP', 2);
    // Windows flag.
    define('IS_WINDOWS', preg_match('#WIN(DOWS|\d+|_?NT)#i', PHP_OS));
    // Directory separator shortcuts.
    define('DIR_SEP', DIRECTORY_SEPARATOR);
    define('PREG_DIR_SEP', preg_quote(DIR_SEP));
    
    /**
     * The original realpath() follows symbolic links which makes it harder to check
     * their paths.
     *
     * Options
     *   file_existence_check:
     *   - FILE_EXISTENCE_CHECK_REQUIRE_FILE: Script will break if the checked
     *     file does not exist (default).
     *   - FILE_EXISTENCE_CHECK: If a file does not exist, a FALSE value will be
     *     returned.
     *   - FILE_EXISTENCE_CHECK_SKIP: File existence will not be checked at all.
     *
     *   follow_link: Resolve a symbolic link or not (default: FALSE).
     */
    function _realpath($path = NULL, $options = array()) {
      // Merge default options with user options.
      $options = array_merge(array(
        'file_existence_check' => FILE_EXISTENCE_CHECK_REQUIRE_FILE,
        'follow_link' => FALSE,
      ), $options);
    
      // Use current working directory if path has not been defined.
      $path = $path ? $path : getcwd();
      // Replace slashes with OS specific slashes.
      $path = preg_replace('#[\\\/]#', DIR_SEP, $path);
    
      // Handle `./`. Another great approach using arrays can be found at:
      // @link p://php.net/manual/en/function.realpath.php#84012
      $path = preg_replace('#' . PREG_DIR_SEP . '(\.?' . PREG_DIR_SEP . ')+#', DIR_SEP, $path);
      // Handle `../`.
      while (preg_match('#^(.*?)' . PREG_DIR_SEP . '[^' . PREG_DIR_SEP . ']+' . PREG_DIR_SEP . '\.\.($|' . PREG_DIR_SEP . '.*)#', $path, $m)) {
        $path = $m[1] . $m[2];
      }
      // Remove trailing slash.
      $path = rtrim($path, DIR_SEP);
    
      // If we are on Windows.
      if (IS_WINDOWS) {
        // If path starts with a lowercase drive letter.
        if (preg_match('#^([a-z]:)(.*)#', $path, $m)) {
          $path = strtoupper($m[1]) . $m[2];
        }
        // If path starts with a slash instead of a drive letter.
        elseif ($path[0] === DIR_SEP) {
          // Add current working directory's drive letter, ie. "D:".
          $path = substr(getcwd(), 0, 2) . $path;
        }
      }
      else {
        // Remove drive letter.
        if (preg_match('#^[A-Z]:(' . PREG_DIR_SEP . '.*)#i', $path, $m)) {
          $path = $m[1];
        }
      }
    
      // If path is relative.
      if (!preg_match('#^([A-Z]:)?' . PREG_DIR_SEP . '#', $path)) {
        // Add current working directory to path.
        $path = getcwd() . DIR_SEP . $path;
      }
    
      // If file existence has to be checked and file does not exist.
      if ($options['file_existence_check'] !== DSC_FILE_EXISTENCE_CHECK_SKIP && !file_exists($path)) {
        // Return FALSE value.
        if ($options['file_existence_check'] === DSC_FILE_EXISTENCE_CHECK) {
          return FALSE;
        }
        // Or throw error.
        else {
          dsc_print_error('File does not exist: ' . $path);
        }
      }
    
      // Follow sybmolic links, but only if the file exists.
      if (!empty($options['follow_link']) && file_exists($path)) {
        $path = readlink($path);
      }
    
      return $path;
    }