phpWhois.org/src/whois.parser.php

887 lines
22 KiB
PHP

<?php
/*
Whois.php PHP classes to conduct whois queries
Copyright (C)1999,2005 easyDNS Technologies Inc. & Mark Jeftovic
Maintained by David Saez
For the most recent version of this package visit:
http://www.phpwhois.org
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//-------------------------------------------------------------------------
function generic_parser_a ($rawdata, $translate, $contacts, $main='domain', $dateformat='dmy')
{
$blocks = generic_parser_a_blocks($rawdata,$translate,$disclaimer);
if (isset($disclaimer) && is_array($disclaimer))
$ret['disclaimer']=$disclaimer;
if (empty($blocks) || !is_array($blocks['main']))
{
$ret['registered']='no';
return $ret;
}
$r = $blocks['main'];
$ret['registered'] = 'yes';
foreach ($contacts as $key => $val)
if (isset($r[$key]))
{
if (is_array($r[$key]))
$blk = $r[$key][count($r[$key])-1];
else
$blk = $r[$key];
$blk = strtoupper(strtok($blk,' '));
if (isset($blocks[$blk])) $ret[$val] = $blocks[$blk];
unset($r[$key]);
}
if ($main) $ret[$main] = $r;
format_dates($ret,$dateformat);
return $ret;
}
//-------------------------------------------------------------------------
function generic_parser_a_blocks ($rawdata, $translate, &$disclaimer)
{
$r = array();
$newblock = false;
$hasdata = false;
$block = array();
$blocks = false;
$gkey = 'main';
$dend = false;
foreach ($rawdata as $key => $val)
{
$val=trim($val);
if ($val != '' && ($val[0] == '%' || $val[0] == '#'))
{
if (!$dend) $disclaimer[]=trim(substr($val,1));
continue;
}
if ($val=='')
{
$newblock = true;
continue;
}
if ($newblock && $hasdata)
{
$blocks[$gkey] = $block;
$block = array();
$gkey = '';
}
$dend = true;
$newblock = false;
$k = trim(strtok($val,':'));
$v = trim(substr(strstr($val,':'),1));
if ($v == '') continue;
$hasdata = true;
if (isset($translate[$k]))
{
$k=$translate[$k];
if ($k=='') continue;
if (strstr($k,'.'))
{
$block = assign($block, $k, $v);
continue;
}
}
else $k=strtolower($k);
if ($k=='handle')
{
$v = strtok($v,' ');
$gkey = strtoupper($v);
}
if (isset($block[$k]) && is_array($block[$k]))
$block[$k][]=$v;
else
if (!isset($block[$k]) || $block[$k]=='')
$block[$k]=$v;
else
{
$x=$block[$k];
unset($block[$k]);
$block[$k][]=$x;
$block[$k][]=$v;
}
}
if ($hasdata) $blocks[$gkey]=$block;
return $blocks;
}
//-------------------------------------------------------------------------
function generic_parser_b ( $rawdata, $items = false, $dateformat='mdy', $hasreg=true, $scanall=false )
{
if (!$items)
$items = array(
'Domain Name:' => 'domain.name',
'Domain ID:' => 'domain.handle',
'Sponsoring Registrar:' => 'domain.sponsor',
'Registrar ID:' => 'domain.sponsor',
'Domain Status:' => 'domain.status.',
'Status:' => 'domain.status.',
'Name Server:' => 'domain.nserver.',
'Nameservers:' => 'domain.nserver.',
'Maintainer:' => 'domain.referer',
'Domain Registration Date:' => 'domain.created',
'Domain Create Date:' => 'domain.created',
'Domain Expiration Date:' => 'domain.expires',
'Domain Last Updated Date:' => 'domain.changed',
'Creation Date:' => 'domain.created',
'Last Modification Date:' => 'domain.changed',
'Expiration Date:' => 'domain.expires',
'Created On:' => 'domain.created',
'Last Updated On:' => 'domain.changed',
'Expiration Date:' => 'domain.expires',
'Registrant ID:' => 'owner.handle',
'Registrant Name:' => 'owner.name',
'Registrant Organization:' => 'owner.organization',
'Registrant Address:' => 'owner.address.street.',
'Registrant Address1:' => 'owner.address.street.',
'Registrant Address2:' => 'owner.address.street.',
'Registrant Street:' => 'owner.address.street.',
'Registrant Street1:' => 'owner.address.street.',
'Registrant Street2:' => 'owner.address.street.',
'Registrant Street3:' => 'owner.address.street.',
'Registrant Postal Code:' => 'owner.address.pcode',
'Registrant City:' => 'owner.address.city',
'Registrant State/Province:' => 'owner.address.state',
'Registrant Country:' => 'owner.address.country',
'Registrant Country/Economy:' => 'owner.address.country',
'Registrant Phone Number:' => 'owner.phone',
'Registrant Phone:' => 'owner.phone',
'Registrant Facsimile Number:' => 'owner.fax',
'Registrant FAX:' => 'owner.fax',
'Registrant Email:' => 'owner.email',
'Registrant E-mail:' => 'owner.email',
'Administrative Contact ID:' => 'admin.handle',
'Administrative Contact Name:' => 'admin.name',
'Administrative Contact Organization:' => 'admin.organization',
'Administrative Contact Address:' => 'admin.address.street.',
'Administrative Contact Address1:' => 'admin.address.street.',
'Administrative Contact Address2:' => 'admin.address.street.',
'Administrative Contact Postal Code:' => 'admin.address.pcode',
'Administrative Contact City:' => 'admin.address.city',
'Administrative Contact State/Province:' => 'admin.address.state',
'Administrative Contact Country:' => 'admin.address.country',
'Administrative Contact Phone Number:' => 'admin.phone',
'Administrative Contact Email:' => 'admin.email',
'Administrative Contact Facsimile Number:' => 'admin.fax',
'Administrative Contact Tel:' => 'admin.phone',
'Administrative Contact Fax:' => 'admin.fax',
'Administrative ID:' => 'admin.handle',
'Administrative Name:' => 'admin.name',
'Administrative Organization:' => 'admin.organization',
'Administrative Address:' => 'admin.address.street.',
'Administrative Address1:' => 'admin.address.street.',
'Administrative Address2:' => 'admin.address.street.',
'Administrative Postal Code:' => 'admin.address.pcode',
'Administrative City:' => 'admin.address.city',
'Administrative State/Province:' => 'admin.address.state',
'Administrative Country/Economy:' => 'admin.address.country',
'Administrative Phone:' => 'admin.phone',
'Administrative E-mail:' => 'admin.email',
'Administrative Facsimile Number:' => 'admin.fax',
'Administrative Tel:' => 'admin.phone',
'Administrative FAX:' => 'admin.fax',
'Admin ID:' => 'admin.handle',
'Admin Name:' => 'admin.name',
'Admin Organization:' => 'admin.organization',
'Admin Street:' => 'admin.address.street.',
'Admin Street1:' => 'admin.address.street.',
'Admin Street2:' => 'admin.address.street.',
'Admin Street3:' => 'admin.address.street.',
'Admin Address:' => 'admin.address.street.',
'Admin Address2:' => 'admin.address.street.',
'Admin Address3:' => 'admin.address.street.',
'Admin City:' => 'admin.address.city',
'Admin State/Province:' => 'admin.address.state',
'Admin Postal Code:' => 'admin.address.pcode',
'Admin Country:' => 'admin.address.country',
'Admin Country/Economy:' => 'admin.address.country',
'Admin Phone:' => 'admin.phone',
'Admin FAX:' => 'admin.fax',
'Admin Email:' => 'admin.email',
'Admin E-mail:' => 'admin.email',
'Technical Contact ID:' => 'tech.handle',
'Technical Contact Name:' => 'tech.name',
'Technical Contact Organization:' => 'tech.organization',
'Technical Contact Address:' => 'tech.address.street.',
'Technical Contact Address1:' => 'tech.address.street.',
'Technical Contact Address2:' => 'tech.address.street.',
'Technical Contact Postal Code:' => 'tech.address.pcode',
'Technical Contact City:' => 'tech.address.city',
'Technical Contact State/Province:' => 'tech.address.state',
'Technical Contact Country:' => 'tech.address.country',
'Technical Contact Phone Number:' => 'tech.phone',
'Technical Contact Facsimile Number:' => 'tech.fax',
'Technical Contact Phone:' => 'tech.phone',
'Technical Contact Fax:' => 'tech.fax',
'Technical Contact Email:' => 'tech.email',
'Technical ID:' => 'tech.handle',
'Technical Name:' => 'tech.name',
'Technical Organization:' => 'tech.organization',
'Technical Address:' => 'tech.address.street.',
'Technical Address1:' => 'tech.address.street.',
'Technical Address2:' => 'tech.address.street.',
'Technical Postal Code:' => 'tech.address.pcode',
'Technical City:' => 'tech.address.city',
'Technical State/Province:' => 'tech.address.state',
'Technical Country/Economy:' => 'tech.address.country',
'Technical Phone Number:' => 'tech.phone',
'Technical Facsimile Number:' => 'tech.fax',
'Technical Phone:' => 'tech.phone',
'Technical Fax:' => 'tech.fax',
'Technical FAX:' => 'tech.fax',
'Technical E-mail:' => 'tech.email',
'Tech ID:' => 'tech.handle',
'Tech Name:' => 'tech.name',
'Tech Organization:' => 'tech.organization',
'Tech Address:' => 'tech.address.street.',
'Tech Address2:' => 'tech.address.street.',
'Tech Address3:' => 'tech.address.street.',
'Tech Street:' => 'tech.address.street.',
'Tech Street1:' => 'tech.address.street.',
'Tech Street2:' => 'tech.address.street.',
'Tech Street3:' => 'tech.address.street.',
'Tech City:' => 'tech.address.city',
'Tech Postal Code:' => 'tech.address.pcode',
'Tech State/Province:' => 'tech.address.state',
'Tech Country:' => 'tech.address.country',
'Tech Country/Economy:' => 'tech.address.country',
'Tech Phone:' => 'tech.phone',
'Tech FAX:' => 'tech.fax',
'Tech Email:' => 'tech.email',
'Tech E-mail:' => 'tech.email',
'Billing Contact ID:' => 'billing.handle',
'Billing Contact Name:' => 'billing.name',
'Billing Contact Organization:' => 'billing.organization',
'Billing Contact Address1:' => 'billing.address.street.',
'Billing Contact Address2:' => 'billing.address.street.',
'Billing Contact Postal Code:' => 'billing.address.pcode',
'Billing Contact City:' => 'billing.address.city',
'Billing Contact State/Province:' => 'billing.address.state',
'Billing Contact Country:' => 'billing.address.country',
'Billing Contact Phone Number:' => 'billing.phone',
'Billing Contact Facsimile Number:' => 'billing.fax',
'Billing Contact Email:' => 'billing.email',
'Billing ID:' => 'billing.handle',
'Billing Name:' => 'billing.name',
'Billing Organization:' => 'billing.organization',
'Billing Address:' => 'billing.address.street.',
'Billing Address1:' => 'billing.address.street.',
'Billing Address2:' => 'billing.address.street.',
'Billing Address3:' => 'billing.address.street.',
'Billing Street:' => 'billing.address.street.',
'Billing Street1:' => 'billing.address.street.',
'Billing Street2:' => 'billing.address.street.',
'Billing Street3:' => 'billing.address.street.',
'Billing City:' => 'billing.address.city',
'Billing Postal Code:' => 'billing.address.pcode',
'Billing State/Province:' => 'billing.address.state',
'Billing Country:' => 'billing.address.country',
'Billing Country/Economy:' => 'billing.address.country',
'Billing Phone:' => 'billing.phone',
'Billing Fax:' => 'billing.fax',
'Billing FAX:' => 'billing.fax',
'Billing Email:' => 'billing.email',
'Billing E-mail:' => 'billing.email',
'Zone ID:' => 'zone.handle',
'Zone Organization:' => 'zone.organization',
'Zone Name:' => 'zone.name',
'Zone Address:' => 'zone.address.street.',
'Zone Address 2:' => 'zone.address.street.',
'Zone City:' => 'zone.address.city',
'Zone State/Province:' => 'zone.address.state',
'Zone Postal Code:' => 'zone.address.pcode',
'Zone Country:' => 'zone.address.country',
'Zone Phone Number:' => 'zone.phone',
'Zone Fax Number:' => 'zone.fax',
'Zone Email:' => 'zone.email'
);
$r = [];
$disok = true;
foreach ($rawdata as $key => $val)
{
if (trim($val) != '')
{
if (($val[0]=='%' || $val[0]=='#') && $disok)
{
$r['disclaimer'][] = trim(substr($val,1));
$disok = true;
continue;
}
$disok = false;
reset($items);
foreach ($items as $match => $field)
{
$pos = strpos($val,$match);
if ($pos !== false)
{
if ($field != '')
{
$itm = trim(substr($val,$pos+strlen($match)));
if ($itm != '')
{
$r = assign($r,$field,str_replace('"','\"',$itm));
}
}
if (!$scanall)
break;
}
}
}
}
if (empty($r))
{
if ($hasreg) $r['registered'] = 'no';
}
else
{
if ($hasreg) $r['registered'] = 'yes';
$r = format_dates($r, $dateformat);
}
return $r;
}
//-------------------------------------------------------------------------
function assign_recursive($array, $parts, $value)
{
$key = array_shift($parts);
if (count($parts) == 0)
{
if (!$key) $array[] = $value;
else $array[$key] = $value;
}
else
{
if (!isset($array[$key])) $array[$key] = [];
$array[$key] = assign_recursive($array[$key], $parts, $value);
}
return $array;
}
//-------------------------------------------------------------------------
function assign($array, $vdef, $value)
{
return assign_recursive($array, explode('.', $vdef), $value);
}
//-------------------------------------------------------------------------
function get_blocks ( $rawdata, $items, $partial_match = false, $def_block = false )
{
$r = array();
$endtag = '';
foreach ($rawdata as $key => $val)
{
$val = trim($val);
if ($val == '') continue;
$var = $found = false;
foreach ($items as $field => $match)
{
$pos = strpos($val,$match);
if ($field != '' && $pos !== false)
{
if ($val == $match)
{
$found = true;
$endtag = '';
$line = $val;
break;
}
$last = substr($val,-1,1);
if ($last == ':' || $last == '-' || $last == ']')
{
$found = true;
$endtag = $last;
$line = $val;
}
else
{
$r = assign($r, strtok($field,'#'), trim(substr($val,$pos+strlen($match))));
}
break;
}
}
if (!$found)
{
if (!$var && $def_block) $r[$def_block][] = $val;
continue;
}
$block = array();
// Block found, get data ...
foreach ($rawdata as $key => $val)
{
$val = trim($val);
if ($val == '' || $val == str_repeat($val[0],strlen($val))) continue;
$last = substr($val,-1,1);
/*
if ($last == $endtag)
{
// Another block found
prev($rawdata);
break;
}
if ($endtag == '' || $partial_match)
*/
if ($endtag == '' || $partial_match || $last == $endtag)
{
//Check if this line starts another block
$et = false;
foreach ($items as $field => $match)
{
$pos = strpos($val,$match);
if ($pos !== false && $pos == 0)
{
$et = true;
break;
}
}
if ($et)
{
// Another block found
prev($rawdata);
break;
}
}
$block[] = $val;
}
if (empty($block)) continue;
foreach ($items as $field => $match)
{
$pos = strpos($line,$match);
if ($pos !== false)
{
$var = strtok($field,'#');
if ($var != '')
{
$r = assign($r, $var, $block);
}
}
}
}
return $r;
}
//-------------------------------------------------------------------------
function easy_parser($data_str, $items, $date_format, $translate = false ,
$has_org = false, $partial_match = false,
$def_block = false )
{
$r = get_blocks($data_str, $items, $partial_match, $def_block);
$r = get_contacts($r, $translate, $has_org);
format_dates($r, $date_format);
return $r;
}
//-------------------------------------------------------------------------
function get_contacts ( $array, $extra_items='', $has_org= false )
{
if (isset($array['billing']))
$array['billing'] = get_contact($array['billing'], $extra_items, $has_org);
if (isset($array['tech']))
$array['tech'] = get_contact($array['tech'], $extra_items, $has_org);
if (isset($array['zone']))
$array['zone'] = get_contact($array['zone'], $extra_items, $has_org);
if (isset($array['admin']))
$array['admin'] = get_contact($array['admin'], $extra_items, $has_org);
if (isset($array['owner']))
$array['owner'] = get_contact($array['owner'], $extra_items, $has_org);
if (isset($array['registrar']))
$array['registrar'] = get_contact($array['registrar'], $extra_items, $has_org);
return $array;
}
//-------------------------------------------------------------------------
function get_contact ( $array, $extra_items='', $has_org= false )
{
if (!is_array($array))
return array();
$items = array (
'fax..:' => 'fax',
'fax.' => 'fax',
'fax-no:' => 'fax',
'fax -' => 'fax',
'fax-' => 'fax',
'fax::' => 'fax',
'fax:' => 'fax',
'[fax]' => 'fax',
'(fax)' => 'fax',
'fax' => 'fax',
'tel. ' => 'phone',
'tel:' => 'phone',
'phone::' => 'phone',
'phone:' => 'phone',
'phone-' => 'phone',
'phone -' => 'phone',
'email:' => 'email',
'e-mail:' => 'email',
'company name:' => 'organization',
'organisation:' => 'organization',
'first name:' => 'name.first',
'last name:' => 'name.last',
'street:' => 'address.street',
'address:' => 'address.street.',
'language:' => '',
'location:' => 'address.city',
'country:' => 'address.country',
'name:' => 'name',
'last modified:' => 'changed'
);
if ($extra_items)
{
foreach($items as $match => $field)
if (!isset($extra_items[$match]))
$extra_items[$match] = $field;
$items = $extra_items;
}
foreach ($array as $key => $val)
{
$ok=true;
while ($ok)
{
reset($items);
$ok = false;
foreach ($items as $match => $field)
{
$pos = strpos(strtolower($val),$match);
if ($pos === false) continue;
$itm = trim(substr($val,$pos+strlen($match)));
if ($field != '' && $itm != '')
{
$r = assign($r, $field, $itm);
}
$val = trim(substr($val,0,$pos));
if ($val == '')
{
unset($array[$key]);
break;
}
else
{
$array[$key] = $val;
$ok = true;
}
//break;
}
if (preg_match("/([+]*[-\(\)\. x0-9]){7,}/", $val, $matches))
{
$phone = trim(str_replace(' ','',$matches[0]));
if (strlen($phone) > 8 && !preg_match('/[0-9]{5}\-[0-9]{3}/',$phone))
{
if (isset($r['phone']))
{
if (isset($r['fax'])) continue;
$r['fax'] = trim($matches[0]);
}
else
{
$r['phone'] = trim($matches[0]);
}
$val = str_replace($matches[0],'',$val);
if ($val == '')
{
unset($array[$key]);
continue;
}
else
{
$array[$key] = $val;
$ok = true;
}
}
}
if (preg_match('/([-0-9a-zA-Z._+&\/=]+@([-0-9a-zA-Z]+[.])+[a-zA-Z]{2,6})/',$val, $matches))
{
$r['email'] = $matches[0];
$val = str_replace($matches[0],'',$val);
$val = trim(str_replace('()','',$val));
if ($val == '')
{
unset($array[$key]);
continue;
}
else
{
if (!isset($r['name']))
{
$r['name'] = $val;
unset($array[$key]);
}
else
$array[$key] = $val;
$ok = true;
}
}
}
}
if (!isset($r['name']) && count($array)>0)
{
$r['name'] = array_shift($array);
}
if ($has_org && count($array)>0)
{
$r['organization'] = array_shift($array);
}
if (isset($r['name']) && is_array($r['name']))
{
$r['name'] = implode($r['name'],' ');
}
if (!empty($array))
{
if (isset($r['address']))
$r['address'] = array_merge($r['address'],$array);
else
$r['address'] = $array;
}
return $r;
}
//-------------------------------------------------------------------------
function format_dates (&$res,$format='mdy')
{
if (!is_array($res)) return $res;
foreach ($res as $key => $val)
{
if (is_array($val))
{
if (!is_numeric($key) && ($key=='expires' || $key=='created' || $key=='changed'))
{
$d = get_date($val[0],$format);
if ($d) $res[$key] = $d;
}
else
{
$res[$key] = format_dates($val,$format);
}
}
else
{
if (!is_numeric($key) && ($key=='expires' || $key=='created' || $key=='changed'))
{
$d = get_date($val,$format);
if ($d) $res[$key] = $d;
}
}
}
return $res;
}
//-------------------------------------------------------------------------
function get_date($date,$format)
{
$months = array( 'jan'=>1, 'ene'=>1, 'feb'=>2, 'mar'=>3, 'apr'=>4, 'abr'=>4,
'may'=>5, 'jun'=>6, 'jul'=>7, 'aug'=>8, 'ago'=>8, 'sep'=>9,
'oct'=>10, 'nov'=>11, 'dec'=>12, 'dic'=>12 );
$parts = explode(' ',$date);
if (strpos($parts[0],'@') !== false)
{
unset($parts[0]);
$date = implode(' ',$parts);
}
$date = str_replace(',',' ',trim($date));
$date = str_replace('.',' ',$date);
$date = str_replace('-',' ',$date);
$date = str_replace('/',' ',$date);
$date = str_replace("\t",' ',$date);
$parts = explode(' ',$date);
$res = [];
if ((strlen($parts[0]) == 8 || count($parts) == 1) && is_numeric($parts[0]))
{
$val = $parts[0];
for ($p=$i=0; $i<3; $i++)
{
if ($format[$i] != 'Y')
{
$res[$format[$i]] = substr($val,$p,2);
$p += 2;
}
else
{
$res['y'] = substr($val,$p,4);
$p += 4;
}
}
}
else
{
$format = strtolower($format);
for ($p=$i=0; $p<count($parts) && $i<strlen($format); $p++)
{
if (trim($parts[$p]) == '')
continue;
if ($format[$i] != '-')
{
$res[$format[$i]] = $parts[$p];
}
$i++;
}
}
if (empty($res)) return $date;
$ok = false;
while (!$ok)
{
reset($res);
$ok = true;
foreach ($res as $key => $val)
{
if ($val == '' || $key == '') continue;
if (!is_numeric($val) && isset($months[substr(strtolower($val),0,3)]))
{
$res[$key] = $res['m'];
$res['m'] = $months[substr(strtolower($val),0,3)];
$ok = false;
break;
}
if ($key != 'y' && $key != 'Y' && $val > 1900)
{
$res[$key] = $res['y'];
$res['y'] = $val;
$ok = false;
break;
}
}
}
if ($res['m'] > 12)
{
$v = $res['m'];
$res['m'] = $res['d'];
$res['d'] = $v;
}
if ($res['y'] < 70)
$res['y'] += 2000;
else
if ($res['y'] <= 99)
$res['y'] += 1900;
return sprintf("%.4d-%02d-%02d",$res['y'],$res['m'],$res['d']);
}