<?php

/**
 * A class to manage and perform whois lookups for all TLDs defined in the $whoisServers array.
 */
class Whois
{
	/**
	 * A domain's SLD
	 */
	public $domainSLD;

	/**
	 * A domain's TLD
	 */
	public $domainTLD;

	/**
	 * A domain's name as: "SLD.TLD"
	 */
	public $domainName;

	/**
	 * The buffer from a successful whois lookup
	 */
	public $whoisBuffer;

	/**
	 * The server for the whois lookup
	 */
	public $whoisServer;

	/**
	 * The match to look for in the whoisBuffer
	 */
	public $whoisMatchString;

	/**
	 * The availability of a domain name
	 */
	public $isAvailable;

	/**
	 * Array of the extened attributes of a domain
	 */
	public $extendedAttributes = array();

	/**
	 * The constructor for a Whois object. This does nothing more than setup class variables as their
	 * default empty values.
	 */
	public function __construct($sld=NULL,$tld=NULL,$execute=false)
	{
		global $whoisServers;
		$this->whoisBuffer = array();
		$this->isAvailable = 0;

		if (!$tld) {
			$tld = "com";
		}

		$this->setDomainSLD($sld);
		$this->setDomainTLD($tld);
		$this->initWhois($tld);

		if ($execute) {
			$this->execute();
			$this->setIsAvailable();
		}
	}

	/**
	 * The execute method will perform the whois lookup.
	 */
	public function execute()
	{
		global $whoisServers;
		$this->setDomainName($this->domainSLD,$this->domainTLD);
		$domainName = $this->getDomainName();
		if (is_null($whoisServer = $this->getWhoisServer())) {
			$buffer = array();
			$buffer[] = "Unsupported TLD: ".$this->domainTLD;
			$this->setWhoisBuffer($buffer);
			return;
		}

		$buffer = array();
		dbg("trying to fix: $whoisServer");
		$whoisServer = str_replace("&amp;", "&", $whoisServer);

		dbg("CheckWhois Ready to Execute [$domainName : $whoisServer]");

		if (eregi('http:\/\/', $whoisServer)) {
			require_once ("lib-mbapi/include/curl/curl.php");

			$url = str_replace(array(
				'%%domain%%',
				'%%domainSLD%%',
				'%%domainTLD%%',
			), array(
				$this->domainName,
				$this->domainSLD,
				$this->domainTLD,
			), unsecureInput($whoisServer));

			$cObj = new Curl( $url );

			$buffer = explode("\n", $cObj->execute());
		} else {
				// with the http: check before we should be alright for this next test
			$server = $port = null;
			list($server, $port) = @explode(':', (string)$whoisServer);

			if (!is_numeric( $port ))	$port = 43;

			$c = @fsockopen($server,$port,$errnr,$errstr,30);

			if (!$c) {
				unset($c);
				$buffer[] = "Unable to connect to the server!";
				$buffer[] = "[".ERROR."] $errstr: ($errnr)";
			} else {
			//	sleep(2);
				fputs($c, $this->domainName."\r\n");
				while (!feof($c)) {
					$buffer[] = fgets($c, 4096);
				}
				fclose($c);
			}
		}

		dbg('Buffer reads : "'.print_r($buffer,1).'"');
		$this->setWhoisBuffer($buffer);
	}

	/**
	 * A method to set the domainSLD for this Whois object.
	 *
	 * @param  value  A domainSLD.
	 */
	public function setDomainSLD($sld)
	{
		$this->domainSLD = $sld;
	}

	/**
	 * A method to get the domainSLD for this Whois object.
	 *
	 * @return  A domainSLD.
	 */
	public function getDomainSLD()
	{
		return $this->domainSLD;
	}

	/**
	 * A method to set the domainTLD for this Whois object.
	 *
	 * @param  value  A domainTLD.
	 */
	public function setDomainTLD($tld)
	{
		$this->domainTLD = $tld;
	}

	/**
	 * A method to get the domainTLD for this Whois object.
	 *
	 * @return  A domainTLD.
	 */
	public function getDomainTLD()
	{
		return $this->domainTLD;
	}

	/**
	 * A method to set the domainName for this Whois object.
	 *
	 * @param  value  A domain's SLD.
	 * @param  value  A domain's TLD.
	 */
	public function setDomainName($sld,$tld)
	{
		$this->domainName = $sld.".".$tld;
	}

