【问题标题】:Checking for relative vs absolute paths/URLs in PHP检查 PHP 中的相对路径和绝对路径/URL
【发布时间】:2011-11-15 13:50:05
【问题描述】:

我需要实现一些函数来检查路径和 url 是相对的、绝对的还是无效的(在语法上无效 - 不是资源是否存在)。我应该寻找哪些案例?

function check_path($dirOrFile) {
    // If it's an absolute path: (Anything that starts with a '/'?)
        return 'absolute';
    // If it's a relative path: 
        return 'relative';
    // If it's an invalid path:
        return 'invalid';
}

function check_url($url) {
    // If it's an absolute url: (Anything that starts with a 'http://' or 'https://'?)
        return 'absolute';
    // If it's a relative url:
        return 'relative';
    // If it's an invalid url:
        return 'invalid';
}

【问题讨论】:

  • nashruddin.com/… 获取该链接中详述的函数的结果并比较之前/之后的结果。如果它改变了,那么你可能有一个相对 url
  • <ocd>您忘记在return 值中关闭单引号。</ocd>
  • @Marc B- 虽然该链接有一些有用的部分,但它对我不起作用,尤其是如果我不知道传递给我的 url 的基础是什么 -我将无法匹配它...

标签: php url relative-path absolute-path relative-url


【解决方案1】:

绝对路径和 URL

你是对的,Linux 中的绝对 URL 必须以 / 开头,因此检查路径开头的斜杠就足够了。

对于 URL,您需要检查 http://https://,正如您所写,但是,还有更多以 ftp://sftp://smb:// 开头的 URL。因此,这很大程度上取决于您想要涵盖的用途范围。

无效的路径和网址

假设您指的是 Linux,路径中唯一被禁止的字符是 /\0。这实际上是非常依赖于文件系统的,但是,您可以假设以上对于大多数用途都是正确的。

在 Windows 中它更复杂。您可以在备注下的Path.GetInvalidPathChars Method 文档中阅读相关内容。

URL 比 Linux 路径更复杂,因为唯一的允许字符是 A-Za-z0-9-._~ ,:,/,?,#,[,],@,!,$,',',',@9876 987654350@、*+,;=(如另一个答案here 中所述)。

相对路径和 URL

一般来说,既不是绝对也不是无效的路径和 URL 是相对的。

【讨论】:

  • 检查前导斜杠是不够,如果您希望您的 PHP 脚本可以移植到其他平台 - Windows 上的绝对路径可能以反斜杠或 "C:\" 开头。 .. 我想出了以下(Preg)正则表达式:/^(?:\/|\\|\w\:\\).*$/ - 这将匹配 "/file""\file""c:\file",但不匹配 "file""path/file" 等。
  • 实际上,我记得曾经在 Linux 上的 Ext3 IIRC 上写过一个包含 \0 的文件名(只是为了好玩)。文件名中的\n 也有效,这两件事可以破坏 99% 的脚本(更不用说如果路径中有空格,它们中的一半已经破坏了哈哈)。
  • 嘿@mindplay.dk,您的正则表达式不适用于 C:/。但它确实适用于 C:\。现在在 Windows 中,C:/ 路径也是合法的!任何想法如何解决?
  • 我添加了一个额外的选项来修复:^(?:\/|\\|\w\:\\|\w\:\/).*$。它现在可以识别 C:/.
  • 由于试图让它在 PHP 上工作,由于 PHP 奇怪地转义反斜杠的方式,正则表达式必须转换为 ^(?:\/|\\\\|\w:\\\\|\w:\/).*$/
【解决方案2】:

由于我的声誉不佳,我无法对答案发表评论,因此我必须使用他从 Drupal 库中复制的函数来回复 ymakux 答案。

我正在使用这个函数,我发现带有查询部分的网址(?符号后的文本)包含 |符号将被评估为假

例如:

https://example.com/image.jpeg?fl=res,749,562,3|shr,,20|jpg,90

将被评估为假。

你所要做的就是添加

\|

查询正则表达式的一部分,使函数看起来像:

