initial commit to mercurial
authorRichard Baron Penman
Wed, 19 Oct 2011 17:09:00 +0900
changeset 0 ea0e45971cea
child 1 41781274f1e9
initial commit to mercurial
pywhois/__init__.py
pywhois/parser.py
pywhois/whois.py
setup.py
test/samples/expected/digg.com
test/samples/expected/google.com
test/samples/expected/imdb.com
test/samples/expected/microsoft.com
test/samples/expected/reddit.com
test/samples/expected/urlowl.com
test/samples/whois/digg.com
test/samples/whois/google.com
test/samples/whois/imdb.com
test/samples/whois/microsoft.com
test/samples/whois/reddit.com
test/samples/whois/shazow.net
test/samples/whois/slashdot.org
test/samples/whois/squatter.net
test/samples/whois/urlowl.com
test/test_parser.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pywhois/__init__.py	Wed Oct 19 17:09:00 2011 +0900
@@ -0,0 +1,44 @@
+import re
+import sys
+import subprocess
+from parser import WhoisEntry
+from whois import NICClient
+
+
+def whois(url):
+    # clean domain to expose netloc
+    domain = extract_domain(url)
+    try:
+        # try native whois command first
+        r = subprocess.Popen(['whois', domain], stdout=subprocess.PIPE)
+        text = r.stdout.read()
+    except OSError:
+        # try experimental client
+        nic_client = NICClient()
+        text = nic_client.whois_lookup(None, domain, 0)
+    return WhoisEntry.load(domain, text)
+
+def extract_domain(url):
+    """Extract the domain from the given URL
+
+    >>> extract_domain('http://www.google.com.au/tos.html')
+    'google.com.au'
+    """
+    suffixes = 'ac', 'ad', 'ae', 'aero', 'af', 'ag', 'ai', 'al', 'am', 'an', 'ao', 'aq', 'ar', 'arpa', 'as', 'asia', 'at', 'au', 'aw', 'ax', 'az', 'ba', 'bb', 'bd', 'be', 'bf', 'bg', 'bh', 'bi', 'biz', 'bj', 'bm', 'bn', 'bo', 'br', 'bs', 'bt', 'bv', 'bw', 'by', 'bz', 'ca', 'cat', 'cc', 'cd', 'cf', 'cg', 'ch', 'ci', 'ck', 'cl', 'cm', 'cn', 'co', 'com', 'coop', 'cr', 'cu', 'cv', 'cx', 'cy', 'cz', 'de', 'dj', 'dk', 'dm', 'do', 'dz', 'ec', 'edu', 'ee', 'eg', 'er', 'es', 'et', 'eu', 'fi', 'fj', 'fk', 'fm', 'fo', 'fr', 'ga', 'gb', 'gd', 'ge', 'gf', 'gg', 'gh', 'gi', 'gl', 'gm', 'gn', 'gov', 'gp', 'gq', 'gr', 'gs', 'gt', 'gu', 'gw', 'gy', 'hk', 'hm', 'hn', 'hr', 'ht', 'hu', 'id', 'ie', 'il', 'im', 'in', 'info', 'int', 'io', 'iq', 'ir', 'is', 'it', 'je', 'jm', 'jo', 'jobs', 'jp', 'ke', 'kg', 'kh', 'ki', 'km', 'kn', 'kp', 'kr', 'kw', 'ky', 'kz', 'la', 'lb', 'lc', 'li', 'lk', 'lr', 'ls', 'lt', 'lu', 'lv', 'ly', 'ma', 'mc', 'md', 'me', 'mg', 'mh', 'mil', 'mk', 'ml', 'mm', 'mn', 'mo', 'mobi', 'mp', 'mq', 'mr', 'ms', 'mt', 'mu', 'mv', 'mw', 'mx', 'my', 'mz', 'na', 'name', 'nc', 'ne', 'net', 'nf', 'ng', 'ni', 'nl', 'no', 'np', 'nr', 'nu', 'nz', 'om', 'org', 'pa', 'pe', 'pf', 'pg', 'ph', 'pk', 'pl', 'pm', 'pn', 'pr', 'pro', 'ps', 'pt', 'pw', 'py', 'qa', 're', 'ro', 'rs', 'ru', 'rw', 'sa', 'sb', 'sc', 'sd', 'se', 'sg', 'sh', 'si', 'sj', 'sk', 'sl', 'sm', 'sn', 'so', 'sr', 'st', 'su', 'sv', 'sy', 'sz', 'tc', 'td', 'tel', 'tf', 'tg', 'th', 'tj', 'tk', 'tl', 'tm', 'tn', 'to', 'tp', 'tr', 'tt', 'tv', 'tw', 'tz', 'ua', 'ug', 'uk', 'us', 'uy', 'uz', 'va', 'vc', 've', 'vg', 'vi', 'vn', 'vu', 'wf', 'ws', 'xn', 'ye', 'yt', 'za', 'zm', 'zw'
+    url = re.sub('^.*://', '', url).split('/')[0].lower()
+    domain = []
+    for section in url.split('.'):
+        if section in suffixes:
+            domain.append(section)
+        else:
+            domain = [section]
+    return '.'.join(domain)
+
+
+if __name__ == '__main__':
+    try:
+        url = sys.argv[1]
+    except IndexError:
+        print 'Usage: %s url' % sys.argv[0]
+    else:
+        print whois(url)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pywhois/parser.py	Wed Oct 19 17:09:00 2011 +0900
@@ -0,0 +1,345 @@
+# parser.py - Module for parsing whois response data
+# Copyright (c) 2008 Andrey Petrov
+#
+# This module is part of pywhois and is released under
+# the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+import re
+import time
+   
+
+class PywhoisError(Exception):
+    pass
+
+
+def cast_date(date_str):
+    """Convert any date string found in WHOIS to a time object.
+    """
+    known_formats = [
+        '%d-%b-%Y', 				# 02-jan-2000
+        '%Y-%m-%d', 				# 2000-01-02
+        '%d-%b-%Y %H:%M:%S %Z',		# 24-Jul-2009 13:20:03 UTC
+        '%a %b %d %H:%M:%S %Z %Y',  # Tue Jun 21 23:59:59 GMT 2011
+        '%Y-%m-%dT%H:%M:%SZ',       # 2007-01-26T19:10:31Z
+    ]
+
+    for format in known_formats:
+        try:
+            return time.strptime(date_str.strip(), format)
+        except ValueError, e:
+            pass # Wrong format, keep trying
+    return None
+
+
+class WhoisEntry(object):
+    """Base class for parsing a Whois entries.
+    """
+    # regular expressions to extract domain data from whois profile
+    # child classes will override this
+    _regex = {
+        'domain_name':      'Domain Name:\s?(.+)',
+        'registrar':        'Registrar:\s?(.+)',
+        'whois_server':     'Whois Server:\s?(.+)',
+        'referral_url':     'Referral URL:\s?(.+)', # http url of whois_server
+        'updated_date':     'Updated Date:\s?(.+)',
+        'creation_date':    'Creation Date:\s?(.+)',
+        'expiration_date':  'Expiration Date:\s?(.+)',
+        'name_servers':     'Name Server:\s?(.+)', # list of name servers
+        'status':           'Status:\s?(.+)', # list of statuses
+        'emails':           '[\w.-]+@[\w.-]+\.[\w]{2,4}', # list of email addresses
+    }
+
+    def __init__(self, domain, text, regex=None):
+        self.domain = domain
+        self.text = text
+        if regex is not None:
+            self._regex = regex
+
+
+    def __getattr__(self, attr):
+        """The first time an attribute is called it will be calculated here.
+        The attribute is then set to be accessed directly by subsequent calls.
+        """
+        whois_regex = self._regex.get(attr)
+        if whois_regex:
+            setattr(self, attr, re.findall(whois_regex, self.text))
+            return getattr(self, attr)
+        else:
+            raise KeyError('Unknown attribute: %s' % attr)
+
+    def __str__(self):
+        """Print all whois properties of domain
+        """
+        return '\n'.join('%s: %s' % (attr, str(getattr(self, attr))) for attr in self.attrs())
+
+
+    def attrs(self):
+        """Return list of attributes that can be extracted for this domain
+        """
+        return sorted(self._regex.keys())
+
+
+    @staticmethod
+    def load(domain, text):
+        """Given whois output in ``text``, return an instance of ``WhoisEntry`` that represents its parsed contents.
+        """
+        if text.strip() == 'No whois server is known for this kind of object.':
+            raise PywhoisError(text)
+
+        if '.com' in domain:
+            return WhoisCom(domain, text)
+        elif '.net' in domain:
+            return WhoisNet(domain, text)
+        elif '.org' in domain:
+            return WhoisOrg(domain, text)
+        elif '.ru' in domain:
+            return WhoisRu(domain, text)
+        elif '.name' in domain:
+        	return WhoisName(domain, text)
+        elif '.us' in domain:
+        	return WhoisUs(domain, text)
+        elif '.me' in domain:
+        	return WhoisMe(domain, text)
+        elif '.uk' in domain:
+        	return WhoisUk(domain, text)
+        else:
+            return WhoisEntry(domain, text)
+
+
+
+class WhoisCom(WhoisEntry):
+    """Whois parser for .com domains
+    """
+    def __init__(self, domain, text):
+        if 'No match for "' in text:
+            raise PywhoisError(text)
+        else:
+            WhoisEntry.__init__(self, domain, text) 
+
+class WhoisNet(WhoisEntry):
+    """Whois parser for .net domains
+    """
+    def __init__(self, domain, text):
+        if 'No match for "' in text:
+            raise PywhoisError(text)
+        else:
+            WhoisEntry.__init__(self, domain, text) 
+
+class WhoisOrg(WhoisEntry):
+    """Whois parser for .org domains
+    """
+    def __init__(self, domain, text):
+        if text.strip() == 'NOT FOUND':
+            raise PywhoisError(text)
+        else:
+            WhoisEntry.__init__(self, domain, text) 
+
+class WhoisRu(WhoisEntry):
+    """Whois parser for .ru domains
+    """
+    regex = {
+        'domain_name': 'domain:\s*(.+)',
+        'registrar': 'registrar:\s*(.+)',
+        'creation_date': 'created:\s*(.+)',
+        'expiration_date': 'paid-till:\s*(.+)',
+        'name_servers': 'nserver:\s*(.+)',  # list of name servers
+        'status': 'state:\s*(.+)',  # list of statuses
+        'emails': '[\w.-]+@[\w.-]+\.[\w]{2,4}',  # list of email addresses
+    }
+
+    def __init__(self, domain, text):
+        if text.strip() == 'No entries found':
+            raise PywhoisError(text)
+        else:
+            WhoisEntry.__init__(self, domain, text, self.regex)
+
+class WhoisName(WhoisEntry):
+    """Whois parser for .name domains
+    """
+    regex = {
+    	'domain_name_id':  'Domain Name ID:\s*(.+)',
+        'domain_name':     'Domain Name:\s*(.+)',
+        'registrar_id':    'Sponsoring Registrar ID:\s*(.+)',
+        'registrar':       'Sponsoring Registrar:\s*(.+)',
+        'registrant_id':   'Registrant ID:\s*(.+)',
+        'admin_id':        'Admin ID:\s*(.+)',
+        'technical_id':    'Tech ID:\s*(.+)',
+        'billing_id':      'Billing ID:\s*(.+)',
+        'creation_date':   'Created On:\s*(.+)',
+        'expiration_date': 'Expires On:\s*(.+)',
+        'updated_date':    'Updated On:\s*(.+)',
+        'name_server_ids': 'Name Server ID:\s*(.+)',  # list of name server ids
+        'name_servers':    'Name Server:\s*(.+)',  # list of name servers
+        'status':          'Domain Status:\s*(.+)',  # list of statuses
+	}
+    def __init__(self, domain, text):
+        if 'No match.' in text:
+            raise PywhoisError(text)
+        else:
+            WhoisEntry.__init__(self, domain, text, self.regex) 
+            
+class WhoisUs(WhoisEntry):
+    """Whois parser for .us domains
+    """
+    regex = {
+        'domain_name':                    'Domain Name:\s*(.+)',
+    	'domain__id':                     'Domain ID:\s*(.+)',
+        'registrar':                      'Sponsoring Registrar:\s*(.+)',
+        'registrar_id':                   'Sponsoring Registrar IANA ID:\s*(.+)',
+        'registrar_url':                  'Registrar URL \(registration services\):\s*(.+)',        
+        'status':                         'Domain Status:\s*(.+)',  # list of statuses
+        'registrant_id':                  'Registrant ID:\s*(.+)',
+        'registrant_name':                'Registrant Name:\s*(.+)',
+        'registrant_address1':            'Registrant Address1:\s*(.+)',
+        'registrant_address2':            'Registrant Address2:\s*(.+)',
+        'registrant_city':                'Registrant City:\s*(.+)',
+        'registrant_state_province':      'Registrant State/Province:\s*(.+)',
+        'registrant_postal_code':         'Registrant Postal Code:\s*(.+)',
+        'registrant_country':             'Registrant Country:\s*(.+)',
+        'registrant_country_code':        'Registrant Country Code:\s*(.+)',
+        'registrant_phone_number':        'Registrant Phone Number:\s*(.+)',
+        'registrant_email':               'Registrant Email:\s*(.+)',
+        'registrant_application_purpose': 'Registrant Application Purpose:\s*(.+)',
+        'registrant_nexus_category':      'Registrant Nexus Category:\s*(.+)',
+        'admin_id':                       'Administrative Contact ID:\s*(.+)',
+        'admin_name':                     'Administrative Contact Name:\s*(.+)',
+        'admin_address1':                 'Administrative Contact Address1:\s*(.+)',
+        'admin_address2':                 'Administrative Contact Address2:\s*(.+)',
+        'admin_city':                     'Administrative Contact City:\s*(.+)',
+        'admin_state_province':           'Administrative Contact State/Province:\s*(.+)',
+        'admin_postal_code':              'Administrative Contact Postal Code:\s*(.+)',
+        'admin_country':                  'Administrative Contact Country:\s*(.+)',
+        'admin_country_code':             'Administrative Contact Country Code:\s*(.+)',
+        'admin_phone_number':             'Administrative Contact Phone Number:\s*(.+)',
+        'admin_email':                    'Administrative Contact Email:\s*(.+)',
+        'admin_application_purpose':      'Administrative Application Purpose:\s*(.+)',
+        'admin_nexus_category':           'Administrative Nexus Category:\s*(.+)',
+        'billing_id':                     'Billing Contact ID:\s*(.+)',
+        'billing_name':                   'Billing Contact Name:\s*(.+)',
+        'billing_address1':               'Billing Contact Address1:\s*(.+)',
+        'billing_address2':               'Billing Contact Address2:\s*(.+)',
+        'billing_city':                   'Billing Contact City:\s*(.+)',
+        'billing_state_province':         'Billing Contact State/Province:\s*(.+)',
+        'billing_postal_code':            'Billing Contact Postal Code:\s*(.+)',
+        'billing_country':                'Billing Contact Country:\s*(.+)',
+        'billing_country_code':           'Billing Contact Country Code:\s*(.+)',
+        'billing_phone_number':           'Billing Contact Phone Number:\s*(.+)',
+        'billing_email':                  'Billing Contact Email:\s*(.+)',
+        'billing_application_purpose':    'Billing Application Purpose:\s*(.+)',
+        'billing_nexus_category':         'Billing Nexus Category:\s*(.+)',
+        'tech_id':                        'Technical Contact ID:\s*(.+)',
+        'tech_name':                      'Technical Contact Name:\s*(.+)',
+        'tech_address1':                  'Technical Contact Address1:\s*(.+)',
+        'tech_address2':                  'Technical Contact Address2:\s*(.+)',
+        'tech_city':                      'Technical Contact City:\s*(.+)',
+        'tech_state_province':            'Technical Contact State/Province:\s*(.+)',
+        'tech_postal_code':               'Technical Contact Postal Code:\s*(.+)',
+        'tech_country':                   'Technical Contact Country:\s*(.+)',
+        'tech_country_code':              'Technical Contact Country Code:\s*(.+)',
+        'tech_phone_number':              'Technical Contact Phone Number:\s*(.+)',
+        'tech_email':                     'Technical Contact Email:\s*(.+)',
+        'tech_application_purpose':       'Technical Application Purpose:\s*(.+)',
+        'tech_nexus_category':            'Technical Nexus Category:\s*(.+)',
+        'name_servers':                   'Name Server:\s*(.+)',  # list of name servers
+        'created_by_registrar':           'Created by Registrar:\s*(.+)',
+        'last_updated_by_registrar':      'Last Updated by Registrar:\s*(.+)',
+        'creation_date':                  'Domain Registration Date:\s*(.+)',
+        'expiration_date':                'Domain Expiration Date:\s*(.+)',
+        'updated_date':                   'Domain Last Updated Date:\s*(.+)',
+	}
+    def __init__(self, domain, text):
+        if 'Not found:' in text:
+            raise PywhoisError(text)
+        else:
+            WhoisEntry.__init__(self, domain, text, self.regex)
+            
+class WhoisMe(WhoisEntry):
+    """Whois parser for .me domains
+    """
+    regex = {
+    	'domain_id':                   'Domain ID:(.+)',
+        'domain_name':                 'Domain Name:(.+)',
+        'creation_date':               'Domain Create Date:(.+)',
+        'updated_date':                'Domain Last Updated Date:(.+)',
+        'expiration_date':             'Domain Expiration Date:(.+)',
+        'transfer_date':               'Last Transferred Date:(.+)',
+        'trademark_name':              'Trademark Name:(.+)',
+        'trademark_country':           'Trademark Country:(.+)',
+        'trademark_number':            'Trademark Number:(.+)',
+        'trademark_application_date':  'Date Trademark Applied For:(.+)',
+        'trademark_registration_date': 'Date Trademark Registered:(.+)',
+        'registrar':                   'Sponsoring Registrar:(.+)',
+        'created_by':                  'Created by:(.+)',
+        'updated_by':                  'Last Updated by Registrar:(.+)',
+        'status':                      'Domain Status:(.+)',  # list of statuses
+        'registrant_id':               'Registrant ID:(.+)',
+        'registrant_name':             'Registrant Name:(.+)',
+        'registrant_org':              'Registrant Organization:(.+)',
+        'registrant_address':          'Registrant Address:(.+)',
+        'registrant_address2':         'Registrant Address2:(.+)',
+        'registrant_address3':         'Registrant Address3:(.+)',
+        'registrant_city':             'Registrant City:(.+)',
+        'registrant_state_province':   'Registrant State/Province:(.+)',
+        'registrant_country':          'Registrant Country/Economy:(.+)',
+        'registrant_postal_code':      'Registrant Postal Code:(.+)',
+        'registrant_phone':            'Registrant Phone:(.+)',
+        'registrant_phone_ext':        'Registrant Phone Ext\.:(.+)',
+        'registrant_fax':              'Registrant FAX:(.+)',
+        'registrant_fax_ext':          'Registrant FAX Ext\.:(.+)',
+        'registrant_email':            'Registrant E-mail:(.+)',
+        'admin_id':                    'Admin ID:(.+)',
+        'admin_name':                  'Admin Name:(.+)',
+        'admin_org':                   'Admin Organization:(.+)',
+        'admin_address':               'Admin Address:(.+)',
+        'admin_address2':              'Admin Address2:(.+)',
+        'admin_address3':              'Admin Address3:(.+)',
+        'admin_city':                  'Admin City:(.+)',
+        'admin_state_province':        'Admin State/Province:(.+)',
+        'admin_country':               'Admin Country/Economy:(.+)',
+        'admin_postal_code':           'Admin Postal Code:(.+)',
+        'admin_phone':                 'Admin Phone:(.+)',
+        'admin_phone_ext':             'Admin Phone Ext\.:(.+)',
+        'admin_fax':                   'Admin FAX:(.+)',
+        'admin_fax_ext':               'Admin FAX Ext\.:(.+)',
+        'admin_email':                 'Admin E-mail:(.+)',
+        'tech_id':                     'Tech ID:(.+)',
+        'tech_name':                   'Tech Name:(.+)',
+        'tech_org':                    'Tech Organization:(.+)',
+        'tech_address':                'Tech Address:(.+)',
+        'tech_address2':               'Tech Address2:(.+)',
+        'tech_address3':               'Tech Address3:(.+)',
+        'tech_city':                   'Tech City:(.+)',
+        'tech_state_province':         'Tech State/Province:(.+)',
+        'tech_country':                'Tech Country/Economy:(.+)',
+        'tech_postal_code':            'Tech Postal Code:(.+)',
+        'tech_phone':                  'Tech Phone:(.+)',
+        'tech_phone_ext':              'Tech Phone Ext\.:(.+)',
+        'tech_fax':                    'Tech FAX:(.+)',
+        'tech_fax_ext':                'Tech FAX Ext\.:(.+)',
+        'tech_email':                  'Tech E-mail:(.+)',
+        'name_servers':                'Nameservers:(.+)',  # list of name servers
+	}
+    def __init__(self, domain, text):
+        if 'NOT FOUND' in text:
+            raise PywhoisError(text)
+        else:
+            WhoisEntry.__init__(self, domain, text, self.regex) 
+
+class WhoisUk(WhoisEntry):
+    """Whois parser for .uk domains
+    """
+    regex = {
+        'domain_name':                    'Domain name:\n\s*(.+)',
+        'registrar':                      'Registrar:\n\s*(.+)',
+        'registrar_url':                  'URL:\s*(.+)',
+        'status':                         'Registration status:\n\s*(.+)',  # list of statuses
+        'registrant_name':                'Registrant:\n\s*(.+)',
+        'creation_date':                  'Registered on:\s*(.+)',
+        'expiration_date':                'Renewal date:\s*(.+)',
+        'updated_date':                   'Last updated:\s*(.+)',
+	}
+    def __init__(self, domain, text):
+        if 'Not found:' in text:
+            raise PywhoisError(text)
+        else:
+            WhoisEntry.__init__(self, domain, text, self.regex)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pywhois/whois.py	Wed Oct 19 17:09:00 2011 +0900
@@ -0,0 +1,232 @@
+"""
+Whois client for python
+
+transliteration of:
+http://www.opensource.apple.com/source/adv_cmds/adv_cmds-138.1/whois/whois.c
+
+Copyright (c) 2010 Chris Wolf
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+  Last edited by:  $Author$
+              on:  $DateTime$
+        Revision:  $Revision$
+              Id:  $Id$
+          Author:  Chris Wolf
+"""
+import sys
+import socket
+import optparse
+#import pdb
+
+
+class NICClient(object) :
+
+    ABUSEHOST           = "whois.abuse.net"
+    NICHOST             = "whois.crsnic.net"
+    INICHOST            = "whois.networksolutions.com"
+    DNICHOST            = "whois.nic.mil"
+    GNICHOST            = "whois.nic.gov"
+    ANICHOST            = "whois.arin.net"
+    LNICHOST            = "whois.lacnic.net"
+    RNICHOST            = "whois.ripe.net"
+    PNICHOST            = "whois.apnic.net"
+    MNICHOST            = "whois.ra.net"
+    QNICHOST_TAIL       = ".whois-servers.net"
+    SNICHOST            = "whois.6bone.net"
+    BNICHOST            = "whois.registro.br"
+    NORIDHOST           = "whois.norid.no"
+    IANAHOST            = "whois.iana.org"
+    GERMNICHOST         = "de.whois-servers.net"
+    DEFAULT_PORT        = "nicname"
+    WHOIS_SERVER_ID     = "Whois Server:"
+    WHOIS_ORG_SERVER_ID = "Registrant Street1:Whois Server:"
+
+
+    WHOIS_RECURSE       = 0x01
+    WHOIS_QUICK         = 0x02
+
+    ip_whois = [ LNICHOST, RNICHOST, PNICHOST, BNICHOST ]
+
+    def __init__(self) :
+        self.use_qnichost = False
+        
+    def findwhois_server(self, buf, hostname):
+        """Search the initial TLD lookup results for the regional-specifc
+        whois server for getting contact details.
+        """
+        nhost = None
+        parts_index = 1
+        start = buf.find(NICClient.WHOIS_SERVER_ID)
+        if (start == -1):
+            start = buf.find(NICClient.WHOIS_ORG_SERVER_ID)
+            parts_index = 2
+        
+        if (start > -1):   
+            end = buf[start:].find('\n')
+            whois_line = buf[start:end+start]
+            whois_parts = whois_line.split(':')
+            nhost = whois_parts[parts_index].strip()
+        elif (hostname == NICClient.ANICHOST):
+            for nichost in NICClient.ip_whois:
+                if (buf.find(nichost) != -1):
+                    nhost = nichost
+                    break
+        return nhost
+        
+    def whois(self, query, hostname, flags):
+        """Perform initial lookup with TLD whois server
+        then, if the quick flag is false, search that result 
+        for the region-specifc whois server and do a lookup
+        there for contact details
+        """
+        #pdb.set_trace()
+        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        s.connect((hostname, 43))
+        if (hostname == NICClient.GERMNICHOST):
+            s.send("-T dn,ace -C US-ASCII " + query + "\r\n")
+        else:
+            s.send(query + "\r\n")
+        response = ''
+        while True:
+            d = s.recv(4096)
+            response += d
+            if not d:
+                break
+        s.close()
+        #pdb.set_trace()
+        nhost = None
+        if (flags & NICClient.WHOIS_RECURSE and nhost == None):
+            nhost = self.findwhois_server(response, hostname)
+        if (nhost != None):
+            response += self.whois(query, nhost, 0)
+        return response
+    
+    def choose_server(self, domain):
+        """Choose initial lookup NIC host"""
+        if (domain.endswith("-NORID")):
+            return NICClient.NORIDHOST
+        pos = domain.rfind('.')
+        if (pos == -1):
+            return None
+        tld = domain[pos+1:]
+        if (tld[0].isdigit()):
+            return NICClient.ANICHOST
+    
+        return tld + NICClient.QNICHOST_TAIL
+    
+    def whois_lookup(self, options, query_arg, flags):
+        """Main entry point: Perform initial lookup on TLD whois server, 
+        or other server to get region-specific whois server, then if quick 
+        flag is false, perform a second lookup on the region-specific 
+        server for contact records"""
+        nichost = None
+        #pdb.set_trace()
+        # this would be the case when this function is called by other then main
+        if (options == None):                     
+            options = {}
+     
+        if ( (not options.has_key('whoishost') or options['whoishost'] == None)
+            and (not options.has_key('country') or options['country'] == None)):
+            self.use_qnichost = True
+            options['whoishost'] = NICClient.NICHOST
+            if ( not (flags & NICClient.WHOIS_QUICK)):
+                flags |= NICClient.WHOIS_RECURSE
+            
+        if (options.has_key('country') and options['country'] != None):
+            result = self.whois(query_arg, options['country'] + NICClient.QNICHOST_TAIL, flags)
+        elif (self.use_qnichost):
+            nichost = self.choose_server(query_arg)
+            if (nichost != None):
+                result = self.whois(query_arg, nichost, flags)           
+        else:
+            result = self.whois(query_arg, options['whoishost'], flags)
+            
+        return result
+#---- END OF NICClient class def ---------------------
+    
+def parse_command_line(argv):
+    """Options handling mostly follows the UNIX whois(1) man page, except
+    long-form options can also be used.
+    """
+    flags = 0
+    
+    usage = "usage: %prog [options] name"
+            
+    parser = optparse.OptionParser(add_help_option=False, usage=usage)
+    parser.add_option("-a", "--arin", action="store_const", 
+                      const=NICClient.ANICHOST, dest="whoishost",
+                      help="Lookup using host " + NICClient.ANICHOST)
+    parser.add_option("-A", "--apnic", action="store_const", 
+                      const=NICClient.PNICHOST, dest="whoishost",
+                      help="Lookup using host " + NICClient.PNICHOST)
+    parser.add_option("-b", "--abuse", action="store_const", 
+                      const=NICClient.ABUSEHOST, dest="whoishost",
+                      help="Lookup using host " + NICClient.ABUSEHOST)
+    parser.add_option("-c", "--country", action="store", 
+                      type="string", dest="country",
+                      help="Lookup using country-specific NIC")
+    parser.add_option("-d", "--mil", action="store_const", 
+                      const=NICClient.DNICHOST, dest="whoishost",
+                      help="Lookup using host " + NICClient.DNICHOST)
+    parser.add_option("-g", "--gov", action="store_const", 
+                      const=NICClient.GNICHOST, dest="whoishost",
+                      help="Lookup using host " + NICClient.GNICHOST)
+    parser.add_option("-h", "--host", action="store", 
+                      type="string", dest="whoishost",
+                       help="Lookup using specified whois host")
+    parser.add_option("-i", "--nws", action="store_const", 
+                      const=NICClient.INICHOST, dest="whoishost",
+                      help="Lookup using host " + NICClient.INICHOST)
+    parser.add_option("-I", "--iana", action="store_const", 
+                      const=NICClient.IANAHOST, dest="whoishost",
+                      help="Lookup using host " + NICClient.IANAHOST)
+    parser.add_option("-l", "--lcanic", action="store_const", 
+                      const=NICClient.LNICHOST, dest="whoishost",
+                      help="Lookup using host " + NICClient.LNICHOST)
+    parser.add_option("-m", "--ra", action="store_const", 
+                      const=NICClient.MNICHOST, dest="whoishost",
+                      help="Lookup using host " + NICClient.MNICHOST)
+    parser.add_option("-p", "--port", action="store", 
+                      type="int", dest="port",
+                      help="Lookup using specified tcp port")
+    parser.add_option("-Q", "--quick", action="store_true", 
+                     dest="b_quicklookup", 
+                     help="Perform quick lookup")
+    parser.add_option("-r", "--ripe", action="store_const", 
+                      const=NICClient.RNICHOST, dest="whoishost",
+                      help="Lookup using host " + NICClient.RNICHOST)
+    parser.add_option("-R", "--ru", action="store_const", 
+                      const="ru", dest="country",
+                      help="Lookup Russian NIC")
+    parser.add_option("-6", "--6bone", action="store_const", 
+                      const=NICClient.SNICHOST, dest="whoishost",
+                      help="Lookup using host " + NICClient.SNICHOST)
+    parser.add_option("-?", "--help", action="help")
+
+        
+    return parser.parse_args(argv)
+    
+if __name__ == "__main__":
+    flags = 0
+    nic_client = NICClient()
+    (options, args) = parse_command_line(sys.argv)
+    if (options.b_quicklookup is True):
+        flags = flags|NICClient.WHOIS_QUICK
+    print nic_client.whois_lookup(options.__dict__, args[1], flags)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/setup.py	Wed Oct 19 17:09:00 2011 +0900
@@ -0,0 +1,26 @@
+from setuptools import setup, find_packages
+import sys, os
+
+version = '0.1'
+
+setup(name='pywhois',
+      version=version,
+      description="Whois querying and parsing of domain registration information.",
+      long_description="""\
+""",
+      classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
+      keywords='whois',
+      author='Andrey Petrov',
+      author_email='andrey.petrov@shazow.net',
+      url='http://code.google.com/p/pywhois/',
+      license='MIT',
+      packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=[
+          # -*- Extra requirements: -*-
+      ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/samples/expected/digg.com	Wed Oct 19 17:09:00 2011 +0900
@@ -0,0 +1,1 @@
+{"updated_date": ["13-mar-2007"], "expiration_date": ["20-feb-2010"], "status": ["clientDeleteProhibited", "clientRenewProhibited", "clientTransferProhibited", "clientUpdateProhibited"], "domain_name": ["DIGG.COM", "DIGG.COM"], "creation_date": ["20-feb-2000"]}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/samples/expected/google.com	Wed Oct 19 17:09:00 2011 +0900
@@ -0,0 +1,1 @@
+{"updated_date": ["10-apr-2006"], "expiration_date": ["14-sep-2011"], "status": ["clientDeleteProhibited", "clientTransferProhibited", "clientUpdateProhibited"], "domain_name": ["GOOGLE.COM", "google.com"], "creation_date": ["15-sep-1997"]}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/samples/expected/imdb.com	Wed Oct 19 17:09:00 2011 +0900
@@ -0,0 +1,1 @@
+{"updated_date": ["28-mar-2008"], "expiration_date": ["04-jan-2016"], "status": ["clientTransferProhibited"], "domain_name": ["IMDB.COM", "IMDB.COM"], "creation_date": ["05-jan-1996"]}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/samples/expected/microsoft.com	Wed Oct 19 17:09:00 2011 +0900
@@ -0,0 +1,1 @@
+{"updated_date": ["10-oct-2006"], "expiration_date": ["03-may-2014"], "status": ["clientDeleteProhibited", "clientTransferProhibited", "clientUpdateProhibited"], "domain_name": ["MICROSOFT.COM"], "creation_date": ["02-may-1991"]}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/samples/expected/reddit.com	Wed Oct 19 17:09:00 2011 +0900
@@ -0,0 +1,1 @@
+{"updated_date": ["04-jun-2008"], "expiration_date": ["29-apr-2009"], "status": ["clientDeleteProhibited", "clientTransferProhibited", "clientUpdateProhibited"], "domain_name": ["REDDIT.COM", "REDDIT.COM"], "creation_date": ["29-apr-2005"]}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/samples/expected/urlowl.com	Wed Oct 19 17:09:00 2011 +0900
@@ -0,0 +1,1 @@
+{"updated_date": ["14-apr-2008"], "expiration_date": ["14-apr-2009"], "status": ["ok"], "domain_name": ["URLOWL.COM", "urlowl.com"], "creation_date": ["14-apr-2008"]}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/samples/whois/digg.com	Wed Oct 19 17:09:00 2011 +0900
@@ -0,0 +1,89 @@
+
+Whois Server Version 2.0
+
+Domain names in the .com and .net domains can now be registered
+with many different competing registrars. Go to http://www.internic.net
+for detailed information.
+
+   Domain Name: DIGG.COM
+   Registrar: GODADDY.COM, INC.
+   Whois Server: whois.godaddy.com
+   Referral URL: http://registrar.godaddy.com
+   Name Server: UDNS1.ULTRADNS.NET
+   Name Server: UDNS2.ULTRADNS.NET
+   Status: clientDeleteProhibited
+   Status: clientRenewProhibited
+   Status: clientTransferProhibited
+   Status: clientUpdateProhibited
+   Updated Date: 13-mar-2007
+   Creation Date: 20-feb-2000
+   Expiration Date: 20-feb-2010
+
+>>> Last update of whois database: Thu, 26 Jun 2008 21:39:08 EDT <<<
+
+NOTICE: The expiration date displayed in this record is the date the 
+registrar's sponsorship of the domain name registration in the registry is 
+currently set to expire. This date does not necessarily reflect the expiration 
+date of the domain name registrant's agreement with the sponsoring 
+registrar.  Users may consult the sponsoring registrar's Whois database to 
+view the registrar's reported date of expiration for this registration.
+
+TERMS OF USE: You are not authorized to access or query our Whois 
+database through the use of electronic processes that are high-volume and 
+automated except as reasonably necessary to register domain names or 
+modify existing registrations; the Data in VeriSign Global Registry 
+Services' ("VeriSign") Whois database is provided by VeriSign for 
+information purposes only, and to assist persons in obtaining information 
+about or related to a domain name registration record. VeriSign does not 
+guarantee its accuracy. By submitting a Whois query, you agree to abide 
+by the following terms of use: You agree that you may use this Data only 
+for lawful purposes and that under no circumstances will you use this Data 
+to: (1) allow, enable, or otherwise support the transmission of mass 
+unsolicited, commercial advertising or solicitations via e-mail, telephone, 
+or facsimile; or (2) enable high volume, automated, electronic processes 
+that apply to VeriSign (or its computer systems). The compilation, 
+repackaging, dissemination or other use of this Data is expressly 
+prohibited without the prior written consent of VeriSign. You agree not to 
+use electronic processes that are automated and high-volume to access or 
+query the Whois database except as reasonably necessary to register 
+domain names or modify existing registrations. VeriSign reserves the right 
+to restrict your access to the Whois database in its sole discretion to ensure 
+operational stability.  VeriSign may restrict or terminate your access to the 
+Whois database for failure to abide by these terms of use. VeriSign 
+reserves the right to modify these terms at any time. 
+
+The Registry database contains ONLY .COM, .NET, .EDU domains and
+Registrars.The data contained in GoDaddy.com, Inc.'s WhoIs database,
+while believed by the company to be reliable, is provided "as is"
+with no guarantee or warranties regarding its accuracy.  This
+information is provided for the sole purpose of assisting you
+in obtaining information about domain name registration records.
+Any use of this data for any other purpose is expressly forbidden without the prior written
+permission of GoDaddy.com, Inc.  By submitting an inquiry,
+you agree to these terms of usage and limitations of warranty.  In particular,
+you agree not to use this data to allow, enable, or otherwise make possible,
+dissemination or collection of this data, in part or in its entirety, for any
+purpose, such as the transmission of unsolicited advertising and
+and solicitations of any kind, including spam.  You further agree
+not to use this data to enable high volume, automated or robotic electronic
+processes designed to collect or compile this data for any purpose,
+including mining this data for your own personal or commercial purposes. 
+
+Please note: the registrant of the domain name is specified
+in the "registrant" field.  In most cases, GoDaddy.com, Inc. 
+is not the registrant of domain names listed in this database.
+
+
+Registrant:
+   Domains by Proxy, Inc.
+
+   Registered through: GoDaddy.com, Inc. (http://www.godaddy.com)
+   Domain Name: DIGG.COM
+
+   Domain servers in listed order:
+      UDNS1.ULTRADNS.NET
+      UDNS2.ULTRADNS.NET
+
+
+   For complete domain details go to:
+   http://who.godaddy.com/whoischeck.aspx?Domain=DIGG.COM
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/samples/whois/google.com	Wed Oct 19 17:09:00 2011 +0900
@@ -0,0 +1,268 @@
+
+Whois Server Version 2.0
+
+Domain names in the .com and .net domains can now be registered
+with many different competing registrars. Go to http://www.internic.net
+for detailed information.
+
+   Server Name: GOOGLE.COM.ZZZZZ.GET.LAID.AT.WWW.SWINGINGCOMMUNITY.COM
+   IP Address: 69.41.185.195
+   Registrar: INNERWISE, INC. D/B/A ITSYOURDOMAIN.COM
+   Whois Server: whois.itsyourdomain.com
+   Referral URL: http://www.itsyourdomain.com
+
+   Server Name: GOOGLE.COM.ZOMBIED.AND.HACKED.BY.WWW.WEB-HACK.COM
+   IP Address: 217.107.217.167
+   Registrar: ONLINENIC, INC.
+   Whois Server: whois.35.com
+   Referral URL: http://www.OnlineNIC.com
+
+   Server Name: GOOGLE.COM.YAHOO.COM.MYSPACE.COM.YOUTUBE.COM.FACEBOOK.COM.THEYSUCK.DNSABOUT.COM
+   IP Address: 72.52.190.30
+   Registrar: GODADDY.COM, INC.
+   Whois Server: whois.godaddy.com
+   Referral URL: http://registrar.godaddy.com
+
+   Server Name: GOOGLE.COM.WORDT.DOOR.VEEL.WHTERS.GEBRUIKT.SERVERTJE.NET
+   IP Address: 62.41.27.144
+   Registrar: KEY-SYSTEMS GMBH
+   Whois Server: whois.rrpproxy.net
+   Referral URL: http://www.key-systems.net
+
+   Server Name: GOOGLE.COM.VN
+   Registrar: ONLINENIC, INC.
+   Whois Server: whois.35.com
+   Referral URL: http://www.OnlineNIC.com
+
+   Server Name: GOOGLE.COM.UY
+   Registrar: DIRECTI INTERNET SOLUTIONS PVT. LTD. D/B/A PUBLICDOMAINREGISTRY.COM
+   Whois Server: whois.PublicDomainRegistry.com
+   Referral URL: http://www.PublicDomainRegistry.com
+
+   Server Name: GOOGLE.COM.UA
+   Registrar: DIRECTI INTERNET SOLUTIONS PVT. LTD. D/B/A PUBLICDOMAINREGISTRY.COM
+   Whois Server: whois.PublicDomainRegistry.com
+   Referral URL: http://www.PublicDomainRegistry.com
+
+   Server Name: GOOGLE.COM.TW
+   Registrar: WEB COMMERCE COMMUNICATIONS LIMITED DBA WEBNIC.CC
+   Whois Server: whois.webnic.cc
+   Referral URL: http://www.webnic.cc
+
+   Server Name: GOOGLE.COM.TR
+   Registrar: DIRECTI INTERNET SOLUTIONS PVT. LTD. D/B/A PUBLICDOMAINREGISTRY.COM
+   Whois Server: whois.PublicDomainRegistry.com
+   Referral URL: http://www.PublicDomainRegistry.com
+
+   Server Name: GOOGLE.COM.SUCKS.FIND.CRACKZ.WITH.SEARCH.GULLI.COM
+   IP Address: 80.190.192.24
+   Registrar: EPAG DOMAINSERVICES GMBH
+   Whois Server: whois.enterprice.net
+   Referral URL: http://www.enterprice.net
+
+   Server Name: GOOGLE.COM.SPROSIUYANDEKSA.RU
+   Registrar: MELBOURNE IT, LTD. D/B/A INTERNET NAMES WORLDWIDE
+   Whois Server: whois.melbourneit.com
+   Referral URL: http://www.melbourneit.com
+
+   Server Name: GOOGLE.COM.SERVES.PR0N.FOR.ALLIYAH.NET
+   IP Address: 84.255.209.69
+   Registrar: GODADDY.COM, INC.
+   Whois Server: whois.godaddy.com
+   Referral URL: http://registrar.godaddy.com
+
+   Server Name: GOOGLE.COM.SA
+   Registrar: OMNIS NETWORK, LLC
+   Whois Server: whois.omnis.com
+   Referral URL: http://domains.omnis.com
+
+   Server Name: GOOGLE.COM.PLZ.GIVE.A.PR8.TO.AUDIOTRACKER.NET
+   IP Address: 213.251.184.30
+   Registrar: OVH
+   Whois Server: whois.ovh.com
+   Referral URL: http://www.ovh.com
+
+   Server Name: GOOGLE.COM.MX
+   Registrar: DIRECTI INTERNET SOLUTIONS PVT. LTD. D/B/A PUBLICDOMAINREGISTRY.COM
+   Whois Server: whois.PublicDomainRegistry.com
+   Referral URL: http://www.PublicDomainRegistry.com
+
+   Server Name: GOOGLE.COM.IS.NOT.HOSTED.BY.ACTIVEDOMAINDNS.NET
+   IP Address: 217.148.161.5
+   Registrar: ENOM, INC.
+   Whois Server: whois.enom.com
+   Referral URL: http://www.enom.com
+
+   Server Name: GOOGLE.COM.IS.HOSTED.ON.PROFITHOSTING.NET
+   IP Address: 66.49.213.213
+   Registrar: NAME.COM LLC
+   Whois Server: whois.name.com
+   Referral URL: http://www.name.com
+
+   Server Name: GOOGLE.COM.IS.APPROVED.BY.NUMEA.COM
+   IP Address: 213.228.0.43
+   Registrar: GANDI SAS
+   Whois Server: whois.gandi.net
+   Referral URL: http://www.gandi.net
+
+   Server Name: GOOGLE.COM.HAS.LESS.FREE.PORN.IN.ITS.SEARCH.ENGINE.THAN.SECZY.COM
+   IP Address: 209.187.114.130
+   Registrar: INNERWISE, INC. D/B/A ITSYOURDOMAIN.COM
+   Whois Server: whois.itsyourdomain.com
+   Referral URL: http://www.itsyourdomain.com
+
+   Server Name: GOOGLE.COM.DO
+   Registrar: GODADDY.COM, INC.
+   Whois Server: whois.godaddy.com
+   Referral URL: http://registrar.godaddy.com
+
+   Server Name: GOOGLE.COM.COLLEGELEARNER.COM
+   IP Address: 72.14.207.99
+   IP Address: 64.233.187.99
+   IP Address: 64.233.167.99
+   Registrar: GODADDY.COM, INC.
+   Whois Server: whois.godaddy.com
+   Referral URL: http://registrar.godaddy.com
+
+   Server Name: GOOGLE.COM.CO
+   Registrar: NAMESECURE.COM
+   Whois Server: whois.namesecure.com
+   Referral URL: http://www.namesecure.com
+
+   Server Name: GOOGLE.COM.BR
+   Registrar: ENOM, INC.
+   Whois Server: whois.enom.com
+   Referral URL: http://www.enom.com
+
+   Server Name: GOOGLE.COM.BEYONDWHOIS.COM
+   IP Address: 203.36.226.2
+   Registrar: TUCOWS INC.
+   Whois Server: whois.tucows.com
+   Referral URL: http://domainhelp.opensrs.net
+
+   Server Name: GOOGLE.COM.AU
+   Registrar: PLANETDOMAIN PTY LTD.
+   Whois Server: whois.planetdomain.com
+   Referral URL: http://www.planetdomain.com
+
+   Server Name: GOOGLE.COM.ACQUIRED.BY.CALITEC.NET
+   IP Address: 85.190.27.2
+   Registrar: ENOM, INC.
+   Whois Server: whois.enom.com
+   Referral URL: http://www.enom.com
+
+   Domain Name: GOOGLE.COM
+   Registrar: MARKMONITOR INC.
+   Whois Server: whois.markmonitor.com
+   Referral URL: http://www.markmonitor.com
+   Name Server: NS1.GOOGLE.COM
+   Name Server: NS2.GOOGLE.COM
+   Name Server: NS3.GOOGLE.COM
+   Name Server: NS4.GOOGLE.COM
+   Status: clientDeleteProhibited
+   Status: clientTransferProhibited
+   Status: clientUpdateProhibited
+   Updated Date: 10-apr-2006
+   Creation Date: 15-sep-1997
+   Expiration Date: 14-sep-2011
+
+>>> Last update of whois database: Thu, 26 Jun 2008 21:39:39 EDT <<<
+
+NOTICE: The expiration date displayed in this record is the date the 
+registrar's sponsorship of the domain name registration in the registry is 
+currently set to expire. This date does not necessarily reflect the expiration 
+date of the domain name registrant's agreement with the sponsoring 
+registrar.  Users may consult the sponsoring registrar's Whois database to 
+view the registrar's reported date of expiration for this registration.
+
+TERMS OF USE: You are not authorized to access or query our Whois 
+database through the use of electronic processes that are high-volume and 
+automated except as reasonably necessary to register domain names or 
+modify existing registrations; the Data in VeriSign Global Registry 
+Services' ("VeriSign") Whois database is provided by VeriSign for 
+information purposes only, and to assist persons in obtaining information 
+about or related to a domain name registration record. VeriSign does not 
+guarantee its accuracy. By submitting a Whois query, you agree to abide 
+by the following terms of use: You agree that you may use this Data only 
+for lawful purposes and that under no circumstances will you use this Data 
+to: (1) allow, enable, or otherwise support the transmission of mass 
+unsolicited, commercial advertising or solicitations via e-mail, telephone, 
+or facsimile; or (2) enable high volume, automated, electronic processes 
+that apply to VeriSign (or its computer systems). The compilation, 
+repackaging, dissemination or other use of this Data is expressly 
+prohibited without the prior written consent of VeriSign. You agree not to 
+use electronic processes that are automated and high-volume to access or 
+query the Whois database except as reasonably necessary to register 
+domain names or modify existing registrations. VeriSign reserves the right 
+to restrict your access to the Whois database in its sole discretion to ensure 
+operational stability.  VeriSign may restrict or terminate your access to the 
+Whois database for failure to abide by these terms of use. VeriSign 
+reserves the right to modify these terms at any time. 
+
+The Registry database contains ONLY .COM, .NET, .EDU domains and
+Registrars.
+MarkMonitor.com - The Leader in Corporate Domain Management
+----------------------------------------------------------
+For Global Domain Consolidation, Research & Intelligence,
+and Enterprise DNS, go to: www.markmonitor.com
+----------------------------------------------------------
+
+The Data in MarkMonitor.com's WHOIS database is provided by MarkMonitor.com
+for information purposes, and to assist persons in obtaining information
+about or related to a domain name registration record.  MarkMonitor.com
+does not guarantee its accuracy.  By submitting a WHOIS query, you agree
+that you will use this Data only for lawful purposes and that, under no
+circumstances will you use this Data to: (1) allow, enable, or otherwise
+support the transmission of mass unsolicited, commercial advertising or
+solicitations via e-mail (spam); or  (2) enable high volume, automated,
+electronic processes that apply to MarkMonitor.com (or its systems).
+MarkMonitor.com reserves the right to modify these terms at any time.
+By submitting this query, you agree to abide by this policy.
+
+Registrant:
+        Dns Admin
+        Google Inc.
+        Please contact contact-admin@google.com 1600 Amphitheatre Parkway
+         Mountain View CA 94043
+        US
+        dns-admin@google.com +1.6502530000 Fax: +1.6506188571
+
+    Domain Name: google.com
+
+        Registrar Name: Markmonitor.com
+        Registrar Whois: whois.markmonitor.com
+        Registrar Homepage: http://www.markmonitor.com
+
+    Administrative Contact:
+        DNS Admin
+        Google Inc.
+        1600 Amphitheatre Parkway
+         Mountain View CA 94043
+        US
+        dns-admin@google.com +1.6506234000 Fax: +1.6506188571
+    Technical Contact, Zone Contact:
+        DNS Admin
+        Google Inc.
+        2400 E. Bayshore Pkwy
+         Mountain View CA 94043
+        US
+        dns-admin@google.com +1.6503300100 Fax: +1.6506181499
+
+    Created on..............: 1997-09-15.
+    Expires on..............: 2011-09-13.
+    Record last updated on..: 2008-06-08.
+
+    Domain servers in listed order:
+
+    ns4.google.com
+    ns3.google.com
+    ns2.google.com
+    ns1.google.com
+    
+
+MarkMonitor.com - The Leader in Corporate Domain Management
+----------------------------------------------------------
+For Global Domain Consolidation, Research & Intelligence,
+and Enterprise DNS, go to: www.markmonitor.com
+----------------------------------------------------------
+--
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/samples/whois/imdb.com	Wed Oct 19 17:09:00 2011 +0900
@@ -0,0 +1,119 @@
+
+Whois Server Version 2.0
+
+Domain names in the .com and .net domains can now be registered
+with many different competing registrars. Go to http://www.internic.net
+for detailed information.
+
+   Server Name: IMDB.COM.MORE.INFO.AT.WWW.BEYONDWHOIS.COM
+   IP Address: 203.36.226.2
+   Registrar: TUCOWS INC.
+   Whois Server: whois.tucows.com
+   Referral URL: http://domainhelp.opensrs.net
+
+   Domain Name: IMDB.COM
+   Registrar: NETWORK SOLUTIONS, LLC.
+   Whois Server: whois.networksolutions.com
+   Referral URL: http://www.networksolutions.com
+   Name Server: UDNS1.ULTRADNS.NET
+   Name Server: UDNS2.ULTRADNS.NET
+   Status: clientTransferProhibited
+   Updated Date: 28-mar-2008
+   Creation Date: 05-jan-1996
+   Expiration Date: 04-jan-2016
+
+>>> Last update of whois database: Thu, 26 Jun 2008 21:40:25 EDT <<<
+
+NOTICE: The expiration date displayed in this record is the date the 
+registrar's sponsorship of the domain name registration in the registry is 
+currently set to expire. This date does not necessarily reflect the expiration 
+date of the domain name registrant's agreement with the sponsoring 
+registrar.  Users may consult the sponsoring registrar's Whois database to 
+view the registrar's reported date of expiration for this registration.
+
+TERMS OF USE: You are not authorized to access or query our Whois 
+database through the use of electronic processes that are high-volume and 
+automated except as reasonably necessary to register domain names or 
+modify existing registrations; the Data in VeriSign Global Registry 
+Services' ("VeriSign") Whois database is provided by VeriSign for 
+information purposes only, and to assist persons in obtaining information 
+about or related to a domain name registration record. VeriSign does not 
+guarantee its accuracy. By submitting a Whois query, you agree to abide 
+by the following terms of use: You agree that you may use this Data only 
+for lawful purposes and that under no circumstances will you use this Data 
+to: (1) allow, enable, or otherwise support the transmission of mass 
+unsolicited, commercial advertising or solicitations via e-mail, telephone, 
+or facsimile; or (2) enable high volume, automated, electronic processes 
+that apply to VeriSign (or its computer systems). The compilation, 
+repackaging, dissemination or other use of this Data is expressly 
+prohibited without the prior written consent of VeriSign. You agree not to 
+use electronic processes that are automated and high-volume to access or 
+query the Whois database except as reasonably necessary to register 
+domain names or modify existing registrations. VeriSign reserves the right 
+to restrict your access to the Whois database in its sole discretion to ensure 
+operational stability.  VeriSign may restrict or terminate your access to the 
+Whois database for failure to abide by these terms of use. VeriSign 
+reserves the right to modify these terms at any time. 
+
+The Registry database contains ONLY .COM, .NET, .EDU domains and
+Registrars.NOTICE AND TERMS OF USE: You are not authorized to access or query our WHOIS
+database through the use of high-volume, automated, electronic processes. The
+Data in Network Solutions' WHOIS database is provided by Network Solutions for information
+purposes only, and to assist persons in obtaining information about or related
+to a domain name registration record. Network Solutions does not guarantee its accuracy.
+By submitting a WHOIS query, you agree to abide by the following terms of use:
+You agree that you may use this Data only for lawful purposes and that under no
+circumstances will you use this Data to: (1) allow, enable, or otherwise support
+the transmission of mass unsolicited, commercial advertising or solicitations
+via e-mail, telephone, or facsimile; or (2) enable high volume, automated,
+electronic processes that apply to Network Solutions (or its computer systems). The
+compilation, repackaging, dissemination or other use of this Data is expressly
+prohibited without the prior written consent of Network Solutions. You agree not to use
+high-volume, automated, electronic processes to access or query the WHOIS
+database. Network Solutions reserves the right to terminate your access to the WHOIS
+database in its sole discretion, including without limitation, for excessive
+querying of the WHOIS database or for failure to otherwise abide by this policy.
+Network Solutions reserves the right to modify these terms at any time.
+
+Get a FREE domain name registration, transfer, or renewal with any annual hosting package.
+
+http://www.networksolutions.com
+
+Visit AboutUs.org for more information about IMDB.COM
+<a href="http://www.aboutus.org/IMDB.COM">AboutUs: IMDB.COM </a>
+
+
+
+
+Registrant:
+IMDb.com, Inc.
+   Legal Dept, PO Box 81226
+   Seattle, WA 98108
+   US
+
+   Domain Name: IMDB.COM
+
+   ------------------------------------------------------------------------
+   Promote your business to millions of viewers for only $1 a month
+   Learn how you can get an Enhanced Business Listing here for your domain name.
+   Learn more at http://www.NetworkSolutions.com/
+   ------------------------------------------------------------------------
+
+   Administrative Contact, Technical Contact:
+      Hostmaster, IMDb		hostmaster@imdb.com
+      IMDb.com, Inc.
+      Legal Dept, PO Box 81226
+      Seattle, WA 98108
+      US
+      +1.2062664064 fax: +1.2062667010
+
+
+   Record expires on 04-Jan-2016.
+   Record created on 05-Jan-1996.
+   Database last updated on 26-Jun-2008 21:38:42 EDT.
+
+   Domain servers in listed order:
+
+   UDNS1.ULTRADNS.NET           
+   UDNS2.ULTRADNS.NET           
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/samples/whois/microsoft.com	Wed Oct 19 17:09:00 2011 +0900
@@ -0,0 +1,316 @@
+
+Whois Server Version 2.0
+
+Domain names in the .com and .net domains can now be registered
+with many different competing registrars. Go to http://www.internic.net
+for detailed information.
+
+   Server Name: MICROSOFT.COM.ZZZZZZ.MORE.DETAILS.AT.WWW.BEYONDWHOIS.COM
+   IP Address: 203.36.226.2
+   Registrar: TUCOWS INC.
+   Whois Server: whois.tucows.com
+   Referral URL: http://domainhelp.opensrs.net
+
+   Server Name: MICROSOFT.COM.ZZZZZ.GET.LAID.AT.WWW.SWINGINGCOMMUNITY.COM
+   IP Address: 69.41.185.194
+   Registrar: INNERWISE, INC. D/B/A ITSYOURDOMAIN.COM
+   Whois Server: whois.itsyourdomain.com
+   Referral URL: http://www.itsyourdomain.com
+
+   Server Name: MICROSOFT.COM.ZZZOMBIED.AND.HACKED.BY.WWW.WEB-HACK.COM
+   IP Address: 217.107.217.167
+   Registrar: ONLINENIC, INC.
+   Whois Server: whois.35.com
+   Referral URL: http://www.OnlineNIC.com
+
+   Server Name: MICROSOFT.COM.ZZZ.IS.0WNED.AND.HAX0RED.BY.SUB7.NET
+   IP Address: 207.44.240.96
+   Registrar: INNERWISE, INC. D/B/A ITSYOURDOMAIN.COM
+   Whois Server: whois.itsyourdomain.com
+   Referral URL: http://www.itsyourdomain.com
+
+   Server Name: MICROSOFT.COM.WILL.LIVE.FOREVER.BECOUSE.UNIXSUCKS.COM
+   IP Address: 185.3.4.7
+   Registrar: MELBOURNE IT, LTD. D/B/A INTERNET NAMES WORLDWIDE
+   Whois Server: whois.melbourneit.com
+   Referral URL: http://www.melbourneit.com
+
+   Server Name: MICROSOFT.COM.WILL.BE.SLAPPED.IN.THE.FACE.BY.MY.BLUE.VEINED.SPANNER.NET
+   IP Address: 216.127.80.46
+   Registrar: COMPUTER SERVICES LANGENBACH GMBH DBA JOKER.COM
+   Whois Server: whois.joker.com
+   Referral URL: http://www.joker.com
+
+   Server Name: MICROSOFT.COM.WILL.BE.BEATEN.WITH.MY.SPANNER.NET
+   IP Address: 216.127.80.46
+   Registrar: COMPUTER SERVICES LANGENBACH GMBH DBA JOKER.COM
+   Whois Server: whois.joker.com
+   Referral URL: http://www.joker.com
+
+   Server Name: MICROSOFT.COM.WAREZ.AT.TOPLIST.GULLI.COM
+   IP Address: 80.190.192.33
+   Registrar: EPAG DOMAINSERVICES GMBH
+   Whois Server: whois.enterprice.net
+   Referral URL: http://www.enterprice.net
+
+   Server Name: MICROSOFT.COM.USERS.SHOULD.HOST.WITH.UNIX.AT.ITSHOSTED.COM
+   IP Address: 74.52.88.132
+   Registrar: ENOM, INC.
+   Whois Server: whois.enom.com
+   Referral URL: http://www.enom.com
+
+   Server Name: MICROSOFT.COM.TOTALLY.SUCKS.S3U.NET
+   IP Address: 207.208.13.22
+   Registrar: ENOM, INC.
+   Whois Server: whois.enom.com
+   Referral URL: http://www.enom.com
+
+   Server Name: MICROSOFT.COM.SOFTWARE.IS.NOT.USED.AT.REG.RU
+   Registrar: MELBOURNE IT, LTD. D/B/A INTERNET NAMES WORLDWIDE
+   Whois Server: whois.melbourneit.com
+   Referral URL: http://www.melbourneit.com
+
+   Server Name: MICROSOFT.COM.SHOULD.GIVE.UP.BECAUSE.LINUXISGOD.COM
+   IP Address: 65.160.248.13
+   Registrar: GKG.NET, INC.
+   Whois Server: whois.gkg.net
+   Referral URL: http://www.gkg.net
+
+   Server Name: MICROSOFT.COM.RAWKZ.MUH.WERLD.MENTALFLOSS.CA
+   Registrar: TUCOWS INC.
+   Whois Server: whois.tucows.com
+   Referral URL: http://domainhelp.opensrs.net
+
+   Server Name: MICROSOFT.COM.OHMYGODITBURNS.COM
+   IP Address: 216.158.63.6
+   Registrar: DOTSTER, INC.
+   Whois Server: whois.dotster.com
+   Referral URL: http://www.dotster.com
+
+   Server Name: MICROSOFT.COM.MORE.INFO.AT.WWW.BEYONDWHOIS.COM
+   IP Address: 203.36.226.2
+   Registrar: TUCOWS INC.
+   Whois Server: whois.tucows.com
+   Referral URL: http://domainhelp.opensrs.net
+
+   Server Name: MICROSOFT.COM.LOVES.ME.KOSMAL.NET
+   IP Address: 65.75.198.123
+   Registrar: GODADDY.COM, INC.
+   Whois Server: whois.godaddy.com
+   Referral URL: http://registrar.godaddy.com
+
+   Server Name: MICROSOFT.COM.LIVES.AT.SHAUNEWING.COM
+   IP Address: 216.40.250.172
+   Registrar: ENOM, INC.
+   Whois Server: whois.enom.com
+   Referral URL: http://www.enom.com
+
+   Server Name: MICROSOFT.COM.IS.NOT.YEPPA.ORG
+   Registrar: OVH
+   Whois Server: whois.ovh.com
+   Referral URL: http://www.ovh.com
+
+   Server Name: MICROSOFT.COM.IS.NOT.HOSTED.BY.ACTIVEDOMAINDNS.NET
+   IP Address: 217.148.161.5
+   Registrar: ENOM, INC.
+   Whois Server: whois.enom.com
+   Referral URL: http://www.enom.com
+
+   Server Name: MICROSOFT.COM.IS.IN.BED.WITH.CURTYV.COM
+   IP Address: 216.55.187.193
+   Registrar: ABACUS AMERICA, INC. DBA NAMES4EVER
+   Whois Server: whois.names4ever.com
+   Referral URL: http://www.names4ever.com
+
+   Server Name: MICROSOFT.COM.IS.HOSTED.ON.PROFITHOSTING.NET
+   IP Address: 66.49.213.213
+   Registrar: NAME.COM LLC
+   Whois Server: whois.name.com
+   Referral URL: http://www.name.com
+
+   Server Name: MICROSOFT.COM.IS.GOD.BECOUSE.UNIXSUCKS.COM
+   IP Address: 161.16.56.24
+   Registrar: MELBOURNE IT, LTD. D/B/A INTERNET NAMES WORLDWIDE
+   Whois Server: whois.melbourneit.com
+   Referral URL: http://www.melbourneit.com
+
+   Server Name: MICROSOFT.COM.IS.A.STEAMING.HEAP.OF.FUCKING-BULLSHIT.NET
+   IP Address: 63.99.165.11
+   Registrar: THE NAME IT CORPORATION DBA NAMESERVICES.NET
+   Whois Server: whois.aitdomains.com
+   Referral URL: http://www.aitdomains.com
+
+   Server Name: MICROSOFT.COM.IS.A.MESS.TIMPORTER.CO.UK
+   Registrar: MELBOURNE IT, LTD. D/B/A INTERNET NAMES WORLDWIDE
+   Whois Server: whois.melbourneit.com
+   Referral URL: http://www.melbourneit.com
+
+   Server Name: MICROSOFT.COM.HAS.ITS.OWN.CRACKLAB.COM
+   IP Address: 209.26.95.44
+   Registrar: DOTSTER, INC.
+   Whois Server: whois.dotster.com
+   Referral URL: http://www.dotster.com
+
+   Server Name: MICROSOFT.COM.HAS.A.PRESENT.COMING.FROM.HUGHESMISSILES.COM
+   IP Address: 66.154.11.27
+   Registrar: TUCOWS INC.
+   Whois Server: whois.tucows.com
+   Referral URL: http://domainhelp.opensrs.net
+
+   Server Name: MICROSOFT.COM.FILLS.ME.WITH.BELLIGERENCE.NET
+   IP Address: 130.58.82.232
+   Registrar: CRONON AG BERLIN, NIEDERLASSUNG REGENSBURG
+   Whois Server: whois.tmagnic.net
+   Referral URL: http://nsi-robo.tmag.de
+
+   Server Name: MICROSOFT.COM.CAN.GO.FUCK.ITSELF.AT.SECZY.COM
+   IP Address: 209.187.114.147
+   Registrar: INNERWISE, INC. D/B/A ITSYOURDOMAIN.COM
+   Whois Server: whois.itsyourdomain.com
+   Referral URL: http://www.itsyourdomain.com
+
+   Server Name: MICROSOFT.COM.ARE.GODDAMN.PIGFUCKERS.NET.NS-NOT-IN-SERVICE.COM
+   IP Address: 216.127.80.46
+   Registrar: TUCOWS INC.
+   Whois Server: whois.tucows.com
+   Referral URL: http://domainhelp.opensrs.net
+
+   Server Name: MICROSOFT.COM.AND.MINDSUCK.BOTH.SUCK.HUGE.ONES.AT.EXEGETE.NET
+   IP Address: 63.241.136.53
+   Registrar: DOTSTER, INC.
+   Whois Server: whois.dotster.com
+   Referral URL: http://www.dotster.com
+
+   Domain Name: MICROSOFT.COM
+   Registrar: TUCOWS INC.
+   Whois Server: whois.tucows.com
+   Referral URL: http://domainhelp.opensrs.net
+   Name Server: NS1.MSFT.NET
+   Name Server: NS2.MSFT.NET
+   Name Server: NS3.MSFT.NET
+   Name Server: NS4.MSFT.NET
+   Name Server: NS5.MSFT.NET
+   Status: clientDeleteProhibited
+   Status: clientTransferProhibited
+   Status: clientUpdateProhibited
+   Updated Date: 10-oct-2006
+   Creation Date: 02-may-1991
+   Expiration Date: 03-may-2014
+
+>>> Last update of whois database: Thu, 26 Jun 2008 21:39:39 EDT <<<
+
+NOTICE: The expiration date displayed in this record is the date the 
+registrar's sponsorship of the domain name registration in the registry is 
+currently set to expire. This date does not necessarily reflect the expiration 
+date of the domain name registrant's agreement with the sponsoring 
+registrar.  Users may consult the sponsoring registrar's Whois database to 
+view the registrar's reported date of expiration for this registration.
+
+TERMS OF USE: You are not authorized to access or query our Whois 
+database through the use of electronic processes that are high-volume and 
+automated except as reasonably necessary to register domain names or 
+modify existing registrations; the Data in VeriSign Global Registry 
+Services' ("VeriSign") Whois database is provided by VeriSign for 
+information purposes only, and to assist persons in obtaining information 
+about or related to a domain name registration record. VeriSign does not 
+guarantee its accuracy. By submitting a Whois query, you agree to abide 
+by the following terms of use: You agree that you may use this Data only 
+for lawful purposes and that under no circumstances will you use this Data 
+to: (1) allow, enable, or otherwise support the transmission of mass 
+unsolicited, commercial advertising or solicitations via e-mail, telephone, 
+or facsimile; or (2) enable high volume, automated, electronic processes 
+that apply to VeriSign (or its computer systems). The compilation, 
+repackaging, dissemination or other use of this Data is expressly 
+prohibited without the prior written consent of VeriSign. You agree not to 
+use electronic processes that are automated and high-volume to access or 
+query the Whois database except as reasonably necessary to register 
+domain names or modify existing registrations. VeriSign reserves the right 
+to restrict your access to the Whois database in its sole discretion to ensure 
+operational stability.  VeriSign may restrict or terminate your access to the 
+Whois database for failure to abide by these terms of use. VeriSign 
+reserves the right to modify these terms at any time. 
+
+The Registry database contains ONLY .COM, .NET, .EDU domains and
+Registrars.Registrant:
+ Microsoft Corporation
+ One Microsoft Way
+ Redmond, WA 98052
+ US
+
+ Domain name: MICROSOFT.COM
+
+
+ Administrative Contact:
+    Administrator, Domain  domains@microsoft.com
+    One Microsoft Way
+    Redmond, WA 98052
+    US
+    +1.4258828080
+ Technical Contact:
+    Hostmaster, MSN  msnhst@microsoft.com
+    One Microsoft Way
+    Redmond, WA 98052
+    US
+    +1.4258828080
+
+
+ Registration Service Provider:
+    DBMS VeriSign, dbms-support@verisign.com
+    800-579-2848 x4
+    Please contact DBMS VeriSign for domain updates, DNS/Nameserver
+    changes, and general domain support questions.
+
+
+ Registrar of Record: TUCOWS, INC.
+ Record last updated on 15-Nov-2007.
+ Record expires on 03-May-2014.
+ Record created on 02-May-1991.
+
+ Registrar Domain Name Help Center:
+    http://domainhelp.tucows.com
+
+ Domain servers in listed order:
+    NS2.MSFT.NET   
+    NS4.MSFT.NET   
+    NS1.MSFT.NET   
+    NS5.MSFT.NET   
+    NS3.MSFT.NET   
+
+
+ Domain status: clientDeleteProhibited
+                clientTransferProhibited
+                clientUpdateProhibited
+
+The Data in the Tucows Registrar WHOIS database is provided to you by Tucows
+for information purposes only, and may be used to assist you in obtaining
+information about or related to a domain name's registration record.
+
+Tucows makes this information available "as is," and does not guarantee its
+accuracy.
+
+By submitting a WHOIS query, you agree that you will use this data only for
+lawful purposes and that, under no circumstances will you use this data to:
+a) allow, enable, or otherwise support the transmission by e-mail,
+telephone, or facsimile of mass, unsolicited, commercial advertising or
+solicitations to entities other than the data recipient's own existing
+customers; or (b) enable high volume, automated, electronic processes that
+send queries or data to the systems of any Registry Operator or
+ICANN-Accredited registrar, except as reasonably necessary to register
+domain names or modify existing registrations.
+
+The compilation, repackaging, dissemination or other use of this Data is
+expressly prohibited without the prior written consent of Tucows.
+
+Tucows reserves the right to terminate your access to the Tucows WHOIS
+database in its sole discretion, including without limitation, for excessive
+querying of the WHOIS database or for failure to otherwise abide by this
+policy.
+
+Tucows reserves the right to modify these terms at any time.
+
+By submitting this query, you agree to abide by these terms.
+
+NOTE: THE WHOIS DATABASE IS A CONTACT DATABASE ONLY.  LACK OF A DOMAIN
+RECORD DOES NOT SIGNIFY DOMAIN AVAILABILITY.
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/samples/whois/reddit.com	Wed Oct 19 17:09:00 2011 +0900
@@ -0,0 +1,125 @@
+
+Whois Server Version 2.0
+
+Domain names in the .com and .net domains can now be registered
+with many different competing registrars. Go to http://www.internic.net
+for detailed information.
+
+   Domain Name: REDDIT.COM
+   Registrar: DSTR ACQUISITION PA I, LLC DBA DOMAINBANK.COM
+   Whois Server: rs.domainbank.net
+   Referral URL: http://www.domainbank.net
+   Name Server: ASIA1.AKAM.NET
+   Name Server: ASIA9.AKAM.NET
+   Name Server: AUS2.AKAM.NET
+   Name Server: NS1-1.AKAM.NET
+   Name Server: NS1-195.AKAM.NET
+   Name Server: USE4.AKAM.NET
+   Name Server: USW3.AKAM.NET
+   Name Server: USW5.AKAM.NET
+   Status: clientDeleteProhibited
+   Status: clientTransferProhibited
+   Status: clientUpdateProhibited
+   Updated Date: 04-jun-2008
+   Creation Date: 29-apr-2005
+   Expiration Date: 29-apr-2009
+
+>>> Last update of whois database: Fri, 27 Jun 2008 01:39:54 UTC <<<
+
+NOTICE: The expiration date displayed in this record is the date the 
+registrar's sponsorship of the domain name registration in the registry is 
+currently set to expire. This date does not necessarily reflect the expiration 
+date of the domain name registrant's agreement with the sponsoring 
+registrar.  Users may consult the sponsoring registrar's Whois database to 
+view the registrar's reported date of expiration for this registration.
+
+TERMS OF USE: You are not authorized to access or query our Whois 
+database through the use of electronic processes that are high-volume and 
+automated except as reasonably necessary to register domain names or 
+modify existing registrations; the Data in VeriSign Global Registry 
+Services' ("VeriSign") Whois database is provided by VeriSign for 
+information purposes only, and to assist persons in obtaining information 
+about or related to a domain name registration record. VeriSign does not 
+guarantee its accuracy. By submitting a Whois query, you agree to abide 
+by the following terms of use: You agree that you may use this Data only 
+for lawful purposes and that under no circumstances will you use this Data 
+to: (1) allow, enable, or otherwise support the transmission of mass 
+unsolicited, commercial advertising or solicitations via e-mail, telephone, 
+or facsimile; or (2) enable high volume, automated, electronic processes 
+that apply to VeriSign (or its computer systems). The compilation, 
+repackaging, dissemination or other use of this Data is expressly 
+prohibited without the prior written consent of VeriSign. You agree not to 
+use electronic processes that are automated and high-volume to access or 
+query the Whois database except as reasonably necessary to register 
+domain names or modify existing registrations. VeriSign reserves the right 
+to restrict your access to the Whois database in its sole discretion to ensure 
+operational stability.  VeriSign may restrict or terminate your access to the 
+Whois database for failure to abide by these terms of use. VeriSign 
+reserves the right to modify these terms at any time. 
+
+The Registry database contains ONLY .COM, .NET, .EDU domains and
+Registrars.
+The information in this whois database is provided for the sole
+purpose of assisting you in obtaining information about domain
+name registration records. This information is available "as is,"
+and we do not guarantee its accuracy. By submitting a whois
+query, you agree that you will use this data only for lawful
+purposes and that, under no circumstances will you use this data
+to: (1) enable high volume, automated, electronic processes that
+stress or load this whois database system providing you this
+information; or (2) allow,enable, or otherwise support the
+transmission of mass, unsolicited, commercial advertising or
+solicitations via facsimile, electronic mail, or by telephone to
+entitites other than your own existing customers.  The
+compilation, repackaging, dissemination or other use of this data
+is expressly prohibited without prior written consent from this
+company. We reserve the right to modify these terms at any
+time. By submitting an inquiry, you agree to these terms of usage
+and limitations of warranty.  Please limit your queries to 10 per
+minute and one connection.
+
+   Domain Services Provided By:
+      Domain Bank, support@domainbank.com
+      http:///www.domainbank.com
+
+Registrant:
+   CONDENET INC
+   Four Times Square
+   New York, NY  10036
+   US
+
+   Registrar: DOMAINBANK
+   Domain Name: REDDIT.COM
+      Created on: 29-APR-05
+      Expires on: 29-APR-09
+      Last Updated on: 04-JUN-08
+
+   Administrative Contact:
+      ,   domain_admin@advancemags.com
+      Advance Magazine Group
+      4 Times Square
+      23rd Floor
+      New York, New York  10036
+      US
+      2122862860
+
+   Technical Contact:
+      ,   domains@advancemags.com
+      Advance Magazine Group
+      1201 N. Market St
+      Wilmington, DE  19801
+      US
+      3028304630
+
+
+   Domain servers in listed order:
+      ASIA1.AKAM.NET 
+      ASIA9.AKAM.NET 
+      AUS2.AKAM.NET 
+      NS1-1.AKAM.NET 
+      NS1-195.AKAM.NET 
+      USE4.AKAM.NET 
+      USW3.AKAM.NET 
+      USW5.AKAM.NET 
+
+End of Whois Information
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/samples/whois/shazow.net	Wed Oct 19 17:09:00 2011 +0900
@@ -0,0 +1,124 @@
+
+Whois Server Version 2.0
+
+Domain names in the .com and .net domains can now be registered
+with many different competing registrars. Go to http://www.internic.net
+for detailed information.
+
+   Domain Name: SHAZOW.NET
+   Registrar: NEW DREAM NETWORK, LLC
+   Whois Server: whois.dreamhost.com
+   Referral URL: http://www.dreamhost.com
+   Name Server: NS1.DREAMHOST.COM
+   Name Server: NS2.DREAMHOST.COM
+   Name Server: NS3.DREAMHOST.COM
+   Status: ok
+   Updated Date: 08-aug-2007
+   Creation Date: 13-sep-2003
+   Expiration Date: 13-sep-2009
+
+>>> Last update of whois database: Thu, 26 Jun 2008 21:39:08 EDT <<<
+
+NOTICE: The expiration date displayed in this record is the date the 
+registrar's sponsorship of the domain name registration in the registry is 
+currently set to expire. This date does not necessarily reflect the expiration 
+date of the domain name registrant's agreement with the sponsoring 
+registrar.  Users may consult the sponsoring registrar's Whois database to 
+view the registrar's reported date of expiration for this registration.
+
+TERMS OF USE: You are not authorized to access or query our Whois 
+database through the use of electronic processes that are high-volume and 
+automated except as reasonably necessary to register domain names or 
+modify existing registrations; the Data in VeriSign Global Registry 
+Services' ("VeriSign") Whois database is provided by VeriSign for 
+information purposes only, and to assist persons in obtaining information 
+about or related to a domain name registration record. VeriSign does not 
+guarantee its accuracy. By submitting a Whois query, you agree to abide 
+by the following terms of use: You agree that you may use this Data only 
+for lawful purposes and that under no circumstances will you use this Data 
+to: (1) allow, enable, or otherwise support the transmission of mass 
+unsolicited, commercial advertising or solicitations via e-mail, telephone, 
+or facsimile; or (2) enable high volume, automated, electronic processes 
+that apply to VeriSign (or its computer systems). The compilation, 
+repackaging, dissemination or other use of this Data is expressly 
+prohibited without the prior written consent of VeriSign. You agree not to 
+use electronic processes that are automated and high-volume to access or 
+query the Whois database except as reasonably necessary to register 
+domain names or modify existing registrations. VeriSign reserves the right 
+to restrict your access to the Whois database in its sole discretion to ensure 
+operational stability.  VeriSign may restrict or terminate your access to the 
+Whois database for failure to abide by these terms of use. VeriSign 
+reserves the right to modify these terms at any time. 
+
+The Registry database contains ONLY .COM, .NET, .EDU domains and
+Registrars.
+Legal Stuff:
+
+The information in DreamHost's whois database is to be used for
+informational purposes only, and to obtain information on a
+domain name registration. DreamHost does not guarantee its
+accuracy.
+
+You are not authorized to query or access DreamHost's whois
+database using high-volume, automated means without written
+permission from DreamHost.
+
+You are not authorized to query or access DreamHost's whois
+database in order to facilitate illegal activities, or to
+facilitate the use of unsolicited bulk email, telephone, or
+facsimile communications.
+
+You are not authorized to collect, repackage, or redistribute the
+information in DreamHost's whois database.
+
+DreamHost may, at its sole discretion, restrict your access to
+the whois database at any time, with or without notice. DreamHost
+may modify these Terms of Service at any time, with or without
+notice.
+
++++++++++++++++++++++++++++++++++++++++++++
+
+   Domain Name: shazow.net
+
+   Registrant Contact:
+      shazow.net Private Registrant         shazow.net@proxy.dreamhost.com
+      DreamHost Web Hosting
+      417 Associated Rd #324
+      Brea, CA 92821
+      US
+      +1.2139471032
+
+   Administrative Contact:
+      shazow.net Private Registrant         shazow.net@proxy.dreamhost.com
+      DreamHost Web Hosting
+      417 Associated Rd #324
+      Brea, CA 92821
+      US
+      +1.2139471032
+
+   Technical Contact:
+      shazow.net Private Registrant         shazow.net@proxy.dreamhost.com
+      DreamHost Web Hosting
+      417 Associated Rd #324
+      Brea, CA 92821
+      US
+      +1.2139471032
+
+   Billing Contact:
+      shazow.net Private Registrant         shazow.net@proxy.dreamhost.com
+      DreamHost Web Hosting
+      417 Associated Rd #324
+      Brea, CA 92821
+      US
+      +1.2139471032
+
+   Record created on 2003-09-12 21:43:11.
+   Record expires on 2009-09-12 21:43:11.
+
+   Domain servers in listed order:
+
+      ns1.dreamhost.com
+      ns2.dreamhost.com
+      ns3.dreamhost.com
+
+DreamHost whois server terms of service: http://whois.dreamhost.com/terms.html
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/samples/whois/slashdot.org	Wed Oct 19 17:09:00 2011 +0900
@@ -0,0 +1,83 @@
+NOTICE: Access to .ORG WHOIS information is provided to assist persons in 
+determining the contents of a domain name registration record in the Public Interest Registry
+registry database. The data in this record is provided by Public Interest Registry
+for informational purposes only, and Public Interest Registry does not guarantee its 
+accuracy.  This service is intended only for query-based access.  You agree 
+that you will use this data only for lawful purposes and that, under no 
+circumstances will you use this data to: (a) allow, enable, or otherwise 
+support the transmission by e-mail, telephone, or facsimile of mass 
+unsolicited, commercial advertising or solicitations to entities other than 
+the data recipient's own existing customers; or (b) enable high volume, 
+automated, electronic processes that send queries or data to the systems of 
+Registry Operator or any ICANN-Accredited Registrar, except as reasonably 
+necessary to register domain names or modify existing registrations.  All 
+rights reserved. Public Interest Registry reserves the right to modify these terms at any 
+time. By submitting this query, you agree to abide by this policy. 
+
+Domain ID:D2289308-LROR
+Domain Name:SLASHDOT.ORG
+Created On:05-Oct-1997 04:00:00 UTC
+Last Updated On:23-Jun-2008 20:00:11 UTC
+Expiration Date:04-Oct-2008 04:00:00 UTC
+Sponsoring Registrar:Tucows Inc. (R11-LROR)
+Status:OK
+Registrant ID:tuIIldggGKu3HogX
+Registrant Name:DNS Administration
+Registrant Organization:SourceForge, Inc.
+Registrant Street1:650 Castro St.
+Registrant Street2:Suite 450
+Registrant Street3:
+Registrant City:Mountain View
+Registrant State/Province:CA
+Registrant Postal Code:94041
+Registrant Country:US
+Registrant Phone:+1.6506942100
+Registrant Phone Ext.:
+Registrant FAX:
+Registrant FAX Ext.:
+Registrant Email:dns-admin@corp.sourceforge.com
+Admin ID:tupyrGGXKEFJLdE5
+Admin Name:DNS Administration
+Admin Organization:SourceForge, Inc.
+Admin Street1:650 Castro St.
+Admin Street2:Suite 450
+Admin Street3:
+Admin City:Mountain View
+Admin State/Province:CA
+Admin Postal Code:94041
+Admin Country:US
+Admin Phone:+1.6506942100
+Admin Phone Ext.:
+Admin FAX:
+Admin FAX Ext.:
+Admin Email:dns-admin@corp.sourceforge.com
+Tech ID:tuLQk02WUyJi47SS
+Tech Name:DNS Technical
+Tech Organization:SourceForge, Inc.
+Tech Street1:650 Castro St.
+Tech Street2:Suite 450
+Tech Street3:
+Tech City:Mountain View
+Tech State/Province:CA
+Tech Postal Code:94041
+Tech Country:US
+Tech Phone:+1.6506942100
+Tech Phone Ext.:
+Tech FAX:
+Tech FAX Ext.:
+Tech Email:dns-tech@corp.sourceforge.com
+Name Server:NS-1.CH3.SOURCEFORGE.COM
+Name Server:NS-2.CH3.SOURCEFORGE.COM
+Name Server:NS-3.CORP.SOURCEFORGE.COM
+Name Server: 
+Name Server: 
+Name Server: 
+Name Server: 
+Name Server: 
+Name Server: 
+Name Server: 
+Name Server: 
+Name Server: 
+Name Server: 
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/samples/whois/squatter.net	Wed Oct 19 17:09:00 2011 +0900
@@ -0,0 +1,102 @@
+
+Whois Server Version 2.0
+
+Domain names in the .com and .net domains can now be registered
+with many different competing registrars. Go to http://www.internic.net
+for detailed information.
+
+   Domain Name: SQUATTER.NET
+   Registrar: DOMAINDISCOVER
+   Whois Server: whois.domaindiscover.com
+   Referral URL: http://www.domaindiscover.com
+   Name Server: NS1.SBRACK.COM
+   Name Server: NS2.SBRACK.COM
+   Status: clientTransferProhibited
+   Updated Date: 07-nov-2007
+   Creation Date: 06-nov-1999
+   Expiration Date: 06-nov-2008
+
+>>> Last update of whois database: Thu, 26 Jun 2008 21:40:25 EDT <<<
+
+NOTICE: The expiration date displayed in this record is the date the 
+registrar's sponsorship of the domain name registration in the registry is 
+currently set to expire. This date does not necessarily reflect the expiration 
+date of the domain name registrant's agreement with the sponsoring 
+registrar.  Users may consult the sponsoring registrar's Whois database to 
+view the registrar's reported date of expiration for this registration.
+
+TERMS OF USE: You are not authorized to access or query our Whois 
+database through the use of electronic processes that are high-volume and 
+automated except as reasonably necessary to register domain names or 
+modify existing registrations; the Data in VeriSign Global Registry 
+Services' ("VeriSign") Whois database is provided by VeriSign for 
+information purposes only, and to assist persons in obtaining information 
+about or related to a domain name registration record. VeriSign does not 
+guarantee its accuracy. By submitting a Whois query, you agree to abide 
+by the following terms of use: You agree that you may use this Data only 
+for lawful purposes and that under no circumstances will you use this Data 
+to: (1) allow, enable, or otherwise support the transmission of mass 
+unsolicited, commercial advertising or solicitations via e-mail, telephone, 
+or facsimile; or (2) enable high volume, automated, electronic processes 
+that apply to VeriSign (or its computer systems). The compilation, 
+repackaging, dissemination or other use of this Data is expressly 
+prohibited without the prior written consent of VeriSign. You agree not to 
+use electronic processes that are automated and high-volume to access or 
+query the Whois database except as reasonably necessary to register 
+domain names or modify existing registrations. VeriSign reserves the right 
+to restrict your access to the Whois database in its sole discretion to ensure 
+operational stability.  VeriSign may restrict or terminate your access to the 
+Whois database for failure to abide by these terms of use. VeriSign 
+reserves the right to modify these terms at any time. 
+
+The Registry database contains ONLY .COM, .NET, .EDU domains and
+Registrars.
+This WHOIS database is provided for information purposes only. We do
+not guarantee the accuracy of this data. The following uses of this 
+system are expressly prohibited: (1) use of this system for unlawful 
+purposes; (2) use of this system to collect information used in the 
+mass transmission of unsolicited commercial messages in any medium; 
+(3) use of high volume, automated, electronic processes against this 
+database. By submitting this query, you agree to abide by this 
+policy.
+
+Registrant:
+   CustomPC
+   4047 N Bayberry St
+   Wichita, KS 67226-2418
+   US
+
+   Domain Name: SQUATTER.NET
+
+   Administrative Contact:
+      CustomPC
+      Derryl Brack
+      4047 N Bayberry St
+      Wichita, KS 67226-2418
+      US
+      3166402868
+      dbrack@cpcsales.com
+
+   Technical Contact, Zone Contact:
+      CustomPC
+      Brack, Derryl
+      4047 N Bayberry St
+      Wichita, KS 67226-2418
+      US
+      316-683-5010
+      316-683-5010 [fax]
+      brack@cpcsales.com
+
+   Domain created on 06-Nov-1999
+   Domain expires on 06-Nov-2008
+   Last updated on 05-Nov-2007
+
+   Domain servers in listed order:
+
+      NS1.SBRACK.COM              
+      NS2.SBRACK.COM              
+
+Domain registration and hosting powered by DomainDiscover
+As low as $9/year, including FREE: responsive toll-free support, 
+URL/frame/email forwarding, easy management system, and full featured DNS.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/samples/whois/urlowl.com	Wed Oct 19 17:09:00 2011 +0900
@@ -0,0 +1,122 @@
+
+Whois Server Version 2.0
+
+Domain names in the .com and .net domains can now be registered
+with many different competing registrars. Go to http://www.internic.net
+for detailed information.
+
+   Domain Name: URLOWL.COM
+   Registrar: NEW DREAM NETWORK, LLC
+   Whois Server: whois.dreamhost.com
+   Referral URL: http://www.dreamhost.com
+   Name Server: NS1.LINODE.COM
+   Name Server: NS2.LINODE.COM
+   Status: ok
+   Updated Date: 14-apr-2008
+   Creation Date: 14-apr-2008
+   Expiration Date: 14-apr-2009
+
+>>> Last update of whois database: Sun, 31 Aug 2008 00:18:23 UTC <<<
+
+NOTICE: The expiration date displayed in this record is the date the 
+registrar's sponsorship of the domain name registration in the registry is 
+currently set to expire. This date does not necessarily reflect the expiration 
+date of the domain name registrant's agreement with the sponsoring 
+registrar.  Users may consult the sponsoring registrar's Whois database to 
+view the registrar's reported date of expiration for this registration.
+
+TERMS OF USE: You are not authorized to access or query our Whois 
+database through the use of electronic processes that are high-volume and 
+automated except as reasonably necessary to register domain names or 
+modify existing registrations; the Data in VeriSign Global Registry 
+Services' ("VeriSign") Whois database is provided by VeriSign for 
+information purposes only, and to assist persons in obtaining information 
+about or related to a domain name registration record. VeriSign does not 
+guarantee its accuracy. By submitting a Whois query, you agree to abide 
+by the following terms of use: You agree that you may use this Data only 
+for lawful purposes and that under no circumstances will you use this Data 
+to: (1) allow, enable, or otherwise support the transmission of mass 
+unsolicited, commercial advertising or solicitations via e-mail, telephone, 
+or facsimile; or (2) enable high volume, automated, electronic processes 
+that apply to VeriSign (or its computer systems). The compilation, 
+repackaging, dissemination or other use of this Data is expressly 
+prohibited without the prior written consent of VeriSign. You agree not to 
+use electronic processes that are automated and high-volume to access or 
+query the Whois database except as reasonably necessary to register 
+domain names or modify existing registrations. VeriSign reserves the right 
+to restrict your access to the Whois database in its sole discretion to ensure 
+operational stability.  VeriSign may restrict or terminate your access to the 
+Whois database for failure to abide by these terms of use. VeriSign 
+reserves the right to modify these terms at any time. 
+
+The Registry database contains ONLY .COM, .NET, .EDU domains and
+Registrars.
+Legal Stuff:
+
+The information in DreamHost's whois database is to be used for
+informational purposes only, and to obtain information on a
+domain name registration. DreamHost does not guarantee its
+accuracy.
+
+You are not authorized to query or access DreamHost's whois
+database using high-volume, automated means without written
+permission from DreamHost.
+
+You are not authorized to query or access DreamHost's whois
+database in order to facilitate illegal activities, or to
+facilitate the use of unsolicited bulk email, telephone, or
+facsimile communications.
+
+You are not authorized to collect, repackage, or redistribute the
+information in DreamHost's whois database.
+
+DreamHost may, at its sole discretion, restrict your access to
+the whois database at any time, with or without notice. DreamHost
+may modify these Terms of Service at any time, with or without
+notice.
+
++++++++++++++++++++++++++++++++++++++++++++
+
+   Domain Name: urlowl.com
+
+   Registrant Contact:
+      urlowl.com Private Registrant         urlowl.com@proxy.dreamhost.com
+      A Happy DreamHost Customer
+      417 Associated Rd #324
+      Brea, CA 92821
+      US
+      +1.2139471032
+
+   Administrative Contact:
+      urlowl.com Private Registrant         urlowl.com@proxy.dreamhost.com
+      A Happy DreamHost Customer
+      417 Associated Rd #324
+      Brea, CA 92821
+      US
+      +1.2139471032
+
+   Technical Contact:
+      urlowl.com Private Registrant         urlowl.com@proxy.dreamhost.com
+      A Happy DreamHost Customer
+      417 Associated Rd #324
+      Brea, CA 92821
+      US
+      +1.2139471032
+
+   Billing Contact:
+      urlowl.com Private Registrant         urlowl.com@proxy.dreamhost.com
+      A Happy DreamHost Customer
+      417 Associated Rd #324
+      Brea, CA 92821
+      US
+      +1.2139471032
+
+   Record created on 2008-04-14 14:34:20.
+   Record expires on 2009-04-14 14:34:20.
+
+   Domain servers in listed order:
+
+      ns1.linode.com
+      ns2.linode.com
+
+DreamHost whois server terms of service: http://whois.dreamhost.com/terms.html
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/test_parser.py	Wed Oct 19 17:09:00 2011 +0900
@@ -0,0 +1,76 @@
+import unittest
+
+import os
+import sys
+sys.path.append('../')
+
+import time
+
+import simplejson
+from glob import glob
+
+from pywhois.parser import WhoisEntry, cast_date
+
+class TestParser(unittest.TestCase):
+    def test_com_expiration(self):
+        data = """
+            Status: ok
+            Updated Date: 14-apr-2008
+            Creation Date: 14-apr-2008
+            Expiration Date: 14-apr-2009
+            
+            >>> Last update of whois database: Sun, 31 Aug 2008 00:18:23 UTC <<<
+        """
+        w = WhoisEntry.load('urlowl.com', data)
+        expires = w.get('expiration_date')
+        self.assertEquals(expires, ['14-apr-2009'])
+
+    def test_cast_date(self):
+        dates = ['14-apr-2008', '2008-04-14']
+        for d in dates:
+            r = time.strftime('%Y-%m-%d', cast_date(d))
+            self.assertEquals(r, '2008-04-14')
+
+    def test_com_allsamples(self):
+        """
+        Iterate over all of the sample/whois/*.com files, read the data,
+        parse it, and compare to the expected values in sample/expected/.
+        Only keys defined in keys_to_test will be tested.
+        
+        To generate fresh expected value dumps, see NOTE below.
+        """
+        keys_to_test = ['domain_name', 'expiration_date', 'updated_date', 'creation_date', 'status']
+        fail = 0
+        for path in glob('test/samples/whois/*.com'):
+            # Parse whois data
+            domain = os.path.basename(path)
+            whois_fp = open(path)
+            data = whois_fp.read()
+            
+            w = WhoisEntry.load(domain, data)
+            results = {}
+            for key in keys_to_test:
+                results[key] = w.get(key)
+
+            # Load expected result
+            expected_fp = open(os.path.join('test/samples/expected/', domain))
+            expected_results = simplejson.load(expected_fp)
+            
+            # NOTE: Toggle condition below to write expected results from the parse results
+            # This will overwrite the existing expected results. Only do this if you've manually
+            # confirmed that the parser is generating correct values at its current state.
+            if False:
+                expected_fp = open(os.path.join('test/samples/expected/', domain), 'w')
+                expected_results = simplejson.dump(results, expected_fp)
+                continue
+            
+            # Compare each key
+            for key in results:
+                result = results.get(key)
+                expected = expected_results.get(key)
+                if expected != result:
+                    print "%s \t(%s):\t %s != %s" % (domain, key, result, expected)
+                    fail += 1
+            
+        if fail:
+            self.fail("%d sample whois attributes were not parsed properly!" % fail)
\ No newline at end of file