	/**
	 * A method to get the domainName for this Whois object.
	 *
	 * @return  A domainName.
	 */
	public function getDomainName()
	{
	 	if (!$this->domainName) {
			$this->setDomainName($this->domainSLD,$this->domainTLD);
	 	}
		return $this->domainName;
	}

	/**
	 * A method to get the whoisServer for this Whois object.
	 *
	 * @return  A whoisServer.
	 */
	public function getWhoisServer()
	{
		return $this->whoisServer;
	}

	/**
	 * A method to get the whoisMatchString for this Whois object.
	 *
	 * @return  A whoisMatchString.
	 */
	public function getWhoisMatchString()
	{
		return $this->whoisMatchString;
	}

	/**
	 * A method to set the whoisBuffer for this Whois object.
	 *
	 * @param  value  A whoisBuffer.
	 */
	public function setWhoisBuffer($value)
	{
		$this->whoisBuffer = $value;
	}

	/**
	 * A method to get the whoisBuffer for this Whois object.
	 *
	 * @return  A whoisBuffer.
	 */
	public function getWhoisBuffer()
	{
		if (notNull($this->whoisBuffer)) {
			return $this->whoisBuffer;
		} else {
			$this->execute();
			return $this->whoisBuffer;
		}
	}

	/**
	 * A method to set the isAvailable for this Whois object.
	 */
	public function setIsAvailable()
	{
		$retval = 0;
		$whoisMatchString = $this->getWhoisMatchString();
		$whoisBuffer = $this->getWhoisBuffer();
		$whoisMatchRules = $this->whoisMatchRules;
		if ($whoisMatchRules=="IN" || empty($whoisMatchRules)){
			$c = count($whoisBuffer);
			for($i=0;$i<$c;$i++) {
				if (strstr($whoisBuffer[$i],$whoisMatchString)) {
					$retval = 1;
					break;
				}
			}
		} elseif ($whoisMatchRules=="NOT IN"){
			$fullBuffer = implode("\n", $whoisBuffer);
			dbg("fullbuffer: ".$fullBuffer,0,1);
			if (strpos($fullBuffer, $whoisMatchString)===false) {
				$retval = 1;
			}
		}
		$this->isAvailable = $retval;
	}

