Ottenere voce principale DNS dal server php; ottenere il nome del dominio senza www, ect

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

  •  21-09-2019
  •  | 
  •  

Domanda

Come si potrebbe ottenere la voce principale DNS da $_SERVER['HTTP_HOST']?

Input:

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

Output:

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

EDIT: elenco di ricerca è molto lunga

È stato utile?

Soluzione

Per questo progetto: http://drupal.org/project/parallel

Utilizzo:

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

Funzioni:

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

Output - Windows:

org.uk
google.com
yahoo.com

Output - Linux:

robknight.org.uk
google.com
yahoo.com

Altri suggerimenti

Credo che sia un po 'mal definito.

Si potrebbe provare a fare ricerche DNS per ogni record padre fino a trovare quello che non restituisce un record.

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

Credo che dovrebbe funzionare.

Come hai scoperto, alcuni paesi utilizzano un dominio di primo livello solo (ad esempio: .tv, .us), altri suddividono il loro dominio di primo livello nazionale (ad esempio: uk).

Idealmente, avrete bisogno di un elenco di ricerca (che non passerà molto tempo) di TLD approvati, e, se suddiviso, il TLD con ogni suddivisione (ad esempio, ".co.uk" invece di ".uk") . Che vi dirà che "punti" (da destra) per mantenere. Quindi spostare un punto alla sinistra di quella (se trovato) e tritare tutto prima di esso.

Senza un elenco di ricerca, è possibile sfruttare il fatto che le suddivisioni (.co, ecc) sono solo per i paesi (che hanno 2 lettere TLD) e sono AFAIK mai più di 3 caratteri stessi e sono sempre le lettere, in modo probabilmente si può riconoscerli con un modello di espressione regolare.

Modifica Nevermind, ha l'elenco dei suffissi pubblici è molto più complessa. Si sta andando ad avere bisogno di utilizzare una tabella di ricerca per capire cosa il suffisso è, tornare al punto precedente, e tagliare a sinistra. RegEx è una soluzione povera qui. Invece, memorizzare l'elenco di suffissi in un dizionario, quindi prova contro il tuo nome di dominio, tagliando via una porzione tratteggiata alla volta da sinistra fino a colpire una corrispondenza, quindi aggiungere di nuovo la parte che hai appena rifilata.

Nota: come sottolineato nei commenti, questo metodo in realtà non funziona in tutti i casi. La ragione di questo è che alcuni domini di primo livello risolvono a indirizzi IP, anche se la maggior parte non lo fanno. Pertanto non è possibile rilevare se un dato nome è di primo livello o il nome di dominio di primo livello pseudo semplicemente controllando se ha un indirizzo IP. Purtroppo, questo probabilmente vuol dire che l'unica soluzione è una lista di ricerca, visto come domini di primo livello trattate in modo incoerente sono in pratica.

Ripeto: non fare affidamento sul codice qui sotto a lavorare per voi. Lascio qui solo per scopi didattici.

C'è un modo per fare questo senza un elenco di ricerca. L'elenco può essere inaffidabili o incomplete, che tale metodo è garantito il funzionamento:

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

?>

In questo caso, il risultato sarà 'robknight.org.uk'. Sarebbe funziona altrettanto bene per .com, .edu, .com.au, .ly o qualsiasi altro dominio di primo livello si opera su.

Funziona a partire da destra e facendo un controllo DNS sulla prima cosa che sembra che potrebbe essere un nome di dominio valida. Nell'esempio di cui sopra, si inizia con 'org.uk', ma scopre che questo non è un nome di dominio effettivo, ma è un ccTLD. Si passa poi per controllare 'robknight.org.uk', che è valida, e restituisce quello. Se il nome di dominio fosse stato, diciamo, 'www.php.net', sarebbe iniziato controllando 'php.net', che è un nome di dominio valido, e che sarebbe tornato immediatamente senza loop. Vorrei anche sottolineare che, se non si trova alcun nome di dominio valido, verrà restituita una stringa vuota ( '').

Questo codice può essere adatta per l'elaborazione di un gran numero di nomi di dominio in un breve lasso di tempo a causa del tempo necessario per le ricerche DNS, ma è perfettamente bene per le ricerche singoli o codice che non è temporalmente critica.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top