7 * Copyright (c) 1997-2003 The PHP Group
8 * Portions Copyright (c) 1980, 1993 The Regents of the University of
9 * California. All rights reserved.
11 * This source file is subject to version 3.01 of the PHP license,
12 * that is bundled with this package in the file LICENSE, and is
13 * available at through the world-wide-web at
14 * http://www.php.net/license/3_01.txt.
15 * If you did not receive a copy of the PHP license and are unable to
16 * obtain it through the world-wide-web, please send a note to
17 * license@php.net so we can mail you a copy immediately.
21 * @author Seamus Venasse <seamus.venasse@polaris.ca>
22 * @copyright 1997-2003 The PHP Group
23 * @copyright 1980-1993 The Regents of the University of California (Portions)
24 * @license http://www.php.net/license/3_01.txt PHP 3.01
25 * @version CVS: $Id: Whois.php 314693 2011-08-10 00:31:45Z kguest $
26 * @link http://pear.php.net/package/Net_Whois
29 require_once 'PEAR.php';
32 * Looks up records in the databases maintained by several Network Information
33 * Centres (NICs). This class uses PEAR's Net_Socket:: class.
37 * @author Seamus Venasse <seamus.venasse@polaris.ca>
38 * @license http://www.php.net/license/3_01.txt PHP 3.01
39 * @link http://pear.php.net/package/Net_Whois
41 class Net_Whois extends PEAR
47 * Retrieve authoritative definition only
52 var $authoritative = false;
55 * Port for whois servers
63 * See options for stream_context_create.
71 * List of NICs to query
76 var $_nicServers = array (
77 'NICHOST' => 'whois.crsnic.net.',
78 'INICHOST' => 'whois.networksolutions.com.',
79 'GNICHOST' => 'whois.nic.gov.',
80 'ANICHOST' => 'whois.arin.net.',
81 'RNICHOST' => 'whois.ripe.net.',
82 'PNICHOST' => 'whois.apnic.net.',
83 'RUNICHOST' => 'whois.ripn.net.',
84 'MNICHOST' => 'whois.ra.net.',
85 'QNICHOST_TAIL' => '.whois-servers.net.',
86 'SNICHOST' => 'whois.6bone.net.',
87 'BNICHOST' => 'whois.registro.br.'
91 * Search string of server to search on
96 var $_whoisServerID = 'Whois Server: ';
99 * Server to search for IP address lookups
104 var $_ipNicServers = array ('RNICHOST', 'PNICHOST', 'BNICHOST');
107 * List of error codes and text
112 var $_errorCodes = array (
113 010 => 'Unable to create a socket object',
114 011 => 'Unable to open socket',
115 012 => 'Write to socket failed',
116 013 => 'Read from socket failed',
117 014 => 'Specified server is null or empty',
121 * Number of seconds to wait on socket connections before assuming
122 * there's no more data from the Whois server. Defaults to no timeout.
123 * @var integer $timeout
126 var $_timeout = false;
131 * Constructs a new Net_Whois object
135 function __construct($error_class = null)
137 parent::__construct();
140 $this->setAuthoritative();
148 * Set timeout value - number of seconds afterwhich an attempt to connect
149 * to a whois server should be aborted.
151 * @param integer $timeout false is also an acceptable value
156 function setTimeout($timeout = false)
158 $this->_timeout = $timeout;
164 * Retrieve timeout value
168 * @return mixed either false or an integer value
170 function getTimeout()
172 return $this->_timeout;
180 * @param bool $authoritative defaults to false
185 function setAuthoritative($authoritative = false)
187 $this->authoritative = $authoritative;
191 // {{{ getAuthoritative()
195 * @return bool Query for authoritative result?
197 function getAuthoritative()
199 return (bool) $this->authoritative;
205 * set which port should be used
207 * @param integer $port Port to use
212 function setPort($port = false)
214 $port = is_numeric($port) ? $port : getservbyname('whois', 'tcp');
215 $this->port = $port ? $port : 43;
221 * Retrieve which port to connect to.
223 * @return integer port to connect to
234 * @param mixed $options
237 function setOptions($options)
239 if ((!is_null($options)) && (!is_array($options))) {
242 $this->options = $options;
247 * Retrieve which port to connect to.
251 function getOptions()
253 return $this->options;
259 * Connect to the necessary servers to perform a domain whois query. Prefix
260 * queries with a "!" to lookup information in InterNIC handle database.
261 * Add a "-arin" suffix to queries to lookup information in ARIN handle
264 * @param string $domain IP address or host name
265 * @param string $userWhoisServer server to query (optional)
268 * @return mixed returns a PEAR_Error on failure, or a string on success
270 function query($domain, $userWhoisServer = null)
272 $domain = trim($domain);
274 if (isset($userWhoisServer)) {
275 $whoisServer = $userWhoisServer;
276 } elseif (preg_match('/^!.*/', $domain)) {
277 $whoisServer = $this->_nicServers['INICHOST'];
278 } elseif (preg_match('/.*?-arin/i', $domain)) {
279 $whoisServer = $this->_nicServers['ANICHOST'];
281 $whoisServer = $this->_chooseServer($domain);
284 $_domain = $this->authoritative ? 'domain ' . $domain : $domain;
285 $whoisData = $this->_connect($whoisServer, $_domain);
287 if (PEAR::isError($whoisData)) {
291 if ($this->authoritative) {
292 $pattern = '/\s+' . preg_quote($this->_whoisServerID) . '(.+?)\n/i';
294 if (preg_match($pattern, $whoisData, $matches)) {
295 $whoisData = $this->_connect(trim(array_pop($matches)), $domain);
304 * Use the Asia/Pacific Network Information Center (APNIC) database.
305 * It contains network numbers used in East Asia, Australia, New
306 * Zealand, and the Pacific islands.
308 * @param string $domain IP address or host name
311 * @return mixed returns a PEAR_Error on failure, or a string on success
313 function queryAPNIC($domain)
315 return $this->query($domain, $this->_nicServers['PNICHOST']);
321 * Use the IPv6 Resource Center (6bone) database. It contains network
322 * names and addresses for the IPv6 network.
324 * @param string $domain IP address or host name
327 * @return mixed returns a PEAR_Error on failure, or a string on success
329 function queryIPv6($domain)
331 return $this->query($domain, $this->_nicServers['SNICHOST']);
337 * Use the Route Arbiter Database (RADB) database. It contains
338 * route policy specifications for a large number of operators'
341 * @param string $ipAddress IP address
344 * @return mixed returns a PEAR_Error on failure, or a string on success
346 function queryRADB($ipAddress)
348 return $this->query($ipAddress, $this->_nicServers['MNICHOST']);
352 // {{{ _chooseServer()
354 * Determines the correct server to connect to based upon the domain
356 * @param string $query IP address or host name
359 * @return string whois server host name
361 function _chooseServer($query)
363 if (!strpos($query, '.')) {
364 return $this->_nicServers['NICHOST'];
367 $TLD = substr($query, strrpos($query, '.') + 1);
369 if (is_numeric($TLD)) {
370 $whoisServer = $this->_nicServers['ANICHOST'];
372 $whoisServer = $this->getDomainServer($query);
379 // {{{ getDomainServer()
381 * Determines the correct whois server to connect to based upon the domain
383 * @param string $q domain name
386 * @return string whois server ip address
388 function getDomainServer($q)
390 $tail = $this->_nicServers['QNICHOST_TAIL'];
391 if (strchr($q, '.')) {
392 //get the last 2 parts
393 $q = array_reverse(explode('.', $q));
394 $a = array($q[1] . '.' . $q[0], $q[0]);
399 //check host has real ip
400 $q = gethostbyname($q . $tail);
401 if (filter_var($q, FILTER_VALIDATE_IP)) {
410 * Connects to the whois server and retrieves domain information
412 * @param string $nicServer FQDN of whois server to query
413 * @param string $domain Domain name to query
416 * @return mixed returns a PEAR_Error on failure, string of whois data on success
418 function _connect($nicServer, $domain)
420 include_once 'Net/Socket.php';
422 if (is_null($nicServer) || (empty($nicServer))) {
423 return new PEAR_Error($this->_errorCodes[014], 14);
426 if (PEAR::isError($socket = new Net_Socket())) {
427 return new PEAR_Error($this->_errorCodes[010], 10);
430 $result = $socket->connect(
437 if (PEAR::isError($result)) {
438 return new PEAR_Error($this->_errorCodes[011], 11);
440 $socket->setBlocking(false);
441 // Querying denic.de requires some special coaxing for a domain query.
442 // http://www.denic.de/en/faq-single/2978/1115.html
443 if (substr($domain, -3) == '.de') {
444 if (PEAR::isError($socket->writeLine("-T dn,ace " . $domain))) {
445 return new PEAR_Error($this->_errorCodes[012], 12);
449 if (PEAR::isError($socket->writeLine($domain))) {
450 return new PEAR_Error($this->_errorCodes[012], 12);
456 $whoisData = $socket->readAll();
457 if (PEAR::isError($whoisData)) {
458 return new PEAR_Error($this->_errorCodes[013], 13);
461 $data = explode("\n", $whoisData);
462 foreach ($data as $line) {
463 $line = rtrim($line);
465 // check for whois server redirection
466 if (!isset($nHost)) {
467 $pattern='/'.$this->_whoisServerID.'([a-z0-9.]+)\n/i';
468 if (preg_match($pattern, $line, $matches)) {
469 $nHost = $matches[1];
470 } elseif ($nicServer == $this->_nicServers['ANICHOST']) {
471 foreach ($this->_ipNicServers as $ipNicServer) {
472 $server = trim($this->_nicServers[$ipNicServer], '.');
473 if (strstr($line, $server)) {
474 $nHost = $this->_nicServers[$ipNicServer];
481 // this should fail, but we'll call it anyway and ignore the error
482 $socket->disconnect();
484 if ($nHost && $nHost != $nicServer) {
485 $tmpBuffer = $this->_connect($nHost, $domain);
486 if (PEAR::isError($tmpBuffer)) {
489 $whoisData .= $tmpBuffer;