class Whois { // Full code and data version string (e.g. 'Whois2.php v3.01:16') var $VERSION; // This release of the package var $CODE_VERSION = "3.0.4"; // Network Solutions registry server var $NSI_REGISTRY = "whois.nsiregistry.net"; // Network Solutions registrar server (?) var $NSI_REGISTRAR = "whois.networksolutions.com"; // Default WHOIS port var $PORT = 43; // Maximum number of retries on connection failure var $RETRY = 0; // Time to wait between retries var $SLEEP = 2; // Read buffer size (0 == char by char) var $BUFFER = 0; // Status response codes var $STAT = array( -1 => "error", 0 => "ready", 1 => "ok" ); // Array to contain all query variables var $Query = array( "tld" => "", "type" => "domain", "string" => "", "status", "server" ); // Various hacks. In a perfect world we don't need these. var $HACKS = array( // force "dom" keywork "nsi_force_dom" => 1, // set if nsiregistry gives wrong whois server for netsol "nsi_referral_loop" => 0, // ??? "wrong_netsol_whois" => "rs.internic.net", // ??? "real_netsol_whois" => "whois.networksolutions.com", // force english output on .jp for us ethnocentric types, unset or comment out for Japanese output "force_slash_e" => "whois.nic.ad.jp", // whois.nic.cx hangs forever "cx_is_broken" => 1 ); // List of servers and handlers (loaded from servers.whois) var $DATA = array(); /* * Constructor function */ function Whois ($query = "") { // Load DATA array @require("servers.whois"); // Set version $this->VERSION = sprintf("Whois2.php v%s:%s", $this->CODE_VERSION, $this->DATA_VERSION); // If domain to query was not set if(!isSet($query) || $query=="") { // Configure to use default whois server $this->Query["server"] = $this->NSI_REGISTRY; return; } // Set domain to query in query array $this->Query["string"] = $domain = strtolower($query); // If query is an ip address do ip lookup if($query == long2ip(ip2long($query))) { // Prepare to do lookup via the 'ipw' handler $ip = gethostbyname($query); $this->Query["server"] = "whois.arin.net"; $this->Query["host_ip"] = $ip; $this->Query["file"] = "ipw.whois"; $this->Query["handler"] = "ipw"; $this->Query["string"] = $ip; $this->Query["tld"] = "ipw"; $this->Query["host_name"] = gethostbyaddr($ip); return; } // Test if we know in advance that no whois server is // available for this domain and that we can get the // data via http request reset($this->HTTPW); while (list($key, $val)=each($this->HTTPW)) if (substr($query,-strlen($key)-1)==".$key") { $this->Query["server"] = str_replace("#",$query,$val); $this->Query["tld"] = $key; // If a handler exists for the tld if(isSet($this->DATA[$key])) { // Set file/handler in query array $handler = $this->DATA[$key]; $this->Query["file"] = sprintf("%s.whois",$handler); $this->Query["handler"] = $handler; } return; } // Determine the top level domain, and it's whois server using // DNS lookups on 'whois-servers.net'. // Assumes a valid DNS response indicates a recognised tld (!?) $tld = ""; $server = ""; $dp = explode(".", $domain); $np = count($dp) -1; $tldtests = array(); for ($i=0; $i<$np; $i++) { array_shift($dp); $tldtests[] = implode(".",$dp); } $pos = strpos(strtolower(getenv ("OS")), "win"); if ($pos === false) $windows=false; else $windows=true; foreach($tldtests as $tld) { if ($windows) $cname = $this->checkdnsrr_win($tld.".whois-servers.net", "CNAME"); else $cname = checkdnsrr($tld.".whois-servers.net", "CNAME"); if(!$cname) continue; //This also works //$server = gethostbyname($tld.".whois-servers.net"); $server = $tld.".whois-servers.net"; break; } if($tld && $server) { // If found, set tld and whois server in query array $this->Query["server"] = $server; $this->Query["tld"] = $tld; // If a handler exists for the tld if(isSet($this->DATA[$tld])) { // Set file/handler in query array $handler = $this->DATA[$tld]; $this->Query["file"] = sprintf("%s.whois", $handler); $this->Query["handler"] = $handler; } return; } // If tld not known, and domain not in DNS, return error unset($this->Query["server"]); $this->Query["status"] = -1; $this->Query["errstr"][] = $this->Query["string"]." domain is not supported"; return; } /* * Checks dns reverse records on win platform */ function checkdnsrr_win($hostName, $recType= '') { if(!empty($hostName)) { if( $recType == '' ) $recType = "MX"; exec("nslookup -type=$recType $hostName", $result); // check each line to find the one that starts with the host // name. If it exists thenthe function succeeded. foreach ($result as $line) { if(eregi("^$hostName",$line)) return true; } // otherwise there was no mail handler for the domain return false; } return false; } /* * Open a socket to the whois server. * * Returns a socket connection pointer on success, or -1 on failure. */ function Connect () { // Fail if server not set if(!isSet($this->Query["server"])) return(-1); // Enter connection attempt loop $server = $this->Query["server"]; $retry = 0; while($retry <= $this->RETRY) { // Set query status $this->Query["status"] = "ready"; // Connect to whois port $ptr = @fsockopen($server, $this->PORT); if($ptr > 0) { $this->Query["status"]="ok"; return($ptr); } // Failed this attempt $this->Query["status"] = "error"; $retry++; // Sleep before retrying sleep($this->SLEEP); } // If we get this far, it hasn't worked return(-1); } /* * Post-process result with handler class. On success, returns the result * from the handler. On failure, returns passed in result unaltered. */ function Process (&$result) { // If the handler has not already been included somehow, include it now $HANDLER_FLAG = sprintf("__%s_HANDLER__", strtoupper($this->Query["handler"])); if(!defined($HANDLER_FLAG)) @include($this->Query["file"]); // If the handler has still not been included, append to query errors list and return if(!defined($HANDLER_FLAG)) { $this->Query["errstr"][] = "Can't find ".$this->Query["tld"]." handler: ".$this->Query["file"]; return($result); } // Pass result to handler $object = $this->Query["handler"]; $handler = new $object($result, $this->Query); // If handler returned an error, append it to the query errors list if(isSet($handler->Query["errstr"])) $this->Query["errstr"][] = $handler->Query["errstr"]; // Return the result return($handler->result); } /* * Convert html output to plain text */ function httpQuery ($query) { $lines = file($this->Query["server"]); $output = ""; $pre = ""; while (list($key, $val)=each($lines)) { $val = trim($val); $pos=strpos(strtoupper($val),"
");
			if ($pos!==false) {
				$pre = "\n";
				$output.=substr($val,0,$pos)."\n";
				$val = substr($val,$pos+5);
			}
			$pos=strpos(strtoupper($val),"
"); if ($pos!==false) { $pre = ""; $output.=substr($val,0,$pos)."\n"; $val = substr($val,$pos+6); } $output.=$val.$pre; } $search = array ( "
", "

", "", "", "", ",", "
", "

", "", "", "", "" ); $output = str_replace($search,"\n",$output); $output = str_replace("2) continue; } else $null=0; $rawdata[]=$val; } return $rawdata; } /* * Perform lookup. Returns an array. The 'rawdata' element contains an * array of lines gathered from the whois query. If a top level domain * handler class was found for the domain, other elements will have been * populated too. */ function Lookup ($query = "") { // If domain to query passed in, use it, otherwise use domain from initialisation $string = !empty($query) ? $query : $this->Query["string"]; // Check if protocol is http if (substr($this->Query["server"],0,7)=="http://") { $result['rawdata'] = $this->httpQuery($this->Query["server"]); // If we have a handler, post-process it with that if(isSet($this->DATA[$this->Query["tld"]])) $result = $this->Process($result); return($result); } // If the '.cx' whois server is broken, return an error now (saves attempting and timing out) if($this->HACKS["cx_is_broken"] && $this->Query["tld"] == "cx") { $this->Query["errstr"][] = ".cx doesn't work. Turn off HACKS[\"cx_is_broken\"] if ".$this->Query["server"]." finally got fixed."; return(""); } // Connect to whois server, or return if failed $ptr = $this->Connect(); if($ptr < 0) { $this->Query["status"] = -1; $this->Query["errstr"][] = "Connect failed to: ".$this->Query["server"]; return(array()); } // This no longer works // Determining on server/hacks in operation, send appropriate request // Hacks no longer need //if(($this->Query["server"] == $this->NSI_REGISTRY || $this->Query["server"] == $this->NSI_REGISTRAR) && $this->HACKS["nsi_force_dom"]) { // fputs($ptr, sprintf("dom %s\r\n", trim($string))); //} //elseif($this->Query["server"] == $this->HACKS["force_slash_e"]) { // fputs($ptr, sprintf("%s/e\r\n", trim($string))); //} if ($this->Query["server"] == "com.whois-servers.net") { fputs($ptr, "=".trim($string)."\r\n"); } else { fputs($ptr, sprintf("%s\r\n", trim($string))); } // Prepare to receive result $raw = ""; $output = array(); while(!feof($ptr)) { // If a buffer size is set, fetch line-by-line into an array if($this->BUFFER) $output[] = fgets($ptr, $this->BUFFER); // If not, fetch char-by-char into a string else $raw .= fgetc($ptr); } // If captured char-by-char, convert to an array of lines if(!$this->BUFFER) $output = explode("\n", $raw); // Drop empty last line unset($output[count($output)-1]); // Create result and set 'rawdata' $result = array(); $result['rawdata'] = $output; // If we have a handler, post-process it with that if(isSet($this->DATA[$this->Query["tld"]])) $result = $this->Process($result); // Add error information if any if (isset($this->Query["errstr"])) $result["errstr"] = $this->Query["errstr"]; // If no rawdata use rawdata from first whois server if (!isset($result["rawdata"])) $result["rawdata"] = $output; return($result); } } ?>