From 2a96927968d139853ea38688d0103591c8895032 Mon Sep 17 00:00:00 2001 From: secynic Date: Mon, 16 Sep 2013 10:41:16 -0500 Subject: [PATCH] 0.1.6 --- CHANGES.rst | 7 ++- README.rst | 33 ++++++++++--- ipwhois/__init__.py | 118 +++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 142 insertions(+), 16 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 9ff0117..4950f54 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,9 +1,12 @@ Changelog ========= -0.1.6 () +0.1.6 (2013-09-16) +------------------ -- +- Added IPWhois.get_host() to resolve hostname information. +- Added address and postal_code fields to parsed results. +- Normalized single/double quote use. 0.1.5 (2013-09-13) ------------------ diff --git a/README.rst b/README.rst index d26d7f7..270b3ca 100644 --- a/README.rst +++ b/README.rst @@ -14,7 +14,7 @@ Typical usage:: >>>> import ipwhois >>>> from pprint import pprint - >>>> obj = ipwhois.IPWhois("74.125.225.229") + >>>> obj = ipwhois.IPWhois('74.125.225.229') >>>> results = obj.lookup(False) >>>> pprint(results) @@ -24,11 +24,13 @@ Typical usage:: 'asn_country_code': 'US', 'asn_date': '2007-03-13', 'asn_registry': 'arin', - 'nets': [{'cidr': '74.125.0.0/16', + 'nets': [{'address': '1600 Amphitheatre Parkway', + 'cidr': '74.125.0.0/16', 'city': 'Mountain View', 'country': 'US', 'description': 'Google Inc.', 'name': 'GOOGLE', + 'postal_code': '94043', 'state': 'CA'}], 'query': '74.125.225.229', 'raw': None @@ -39,7 +41,7 @@ REST (HTTP):: >>>> import ipwhois >>>> from pprint import pprint - >>>> obj = ipwhois.IPWhois("74.125.225.229") + >>>> obj = ipwhois.IPWhois('74.125.225.229') >>>> results = obj.lookup_rws(False) >>>> pprint(results) @@ -49,17 +51,21 @@ REST (HTTP):: 'asn_country_code': 'US', 'asn_date': '2007-03-13', 'asn_registry': 'arin', - 'nets': [{'cidr': '74.0.0.0/8', + 'nets': [{'address': '3635 Concorde Parkway\nSuite 200', + 'cidr': '74.0.0.0/8', 'city': 'Chantilly', 'country': 'US', 'description': 'American Registry for Internet Numbers', 'name': 'NET74', + 'postal_code': '20151', 'state': 'VA'}, - {'cidr': '74.125.0.0/16', + {'address': '1600 Amphitheatre Parkway', + 'cidr': '74.125.0.0/16', 'city': 'Mountain View', 'country': 'US', 'description': 'Google Inc.', 'name': 'GOOGLE', + 'postal_code': '94043', 'state': 'CA'}], 'query': '74.125.225.229', 'raw': None @@ -68,14 +74,25 @@ REST (HTTP):: Proxy (Optional before ipwhois.IPWhois.lookup_rws()):: >>>> import ipwhois - >>>> ipwhois.set_proxy("192.168.0.1", "80", "some_username", "some_password") + >>>> ipwhois.set_proxy('192.168.0.1', '80', 'some_username', 'some_password') + +Hostname:: + + >>>> import ipwhois + >>>> from pprint import pprint + + >>>> obj = ipwhois.IPWhois('74.125.225.229') + >>>> results = obj.get_host() + >>>> pprint(results) + ('dfw06s26-in-f5.1e100.net', [], ['74.125.225.229']) + Countries:: >>>> import ipwhois >>>> countries = ipwhois.get_countries() - >>>> obj = ipwhois.IPWhois("74.125.225.229") + >>>> obj = ipwhois.IPWhois('74.125.225.229') >>>> results = obj.lookup(False) >>>> print(countries[results['nets'][0]['country']]) @@ -95,7 +112,7 @@ Latest version from GitHub:: Parsing ======= -Parsing is currently limited to CIDR, country, description, name, and state fields. This is assuming that those fields are present. +Parsing is currently limited to CIDR, country, description, name, state, city, address, and postal_code fields. This is assuming that those fields are present. Some IPs have parent networks listed. The parser attempts to recognize this, and break the networks into individual dictionaries. If a single network has multiple CIDRs, they will be separated by ', '. diff --git a/ipwhois/__init__.py b/ipwhois/__init__.py index 5fb5458..da7d60c 100644 --- a/ipwhois/__init__.py +++ b/ipwhois/__init__.py @@ -58,7 +58,9 @@ 'description': '^(OrgName|CustName):[^\S\n]+(.+)$', 'country': '^(Country):[^\S\n]+(.+)$', 'state': '^(StateProv):[^\S\n]+(.+)$', - 'city': '^(City):[^\S\n]+(.+)$' + 'city': '^(City):[^\S\n]+(.+)$', + 'address': '^(Address):[^\S\n]+(.+)$', + 'postal_code': '^(PostalCode):[^\S\n]+(.+)$' } }, 'ripencc': { @@ -67,7 +69,8 @@ 'fields': { 'name': '^(netname):[^\S\n]+(.+)$', 'description': '^(descr):[^\S\n]+(.+)$', - 'country': '^(country):[^\S\n]+(.+)$' + 'country': '^(country):[^\S\n]+(.+)$', + 'address': '^(address):[^\S\n]+(.+)$' } }, 'apnic': { @@ -76,7 +79,8 @@ 'fields': { 'name': '^(netname):[^\S\n]+(.+)$', 'description': '^(descr):[^\S\n]+(.+)$', - 'country': '^(country):[^\S\n]+(.+)$' + 'country': '^(country):[^\S\n]+(.+)$', + 'address': '^(address):[^\S\n]+(.+)$' } }, 'lacnic': { @@ -93,7 +97,8 @@ 'fields': { 'name': '^(netname):[^\S\n]+(.+)$', 'description': '^(descr):[^\S\n]+(.+)$', - 'country': '^(country):[^\S\n]+(.+)$' + 'country': '^(country):[^\S\n]+(.+)$', + 'address': '^(address):[^\S\n]+(.+)$' } } } @@ -604,6 +609,47 @@ def get_rws(self, url = None, retry_count = 3): except: return None + + def get_host(self, retry_count = 3): + """ + The function for retrieving host information for an IP address. + + Args: + retry_count: The number of times to retry in case socket errors, timeouts, connection resets, etc. are encountered. + + Returns: + Tuple: hostname, aliaslist, ipaddrlist + """ + + try: + + default_timeout_set = False + if not socket.getdefaulttimeout(): + + socket.setdefaulttimeout(self.timeout) + default_timeout_set = True + + ret = socket.gethostbyaddr(self.address_str) + + if default_timeout_set: + + socket.setdefaulttimeout(None) + + return ret + + except (socket.timeout, socket.error): + + if retry_count > 0: + + return self.get_host(retry_count - 1) + + else: + + return None + + except: + + return None def lookup(self, inc_raw = False): """ @@ -663,6 +709,8 @@ def lookup(self, inc_raw = False): 'country': None, 'state': None, 'city': None, + 'address': None, + 'postal_code': None, 'start': None, 'end': None } @@ -873,7 +921,9 @@ def lookup_rws(self, inc_raw = False): 'description': None, 'country': None, 'state': None, - 'city': None + 'city': None, + 'address': None, + 'postal_code': None } nets = [] @@ -910,6 +960,29 @@ def lookup_rws(self, inc_raw = False): if res: + if 'streetAddress' in res['customer']: + + addr_list = res['customer']['streetAddress']['line'] + + if not isinstance(addr_list, list): + + addr_list = [addr_list] + + value = '' + for line in addr_list: + + if value != '': + + value += '\n' + + value += line['$'].strip() + + net['address'] = value + + if 'postalCode' in res['customer']: + + net['postal_code'] = res['customer']['postalCode']['$'] + if 'city' in res['customer']: net['city'] = res['customer']['city']['$'] @@ -928,9 +1001,32 @@ def lookup_rws(self, inc_raw = False): org_url = n['orgRef']['$'].strip() res = self.get_rws(org_url) - + if res: + if 'streetAddress' in res['org']: + + addr_list = res['org']['streetAddress']['line'] + + if not isinstance(addr_list, list): + + addr_list = [addr_list] + + value = '' + for line in addr_list: + + if value != '': + + value += '\n' + + value += line['$'].strip() + + net['address'] = value + + if 'postalCode' in res['org']: + + net['postal_code'] = res['org']['postalCode']['$'] + if 'city' in res['org']: net['city'] = res['org']['city']['$'] @@ -1034,6 +1130,16 @@ def lookup_rws(self, inc_raw = False): net['country'] = a['value'].strip() + elif a['name'] == 'address': + + if net['address']: + + net['address'] += '\n' + a['value'].strip() + + else: + + net['address'] = a['value'].strip() + nets.append(net) break