	/**
	 * A method to grab the extended attributes
	 */
	public function getExtended()
	{
		$vars = array();

		$this->setIsAvailable();
		if ($this->isAvailable) {
			return array();
		}

		$whoisBuffer =& $this->getWhoisBuffer();
		$oldENC = mb_regex_encoding();
		mb_regex_encoding("UTF-8");
		for( $i=0, $n=count($whoisBuffer); $i<$n; $i++ ) {
			$line =& $whoisBuffer[ $i ]; //pointer
			if (!notNull($line))	continue;

			// looking for a "normal" line response like "<key>: <value>"
			if (mb_eregi("^(?!:%|#|;)\s{0,20}\[{0,1}([\S].{1,60})\]{0,1}\:{0,1}\s{1,60}([\S].{1,60}[^\W\:])\s*\r{0,1}\n$", $line, $matches)) {
				switch( true ) {
				case mb_eregi("registrar", $matches[1]):

					if (mb_eregi("server|url|http", $matches[0]) || !mb_strlen(trim($matches[2])))	continue;

					// looking for Regisrtrar: <name> Format
					if ( ($pos = mb_strpos($matches[0], ':')) != false) {
						if (mb_eregi(".*\:\s+(.*)\s*\r{0,1}\n$",$matches[0], $matches)) {
							if (!in_array($matches[1], (array)$vars["registrar"])) {
								$vars["registrar"][] = $matches[1];
							}
						}

						break;
					}
					unset($pos);
				break;
				case mb_eregi("creat|registration|registered", $matches[1]):
					if ( ($pos = mb_strpos($matches[0], ':')) !== false) {
						$tt = mb_substr($matches[0], $pos+1);
						if ( ($tt = strtotime($tt)) != false ) {
							$vars["created"][] = $tt;
						}
					} elseif (($tt = strtotime($matches[2])) != false) {
						$vars["created"][] = $tt;
					} elseif (mb_eregi("service", $matches[0])) {
						$vars["registrar"][0] = $matches[2];
					}
					unset($tt);
				break;
				case mb_eregi("expir", $matches[1]):
					if (($matches[2] = strtotime($matches[2])) != false) {
						$vars["expire"][]  = $matches[2];
					}
				break;
				case mb_eregi("status", $matches[1]):
					$vars["status"][] = $matches[2];
				break;

				case mb_eregi("server", $matches[1]):
					if (mb_eregi("name", $matches[1])) {
						if (notNull($matches[2]) && mb_eregi(".*\..*\..{2,8}", $matches[2])) {
							$vars["ns"][] = $matches[2];
						}
					}
				break;

				// other!
				default:
					if (!notNull($matches[0])) break;
					if (mb_eregi("address|version|contact", $matches[0])) break;

					switch( true ) {
					// maybe our status
					case mb_eregi('^active$', $matches[2]):
						$vars['status'][] = 'active';
					break;

					// a expire/create date perhaps?
					case ( ($time = strtotime($matches[2])) && (mb_strlen($matches[2])>6) ):
						// could be a date

						if (mb_eregi("update|lookup", $matches[0]))	break;
						if (mb_strlen($matches[2]) < 4)	break;


						$low = isset($vars["created"][0]) ? $vars["created"][0] : 0;
						$high = isset($vars["expire"][0]) ? $vars["expire"][0] : 0;

						if (!$low && !$high) {
							if ($time >= time()) {
								$vars["expire"][0] = $time;
							} else {
								$vars["created"][0] = $time;
							}
							unset($high, $low, $time);
							break;
						}

						if ($time > $high) {
							$vars["expire"][0] = $time;
						} elseif ($time < $low) {
							$vars["created"][0] = $time;
						}
						unset($high, $low, $time);
					break;
					}
				break;
				}
			} elseif (mb_eregi("registrar", $line)) {
				// found a registrar on this line, but doesn't match format, probably on next 2 line, lets peak
				for( $k=0; $k<2; $k++ ) {
					$nextLine =& $whoisBuffer[ $i + $k ]; // pointer

					if (mb_eregi("server|url|http", $nextLine) || !mb_strlen(trim($nextLine)))	continue;

					if ( ($pos = mb_strpos($nextLine, ':')) != false) {
						$pos = mb_ereg_replace('(.+)(?!:http[s]{0,1})\:\s{1,30}', null, $nextLine);
						if (!in_array($pos, (array)$vars["registrar"]) && mb_strlen(trim($pos))) {

							$vars["registrar"][] = $pos;
						}
					} elseif (notNull($nextLine) && mb_eregi("url\:", $whoisBuffer[ $i + $k + 1 ]) ) {
						// this line contains data, the next does not, probably the registrar is here
						if (mb_eregi("^\s*(.+)\s*$", $nextLine, $matches)) {
							if (notNull($matches[1])) {
								$vars["registrar"][] = $matches[1];
							}
						}
						unset($matches);
					}
					unset($nextLine, $pos);
				}
				unset($k);
			} elseif (mb_eregi("server", $line) && mb_eregi("name", $line)) {
				for( $k=0; $k<=4; $k++ ) {
					if (mb_eregi("\s*(.*\..*\..{2,8})", $whoisBuffer[$i + $k ], $matches)) {
						if (notNull($matches[1])) {
							$vars["ns"][] = $matches[1];
						}
					}
				}
				unset($k);
			}
			/* else {
				echo "<div style=\"background-color:#EEEEEE\">";
					ob_start();
					var_dump($line);
					$str = ob_get_contents();
					ob_end_clean();
					show($str);
					echo "</div>";
			}*/
			unset($matches, $line);
		}

		mb_regex_encoding($oldENC);
		/*
			Trim the ENTIRE array
		*/
		foreach( (array)$vars as $k => $v ) {
			for( $i=0, $n=count($v); $i<$n; $i++ ) {
				$vars[ $k ][ $i ] = trim($v[ $i ]);
			}
		}

		$this->extendedAttributes = $vars;
		return $this->extendedAttributes;
	}

	/**
	 * A method to get the isAvailable for this Whois object.
	 *
	 * @return  A isAvailable.
	 */
	public function getIsAvailable()
	{
		return $this->isAvailable;
	}

	/**
	 * A method to retrieve the proper (possibly overloaded) whois server for a specified tld.
	 * @return string
	 */
	private function initWhois($tld)
	{
		$currentTld = reset(Factory()->TLDList(array("tld_extension" => $tld)));
		if (false !== $currentTld && "" != $currentTld->tld_whois_server ) {
			$this->whoisServer = $currentTld->tld_whois_server;
			$this->whoisMatchString = $currentTld->tld_whois_resp;
			$this->whoisMatchRules = $currentTld->tld_whois_match_rule;
			return;
		}

		if (!isset($this->whoisServers[$tld])) {
			return;
		}

		$this->whoisServer = $this->whoisServers[$tld][0];
		$this->whoisMatchString = $this->whoisServers[$tld][1];
		$this->whoisMatchRules = isset($this->whoisServers[$tld][2]) ? $this->whoisServers[$tld][2] : NULL;
	}

