Obtenir l'entrée racine DNS du serveur php; obtenir le nom de domaine sans www, ect

StackOverflow https://stackoverflow.com/questions/1375647

  •  21-09-2019
  •  | 
  •  

Question

Comment peut-on obtenir l'entrée DNS racine de $_SERVER['HTTP_HOST']?

Entrée:

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

Sortie:

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

EDIT: Liste de recherche est très longue

Était-ce utile?

La solution

Pour ce projet: http://drupal.org/project/parallel

Utilisation:

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>";

Fonctions:

/**
 * 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);
  }
}

Sortie - Windows:

org.uk
google.com
yahoo.com

Sortie - Linux:

robknight.org.uk
google.com
yahoo.com

Autres conseils

Je pense que ce un peu mal défini.

Vous pouvez essayer de faire des recherches DNS pour chaque enregistrement parent jusqu'à ce que vous trouviez un qui ne retourne pas un enregistrement.

/[^\.]+\.[escaped|list|of|domains]$/

Je pense que cela devrait fonctionner.

Comme vous l'avez découvert, certains pays utilisent un TLD seulement (exemple: .tv, .us), d'autres subdivisent leur pays TLD (exemple: uk).

Idéalement, vous aurez besoin d'une liste de recherche (il ne sera pas long) de TLDs approuvés, et, si subdivisé, le TLD avec chaque subdivision (par exemple, « .co.uk » au lieu de « .uk ») . Cela vous dira quels « points » (de droite) de garder. Ensuite, passez un point à gauche de cette (si elle est trouvée) et tout couper devant lui.

Sans une liste de recherche, vous pouvez exploiter le fait que les subdivisions (.co, etc.) ne sont que pour les pays (qui ont deux lettres TLDs) et sont jamais plus de afaik 3 caractères eux-mêmes et sont toujours des lettres, donc vous pouvez probablement les reconnaître avec un motif regex.

Modifier Nevermind la liste actuelle des suffixes publics est beaucoup plus complexe. Vous allez avoir besoin d'utiliser une table de consultation pour savoir ce que le suffixe est, revenir au point précédent, et garniture gauche. RegEx est une solution pauvre ici. Au lieu de cela, stocker la liste des suffixes dans un dictionnaire, puis testez contre votre nom de domaine, élaguer une partie en pointillés à la fois de la gauche jusqu'à ce que vous frappez un match, puis rajouter la partie que vous venez rogné.

Note: comme indiqué dans les commentaires, cette méthode ne fonctionne pas vraiment dans tous les cas. La raison est que certains domaines de premier niveau ne résolvent à des adresses IP, même si la plupart ne le font pas. Par conséquent, il est impossible de détecter si un nom donné est de haut niveau ou pseudo-haut niveau nom de domaine simplement en vérifiant si elle a une adresse IP. Malheureusement, cela signifie probablement que la seule solution est une liste de recherche, étant donné la façon dont les domaines de premier niveau sont traitées de manière incompatible dans la pratique.

Je le répète: ne comptez pas sur le code ci-dessous pour travailler pour vous. Je laisse ici qu'à des fins éducatives.

Il y a une façon de le faire sans une liste de recherche. La liste peut être incomplète ou peu fiables, alors que cette méthode est garanti pour fonctionner:

<?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;

?>

Dans ce cas, il affichera « robknight.org.uk ». Il fonctionnerait aussi bien pour les .com, .edu, .com.au, .ly ou tout autre domaine de premier niveau vous travaillez sur.

Il agit en partant de la droite et de faire une vérification de DNS sur la première chose qui ressemble à ce pourrait être un nom de domaine viable. Dans l'exemple ci-dessus, il commence par « org.uk », mais découvre que ce n'est pas un nom de domaine réel, mais est un ccTLD. Il passe ensuite à vérifier « robknight.org.uk », qui est valide et retourne cela. Si le nom de domaine avait été, disons, « www.php.net », il aurait commencé par la vérification « php.net », qui est un nom de domaine valide et aurait retourné qu'immédiatement sans boucle. Je tiens également à souligner que si aucun nom de domaine valide se trouve, une chaîne vide ( « ») sera retourné.

Ce code peut ne pas convenir pour le traitement d'un grand nombre de noms de domaine dans un court laps de temps en raison du temps nécessaire pour les recherches DNS, mais il est parfaitement bien pour les recherches simples ou un code qui ne sont pas sensibles au facteur temps.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top