fixed test cases
authorRichard Baron Penman
Tue, 08 Jan 2013 18:23:18 +1100
changeset 12 c57439b500cb
parent 11 5083c26d8f93
child 13 f8d7b881701d
fixed test cases
pywhois/__init__.py
pywhois/parser.py
pywhois/whois.py
setup.py
test/test_parser.py
whois/__init__.py
whois/parser.py
whois/whois.py
--- a/pywhois/__init__.py	Tue Jan 08 16:43:03 2013 +1100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-import re
-import sys
-import subprocess
-import socket
-from parser import WhoisEntry
-from whois import NICClient
-
-
-def whois(url):
-    # clean domain to expose netloc
-    domain = extract_domain(url)
-    try:
-        raise OSError()
-        # 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)
-    print text
-    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'
-    >>> extract_domain('http://blog.webscraping.com')
-    'webscraping.com'
-    >>> extract_domain('69.59.196.211')
-    'stackoverflow.com'
-    """
-    if re.match(r'\d+.\d+.\d+.\d+', url):
-        # this is an IP address
-        return socket.gethostbyaddr(url)[0]
-
-    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)
--- a/pywhois/parser.py	Tue Jan 08 16:43:03 2013 +1100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,451 +0,0 @@
-# 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
-from datetime import datetime
-   
-
-class PywhoisError(Exception):
-    pass
-
-
-def cast_date(s):
-    """Convert any date string found in WHOIS to a datetime object.
-    """
-    known_formats = [
-        '%d-%b-%Y', 				# 02-jan-2000
-        '%Y-%m-%d', 				# 2000-01-02
-        '%d.%m.%Y', 				# 2000-01-02
-        '%Y.%m.%d',                 # 2000.01.02
-        '%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 known_format in known_formats:
-        try:
-            return datetime.strptime(s.strip(), known_format)
-        except ValueError, e:
-            pass # Wrong format, keep trying
-    return s
-
-
-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:
-            values = re.findall(whois_regex, self.text)
-            # try casting to date format
-            values = [cast_date(value.strip()) for value in values]
-            if len(values) == 1:
-                values = values[0]
-            setattr(self, attr, values)
-            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 domain.endswith('.com'):
-            return WhoisCom(domain, text)
-        elif domain.endswith('.net'):
-            return WhoisNet(domain, text)
-        elif domain.endswith('.org'):
-            return WhoisOrg(domain, text)
-        elif domain.endswith('.name'):
-        	return WhoisName(domain, text)
-        elif domain.endswith('.me'):
-        	return WhoisMe(domain, text)
-        elif domain.endswith('.ru'):
-            return WhoisRu(domain, text)
-        elif domain.endswith('.us'):
-        	return WhoisUs(domain, text)
-        elif domain.endswith('.uk'):
-        	return WhoisUk(domain, text)
-        elif domain.endswith('.fr'):
-            return WhoisFr(domain, text)
-        elif domain.endswith('.fi'):
-        	return WhoisFi(domain, text)
-        elif domain.endswith('.jp'):
-            return WhoisJp(domain, text)
-        elif domain.endswith('.pl'):
-            return WhoisPl(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 WhoisPl(WhoisEntry):
-   """Whois parser for .uk domains
-   """
-   regex = {
-       'domain_name':                    'DOMAIN NAME:\s*(.+)\n',
-       'registrar':                      'REGISTRAR:\n\s*(.+)',
-       'registrar_url':                  'URL:\s*(.+)',        # not available
-       'status':                         'Registration status:\n\s*(.+)',  # not available
-       'registrant_name':                'Registrant:\n\s*(.+)',   # not available
-       'creation_date':                  'created:\s*(.+)\n',
-       'expiration_date':                'renewal date:\s*(.+)',
-       'updated_date':                   'last modified:\s*(.+)\n',
-   }
-   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':                'Expiry date:\s*(.+)',
-        'updated_date':                   'Last updated:\s*(.+)',
-        'name_servers':                   'Name servers:\s*(.+)',
-	}
-    def __init__(self, domain, text):
-        if 'Not found:' in text:
-            raise PywhoisError(text)
-        else:
-            WhoisEntry.__init__(self, domain, text, self.regex)
-
-
-class WhoisFr(WhoisEntry):
-    """Whois parser for .fr domains
-    """
-    regex = {
-        'domain_name': 'domain:\s*(.+)',
-        'registrar': 'registrar:\s*(.+)',
-        'creation_date': 'created:\s*(.+)',
-        'expiration_date': 'anniversary:\s*(.+)',
-        'name_servers': 'nserver:\s*(.+)',  # list of name servers
-        'status': 'status:\s*(.+)',  # list of statuses
-        'emails': '[\w.-]+@[\w.-]+\.[\w]{2,4}',  # list of email addresses
-        'updated_date': 'last-update:\s*(.+)',
-    }
-
-    def __init__(self, domain, text):
-        if text.strip() == 'No entries found':
-            raise PywhoisError(text)
-        else:
-            WhoisEntry.__init__(self, domain, text, self.regex)
-
-
-class WhoisFi(WhoisEntry):
-    """Whois parser for .fi domains
-    """
-    regex = {
-        'domain_name':                    'domain:\s*([\S]+)',
-        'registrant_name':                'descr:\s*([\S\ ]+)',
-        'registrant_address':             'address:\s*([\S\ ]+)',
-        'registrant_phone':               'phone:\s*([\S\ ]+)',
-        'status':                         'status:\s*([\S]+)',  # list of statuses
-        'creation_date':                  'created:\s*([\S]+)',
-        'updated_date':                   'modified:\s*([\S]+)',
-        'expiration_date':                'expires:\s*([\S]+)',
-        'name_servers':                   'nserver:\s*([\S]+) \[(\S+)\]',  # list of name servers
-        'dnssec':                   'dnssec:\s*([\S]+)',  # 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 WhoisJp(WhoisEntry):
-    """Whois parser for .jp domains
-    """
-    regex = {
-        'domain_name': 'a\. \[Domain Name\]\s*(.+)',
-        'registrant_org': 'g\. \[Organization\](.+)',
-        'creation_date': r'\[Registered Date\]\s*(.+)',
-        'name_servers': 'p\. \[Name Server\]\s*(.+)',  # list of name servers
-        'updated_date':  '\[Last Update\]\s?(.+)',
-        'status': '\[State\]\s*(.+)',  # list of statuses
-    }
-
-    def __init__(self, domain, text):
-        if text.strip() == 'No entries found':
-            raise PywhoisError(text)
-        else:
-            WhoisEntry.__init__(self, domain, text, self.regex)
--- a/pywhois/whois.py	Tue Jan 08 16:43:03 2013 +1100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,275 +0,0 @@
-"""
-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
-
-def enforce_ascii(a):
-    if isinstance(a, str) or isinstance(a, unicode):
-        # return a.encode('ascii', 'replace')
-        r = ""
-        for i in a:
-            if ord(i) >= 128:
-                r += "?"
-            else:
-                r += i
-        return r
-    else:
-        return a
-
-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"
-    DENICHOST           = "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.
-        """
-        #print 'finding whois server'
-        #print 'parameters:', buf, 'hostname', hostname
-        nhost = None
-        parts_index = 1
-        start = buf.find(NICClient.WHOIS_SERVER_ID)
-        #print 'start', start
-        if (start == -1):
-            start = buf.find(NICClient.WHOIS_ORG_SERVER_ID)
-            parts_index = 2
-       
-        if (start > -1):  
-            end = buf[start:].find('\n')
-            #print 'end:', end
-            whois_line = buf[start:end+start]
-            #print 'whois_line', whois_line
-            nhost = whois_line.split(NICClient.WHOIS_SERVER_ID+' ').pop()
-            nhost = nhost.split('http://').pop()
-            #if the whois address is domain.tld/something then
-            #s.connect((hostname, 43)) does not work
-            if nhost.count('/') > 0:
-                nhost = None
-            #print 'nhost:',nhost
-        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
-        """
-        #print 'Performing the whois'
-        #print 'parameters given:', query, hostname, flags
-        #pdb.set_trace()
-        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        s.connect((hostname, 43))
-        """send takes bytes as an input
-        """
-        queryBytes = None
-        if (hostname == NICClient.DENICHOST):
-            #print 'the domain is in NIC DENIC'
-            queryBytes = ("-T dn,ace -C UTF-8 " + query + "\r\n").encode()
-            #print 'queryBytes:', queryBytes
-        else:
-            queryBytes = (query  + "\r\n").encode()        
-        s.send(queryBytes)
-        """recv returns bytes
-        """
-        #print s
-        response = b''
-        while True:
-            d = s.recv(4096)
-            response += d
-            if not d:
-                break
-        s.close()
-        #pdb.set_trace()
-        nhost = None
-        #print 'response', response
-        response = enforce_ascii(response)
-        if (flags & NICClient.WHOIS_RECURSE and nhost == None):
-            #print 'Inside first if'
-            nhost = self.findwhois_server(response.decode(), hostname)
-            #print 'nhost is:', nhost
-        if (nhost != None):
-            #print 'inside second if'
-            response += self.whois(query, nhost, 0)
-            #print 'response', response
-        #print 'returning whois response'
-        return response.decode()
-   
-    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"""
-        #print 'whois_lookup'
-        nichost = None
-        #pdb.set_trace()
-        # this would be the case when this function is called by other than main
-        if (options == None):                    
-            options = {}
-     
-        if ( (not 'whoishost' in options or options['whoishost'] == None)
-            and (not 'country' in options or options['country'] == None)):
-            self.use_qnichost = True
-            options['whoishost'] = NICClient.NICHOST
-            if ( not (flags & NICClient.WHOIS_QUICK)):
-                flags |= NICClient.WHOIS_RECURSE
-           
-        if ('country' in options 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)
-        #print 'whois_lookup finished'
-        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))
-
-
--- a/setup.py	Tue Jan 08 16:43:03 2013 +1100
+++ b/setup.py	Tue Jan 08 18:23:18 2013 +1100
@@ -1,10 +1,10 @@
 from setuptools import setup, find_packages
 import sys, os
 
-version = '0.1'
+version = '0.2'
 
 setup(
-    name='whois',
+    name='python-whois',
     version=version,
     description="Whois querying and parsing of domain registration information.",
     long_description='',
@@ -16,13 +16,13 @@
         'Programming Language :: Python',
         'Topic :: Internet :: WWW/HTTP'
     ],
-    keywords='whois',
+    keywords='whois, python',
     author='Richard Penman',
     author_email='richard@webscraping.com',
     url='http://code.google.com/p/pywhois/',
     license='MIT',
-    packages=['pywhois'],
-    package_dir={'pywhois':'pywhois'},
+    packages=['whois'],
+    package_dir={'whois':'whois'},
     include_package_data=True,
     zip_safe=False,
 )
--- a/test/test_parser.py	Tue Jan 08 16:43:03 2013 +1100
+++ b/test/test_parser.py	Tue Jan 08 18:23:18 2013 +1100
@@ -4,12 +4,12 @@
 import sys
 sys.path.append('../')
 
-import time
+import datetime
 
 import simplejson
 from glob import glob
 
-from pywhois.parser import WhoisEntry, cast_date
+from whois.parser import WhoisEntry, cast_date
 
 class TestParser(unittest.TestCase):
     def test_com_expiration(self):
@@ -22,13 +22,13 @@
             >>> 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'])
+        expires = w.expiration_date.strftime('%Y-%m-%d')
+        self.assertEquals(expires, '2009-04-14')
 
     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))
+            r = cast_date(d).strftime('%Y-%m-%d')
             self.assertEquals(r, '2008-04-14')
 
     def test_com_allsamples(self):
@@ -73,4 +73,8 @@
                     fail += 1
             
         if fail:
-            self.fail("%d sample whois attributes were not parsed properly!" % fail)
\ No newline at end of file
+            self.fail("%d sample whois attributes were not parsed properly!" % fail)
+
+
+if __name__ == '__main__':
+    unittest.main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/whois/__init__.py	Tue Jan 08 18:23:18 2013 +1100
@@ -0,0 +1,55 @@
+import re
+import sys
+import subprocess
+import socket
+from parser import WhoisEntry
+from whois import NICClient
+
+
+def whois(url):
+    # clean domain to expose netloc
+    domain = extract_domain(url)
+    try:
+        raise OSError()
+        # 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'
+    >>> extract_domain('http://blog.webscraping.com')
+    'webscraping.com'
+    >>> extract_domain('69.59.196.211')
+    'stackoverflow.com'
+    """
+    if re.match(r'\d+.\d+.\d+.\d+', url):
+        # this is an IP address
+        return socket.gethostbyaddr(url)[0]
+
+    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/whois/parser.py	Tue Jan 08 18:23:18 2013 +1100
@@ -0,0 +1,451 @@
+# 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
+from datetime import datetime
+   
+
+class PywhoisError(Exception):
+    pass
+
+
+def cast_date(s):
+    """Convert any date string found in WHOIS to a datetime object.
+    """
+    known_formats = [
+        '%d-%b-%Y', 				# 02-jan-2000
+        '%Y-%m-%d', 				# 2000-01-02
+        '%d.%m.%Y', 				# 2000-01-02
+        '%Y.%m.%d',                 # 2000.01.02
+        '%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 known_format in known_formats:
+        try:
+            return datetime.strptime(s.strip(), known_format)
+        except ValueError as e:
+            pass # Wrong format, keep trying
+    return s
+
+
+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:
+            values = re.findall(whois_regex, self.text, re.IGNORECASE)
+            # try casting to date format
+            values = [cast_date(value.strip()) for value in values]
+            if len(values) == 1:
+                values = values[0]
+            setattr(self, attr, values)
+            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 domain.endswith('.com'):
+            return WhoisCom(domain, text)
+        elif domain.endswith('.net'):
+            return WhoisNet(domain, text)
+        elif domain.endswith('.org'):
+            return WhoisOrg(domain, text)
+        elif domain.endswith('.name'):
+        	return WhoisName(domain, text)
+        elif domain.endswith('.me'):
+        	return WhoisMe(domain, text)
+        elif domain.endswith('.ru'):
+            return WhoisRu(domain, text)
+        elif domain.endswith('.us'):
+        	return WhoisUs(domain, text)
+        elif domain.endswith('.uk'):
+        	return WhoisUk(domain, text)
+        elif domain.endswith('.fr'):
+            return WhoisFr(domain, text)
+        elif domain.endswith('.fi'):
+        	return WhoisFi(domain, text)
+        elif domain.endswith('.jp'):
+            return WhoisJp(domain, text)
+        elif domain.endswith('.pl'):
+            return WhoisPl(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 WhoisPl(WhoisEntry):
+   """Whois parser for .uk domains
+   """
+   regex = {
+       'domain_name':                    'DOMAIN NAME:\s*(.+)\n',
+       'registrar':                      'REGISTRAR:\n\s*(.+)',
+       'registrar_url':                  'URL:\s*(.+)',        # not available
+       'status':                         'Registration status:\n\s*(.+)',  # not available
+       'registrant_name':                'Registrant:\n\s*(.+)',   # not available
+       'creation_date':                  'created:\s*(.+)\n',
+       'expiration_date':                'renewal date:\s*(.+)',
+       'updated_date':                   'last modified:\s*(.+)\n',
+   }
+   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':                'Expiry date:\s*(.+)',
+        'updated_date':                   'Last updated:\s*(.+)',
+        'name_servers':                   'Name servers:\s*(.+)',
+	}
+    def __init__(self, domain, text):
+        if 'Not found:' in text:
+            raise PywhoisError(text)
+        else:
+            WhoisEntry.__init__(self, domain, text, self.regex)
+
+
+class WhoisFr(WhoisEntry):
+    """Whois parser for .fr domains
+    """
+    regex = {
+        'domain_name': 'domain:\s*(.+)',
+        'registrar': 'registrar:\s*(.+)',
+        'creation_date': 'created:\s*(.+)',
+        'expiration_date': 'anniversary:\s*(.+)',
+        'name_servers': 'nserver:\s*(.+)',  # list of name servers
+        'status': 'status:\s*(.+)',  # list of statuses
+        'emails': '[\w.-]+@[\w.-]+\.[\w]{2,4}',  # list of email addresses
+        'updated_date': 'last-update:\s*(.+)',
+    }
+
+    def __init__(self, domain, text):
+        if text.strip() == 'No entries found':
+            raise PywhoisError(text)
+        else:
+            WhoisEntry.__init__(self, domain, text, self.regex)
+
+
+class WhoisFi(WhoisEntry):
+    """Whois parser for .fi domains
+    """
+    regex = {
+        'domain_name':                    'domain:\s*([\S]+)',
+        'registrant_name':                'descr:\s*([\S\ ]+)',
+        'registrant_address':             'address:\s*([\S\ ]+)',
+        'registrant_phone':               'phone:\s*([\S\ ]+)',
+        'status':                         'status:\s*([\S]+)',  # list of statuses
+        'creation_date':                  'created:\s*([\S]+)',
+        'updated_date':                   'modified:\s*([\S]+)',
+        'expiration_date':                'expires:\s*([\S]+)',
+        'name_servers':                   'nserver:\s*([\S]+) \[(\S+)\]',  # list of name servers
+        'dnssec':                   'dnssec:\s*([\S]+)',  # 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 WhoisJp(WhoisEntry):
+    """Whois parser for .jp domains
+    """
+    regex = {
+        'domain_name': 'a\. \[Domain Name\]\s*(.+)',
+        'registrant_org': 'g\. \[Organization\](.+)',
+        'creation_date': r'\[Registered Date\]\s*(.+)',
+        'name_servers': 'p\. \[Name Server\]\s*(.+)',  # list of name servers
+        'updated_date':  '\[Last Update\]\s?(.+)',
+        'status': '\[State\]\s*(.+)',  # list of statuses
+    }
+
+    def __init__(self, domain, text):
+        if text.strip() == 'No entries found':
+            raise PywhoisError(text)
+        else:
+            WhoisEntry.__init__(self, domain, text, self.regex)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/whois/whois.py	Tue Jan 08 18:23:18 2013 +1100
@@ -0,0 +1,273 @@
+"""
+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
+
+def enforce_ascii(a):
+    if isinstance(a, str) or isinstance(a, unicode):
+        # return a.encode('ascii', 'replace')
+        r = ""
+        for i in a:
+            if ord(i) >= 128:
+                r += "?"
+            else:
+                r += i
+        return r
+    else:
+        return a
+
+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"
+    DENICHOST           = "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.
+        """
+        #print 'finding whois server'
+        #print 'parameters:', buf, 'hostname', hostname
+        nhost = None
+        parts_index = 1
+        start = buf.find(NICClient.WHOIS_SERVER_ID)
+        #print 'start', start
+        if (start == -1):
+            start = buf.find(NICClient.WHOIS_ORG_SERVER_ID)
+            parts_index = 2
+       
+        if (start > -1):  
+            end = buf[start:].find('\n')
+            #print 'end:', end
+            whois_line = buf[start:end+start]
+            #print 'whois_line', whois_line
+            nhost = whois_line.split(NICClient.WHOIS_SERVER_ID+' ').pop()
+            nhost = nhost.split('http://').pop()
+            #if the whois address is domain.tld/something then
+            #s.connect((hostname, 43)) does not work
+            if nhost.count('/') > 0:
+                nhost = None
+            #print 'nhost:',nhost
+        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
+        """
+        #print 'Performing the whois'
+        #print 'parameters given:', query, hostname, flags
+        #pdb.set_trace()
+        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        s.connect((hostname, 43))
+        """send takes bytes as an input
+        """
+        queryBytes = None
+        if (hostname == NICClient.DENICHOST):
+            #print 'the domain is in NIC DENIC'
+            queryBytes = ("-T dn,ace -C UTF-8 " + query + "\r\n").encode()
+            #print 'queryBytes:', queryBytes
+        else:
+            queryBytes = (query  + "\r\n").encode()        
+        s.send(queryBytes)
+        """recv returns bytes
+        """
+        #print s
+        response = b''
+        while True:
+            d = s.recv(4096)
+            response += d
+            if not d:
+                break
+        s.close()
+        #pdb.set_trace()
+        nhost = None
+        #print 'response', response
+        response = enforce_ascii(response)
+        if (flags & NICClient.WHOIS_RECURSE and nhost == None):
+            #print 'Inside first if'
+            nhost = self.findwhois_server(response.decode(), hostname)
+            #print 'nhost is:', nhost
+        if (nhost != None):
+            #print 'inside second if'
+            response += self.whois(query, nhost, 0)
+            #print 'response', response
+        #print 'returning whois response'
+        return response.decode()
+   
+    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"""
+        #print 'whois_lookup'
+        nichost = None
+        #pdb.set_trace()
+        # this would be the case when this function is called by other than main
+        if (options == None):                    
+            options = {}
+     
+        if ( (not 'whoishost' in options or options['whoishost'] == None)
+            and (not 'country' in options or options['country'] == None)):
+            self.use_qnichost = True
+            options['whoishost'] = NICClient.NICHOST
+            if ( not (flags & NICClient.WHOIS_QUICK)):
+                flags |= NICClient.WHOIS_RECURSE
+           
+        if ('country' in options 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)
+        #print 'whois_lookup finished'
+        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))