Ottenere voce principale DNS dal server php; ottenere il nome del dominio senza www, ect
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
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.