2

将如何获得根 DNS 条目$_SERVER['HTTP_HOST']

输入:

example.co.uk
www.example.com
blog.example.com
forum.example.co.uk 

输出:

example.co.uk
example.com
example.com
example.co.uk

编辑:查找列表很长

4

5 回答 5

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
于 2009-09-04T23:49:42.687 回答
0

我认为这有点不明确。

您可以尝试对每个父记录进行 DNS 查找,直到找到不返回 A 记录的记录。

于 2009-09-03T20:08:01.993 回答
0

正如您所发现的,有些国家只使用 TLD(例如:.tv、.us),而另一些国家则细分其国家的 TLD(例如:uk)。

理想情况下,您需要一个已批准 TLD 的查找列表(不会很长),并且如果细分,还需要每个细分的 TLD(例如,“.co.uk”而不是“.uk”)。这将告诉您要保留哪些“点”(从右侧开始)。然后将一个点移到左侧(如果找到)并切碎它之前的所有内容。

如果没有查找列表,您可以利用以下事实:细分(.co 等)仅适用于国家/地区(具有 2 个字母的顶级域名)并且 AFAIK 本身不超过 3 个字符并且始终是字母,因此您可能可以用正则表达式模式识别它们。

编辑:没关系,公共后缀的实际列表要复杂得多。您将需要使用查找表来确定后缀是什么,回到前一个点,然后向左修剪。RegEx 在这里是一个糟糕的解决方案。取而代之的是,将后缀列表存储在字典中,然后针对您的域名进行测试,从左侧一次删除一个虚线部分,直到找到匹配项,然后添加回您刚刚修剪掉的部分。

于 2009-09-03T20:14:09.983 回答
0
/[^\.]+\.[escaped|list|of|domains]$/

我认为这应该有效。

于 2009-09-03T20:18:26.617 回答
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 查找所花费的时间,此代码可能不适合在短时间内处理大量域名,但对于单个查找或时间要求不严格的代码来说,它是完全可以的。

于 2009-09-03T20:35:04.130 回答