lookup($domain, $usecache); } return $checkzone_obj; } // End of function checkzone // This works similar to array_intersect_key, but uses regexps in the second array // I initially used array_intersect_ukey with a callback function, but // for some reason that was behaving erroneously function array_intersect_ekey($haystack, $needles) { foreach($haystack as $payload => $value) { // Test this twig against the regexps in $needles foreach($needles as $pattern => $noop) { $matches = preg_match($pattern, $payload); if($matches == 1) { $intersect[$payload] = $value; } } } if(empty($intersect)) $intersect = array(); return $intersect; } // End of function array_intersect_ekey function get_array_intersect_entry($haystack, $needles) { $intersect = array_intersect_ekey($haystack, $needles); //$entry = current(array_values($intersect)); foreach($intersect as $member) { foreach($member as $particle) { $entry[] = $particle; } } if(empty($entry)) { $entry = array(); } return $entry; } // Test purposes only if(false) { $pattern = "/^Technical Contact (?!ID).+$/"; $payload = "Technical Contact Pass ID"; echo "$pattern <-> $payload == "; echo preg_match($pattern, $payload); die; } /* Class zonecheck */ class zonecheck { var $domain; var $debug; var $tld; var $info = array(); var $meta = array(); var $ns = array(); var $parseddomain; var $registrar; var $rsp; var $registrant; var $admincontact; var $techcontact; var $ns_ns = array(); var $ns_mx = array(); // Definition of array matrices to intercept keys // This array has all tokens that we have seen to contain domain name data var $tokens_domain = array( "/^Domain$/" => 0, "/^Domain name$/i" => 0, "/^Domain Name \(ASCII\)$/i" => 0); // This array has all tokens that we have seen to contain nameserver data var $tokens_ns = array( "/^Domain nameservers$/" => 0, "/^Domain servers in listed order$/" => 0, "/^Nserver$/" => 0, "/^Nameserver(s)?$/" => 0, "/^Name Server$/" => 0); // This array has all tokens that we have seen to contain registrant data var $tokens_registrant = array( "/^Registrars\.Registrant$/" => 0, "/^Registrant (?!ID).+$/" => 0, "/^Holder (?!ID).+$/" => 0, "/^Registrant$/" => 0); // This array has all tokens that we have seen to contain registrar data var $tokens_registrar = array( "/^Sponsoring Registrar$/" => 0, "/^Zone-C (?!ID).+$/" => 0, "/^Registrar$/" => 0); // This array has all tokens that we have seen to contain admin contact data var $tokens_admincontact = array( "/^Administrative Contact (?!ID).+$/" => 0, "/^Administrative Contact,/" => 0, "/^Admin(-C)? (?!ID).+$/" => 0, "/^Administrative Contact$/i" => 0); // This array has all tokens that we have seen to contain tech contact data var $tokens_techcontact = array( "/^Technical Contact,/" => 0, "/^.+Technical Contact$/" => 0, "/^Technical Contact (?!ID).+$/" => 0, "/^Tech(-C)? (?!ID).+$/" => 0, "/^Technical contact(?:\(s\))?$/i" => 0); // This array has all tokens that we have seen to contain rsp data var $tokens_rsp = array( "/^Registration Service Provider$/" => 0); // Constructor function zonecheck($domainname, $usecache=true, $debug=false) { $this->debug = $debug; return $this->lookup($domainname, $usecache, $debug); } // End function zonecheck (Constructor) function debug($debugtext) { if($this->debug) echo $this->domain.": ".$debugtext."\n"; } // End of function debug function lookup($domainname, $usecache=true, $debug=false) { $this->debug = $debug; $this->domain = $domainname; $this->tld = substr($this->domain, strrpos($this->domain, ".")); $this->info = array(); $this->meta = array(); $this->ns = array(); $this->parseddomain = ""; $this->registrar = ""; $this->rsp = ""; $this->registrant = ""; $this->admincontact = ""; $this->techcontact = ""; $this->ns_ns = array(); $this->ns_mx = array(); // Check cache $cached = false; $cachefilename = CACHEDIR."/".$domainname.".txt"; if($usecache) { if(file_exists($cachefilename)) { $this->debug("found cached in file $cachefilename"); if((time()-filemtime($cachefilename)) < CACHEEXPIRE) { $this->debug("accepted cached file $cachefilename"); $this->info = file($cachefilename); $cached = true; } else { $this->debug("expired cached file $cachefilename"); } } } else { $this->debug("cache not used by request"); } if(!$cached) { $this->debug("performing whois query"); // Get the raw data $args = ""; switch($this->tld) { case ".me": $args = "-h whois.nic.me"; break; } $cmd = "whois $args $domainname"; $retcode = exec($cmd, $this->info); } // Normalize the array and save to cache if needed for($line=0; $lineinfo); $line++) { $this->info[$line] = trim($this->info[$line]); } if(!$cached && is_writable(CACHEDIR)) { $cachefp = fopen($cachefilename, 'w'); if($cachefp !== false) { for($line=0; $lineinfo); $line++) { fwrite($cachefp, $this->info[$line]."\r\n"); } fclose($cachefp); } } // Parse more intelligent stuff $this->enkey_data(); $this->compose_members(); $this->extract_registrar(); $this->extract_domainname(); $this->extract_nameservers(); $this->extract_registrant(); $this->extract_admincontact(); $this->extract_techcontact(); $this->extract_rsp(); $this->nslookup(); } // End function lookup function enkey_data() { $key = "general"; $initoken = ""; $this->debug("building key/value array"); // Basically a simple state machine that parses the whois output for($line=0; $lineinfo); $line++) { // Check if this is an INI-style whois line if((substr($this->info[$line],0,1) == "[") && (substr($this->info[$line],-1,1) == "]")) { // INI-style formatting found (like .de domain) $initoken = substr($this->info[$line],1,strlen($this->info[$line])-2); } // Locate the first : in line $tokenpos = strpos($this->info[$line], ":"); if($tokenpos !== false) { // Don't count it if it is part of something generic $contextpos = strpos($this->info[$line], "http://"); if($contextpos !== false && $contextpos == $tokenpos-4) $tokenpos = false; $contextpos = strpos($this->info[$line], "Last update of whois database:"); if($contextpos !== false && $contextpos == $tokenpos-29) $tokenpos = false; $contextpos = strpos($this->info[$line], "to: (1) allow"); if($contextpos !== false && $contextpos == $tokenpos-2) $tokenpos = false; $contextpos = strpos($this->info[$line], "terms of use: You agree"); if($contextpos !== false && $contextpos == $tokenpos-12) $tokenpos = false; $contextpos = strpos($this->info[$line], "NOTICE: The expiration"); if($contextpos !== false && $contextpos == $tokenpos-6) $tokenpos = false; $contextpos = strpos($this->info[$line], "TERMS OF USE: You are not"); if($contextpos !== false && $contextpos == $tokenpos-12) $tokenpos = false; $contextpos = strpos($this->info[$line], "NOTE: THE WHOIS DATABASE"); if($contextpos !== false && $contextpos == $tokenpos-4) $tokenpos = false; $contextpos = strpos($this->info[$line], "under no circumstances will you use this data to:"); if($contextpos !== false && $contextpos == $tokenpos-48) $tokenpos = false; $contextpos = strpos($this->info[$line], "% Version: "); if($contextpos !== false && $contextpos == $tokenpos-9) $tokenpos = false; } // Split key/value pairs if($tokenpos === false) { // No key in this line, so use the previous key $value = trim($this->info[$line]); if($value == "") { // Empty lines reset the key and inittoken $key = "general"; $initoken = ""; } else { $this->meta[$key][] = $value; } } else { // Key in line, so split the parts $key = trim(substr($this->info[$line], 0, strpos($this->info[$line], ":"))); if($initoken != "") $key = "$initoken $key"; $value = trim(substr($this->info[$line], strpos($this->info[$line], ":")+1)); if($value != "") { // Don't care about superfluous empty lines $this->meta[$key][] = $value; } } } // Clean up metadata we really don't need again unset($this->meta["general"]); } // End function build_array function compose_members() { // For .info: switch($this->tld) { case ".info": $this->meta["Registrant"][] = $this->meta["Registrant ID"]; $this->meta["Registrant"][] = $this->meta["Registrant Name"]; $this->meta["Registrant"][] = $this->meta["Registrant Organisation"]; $this->meta["Registrant"][] = $this->meta["Registrant Address1"]; $this->meta["Administrative Contact"][] = $this->meta["Administrative Contact ID"]; $this->meta["Administrative Contact"][] = $this->meta["Administrative Contact Name"]; } } function extract_nameservers() { $this->debug("locating nameserver info"); $this->ns=get_array_intersect_entry($this->meta, $this->tokens_ns); for($i=0; $ins); $i++) { if(strpos($this->ns[$i], " ") !== false) { $this->ns[$i] = substr($this->ns[$i], 0, strpos($this->ns[$i], " ")); } } sort($this->ns); } // End function extract_nameservers function extract_registrant() { $this->debug("locating registrant info"); $this->registrant=implode("\n", get_array_intersect_entry($this->meta, $this->tokens_registrant)); } // End function extract_registrant function extract_admincontact() { $this->debug("locating admin contact info"); $this->admincontact=implode("\n", get_array_intersect_entry($this->meta, $this->tokens_admincontact)); } // End function extract_admincontact function extract_techcontact() { $this->debug("locating tech contact info"); $this->techcontact=implode("\n", get_array_intersect_entry($this->meta, $this->tokens_techcontact)); } // End function extract_techcontact function extract_domainname() { $this->debug("locating domainname info"); $this->parseddomain=implode("\n", array_unique(get_array_intersect_entry($this->meta, $this->tokens_domain))); } // End function extract_domainname function extract_registrar() { $this->debug("locating registrar info"); $this->registrar=implode("\n", get_array_intersect_entry($this->meta, $this->tokens_registrar)); } // End function extract_registrar function extract_rsp() { $this->debug("locating registration service provider info"); $this->rsp=implode("\n", get_array_intersect_entry($this->meta, $this->tokens_rsp)); } // End function extract_rsp function nslookup() { // $ttl = array(); // $ns = array(); $this->ns_mx = dns_get_record($this->domain, DNS_MX, $ns, $ttl); echo "
";
var_dump($ns);
var_dump($this->ns_mx);
echo "
"; } // End function nslookup_ns } ?>