如何从$_SERVER['HTTP_HOST']
获取根DNS条目?
输入:
example.co.uk
www.example.com
blog.example.com
forum.example.co.uk
输出:
example.co.uk
example.com
example.com
example.co.uk
编辑: 查找列表为very long
答案 0 :(得分:1)
对于这个项目:http://drupal.org/project/parallel
用法:
echo parallel_get_domain("www.robknight.org.uk") . "<br>";
echo parallel_get_domain("www.google.com") . "<br>";
echo parallel_get_domain("www.yahoo.com") . "<br>";
功能:
/**
* Given host name returns top domain.
*
* @param $host
* String containing the host name: www.example.com
*
* @return string
* top domain: example.com
*/
function parallel_get_domain($host) {
if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' && strnatcmp(phpversion(),'5.3.0') < 0) {
// This works 1/2 the time... CNAME doesn't work with nslookup
for ($end_pieces = substr_count($host, '.'); $end_pieces > 0; $end_pieces--) {
$test_domain = end(explode('.', $host, $end_pieces));
if (checkdnsrr($test_domain)) {
$domain = $test_domain;
break;
}
}
return isset($domain) ? $domain : FALSE;
}
else {
// This always works
$sections = explode('.', $host);
array_unshift($sections, '');
foreach($sections as $key => $value) {
$parts[$key] = $value;
$test_domain = implode('.', parallel_array_xor($parts, $sections));
if (checkdnsrr($test_domain, 'NS') && !checkdnsrr($test_domain, 'CNAME')) {
$domain = $test_domain;
break;
}
}
return isset($domain) ? $domain : FALSE;
}
}
/**
* Opposite of array_intersect().
*
* @param $array_a
* First array
* @param $array_b
* Second array
*
* @return array
*/
function parallel_array_xor ($array_a, $array_b) {
$union_array = array_merge($array_a, $array_b);
$intersect_array = array_intersect($array_a, $array_b);
return array_diff($union_array, $intersect_array);
}
/**
* Win compatible version of checkdnsrr.
*
* checkdnsrr() support for Windows by HM2K <php [spat] hm2k.org>
* http://us2.php.net/manual/en/function.checkdnsrr.php#88301
*
* @param $host
* String containing host name
* @param $type
* String containing the DNS record type
*
* @return bool
*/
function parallel_win_checkdnsrr($host, $type='MX') {
if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') { return FALSE; }
if (empty($host)) { return FALSE; }
$types=array('A', 'MX', 'NS', 'SOA', 'PTR', 'CNAME', 'AAAA', 'A6', 'SRV', 'NAPTR', 'TXT', 'ANY');
if (!in_array($type, $types)) {
user_error("checkdnsrr() Type '$type' not supported", E_USER_WARNING);
return FALSE;
}
@exec('nslookup -type=' . $type . ' ' . escapeshellcmd($host), $output);
foreach($output as $line){
if (preg_match('/^' . $host . '/', $line)) { return TRUE; }
}
}
// Define checkdnsrr() if it doesn't exist
if (!function_exists('checkdnsrr')) {
function checkdnsrr($host, $type='MX') {
return parallel_win_checkdnsrr($host, $type);
}
}
输出 - Windows:
org.uk
google.com
yahoo.com
输出 - Linux:
robknight.org.uk
google.com
yahoo.com
答案 1 :(得分:0)
我认为这有点不明确。
您可以尝试为每个父记录执行DNS查找,直到找到不返回A记录的记录。
答案 2 :(得分:0)
正如您所发现的,某些国家/地区仅使用顶级域名(例如:.tv,.us),其他国家/地区则细分其国家/地区顶级域名(例如:英国)。
理想情况下,您需要一个经过批准的TLD的查找列表(不会很长),如果细分,则需要每个细分的TLD(例如,“。co.uk”而不是“.uk”) 。这将告诉你要保留哪些“点”(从右边)。然后在其左侧移动一个点(如果找到)并在其前面切掉一切。
如果没有查找列表,您可以利用细分(.co等)仅针对国家/地区(具有双字母TLD)的事实,并且AFAIK本身永远不会超过3个字符,并且始终是字母,因此你可以用正则表达式识别它们。
编辑:没关系,实际的公共后缀列表要复杂得多。您将需要使用查找表来确定后缀是什么,返回上一个点,然后向左修剪。 RegEx在这里是一个糟糕的解决方案。相反,将后缀列表存储在一个词典中,然后根据你的域名进行测试,从左边一次砍掉一个虚线部分,直到你找到一个匹配,然后加回你刚剪掉的部分。
答案 3 :(得分:0)
/[^\.]+\.[escaped|list|of|domains]$/
我认为这应该有用。
答案 4 :(得分:0)
注意:正如评论中所指出的,此方法实际上并不适用于所有情况。这样做的原因是一些顶级域确实解析为IP地址,即使大多数没有。因此,仅通过检查它是否具有IP地址,无法检测给定名称是顶级域名还是伪顶级域名。不幸的是,这可能意味着唯一的解决方案是查找列表,考虑到在实践中处理不一致的顶级域名。
我再说一遍:不要依赖下面的代码为你工作。我将它留在这里仅用于教育目的。
有一种方法可以在没有查找列表的情况下执行此操作。该列表可能不可靠或不完整,但保证此方法有效:
<?php
function get_domain($url) {
$dots = substr_count($url, '.');
$domain = '';
for ($end_pieces = $dots; $end_pieces > 0; $end_pieces--) {
$test_domain = end(explode('.', $url, $end_pieces));
if (dns_check_record($test_domain, 'A')) {
$domain = $test_domain;
break;
}
}
return $domain;
}
$my_domain = get_domain('www.robknight.org.uk');
echo $my_domain;
?>
在这种情况下,它将输出'robknight.org.uk'。它对.com,.edu,.com.au,.ly或您正在运行的任何其他顶级域名同样有效。
它的工作原理是从右边开始并对第一件看起来可能是可行的域名的东西进行DNS检查。在上面的示例中,它以'org.uk'开头,但发现这不是实际的域名,而是ccTLD。然后继续检查'robknight.org.uk', 有效,然后返回。如果域名是'www.php.net',它可以通过检查'php.net'开始,这是一个有效的域名,并且会在没有循环的情况下立即返回。我还应该指出,如果找不到有效的域名,将返回一个空字符串('')。
由于DNS查找所花费的时间,此代码可能不适合在短时间内处理大量域名,但对于单个查找或非时间关键的代码来说,这完全没问题。