public static function isAbsoluteUrl($url)
    {
        $pattern = "/^(?:ftp|https?|feed)?:?\/\/(?:(?:(?:[\w\.\-\+!$&'\(\)*\+,;=]|%[0-9a-f]{2})+:)*
        (?:[\w\.\-\+%!$&'\(\)*\+,;=]|%[0-9a-f]{2})+@)?(?:
        (?:[a-z0-9\-\.]|%[0-9a-f]{2})+|(?:\[(?:[0-9a-f]{0,4}:)*(?:[0-9a-f]{0,4})\]))(?::[0-9]+)?(?:[\/|\?]
        (?:[\w#!:\.\?\+\|=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2})*)?$/xi";

        return (bool) preg_match($pattern, $url);
    }

希望它可以帮助某人:)

【讨论】:

  • 现在最难的部分...尝试将修复程序放入 Drupal :)
【解决方案3】:

如果您已经知道网址格式正确

if(strpos($uri,'://')!==false){
    //protocol: absolute url
}elseif(substr($uri,0,1)=='/'){
    //leading '/': absolute to domain name (half relative)
}else{
    //no protocol and no leading slash: relative to this page
}

【讨论】:

  • substr($uri,0,1) != '/ 应该是 substr($uri,0,1) == '/ 吗?
  • 是的@ChrisHappy,奇怪的是有些人用那个错字标记:|也许他们用 cmets 修复了它
【解决方案4】:

我最近启动了一个 composer 包,它可能有助于检查 URL 是相对/绝对(当然还有更多)。

在此处查看存储库:https://github.com/Enrise/UriHelper 或者这里的 composer Packagists 包:https://packagist.org/packages/enrise/urihelper

一些例子:

$uri = new \Enrise\Uri('http://usr:pss@example.com:81/mypath/myfile.html?a=b&b[]=2&b[]=3#myfragment');
echo $uri->getScheme(); // http
echo $uri->getUser(); // usr
echo $uri->getPass(); // pss
echo $uri->getHost(); // example.com
echo $uri->getPort(); // 81
echo $uri->getPath(); // /mypath/myfile.html
echo $uri->getQuery(); // a=b&b[]=2&b[]=3
echo $uri->getFragment(); // myfragment
echo $uri->isSchemeless(); // false
echo $uri->isRelative(); // false

$uri->setScheme('scheme:child:scheme.VALIDscheme123:');
$uri->setPort(null);

echo $uri->getUri(); //scheme:child:scheme.VALIDscheme123:usr:pss@example.com/mypath/myfile.html?a=b&b[]=2&b[]=3#myfragment

【讨论】:

    【解决方案5】:

    这个函数取自 Drupal

    public function is_absolute($url)
    {
        $pattern = "/^(?:ftp|https?|feed):\/\/(?:(?:(?:[\w\.\-\+!$&'\(\)*\+,;=]|%[0-9a-f]{2})+:)*
        (?:[\w\.\-\+%!$&'\(\)*\+,;=]|%[0-9a-f]{2})+@)?(?:
        (?:[a-z0-9\-\.]|%[0-9a-f]{2})+|(?:\[(?:[0-9a-f]{0,4}:)*(?:[0-9a-f]{0,4})\]))(?::[0-9]+)?(?:[\/|\?]
        (?:[\w#!:\.\?\+=&@$'~*,;\/\(\)\[\]\-]|%[0-9a-f]{2})*)?$/xi";
    
        return (bool) preg_match($pattern, $url);
    }
    

    【讨论】:

      【解决方案6】:

      Symfony FileSystem component检查路径是否为绝对路径:

      public function isAbsolutePath($file)
      {
          return strspn($file, '/\\', 0, 1)
              || (strlen($file) > 3 && ctype_alpha($file[0])
                  && substr($file, 1, 1) === ':'
                  && strspn($file, '/\\', 2, 1)
              )
              || null !== parse_url($file, PHP_URL_SCHEME)
          ;
      }
      

      【讨论】:

        【解决方案7】:

        用途:

        function isAbsolute($url) {
          return isset(parse_url($url)['host']);
        }
        

        说明:

        如果设置了主机,则路径是绝对的。

        例如:

        $test = [
        '/link?param=1'=>parse_url('/assa?ass'),
        '//aaa.com/link?param=1'=>parse_url('//assa?ass'),
        'http://aaa.com/link?param=1'=>parse_url('http://as.plassa?ass')
        ];
        var_export($test);
        
        /* Output:
        [
          "/link?param=1" => array:2 [▼ // Not absolute
            "path" => "/assa"
            "query" => "ass"
          ]
          "//aaa.com/link?param=1" => array:2 [▼ // Absolute because of host
            "host" => "assa"
            "query" => "ass"
          ]
          "http://aaa.com/link?param=1" => array:3 [▼ // Absolute because of host
            "scheme" => "http"
            "host" => "as.plassa"
            "query" => "ass"
          ]
        ]
        */
        

        【讨论】:

          猜你喜欢
          • 2010-12-17
          • 1970-01-01
          • 2011-11-25
          • 2010-09-15
          • 2014-03-09
          • 2011-10-16
          • 2013-11-30
          • 1970-01-01
          • 2013-07-14
          相关资源
          最近更新 更多