Whois Abfrage mittels Whois Serverliste aus einer relationalen Datenbank (mySQL)

Jetzt kommen wir endlich zur eigentlichen Whois Abfrage. Die läuft im Prinzip sehr einfach ab. Das PHP Script verbindet sich mit dem Whois Server, sendet ihm die Domain (die mit einem \r\n endet) und liest das Ergebnis.

Die triviale Whois Abfrage

1   $domain = 'test.de';
2   $server = 'whois.nic.de';
3   
4   if (!($fp = fsockopen($server, 43))) {
5   	die('Could not connect to '.$server.'.');
6   }
7   
8   fwrite($fp, $domain."\r\n");
9   
10  $result = '';
11  while (!feof($fp)) {
12  	$result .= fread($fp, 1024);
13  }
14  
15  fclose($fp);
16  
17  echo $result;

So einfach kann's sein. Doch dafür haben wir nicht unsere Klassen und Datenbank gemacht. Unser Whois Script soll schon etwas mehr können. Es soll anhand der TLD den richtigen Whois Server auswählen. Ausserdem brauchen wir nicht das ganze Ergebnis vom Whois Server. Wir haben ja den Suchstring, mit dem wir ganz leicht sehen können ob die Domain noch frei ist.

Die Whois_Request Klasse

Diese Klasse soll sich um die komplette Kommunikation mit dem Whois Server kümmern. Zu diesem Zweck erbt sie von der Request Klasse, die wir schon früher kennen gelernt haben.
Die Request Klasse ist eigentich schon fast optimal. Wir müssen nur zwei triviale Kleinigkeiten ändern. Der Konstruktor kommt nur noch mit einem Argument aus, dem Server und ruft den alten Konstruktor mit diesem Server und Port 43 auf. Whois Server lauschen in der Regel immer auf Port 43. Die write() Methode wird so umgeschrieben, dass ihr nur die Domain übergeben werden kann. D. h. Sie hängt ein "\r\n" an die Domain dran und ruft die alte write() auf.

1   class Whois_Request extends Request {
2   
3   	function Whois_Request($server) {
4   		$this->Constructor($server, 43);
5   	}
6   
7   	function write($domain) {
8   		parent::write($domain."\r\n");
9   	}
10  
11  }

Damit ist noch nicht viel erreicht. Mit dieser Klasse können wir immerhin die triviale Whois Abfrage extrem vereinfachen:

1   $server = 'whois.nic.de';
2   $domain = 'test.de';
3   
4   $whois_request = &new Whois_Request($server);
5   echo $whois_request->doRequest($domain);

Die Whois_Query Klasse

Kommen wir nun endlich dazu unser Script etwas potenter zu gestalten. Schließlich haben wir ja mit viel Mühe eine Datenbank mit Whois Servern erstellt.
Die Whois_Query Klasse erhält im Konstruktor die Domain und belegt damit das $domain Attribut. Die weiteren Attribute wird sie sich selbst über die Datenbank belegen.
$tld ist die am passendste Domain Endung, für die ein Whois Server bekannt ist. Bei domain.co.uk wäre $tld mit co.uk belegt.
$server ist der entsprechende Whois Server.
$string ist der Suchstring um damit das Ergebnis zu interpretieren.
$is_free sagt dann ob die Domain noch frei ist, oder nicht.

Die Methode queryServer() macht dann mit den Attributen $server und $domain einen Whois Request. In dem klein geschriebenen Ergebnis wird dann der Suchstring gesucht und je nach Erfolg der Suche $is_free belegt.

1   class Whois_Query {
2   
3   	var $domain, $server, $string, $tld, $is_free;
4   
5   	function Whois_Query($domain) {
6   		$this->domain = $domain;
7   	}
8   
9   	function queryServer() {
10  		$request = &new Whois_Request($this->server);
11  		$result  = $request->doRequest($this->domain);
12  		if (!$result) {
13  			return false;
14  		}
15  
16  		$this->is_free = strpos(strtolower($result), $this->string) !== false;
17  
18  		return true;
19  	}
20  
21  	function is_free() {
22  		return $this->is_free;
23  	}
24  
25  	...
26  
27  }

Jetzt fehlt uns noch die letzte Methode getServer() die sich um die Belegung der Attribute $server, $tld und $string kümmert.

