Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用PHP验证URL并仅返回主机域名。_Php - Fatal编程技术网

使用PHP验证URL并仅返回主机域名。

使用PHP验证URL并仅返回主机域名。,php,Php,我想验证一个域名,然后将主域名分条返回到example.co.uk 我已经从各种来源的帮助开始了,并且可以通过.com、.net、.org、.info和所有的.uk来实现这一点 $targetUrl = 'http://sub.example.uk/test/'; $host = filter(get_domain($targetUrl)); function filter($domain){ if($domain){ $domain_array = explode

我想验证一个域名,然后将主域名分条返回到example.co.uk 我已经从各种来源的帮助开始了,并且可以通过.com、.net、.org、.info和所有的.uk来实现这一点

$targetUrl = 'http://sub.example.uk/test/';

$host = filter(get_domain($targetUrl));

function filter($domain){
    if($domain){

        $domain_array = explode(".", $domain);
        $domain_count = count($domain_array);
        $domain_last = end($domain_array);
        $domain_first = $domain_array[0];
        $domain_second = $domain_array[1];
        $domain_second_last = array_slice($domain_array, -2, 1);
        $domain_second_last = $domain_second_last[0];
        $domain_third_last = array_slice($domain_array, -3, 1);
        $domain_third_last = $domain_third_last[0];


        // UK Validation
        $uk_second = array('ac', 'co', 'gov', 'judiciary', 'ltd', 'me', 'mod', 'net', 'nhs', 'nic', 'org', 'parliament', 'plc', 'police', 'sch');
        if($domain_last == 'uk'){
            if($domain_count == '2'){
                // if domain.uk
                return $domain;
            }elseif(in_array($domain_second, $uk_second)){
                //if domain.$uk_second.uk
                return $domain;
            }elseif(in_array($domain_second_last, $uk_second)){
                // if subdomain on 2 dd.dd.co.uk rename to dd.co.uk
                $domain = $domain_third_last.'.'.$domain_second_last.'.'.$domain_last;
                return $domain;
            }else{
                // finaly it must be a dsd.sds.uk so lets remove the subdomain 
                $domain = $domain_second_last.'.'.$domain_last;
                return $domain;
            }
        }
        // END .UK
        // SImple Single TLDs 
        $single_tlds = array('com', 'net', 'org', 'info');
        if(in_array($domain_last, $single_tlds)){
            if($domain_count == '2'){
                // simple is it a ddd.com
                return $domain;
            }else{
                $domain = $domain_second_last.'.'.$domain_last;
                return $domain;
            }
        }
    }//if domain
}



function get_domain($domain) {
        $domain = strtolower($domain);   
        if (!filter_var($domain, FILTER_VALIDATE_URL) === false) {
            $urlParts = parse_url($domain);
            $domain = $urlParts['host'];
            $domain = str_ireplace('www.','',$domain); 
            $original = $domain = strtolower($domain);     
            if (filter_var($domain, FILTER_VALIDATE_IP)) { return $domain; }    
            $arr = array_slice(array_filter(explode('.', $domain, 4), function($value){
                                return $value !== 'www'; }), 0); //rebuild array indexes

            if (count($arr) > 2)    {
                $count = count($arr);
                $_sub = explode('.', $count === 4 ? $arr[3] : $arr[2]);

                if (count($_sub) === 2)  { // two level TLD
                    $removed = array_shift($arr);
                    if ($count === 4) // got a subdomain acting as a domain
                        $removed = array_shift($arr);            

                }
                elseif (count($_sub) === 1){ // one level TLD
                    $removed = array_shift($arr); //remove the subdomain             
                    if (strlen($_sub[0]) === 2 && $count === 3) // TLD domain must be 2 letters
                        array_unshift($arr, $removed);                
                    else{
                        // non country TLD according to IANA
                        $tlds = array(    'aero',    'arpa',    'asia',    'biz',    'cat',    'com',    'coop',    'edu',    'gov',    'info',    'jobs',    'mil',    'mobi',    'museum',    'name',    'net',    'org',    'post',    'pro',    'tel',    'travel',    'xxx',    );             
                        if (count($arr) > 2 && in_array($_sub[0], $tlds) !== false) {//special TLD don't have a country
                            array_shift($arr);
                        }
                    }

                }
                else { // more than 3 levels, something is wrong
                    for ($i = count($_sub); $i > 1; $i--) 
                        $removed = array_shift($arr);

                }
            }
            elseif (count($arr) === 2) {
                $arr0 = array_shift($arr);     
                if (strpos(join('.', $arr), '.') === false
                            && in_array($arr[0], array('localhost','test','invalid')) === false) // not a reserved domain
                {

                    // seems invalid domain, restore it
                    array_unshift($arr, $arr0);
                }
            }     

            return join('.', $arr);

        }

}
它的可伸缩性不是很好,我必须遍历所有的域后缀并添加它们。我相信一定有更简单的方法?有人能帮忙吗?也许可以通过某种方式从中加载列表

因此,对于一系列数据和结果,我希望看到的是:

http://subdomain.example.co.uk/path/site.php -> example.co.uk
http://subdomain.example.uk/path/site.php -> example.uk
www.subdomain.example.uk/path/site.php -> example.uk
subdomain.example.uk -> example.uk
http://gobble.gobble.notavalidsuffix -> false
给你:

给你:


事实上,在PHP中验证url是一项复杂的任务

您可以使用内置的和函数,但正如PHP.net上的许多用户评论,甚至文档所指出的那样,它们并不十分可靠

首先,它们不支持国际化域名(URL包含非ASCII字符,例如Unicode字符)

请注意,该函数将只查找有效的ASCII URL国际化域名(包含非ASCII字符)将失败

另一方面,他们通过了很多误报

请注意,有效的URL可能未指定HTTP协议HTTP://因此可能需要进一步验证以确定URL是否使用预期的协议,例如ssh://或mailto:

它们也没有有效的名称扩展名列表。这意味着类似于
asdf://asdf.asdf
通过filter\u var。我试过了,实际上是这样

filter\u var
也可能是一个潜在的XSS漏洞,因为它传递类似
j的信息avascript://comment%0Aalert(1) “您好
有效

很抱歉,这是一个坏消息,但这是事实。我确实发现了一些PHP验证库,其中包括url,但它们仍然基于
parse\u url
filter\u var
。我也不相信regex能胜任这项工作


然而,(plug time:)我正在开发一个PHP库,它应该能够实现您想要的,我希望在几天内完成它。事实是,在PHP中验证url是一项复杂的任务

您可以使用内置的和函数,但正如PHP.net上的许多用户评论,甚至文档所指出的那样,它们并不十分可靠

首先,它们不支持国际化域名(URL包含非ASCII字符,例如Unicode字符)

请注意,该函数将仅查找有效的ASCII URL;国际化域名(包含非ASCII字符)将失败

另一方面,他们通过了很多误报

请注意,有效的URL可能未指定HTTP协议HTTP://因此可能需要进一步验证以确定URL是否使用预期的协议,例如ssh://或mailto:

它们也没有有效的名称扩展名列表。这意味着类似于
asdf://asdf.asdf
通过filter\u var。我试过了,实际上是这样

filter\u var
也可能是一个潜在的XSS漏洞,因为它传递类似
j的信息avascript://comment%0Aalert(1) “您好
有效

很抱歉,我带来了坏消息,但这是事实。我确实在PHP中发现了许多包含url的验证库,但它们都是基于
parse\u url
filter\u var
构建的。我也不相信regex能胜任这份工作


然而,(plug time:)我正在开发一个PHP库,它应该能够实现您想要的,我希望在几天内完成它 下面将通过剥离不必要的URL参数等来验证URL。。然后将此字符串传递到
gethostbyname()
。然后,这将查询给定根域的DNS服务器,如果成功,将向您返回IP,如果不成功,将返回相同的输入字符串。然后,我将这个结果传递到一个过滤器中,该过滤器验证IP字符串。如果成功,它将以给定的格式返回域。只需确保您指向的DNS提供商不会解析每个DNS查找…例如,我在英国的ISP会自动解析每个失败的DNS查找,并使用有效的a记录,该记录会解析为显示“无此类网页”的网页。谷歌DNS工作正常,所以如果可以,请使用它

function validDom($url) {

    $newUrl = (filter_var($url, FILTER_VALIDATE_URL)) ? $url : FALSE;

    if ($newUrl === FALSE) {

        return FALSE;
    }

    $urlSplit = explode('/', $newUrl); 

    foreach ($urlSplit as $k=>$v) {

        if(substr_count($v, '.') >= 2) {

            $newUrl = $v;

        } 
    }

    $cleanDomain = substr_replace($newUrl, '', 0, strpos($newUrl, '.')+1);
    $chkDNS = gethostbyname($cleanDomain);

    if (filter_var($chkDNS, FILTER_VALIDATE_IP) !== FALSE) {

        return $cleanDomain;

    }

    return false;

}
测试域

$domainArr = [

'https://www.facebook.com',
'https://www.care.org.uk',
'https://www.facebook.co.uk',
'https://www.google.com/dfsdfsdfsd/sdfsdf',
'https://sub.fsdfsdfsdfsdfsd.co.uk/dfsdfsdf', 
'https://www.nhs.uk/dfsdfsdfsdfsd?fgfg=fgfg',
'javascript://comment%0Aalert(1)"hello',

];

        foreach($domainArr as $k=>$v) {

                var_dump(validDom($v));
                echo '<br>';

        }
编辑:


此功能还可以解决由于
j而绕过
FILTER\u VALIDATE\u URL
的恶意代码问题avascript://comment%0Aalert(1)“您好”
未通过DNS解析,最终导致失败

下面将通过剥离不必要的URL参数等来验证URL。。然后将此字符串传递到
gethostbyname()
。然后,这将查询给定根域的DNS服务器,如果成功,将向您返回IP,如果不成功,将返回相同的输入字符串。然后,我将这个结果传递到一个过滤器中,该过滤器验证IP字符串。如果成功,它将以给定的格式返回域。只需确保您指向的DNS提供商不会解析每个DNS查找…例如,我在英国的ISP会自动解析每个失败的DNS查找,并使用有效的a记录,该记录会解析为显示“无此类网页”的网页。谷歌DNS工作正常,所以如果可以,请使用它

function validDom($url) {

    $newUrl = (filter_var($url, FILTER_VALIDATE_URL)) ? $url : FALSE;

    if ($newUrl === FALSE) {

        return FALSE;
    }

    $urlSplit = explode('/', $newUrl); 

    foreach ($urlSplit as $k=>$v) {

        if(substr_count($v, '.') >= 2) {

            $newUrl = $v;

        } 
    }

    $cleanDomain = substr_replace($newUrl, '', 0, strpos($newUrl, '.')+1);
    $chkDNS = gethostbyname($cleanDomain);

    if (filter_var($chkDNS, FILTER_VALIDATE_IP) !== FALSE) {

        return $cleanDomain;

    }

    return false;

}
测试域

$domainArr = [

'https://www.facebook.com',
'https://www.care.org.uk',
'https://www.facebook.co.uk',
'https://www.google.com/dfsdfsdfsd/sdfsdf',
'https://sub.fsdfsdfsdfsdfsd.co.uk/dfsdfsdf', 
'https://www.nhs.uk/dfsdfsdfsdfsd?fgfg=fgfg',
'javascript://comment%0Aalert(1)"hello',

];

        foreach($domainArr as $k=>$v) {

                var_dump(validDom($v));
                echo '<br>';

        }
编辑:


此功能还可以解决由于
j而绕过
FILTER\u VALIDATE\u URL
的恶意代码问题avascript://comment%0Aalert(1)“您好”
未通过DNS解析,最终导致失败

这里的确切问题是什么?这里的确切问题是什么?@shalvah的问题不是很清楚。域名必须包含一些后缀吗?还有什么其他要求?@shalvah的问题不是很清楚。必须域na