	private $whoisServers = array(
		'ac' 		=> array('whois.nic.ac', 'Available'),
		'aero' 		=> array('aero.whois-servers.net', 'NOT FOUND'),
		'ag' 		=> array('whois.nic.ag', 'NOT FOUND'),
		'al' 		=> array('whois.ripe.net', 'No entries found'),
		'am' 		=> array('whois.amnic.net', 'No match'),
		'as' 		=> array('whois.nic.as', 'Domain Not Found'),
		'asia' 		=> array('whois.nic.asia', 'NOT FOUND'),
		'at' 		=> array('whois.nic.at', 'nothing found'),
		'co.at' 	=> array('whois.nic.at', 'nothing found'),
		'or.at' 	=> array('whois.nic.at', 'nothing found'),
		'au' 		=> array('whois.ausregistry.net.au', 'No Data Found'),
		'asn.au' 	=> array('whois.ausregistry.net.au', 'No Data Found'),
		'com.au' 	=> array('whois.ausregistry.net.au', 'No Data Found'),
		'conf.au' 	=> array('whois.ausregistry.net.au', 'No Data Found'),
		'csiro.au' 	=> array('whois.ausregistry.net.au', 'No Data Found'),
		'edu.au' 	=> array('whois.ausregistry.net.au', 'No Data Found'),
		'gov.au' 	=> array('whois.ausregistry.net.au', 'No Data Found'),
		'id.au' 	=> array('whois.ausregistry.net.au', 'No Data Found'),
		'emu.id.au'	=> array('whois.ausregistry.net.au', 'No Data Found'),
		'wattle.id.au'	=> array('whois.ausregistry.net.au', 'No Data Found'),
		'info.au' 	=> array('whois.ausregistry.net.au', 'No Data Found'),
		'net.au' 	=> array('whois.ausregistry.net.au', 'No Data Found'),
		'org.au' 	=> array('whois.ausregistry.net.au', 'No Data Found'),
		'az' 		=> array('whois.ripe.net', 'no entries found'),
		'ba' 		=> array('whois.ripe.net', 'No entries found'),
		'be' 		=> array('whois.geektools.com', 'FREE'),
		'bg' 		=> array('whois.register.bg', 'does not exist'),
		'biz' 		=> array('whois.biz', 'Not found'),
		'br' 		=> array('whois.registro.br', 'No match'),
		'adm.br' 	=> array('whois.nic.br', 'No match'),
		'adv.br' 	=> array('whois.nic.br', 'No match'),
		'agr.br' 	=> array('whois.nic.br', 'No match'),
		'am.br' 	=> array('whois.nic.br', 'No match'),
		'arq.br' 	=> array('whois.nic.br', 'No match'),
		'art.br' 	=> array('whois.nic.br', 'No match'),
		'ato.br' 	=> array('whois.nic.br', 'No match'),
		'bio.br' 	=> array('whois.nic.br', 'No match'),
		'bmd.br' 	=> array('whois.nic.br', 'No match'),
		'cim.br' 	=> array('whois.nic.br', 'No match'),
		'cng.br' 	=> array('whois.nic.br', 'No match'),
		'cnt.br' 	=> array('whois.nic.br', 'No match'),
		'com.br' 	=> array('whois.nic.br', 'No match'),
		'ecn.br' 	=> array('whois.nic.br', 'No match'),
		'edu.br' 	=> array('whois.nic.br', 'No match'),
		'eng.br' 	=> array('whois.nic.br', 'No match'),
		'esp.br' 	=> array('whois.nic.br', 'No match'),
		'etc.br' 	=> array('whois.nic.br', 'No match'),
		'eti.br' 	=> array('whois.nic.br', 'No match'),
		'far.br' 	=> array('whois.nic.br', 'No match'),
		'fm.br' 	=> array('whois.nic.br', 'No match'),
		'fnd.br' 	=> array('whois.nic.br', 'No match'),
		'fot.br' 	=> array('whois.nic.br', 'No match'),
		'fst.br' 	=> array('whois.nic.br', 'No match'),
		'g12.br' 	=> array('whois.nic.br', 'No match'),
		'ggf.br' 	=> array('whois.nic.br', 'No match'),
		'gov.br' 	=> array('whois.nic.br', 'No match'),
		'imb.br' 	=> array('whois.nic.br', 'No match'),
		'ind.br' 	=> array('whois.nic.br', 'No match'),
		'inf.br' 	=> array('whois.nic.br', 'No match'),
		'jor.br' 	=> array('whois.nic.br', 'No match'),
		'lel.br' 	=> array('whois.nic.br', 'No match'),
		'mat.br' 	=> array('whois.nic.br', 'No match'),
		'med.br' 	=> array('whois.nic.br', 'No match'),
		'mil.br' 	=> array('whois.nic.br', 'No match'),
		'mus.br' 	=> array('whois.nic.br', 'No match'),
		'net.br' 	=> array('whois.nic.br', 'No match'),
		'not.br' 	=> array('whois.nic.br', 'No match'),
		'ntr.br' 	=> array('whois.nic.br', 'No match'),
		'odo.br' 	=> array('whois.nic.br', 'No match'),
		'oop.br' 	=> array('whois.nic.br', 'No match'),
		'org.br' 	=> array('whois.nic.br', 'No match'),
		'ppg.br' 	=> array('whois.nic.br', 'No match'),
		'pro.br' 	=> array('whois.nic.br', 'No match'),
		'psc.br' 	=> array('whois.nic.br', 'No match'),
		'psi.br' 	=> array('whois.nic.br', 'No match'),
		'qsl.br' 	=> array('whois.nic.br', 'No match'),
		'rec.br' 	=> array('whois.nic.br', 'No match'),
		'slg.br' 	=> array('whois.nic.br', 'No match'),
		'srv.br' 	=> array('whois.nic.br', 'No match'),
		'tmp.br' 	=> array('whois.nic.br', 'No match'),
		'trd.br' 	=> array('whois.nic.br', 'No match'),
		'tur.br' 	=> array('whois.nic.br', 'No match'),
		'tv.br' 	=> array('whois.nic.br', 'No match'),
		'vet.br' 	=> array('whois.nic.br', 'No match'),
		'zlg.br' 	=> array('whois.nic.br', 'No match'),
		'by' 		=> array('whois.ripe.net', 'no entries found'),
		'ca' 		=> array('whois.cira.ca', 'Domain status:         available'),
		'cc' 		=> array('whois.nic.cc', 'No match'),
		'cd' 		=> array('whois.nic.cd', 'Domain Not Found'),
		'ch' 		=> array('whois.nic.ch', 'We do not have an entry'),
		'ck' 		=> array('whois.nic.ck', 'No entries found'),
		'cl' 		=> array('whois.nic.cl', 'no existe'),
		'cn' 		=> array('whois.cnnic.net.cn', 'no matching record'),
		'ac.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'ah.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'bj.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'com.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'cq.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'fj.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'gd.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'gov.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'gs.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'gx.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'gz.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'ha.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'hb.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'he.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'hi.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'hk.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'hl.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'hn.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'jl.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'js.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'jx.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'ln.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'mo.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'net.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'nm.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'nx.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'org.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'qh.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'sc.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'sd.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'sh.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'sn.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'sx.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'tj.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'tw.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'xj.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'xz.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'yn.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'zj.cn' 	=> array('whois.cnnic.net.cn', 'no matching record'),
		'com' 	=> array('whois.verisign-grs.com', 'No match for'),
		'br.com' 	=> array('whois.centralnic.net', 'DOMAIN NOT FOUND'),
		'cn.com' 	=> array('whois.centralnic.net', 'DOMAIN NOT FOUND'),
		'de.com' 	=> array('whois.centralnic.net', 'DOMAIN NOT FOUND'),
		'eu.com' 	=> array('whois.centralnic.net', 'DOMAIN NOT FOUND'),
		'gb.com' 	=> array('whois.centralnic.net', 'DOMAIN NOT FOUND'),
		'hu.com' 	=> array('whois.centralnic.net', 'DOMAIN NOT FOUND'),
		'no.com' 	=> array('whois.centralnic.net', 'DOMAIN NOT FOUND'),
		'qc.com' 	=> array('whois.centralnic.net', 'DOMAIN NOT FOUND'),
		'ru.com' 	=> array('whois.centralnic.net', 'DOMAIN NOT FOUND'),
		'sa.com' 	=> array('whois.centralnic.net', 'DOMAIN NOT FOUND'),
		'se.com' 	=> array('whois.centralnic.net', 'DOMAIN NOT FOUND'),
		'uk.com' 	=> array('whois.centralnic.net', 'DOMAIN NOT FOUND'),
		'us.com' 	=> array('whois.centralnic.net', 'DOMAIN NOT FOUND'),
		'uy.com' 	=> array('whois.centralnic.net', 'DOMAIN NOT FOUND'),
		'za.com' 	=> array('whois.centralnic.net', 'DOMAIN NOT FOUND'),
		'cy' 		=> array('whois.ripe.net', 'no entries found'),
		'cz' 		=> array('whois.nic.cz', 'no entries found'),
		'de' 		=> array('whois.denic.de', 'free'),
		'dk' 		=> array('whois.dk-hostmaster.dk', 'No entries found'),
		'dz' 		=> array('whois.ripe.net', 'no entries found'),
		'edu'	 	=> array('whois.verisign-grs.net', 'No match'),
		'ee' 		=> array('whois.eenet.ee', 'no entries found'),
		'eg' 		=> array('whois.ripe.net', 'no entries found'),
		'com.eg' 	=> array('whois.ripe.net', 'no entries found'),
		'eun.eg' 	=> array('whois.ripe.net', 'no entries found'),
		'net.eg' 	=> array('whois.ripe.net', 'no entries found'),
		'es' 		=> array('whois.ripe.net', 'no entries found'),
		'eu'		=> array('whois.eu', 'AVAILABLE'),
		'fi' 		=> array('whois.ripe.net', 'No entries found'),
		'fo' 		=> array('whois.ripe.net', 'no entries found'),
		'fr' 		=> array('whois.nic.fr', 'No entries found'),
		'gb' 		=> array('whois.ripe.net', 'no entries found'),
		'ge' 		=> array('whois.ripe.net', 'no entries found'),
		'gl' 		=> array('whois.ripe.net', 'no entries found'),
		'gr' 		=> array('whois.ripe.net', 'no entries found'),
		'gs' 		=> array('whois.adamsnames.tc', 'is not registered'),
		'hk' 		=> array('whois.hknic.net.hk', 'domain has not been registered'),
		'com.hk' 	=> array('whois.hknic.net.hk', 'domain has not been registered'),
		'gov.hk' 	=> array('whois.hknic.net.hk', 'domain has not been registered'),
		'net.hk' 	=> array('whois.hknic.net.hk', 'domain has not been registered'),
		'org.hk' 	=> array('whois.hknic.net.hk', 'domain has not been registered'),
		'hm' 		=> array('whois.registry.hm', '(null)'), // return incorrect result
		'hu' 		=> array('whois.ripe.net', 'no entries found'),
		'ie' 		=> array('whois.domainregistry.ie', 'Not Registered'),
		'il' 		=> array('whois.isoc.org.il', 'No data was found'),
		'info'		=> array('whois.afilias.info', 'NOT FOUND'),
		'int' 		=> array('whois.iana.org', 'not found'), // return incorrect result
		'is' 		=> array('whois.isnic.is', 'No entries found'),
		'it' 		=> array('whois.nic.it', 'AVAILABLE'),
		'jp' 		=> array('whois.jprs.jp', 'No match'),
		'ac.jp' 	=> array('whois.jprs.jp', 'No match'),
		'ad.jp' 	=> array('whois.jprs.jp', 'No match'),
		'co.jp' 	=> array('whois.jprs.jp', 'No match'),
		'gr.jp' 	=> array('whois.jprs.jp', 'No match'),
		'ne.jp' 	=> array('whois.jprs.jp', 'No match'),
		'or.jp' 	=> array('whois.jprs.jp', 'No match'),
		'ke' 		=> array('whois.rg.net', 'No entries found'),
		'co.ke'	=> array('whois.rg.net', 'No entries found'),
		'org.ke'	=> array('whois.rg.net', 'No entries found'),
		'co.kr' 	=> array('whois.nic.or.kr', 'is not registered'),
		'ne.kr' 	=> array('whois.nic.or.kr', 'is not registered'),
		'or.kr' 	=> array('whois.nic.or.kr', 'is not registered'),
		'la' 		=> array('la.whois-servers.net', 'NOT FOUND'),
		'li' 		=> array('whois.nic.ch', 'We do not have an entry'),
		'lk' 		=> array('whois.nic.lk', 'Domain is not available'),
		'lt' 		=> array('whois.domreg.lt', 'available'),
		'lu' 		=> array('whois.dns.lu', 'No such domain'),
		'net.lu' 	=> array('whois.dns.lu', 'No such domain'),
		'org.lu' 	=> array('whois.dns.lu', 'No such domain'),
		'lv' 		=> array('whois.ripe.net', 'No entries found'),
		'ma' 		=> array('whois.ripe.net', 'no entries found'),
		'mc' 		=> array('whois.ripe.net', 'no entries found'),
		'md' 		=> array('whois.ripe.net', 'no entries found'),
		'mk' 		=> array('whois.ripe.net', 'no entries found'),
		'mn' 		=> array('whois.internic.net', 'No match for domain'),
		'mobi'	=> array('whois.dotmobiregistry.net', 'NOT FOUND'),
		'ms'	 	=> array('whois.adamsnames.tc', 'is not registered'),
		'mt' 		=> array('whois.ripe.net', 'No entries found'),
		'mx' 		=> array('whois.nic.mx', 'Object_Not_Found'),
		'com.mx' 	=> array('whois.nic.mx', 'Object_Not_Found'),
		'gob.mx' 	=> array('whois.nic.mx', 'Object_Not_Found'),
		'net.mx' 	=> array('whois.nic.mx', 'Object_Not_Found'),
		'my'		=> array('whois.mynic.net.my', 'does not exist'),
		'com.my'	=> array('whois.mynic.net.my', 'does not exist'),
		'net.my'	=> array('whois.mynic.net.my', 'does not exist'),
		'org.my'	=> array('whois.mynic.net.my', 'does not exist'),
		'name.my'	=> array('whois.mynic.net.my', 'does not exist'),
		'edu.my'	=> array('whois.mynic.net.my', 'does not exist'),
		'gov.my'	=> array('whois.mynic.net.my', 'does not exist'),
		'mil.my'	=> array('whois.mynic.net.my', 'does not exist'),
		'name'	=> array('whois.nic.name', 'No match'),
		'net' 		=> array('whois.crsnic.net', 'No match'),
		'nl' 		=> array('whois.domain-registry.nl', 'is free'),
		'no' 		=> array('whois.norid.no', 'No match'),
		'nu' 		=> array('whois.nic.nu', 'NO MATCH for'),
		'co.nz' 	=> array('whois.srs.net.nz', 'Available'),
		'net.nz' 	=> array('whois.srs.net.nz', 'Available'),
		'org.nz' 	=> array('whois.srs.net.nz', 'Available'),
		'geek.nz' 	=> array('whois.srs.net.nz', 'Available'),
		'school.nz'	=> array('whois.srs.net.nz', 'Available'),
		'gen.nz' 	=> array('whois.srs.net.nz', 'Available'),
		'govt.nz' 	=> array('whois.srs.net.nz', 'Available'),
		'maori.nz' 	=> array('whois.srs.net.nz', 'Available'),
		'ac.nz' 	=> array('whois.srs.net.nz', 'Available'),
		'iwi.nz' 	=> array('whois.srs.net.nz', 'Available'),
		'cri.nz' 	=> array('whois.srs.net.nz', 'Available'),
		'mil.nz' 	=> array('whois.srs.net.nz', 'Available'),
		'org' 		=> array('whois.pir.org', 'NOT FOUND'),
		'pk' 		=> array('whois.pknic.net', 'is not registered'),
		'pl' 		=> array('whois.ripe.net', 'no entries found'),
		'pt' 		=> array('whois.dns.pt', 'no match'),
		'ro' 		=> array('whois.ripe.net', 'no entries found'),
		'xn--p1ai' 	=> array('whois.ripn.net', 'No entries found'),
		'ru' 		=> array('whois.ripn.net', 'No entries found'),
		'com.ru' 	=> array('whois.ripn.net', 'No entries found'),
		'net.ru' 	=> array('whois.ripn.net', 'No entries found'),
		'org.ru' 	=> array('whois.ripn.net', 'No entries found'),
		'pp.ru' 	=> array('whois.ripn.net', 'No entries found'),
		'se' 		=> array('whois.nic-se.se', 'not found'),
		'sg' 		=> array('whois.nic.net.sg', 'Domain Not Found'),
		'com.sg' 	=> array('whois.nic.net.sg', 'Domain Not Found'),
		'org.sg' 	=> array('whois.nic.net.sg', 'Domain Not Found'),
		'edu.sg' 	=> array('whois.nic.net.sg', 'Domain Not Found'),
		'per.sg' 	=> array('whois.nic.net.sg', 'Domain Not Found'),
		'sh' 		=> array('whois.nic.sh', 'Available'),
		'si' 		=> array('whois.arnes.si', 'No entries found'),
		'sk' 		=> array('whois.ripe.net', 'no entries found'),
		'sm' 		=> array('whois.ripe.net', 'no entries found'),
		'st' 		=> array('whois.nic.st', 'No entries found'),
		'su' 		=> array('whois.ripe.net', 'no entries found'),
        'tashkent.su' 	=> array('whois.ripn.net', 'No entries found'),
        'bukhara.su' 	=> array('whois.ripn.net', 'No entries found'),
        'grozny.su' 	=> array('whois.ripn.net', 'No entries found'),
        'jambyl.su' 	=> array('whois.ripn.net', 'No entries found'),
        'kurgan.su' 	=> array('whois.ripn.net', 'No entries found'),
        'lenug.su' 		=> array('whois.ripn.net', 'No entries found'),
        'obninsk.su' 	=> array('whois.ripn.net', 'No entries found'),
        'penza.su' 		=> array('whois.ripn.net', 'No entries found'),
		'tc' 		=> array('whois.adamsnames.tc', 'is not registered'),
		'th' 		=> array('th.whois-servers.net', 'No match for'),
		'tm' 		=> array('whois.nic.tm', 'Available'),
		'tn' 		=> array('whois.ripe.net', 'no entries found'),
		'to' 		=> array('whois.tonic.to', 'No match'), // return incorrect result
		'tr' 		=> array('whois.ripe.net', 'no entries found'),
		'av.tr' 	=> array('whois.nic.tr', 'No match found'),
		'bel.tr' 	=> array('whois.nic.tr', 'No match found'),
		'biz.tr' 	=> array('whois.nic.tr', 'No match found'),
		'com.tr' 	=> array('whois.nic.tr', 'No match found'),
		'dr.tr' 	=> array('whois.nic.tr', 'No match found'),
		'edu.tr' 	=> array('whois.nic.tr', 'No match found'),
		'gen.tr' 	=> array('whois.nic.tr', 'No match found'),
		'gov.tr' 	=> array('whois.nic.tr', 'No match found'),
		'info.tr' 	=> array('whois.nic.tr', 'No match found'),
		'k12.tr' 	=> array('whois.nic.tr', 'No match found'),
		'mil.tr' 	=> array('whois.nic.tr', 'No match found'), // return incorrect result
		'name.tr' 	=> array('whois.nic.tr', 'No match found'),
		'net.tr' 	=> array('whois.nic.tr', 'No match found'),
		'org.tr' 	=> array('whois.nic.tr', 'No match found'),
		'pol.tr' 	=> array('whois.nic.tr', 'No match found'),
		'tel.tr' 	=> array('whois.nic.tr', 'No match found'),
		'web.tr' 	=> array('whois.nic.tr', 'No match found'),
		'tv' 		=> array('whois.nic.tv', 'No match for'),
		'tw' 		=> array('whois.twnic.net', 'No Found'),
		'com.tw' 	=> array('whois.twnic.net', 'No Found'),
		'idv.tw' 	=> array('whois.twnic.net', 'No Found'),
		'net.tw' 	=> array('whois.twnic.net', 'No Found'),
		'org.tw' 	=> array('whois.twnic.net', 'No Found'),
		'ua' 		=> array('whois.ripe.net', 'no entries found'),
		'uk' 		=> array('whois.thnic.net', 'No match for'),
		'ac.uk' 	=> array('whois.ja.net', 'No such domain'),
		'co.uk' 	=> array('whois.nic.uk', 'No match for'),
		'ltd.uk' 	=> array('whois.nic.uk', 'No match for'),
		'me.uk' 	=> array('whois.nic.uk', 'No match for'),
		'net.uk' 	=> array('whois.nic.uk', 'No match for'),
		'org.uk' 	=> array('whois.nic.uk', 'No match for'),
		'plc.uk' 	=> array('whois.nic.uk', 'No match for'),
		'kids.us' 	=> array('whois.nic.us', 'Not found'),
		'us' 		=> array('whois.nic.us', 'Not found'),
		'va' 		=> array('whois.ripe.net', 'No entries found'),
		'vg' 		=> array('whois.adamsnames.tc', 'is not registered'),
		'ws' 		=> array('whois.worldsite.ws', 'No match for'),
		'yu' 		=> array('whois.ripe.net', 'no entries found'),
		'ac.za' 	=> array('whois.ac.za', 'No domain'),
	);
}