<?php
//
// whois.php3 v1.8.4 1999/08/08
//
// Copyright (c) 1998, 1999 Mark Jeftovic / easyDNS Technologies Inc.
// email: markjr@easyDNS.com
//
// For most recent version check:
http://www.shmOOze.net/~markjr/whois/ //
// All rights reserved.
// This code provided \"As Is\" with no warrantees express or implied.
// The author and contributors are not liable for anything good or
// bad that results from your use of this code.
//
// You are free to distribute this for free provided this notice is
// included. Please forward fixes/enhancements to the author for
// inclusion in the next revision.
//
// CHANGES:
// 1.8.4 (11/08/99): should be sending query with \\r\\n, not
// just \\n, thanks to Steve Bright <steve@netdevils.net>
// for noticing
// 1.8.3 (08/20/99): added adamsnames TLD\'s and .ac and .sh
// 1.8.2 (07/12/99): added $this->DISCLAIMER for the floating
// goddamn disclaimer they keep moving around
// 1.8.0 (07/03/99): added getRegInfo() and parseRegInfo() which
// get called from zonelookup() so it\'ll work
// for .com/.net/.org regardless of registrar
// because it\'ll ask whois.crsnic.net first
// 1.7.1 (05/15/99): added not found string for whois.ripe.net
// 1.7 - (05/13/99): added getTLD() in order to support 2nd level
// registries like nominet, which we now support as well
// (.uk.com/.gb.net/.gb.com)
// 1.6 - (05/04/99): added .sg to server list.
// -changed all easydns TLD\'s to whois.easydns.net
// 1.5 - (04/22/99): DOMAIN_STATUS and CREATED are back in
// - added support for pretty well every TLD, including
// ccTLD\'s and alternate like ORSC, SuperRoot and our
// own. parsezone() probably won\'t work outside .com/.net/.org
// and found/not found might be broken for a given whois/tld
// your milage may vary, let me know of any tweaks
// 1.4b4 -(03/24/99): A few changes by Colin Viebrock (cmv@easydns.com)
// - tried to trim() as much of the returned data as possible
// - removed DOMAIN_STATUS and CREATED, since Internic decided
// not to give out this info anymore
// - added dns_query() function which just checks the DNS records
// of the domain for NS entries and returns true if it finds
// some, false otherwise ... this needs to be integrated into
// into the class better (toggle for LOOKUP_METHOD, perhaps?)
// 1.4b3 -(01/05/99): Internic chenged the \"Too Busy\" message wording
// again. Reported by Gregory A. Carter <omni@dynmc.net>
// 1.4b2 -(08/24/98): put the old code back in parse_contact_line() with
// a bit ofa modification (the version in 1.4b couldn\'t parse
// the result from doing a rawlookup() on a nic handle properly)
// 1.4b - (08/17/98): added ability to cache results, set $whois->use_cache
// and rawlookup() will
// a) check the cache_dir for a previously cached zone file
// and use it if it finds it, sets $whois->FROM_CACHE
// b) write a zone record there after it looks it up
// It\'s up to the user to expire the cache (i.e. cron job to delete
// entries older than x seconds)
// -TODO: if caching is turned on and $whois->HANDLES is set (query
// returned multiple handles) the result still gets cached. I don\'t
// want this but it happens anyways. This is probably a bug.
// - pushed default server (whois.internic.net) from param to connect()
// to rawlookup(), because i realized you couldn\'t do rawlookup()
// to other whois servers the old way. For now just use:
// $whois->rawlookup(\"example.ca\", \"whois.cdnnet.ca\") to do
// alternate lookups
// -parse_contact_line() rewritten by Ben Ginter <bginter@abilnet.com>
// (although I added the chop()\'s, some code here broke without them)
// 1.3 - (07/28/98): the whois server is starting to spit out a couple
// or few blank lines and then dying, which wouldn\'t set
// $whois->ERROR, even though it should, so now it does
// 1.2 - format change on Internic side, Organization info preceded by
// a \"Registrant:\" line.
// 1.1 - couple of bugfixes by Colin Viebrock <cmv@privateworld.com>
// ORG_ADDRESS wasn\'t getting caught because of a typo
//
// added trim() function (now internal to php anyways i think)
//
// USAGE:
// $domain = \"somedomain.com\";
// $whois = new whois;
//
// the following line simply loads an array with the raw output of
// a whois query and sets $whois->FOUND (if the query finds no
// match $whois->FOUND will be 0) if an error occurs in the lookup
// $whois->ERROR will be set.
// $array = $whois->rawlookup($domain)
//
// this parses the array into variables available to the package:
// $whois->parsezone($array);
//
// will set vars such as $whois->ORGANIZATION, $whois->ORG_HANDLE
// $whois->DOMAIN_NAME, the hashes $whois->TECH, $whois->ADMIN, etc.
// and the arrays: $whois->DNS_NAME and $whois->DNS_IP
// (for a complete list, see below)
//
// you can complete both steps (rawlookup and parsezone) with:
// $whois->zonelookup($domain);
//
// TODO:
// - support to parse other types of queries (host, contact, etc)
// (you can still use rawlookup for these types of handles)
// - support for alternate servers/queries (i.e. netblocks via
// whois.arin.net)
// - need to verify found/not found syntax for all the other
// whois servers in the $SERVER array \"not found\" or
// \"no match for\" case insensitive seems to be a pretty safe bet
// so far
// - now we need to be able to parse the various output formats from
// the shared registrars (what a fucking mess)
//
class whois {
var $use_cache = 0;
var $FROM_CACHE=0;
var $cache_dir = $DIRS[ \"whois_cache\"];
var $port = 43;
var $MAXLEN = 1024;
// we need querytype now that we will support queries outside of
// .com/.net/.org
// possible values (whether support is in this version or not):
// \"raw\" = unspecified
// \"domain\" = domain name
// \"handle\" = contact handle
// \"server\" = nameserver
// \"registrar\"
var $QUERY_TYPE = \"domain\";
var $DEFAULT_SERVER = \"whois.internic.net\";
var $REGISTRY_SERVER = \"whois.crsnic.net\";
var $REG_INFO; // array of \"domain\",\"registrar\",\"whois\",\"referrer\" and
// \"nameserver[]\";
var $REG_FIELDS = array( \"domain\"=> \"Domain Name\",
\"registrar\"=> \"Registrar\",
\"whois\"=> \"Whois Server\",
\"referrer\"=> \"Referral URL\",
\"nameserver\"=> \"Name Server\", // identical descriptors
\"upadated\"=> \"Updated Date\"
);
// if we want to automagically retry after a failed connect then
// set $MAX_RETRIES the number of retries you want
var $MAX_RETRIES = 0;
var $SLEEP_VAL = 1;
var $RETRY = 0;
var $FOUND = 0; // this will be 0 if the query yields no match
var $ERROR = 0; // this will be set if an error occurs in the lookup
var $DATA_MIN = 8; // we should at least this many bytes of data, or
// we assume the whois server just spit out nothing
// and died (which it\'s starting to do more often)
var $DATA_COUNT = 0;
// these are the vars set when you parse the results of a domain lookup
var $DISCLAIMER;
var $ORGANIZATION;
var $ORG_HANDLE;
var $ORG_ADDRESS; // array that holds the org\'s address info
var $DOMAIN_NAME;
var $DOMAIN_STATUS;
var $ADMIN; // hash with subscripts: \"name\", \"nic\" and \"email\"
var $TECH; // hash with subscripts: \"name\", \"nic\" and \"email\"
var $ZONE; // hash with subscripts: \"name\", \"nic\" and \"email\"
var $BILLING;
var $UPDATED;
var $CREATED;
var $DNS_NAME; // array of nameserver hostnames (primary first)
var $DNS_IP; // array of nameserver ips (primary first)
var $HANDLES; // array of nic handles if a zonelookup yields
// multiple results
var $SERVER = array(
\"ac\"=> \"whois.nic.ac\",
\"al\"=> \"whois.ripe.net\",
\"am\"=> \"whois.amnic.net\",
\"art\"=> \"whois.skyscape.net\",
\"arts\"=> \"whois.skyscape.net\",
\"at\"=> \"whois.ripe.net\",
\"au\"=> \"whois.aunic.net\",
\"az\"=> \"whois.ripe.net\",
\"ba\"=> \"whois.ripe.net\",
\"bank\"=> \"whois.skyscape.net\",
\"be\"=> \"whois.ripe.net\",
\"bg\"=> \"whois.ripe.net\",
\"biz\"=> \"rs.mcs.net\",
\"by\"=> \"whois.ripe.net\",
\"ca\"=> \"whois.cdnnet.ca\",
\"can\"=> \"whois.easydns.net\",
\"cc\"=> \"whois.nic.cc\",
\"cdn\"=> \"whois2.vrx.net\",
\"ch\"=> \"whois.nic.ch\",
\"cn\"=> \"whois.apnic.net\",
\"com\"=> \"rs.internic.net\",
\"corp\"=> \"rs.mcs.net\",
\"cx\"=> \"whois.nic.cx\",
\"cy\"=> \"whois.ripe.net\",
\"cz\"=> \"whois.ripe.net\",
\"dds\"=> \"whois.vrx.net\",
\"de\"=> \"whois.ripe.net\",
\"dir\"=> \"whois.skyscape.net\",
\"dk\"=> \"whois.ripe.net\",
\"dz\"=> \"whois.ripe.net\",
\"edu\"=> \"rs.internic.net\",
\"ee\"=> \"whois.ripe.net\",
\"eg\"=> \"whois.ripe.net\",
\"es\"=> \"whois.ripe.net\",
\"etc\"=> \"whois.easydns.net\",
\"faq\"=> \"whois.vrx.net\",
\"fi\"=> \"whois.ripe.net\",
\"film\"=> \"whois.skyscape.net\",
\"fo\"=> \"whois.ripe.net\",
\"fr\"=> \"whois.ripe.net\",
\"fund\"=> \"whois.skyscape.net\",
\"gallery\"=> \"whois.vrx.net\",
\"gb\"=> \"whois.ripe.net\",
\"gb.com\"=> \"whois.nomination.net\",
\"gb.net\"=> \"whois.nomination.net\",
\"ge\"=> \"whois.ripe.net\",
\"gmbh\"=> \"whois.vrx.net\",
\"gov\"=> \"whois.nic.gov\",
\"gr\"=> \"whois.ripe.net\",
\"gs\"=> \"whois.adamsnames.tc\",
\"help\"=> \"whois.skyscape.net\",
\"hk\"=> \"whois.apnic.net\",
\"hotel\"=> \"whois.skyscape.net\",
\"hr\"=> \"whois.ripe.net\",
\"hu\"=> \"whois.ripe.net\",
\"ie\"=> \"whois.ripe.net\",
\"il\"=> \"whois.ripe.net\",
\"is\"=> \"whois.ripe.net\",
\"isp\"=> \"whois.skyscape.net\",
\"it\"=> \"whois.nic.it\",
\"jp\"=> \"whois.nic.ad.jp\",
\"k12\"=> \"rs.mcs.net\",
\"kr\"=> \"whois.apnic.net\",
\"li\"=> \"whois.nic.ch\",
\"list\"=> \"whois.vrx.net\",
\"llb\"=> \"whois.vrx.net\",
\"lt\"=> \"whois.ripe.net\",
\"lu\"=> \"whois.ripe.net\",
\"lv\"=> \"whois.ripe.net\",
\"ma\"=> \"whois.ripe.net\",
\"md\"=> \"whois.ripe.net\",
\"med\"=> \"whois.skyscape.net\",
\"mil\"=> \"whois.nic.mil\",
\"mk\"=> \"whois.ripe.net\",
\"ms\"=> \"whois.adamsnames.tc\",
\"mt\"=> \"whois.ripe.net\",
\"mx\"=> \"nic.mx\",
\"music\"=> \"whois.skyscape.net\",
\"net\"=> \"rs.internic.net\",
\"nic\"=> \"whois.vrx.net\",
\"nl\"=> \"domain-registry.nl\",
\"no\"=> \"whois.ripe.net\",
\"npo\"=> \"rs.mcs.net\",
\"org\"=> \"rs.internic.net\",
\"php\"=> \"whois.easydns.net\",
\"pl\"=> \"whois.ripe.net\",
\"prices\"=> \"whois.vrx.net\",
\"pt\"=> \"whois.ripe.net\",
\"radio\"=> \"whois.skyscape.net\",
\"ro\"=> \"whois.ripe.net\",
\"ru\"=> \"whois.ripn.ru\",
\"se\"=> \"whois.nic-se.se\",
\"sg\"=> \"whois.nic.net.sg\",
\"si\"=> \"whois.ripe.net\",
\"sh\"=> \"whois.nic.sh\",
\"sk\"=> \"whois.ripe.net\",
\"sky\"=> \"whois.skyscape.net\",
\"sm\"=> \"whois.ripe.net\",
\"sql\"=> \"whois.vrx.net\",
\"su\"=> \"whois.ripe.net\",
\"tc\"=> \"whois.adamsnames.tc\",
\"tf\"=> \"whois.adamsnames.tc\",
\"tj\"=> \"whois.nic.tj\",
\"tn\"=> \"whois.ripe.net\",
\"tr\"=> \"whois.ripe.net\",
\"tw\"=> \"whois.apnic.net\",
\"ua\"=> \"whois.ripe.net\",
\"uk\"=> \"whois.nic.uk\",
\"uk.com\"=> \"whois.nomination.net\",
\"us\"=> \"whois.isi.edu\",
\"va\"=> \"whois.ripe.net\",
\"vg\"=> \"whois.adamsnames.tc\",
\"video\"=> \"whois.skyscape.net\",
\"xxx\"=> \"whois.skyscape.net\",
\"y2k\"=> \"whois.easydns.net\",
\"yu\"=> \"whois.ripe.net\",
\"zine\"=> \"whois.skyscape.net\",
\"zoo\"=> \"whois.vrx.net\",
\"666\"=> \"whois.easydns.net\",
\"800\"=> \"whois.vrx.net\",
\"888\"=> \"whois.vrx.net\",
\"int\"=> \"whois.isi.edu\"
);
var $TLD;
var $RAWINFO;
var $i, $k, $tld, $max;
// open a socket to the whois server
// defaults to whois.internic.net if an alternate is not passed
// returns: a pointer on success, sets $this->ERROR on fail
function connect ($server) {
while($this->RETRY <= $this->MAX_RETRIES):
$ptr = fsockopen($server, $this->port);
if($ptr>0):
$this->ERROR=0; // just in case we\'re on a retry
return($ptr);
else:
$this->ERROR++;
$this->RETRY++;
sleep($this->SLEEP_VAL);
endif;
endwhile;
}
// getTLD($domain)
// this returns the registry level domain since we\'re
// now supporting a registry with 2nd-level domains
// (nominet\'s uk.com, gb.net and gb.com)
function getTLD ($domain) {
// unfortunately the only reliable way to do this is
// to blow through the entire server/tld list
reset($this->SERVER);
for($this->i=0,$this->max=count($this->SERVER);$this->i<$this->max;
$this->i++) {
$this->k=key($this->SERVER);
if(eregi( \"$this->k$\", $domain)) {
if(!empty($this->tld)) {
// FIXME: we assume we\'ll never support a 3rd
// level registry. If we do, this breaks.
$this->tld = strchr($this->k, \".\") ?
$this->k : $this->tld;
}
else { $this->tld = $this->k; }
}
next($this->SERVER);
}
return($this->tld);
}
// simply gets the output of the query from the whois server
// and loads it into array
function rawlookup ($query) {
if(!$query):
return( \"\");
endif;
$this->TLD=$this->getTLD(strtolower($query));
if($this->QUERY_TYPE== \"domain\" && empty($this->REG_INFO[whois])):
$server =
!empty($this->TLD) && isSet($this->SERVER[$this->TLD]) ?
$this->SERVER[$this->TLD] : $this->DEFAULT_SERVER;
elseif($this->QUERY_TYPE== \"registrar\"):
$server=$this->REGISTRY_SERVER;
else:
$server=$this->DEFAULT_SERVER;
endif;
$ptr=$this->connect($server);
if($ptr):
fputs($ptr, sprintf( \"%s\\r\\n\",trim($query)));
$i=0;
$this->FOUND=1;
while(!feof($ptr)):
$array[$i]=fgets($ptr,$this->MAXLEN);
$this->DATA_COUNT+=strlen(trim($array[$i]));
if(eregi( \"No match for\", $array[$i])):
$this->FOUND=0;
elseif(eregi( \"Not found\", $array[$i])):
$this->FOUND=0;
elseif(eregi( \"No entries found for the selected source\", $array[$i])):
$this->FOUND=0;
elseif(eregi( \"WHOIS database is down\",$array[$i])):
$this->ERROR++;
$this->FOUND=0;
elseif(eregi( \"Please wait a while and try again\",$array[$i])):
$this->ERROR++;
$this->FOUND=0;
break;
endif;
$i++;
endwhile;
fclose($ptr);
if($this->DATA_COUNT>$this->DATA_MIN):
return($array);
else:
$this->ERROR++;
endif;
else:
$this->ERROR++;
endif;
}
// takes a contact info line from a zone record and parses it
// into name, nic, and email
// reverted to old code with a modified email pattern in 1.4b_2
function parse_contact_line ($line) {
$hash[ \"name\"]=trim(ereg_replace( \"(.+) \\(.+\", \"\\\\1\", $line));
$hash[ \"nic\"]=ereg_replace( \".+\\((.+)\\).+\", \"\\\\1\", $line);
$hash[ \"email\"]=trim(ereg_replace( \".+\\)[[:space:]]+(.+)\", \"\\\\1\", $line));
return($hash);
}
// parses an array with zone info into the package variables for e-z access
function parsezone ($array) {
if(!$array || !$this->FOUND || $this->ERROR):
return( \"\");
endif;
// alas, we need to blow through this array twice, the
// first time to determine a few things
$lookahead=0;
$dis_start=0;
$dis_stop=0;
while($lookahead<count($array)):
// at what point will we stop assuming input
// gets added to $this->ORG_ADDRESS
if(ereg( \"Domain Name: .+\",$array[$lookahead])):
$dline=$lookahead;
elseif(ereg( \"Registrant:\", $array[$lookahead])):
$dis_stop=$lookahead-1;
elseif(ereg( \"To single out one record\", $array[$lookahead])):
$this->FOUND++;
endif;
$lookahead++;
endwhile;
$i=0;
while($i<count($array)):
if($this->FOUND==1):
if(ereg( \"Registrant:\", $array[$i])):
$i++;
list($this->ORGANIZATION,$this->ORG_HANDLE)=split( \"\\(\",$array[$i],2);
$this->ORGANIZATION = trim($this->ORGANIZATION);
$this->ORG_HANDLE=ereg_replace( \"\\)$\", \"\",trim($this->ORG_HANDLE));
$bline=$i;
elseif($i>dis_start && $i<$dis_stop):
$this->DISCLAIMER[]=$array[$i];
elseif($i>bline && $i<$dline):
$x1 = trim($array[$i]);
if ($x1):
$this->ORG_ADDRESS[] = $x1;
endif;
elseif(ereg( \"Domain Name: .+\", $array[$i])):
$x1 = ereg_replace( \"Domain Name: (.+$)\", \"\\\\1\",$array[$i]);
$this->DOMAIN_NAME = trim($x1);
elseif(ereg( \"Domain Status: .+\", $array[$i])):
$this->DOMAIN_STATUS=ereg_replace( \"Domain Status: (.+$)\", \"\\\\1\",$array[$i]);
elseif(ereg( \"Record last updated on\",$array[$i])):
$x1 = ereg_replace( \"Record last updated on (.+$)\", \"\\\\1\",$array[$i]);
$this->UPDATED = ereg_replace( \"\\.$\", \"\", trim($x1));
elseif(ereg( \"Record created on\",$array[$i])):
$this->CREATED=ereg_replace( \"Record created on (.+$)\", \"\\\\1\",$array[$i]);
elseif(ereg( \"Domain servers in listed order:\",$array[$i])):
$i++;
while($i<count($array)):
$i++;
if(ereg( \".+\\..+\\..+[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+\", $array[$i])):
list($x1,$x2) = split( \"(\\20|\\t)+\",$array[$i],2);
$this->DNS_NAME[] = trim($x1);
$this->DNS_IP[] = trim($x2);
endif;
endwhile;
endif;
// looks like we can\'t use backreferences outside the
// regex functions they\'re used in, so we\'re kinda
// stuck here and have to put these checks
// outside the above switch. (cause two or more
// of these could appear on the same line)
if(ereg( \"Administrative Contact\",$array[$i])):
$this->ADMIN=$this->parse_contact_line($array[$i+1]);
endif;
if(ereg( \"Technical Contact\",$array[$i])):
$this->TECH=$this->parse_contact_line($array[$i+1]);
endif;
if(ereg( \"Zone Contact\",$array[$i])):
$this->ZONE=$this->parse_contact_line($array[$i+1]);
endif;
if(ereg( \"Billing Contact\",$array[$i])):
$this->BILLING=$this->parse_contact_line($array[$i+1]);
endif;
else:
if(ereg( \".+\\(.+\\).+\", $array[$i])):
$this->HANDLES[]=ereg_replace( \".+\\((.+)\\).+\", \"\\\\1\",$array[$i]);
$this->FOUND++;
endif;
endif;
$i++;
endwhile;
// we still get spurious blank results, so we\'ll check that
// the nic handles aren\'t null and set $this->ERROR if they are
if(!count($this->ADMIN) || !count($this->TECH)) { $this->ERROR++; }
}
// gets the registry/registrar info now that .com/.net/.org has a
// sahred registry
function getRegInfo ($query) {
$old_type = $this->QUERY_TYPE;
$this->QUERY_TYPE= \"registrar\";
$raw_reg_info=$this->rawlookup($query);
$this->QUERY_TYPE=$old_type;
return($this->parseRegInfo($raw_reg_info));
}
function parseRegInfo ($array) {
for($i=0,$max=count($array);$i<$max;$i++) {
reset($this->REG_FIELDS);
while(list($key,$val)=each($this->REG_FIELDS)):
list($f_name,$f_val)=split( \":\", $array[$i]);
if($val==trim($f_name)) {
if($key== \"nameserver\") {
$ret_val[$key][]=trim($f_val);
} else {
$ret_val[$key]=trim($f_val);
}
break;
}
endwhile;
}
return($ret_val);
}
// does rawlookup() and passes the resultant array to parsezone()
function zonelookup ($query) {
if($this->use_cache):
$rawinfo = $this->cache_lookup(strtolower(trim($query)));
if($this->FOUND && !$this->FROM_CACHE && !$this->HANDLES):
$this->cache_write($query, $rawinfo);
endif;
else:
$this->REG_INFO = $this->getRegInfo($query);
if(!empty($this->REG_INFO[whois])) {
$this->DEFAULT_SERVER=$this->REG_INFO[whois];
}
$this->RAWINFO = $this->rawlookup($query);
endif;
if($this->FOUND):
$this->parsezone($this->RAWINFO);
endif;
}
function cache_lookup ($query) {
$cache_file = $this->cache_dir . \"/\". $query;
if(file_exists($cache_file)):
$this->FROM_CACHE=1;
$this->FOUND=1;
return(file($cache_file));
else:
$rawinfo = $this->rawlookup($query);
if(!$this->ERROR && $this->FOUND):
return($rawinfo);
endif;
endif;
}
function cache_write ($query, $rawinfo) {
$fp = fopen( \"$this->cache_dir/$query\", \"w\");
for($i=0,$num=count($rawinfo);$i<$num;$i++) {
fputs($fp, $rawinfo[$i]);
}
}
function dns_lookup($query) {
return checkdnsrr($query, \"NS\");
}
};
?>
Det er nok det beste :) funder på:
http://www.shmooze.net/~markjr/whois/