Um die passende Domain Endung zu finden, müssen wir in der WHERE Bedingung nach allen möglichen Domain Endungen suchen. Also wird die Domain erstmal mit explode() in ein Array geteilt, wobei die Punkte die Teilungsstellen sind. In einer For-Schleife werden dann Rückwärts aus diesem Array alle möglichen Endungen durchgegangen. In dieser Schleife wird einmal ein String für die WHERE Bedingung erweitert. Und ausserdem wird ein assoziatives Array erstellt, welches die Endungen bewertet. Um so tiefer die Endung geht, um so höher ist die Bewertung. D.h. co.uk bekommt eine höhere Wertung als uk. Dieses Bewertungs-Array brauchen wir nacher um aus den verschiedenen Servern, den passendsten zu finden.

1   class Whois_Query {
2   
3   	...
4   
5   	function getServer() {
6   		if (strpos($this->domain, '.') === false) {
7   			trigger_error('No Top Level Domain was specified in '.$this->domain);
8   			return false;
9   		}
10  
11  		$tlds   = explode('.', $this->domain);
12  		$tld    = $tlds[count($tlds) - 1];
13  		$where  = 'WHERE tld="'.$tld.'"';
14  		$fitMap = array($tld => 0);
15  
16  		for ($i = count($tlds) - 2; $i > 0; $i--) {
17  			$tld          = $tlds[$i].'.'.$tld;
18  			$fitMap[$tld] = count($tlds) - 1 - $i;
19  			$where       .= ' OR tld="'.$tld.'"';
20  		}
21  
22  		...
23  
24  	}
25  
26  }

In dem SELECT Statement brauchen wir tld, server und string. Da wir nur die Domainendung haben, aber Daten aus der Server Tabelle brauchen, müssen wir die Tabellen mit JOIN über die IDs verknüpfen. Da es durchaus vorkommen kann, dass mehrer Whois Server für eine TLD existieren, benutzen wir GROUP BY um nur einen Server pro tld zu erhalten.

1   class Whois_Query {
2   
3   	...
4   
5   	function getServer() {
6   
7   		...
8   
9   		$query = 'SELECT tld, server, string FROM tld
10  		          	INNER JOIN tld_server USING(tld_id)
11  		          	INNER JOIN server USING(server_id)
12  		          	'.$where.'
13  		          	GROUP BY tld';
14  
15  		if (!($result = mysql_query($query)) || mysql_num_rows($result) == 0) {
16  			trigger_error('There is no Whois Server mapped to this Top Level Domain.');
17  			return false;
18  		}
19  
20  		...
21  
22  	}
23  
24  }

Der letzte Teil der getServer() Methode holt sich aus dem Ergebnis den passenden Server und belegt damit die Attribute. Dies geschieht mit dem Bewertungs-Array.

1   class Whois_Query {
2   
3   	...
4   
5   	function getServer() {
6   
7   		...
8   
9   		$fit = -1;
10  		while ($row = mysql_fetch_assoc($result)) {
11  			if ($fitMap[$row['tld']] > $fit) {
12  				$fit    = $fitMap[$row['tld']];
13  				$server = $row;
14  			}
15  		}
16  
17  		$this->server = $server['server'];
18  		$this->tld    = $server['tld'];
19  		$this->string = $server['string'];
20  
21  		return true;
22  	}
23  
24  }

Um ein Whois_Query Objekt zu nutzen, müssen Sie es erst mit der Domain initialisieren. Natürlich muss auch eine Datenbankverbindung bestehen. Wenn getServer() erfolgreich war, können Sie queryServer() aufrufen. Bei Erfolg von queryServer haben Sie den Status der Domain mit is_free().
Ein Beispiel, bei dem Sie die Domain aus der $_GET Variable 'domain' erhalten, könnte so aussehen:

1   if (!empty($_GET['domain'])) {
2   
3   	if (!DB_Element::connect()) {
4   		die('Not connected with database.');
5   	}
6   
7   	$query = &new Whois_Query($_GET['domain']);
8   
9   	if (!$query->getServer()) {
10  		die('no server found for this tld.');
11  	}
12  
13  	if (!$query->queryServer()) {
14  		die('Server is not reachable.');
15  	}
16  
17  	echo $_GET['domain'].' is '.($query->is_free() ? '' : 'not ').'free.';
18  
19  }

PHP Manual Referenz

mySQL Manual Referenz