# Written by Jie Yang # see LICENSE.txt for license information try: True except: True = 1 False = 0 DEBUG = False import socket import urllib2 try: import GeoIP geoip_installed = True except: geoip_installed = False no_info = {'country_name':'', 'country_code':'', 'city':'', 'latitude':999, 'longitude':999} # in case of error country_prefix = 'Country: ' city_prefix = 'City: ' latitude_prefix = 'Latitude: ' longitude_prefix = 'Longitude: ' unknown_country = 'Unknown Country?' unknown_city = 'Unknown City?' class IPInfo: def __init__(self, ip=''): self.ip = ip self.ip_info = None # @staticmethod # used by python 2.4 def foundIPLocation(ip_info): try: if ip_info['latitude'] > 180 or ip_info['latitude'] < -180 or \ ip_info['longitude'] > 180 or ip_info['longitude'] < -180: return False else: return True except: return False foundIPLocation = staticmethod(foundIPLocation) # Try different ways to find IP location # @staticmethod # used by python 2.4 def lookupIPInfo(ip): """ This function obtains latitude and longitude of an IP. The returned dictory contains: 'country_name', 'country_code', 'city', 'latitude' and 'longitude' If the IP cannot be located, its latitude and longitude are set as 999 """ def getIPInfoByURL(url, proxy=None): """ Get IP location by visit some ip search engine page """ #TODO: getIPInfoByURL with Proxy support #Known urls: http://www.hostip.info/api/get.html?ip=xxx&position=true # http://www.melissadata.com/Lookups/iplocation.asp?ipaddress=xxx&submit=submit (using IP2Location database without coordinate) # Arno: make this quick. Not really necessary anymore because the # RawServer no longer runs this (see peer.py), but nice none the less. timeout = None try: timeout = socket.getdefaulttimeout() socket.setdefaulttimeout(1.0) ip_info = urllib2.urlopen(url).read() socket.setdefaulttimeout(timeout) except: socket.setdefaulttimeout(timeout) if DEBUG: print >> sys.stderr,"ipinfo: getIPInfoByURL failed: cannot access", url raise Exception return ip_info def getIPInfoByHostIP2(ip): return getIPInfoByHostIP('http://www.hostip.info', ip) def getIPInfoByHostIP1(ip): url = "http://superpeer1.das2.ewi.tudelft.nl/hostip" # url = "http://hostip1.bit-torrent.sourceforge.net" return getIPInfoByHostIP(url, ip) def getIPInfoByHostIP(site_url, ip): """ Using hostip.info to find IP location """ try: url = site_url + '/api/get.html?ip=' + ip + '&position=true' ip_info = getIPInfoByURL(url) except Exception, message: if DEBUG: print >> sys.stderr,"ipinfo: getIPInfoByURL failed:", message return no_info # Parse the ip_info string and translate it into a standard dict format info_list = ip_info.split('\n') ip_info = {} for item in info_list: if item.find(country_prefix) != -1: if item.find(unknown_country) != -1: # country unknown? ip_info['country_name'] = '' ip_info['country_code'] = '' else: ip_info['country_name'] = item[len(country_prefix):item.index('(')-1] ip_info['country_code'] = item[item.index('(')+1:item.index(')')] elif item.find(city_prefix) != -1: if item.find(unknown_city) != -1: # city unknown? ip_info['city'] = '' else: ip_info['city'] = item[len(city_prefix):] elif item.find(latitude_prefix) != -1: if item[len(latitude_prefix):] == '': ip_info['latitude'] = 999 else: ip_info['latitude'] = float(item[len(latitude_prefix):]) elif item.find(longitude_prefix) != -1: if item[len(longitude_prefix):] == '': ip_info['longitude'] = 999 else: ip_info['longitude'] = float(item[len(longitude_prefix):]) return ip_info def getIPInfoByGeoIP(ip): """ Using GeoIP library to transfer ip into locality """ if not geoip_installed: return no_info try: geoip_lib = '/usr/local/share/GeoIP/GeoIPCity.dat' gi = GeoIP.open(geoip_lib, GeoIP.GEOIP_MEMORY_CACHE) except: try: if DEBUG: print 'ipinfo: cannot open GeoIP library at ' + geoip_lib geoip_lib = './GeoIPCity.dat' gi = GeoIP.open(geoip_lib, GeoIP.GEOIP_MEMORY_CACHE) except Exception: if DEBUG: print 'ipinfo: cannot open GeoIP library at ' + geoip_lib return no_info try: ip_info = gi.record_by_addr(ip) except: return no_info if not ip_info: return no_info # Translate ip_info into a standard dict format if ip_info['country_name'] == None: ip_info['country_name'] = '' if ip_info['country_code'] == None: ip_info['country_code'] = '' if ip_info['city'] == None: ip_info['city'] = '' if ip_info['latitude'] == None: ip_info['latitude'] = '' if ip_info['longitude'] == None: ip_info['longitude'] = '' return ip_info # Add lookup-IP methods into method list getIPInfoMethods = [] getIPInfoMethods.append(getIPInfoByHostIP1) getIPInfoMethods.append(getIPInfoByHostIP2) getIPInfoMethods.append(getIPInfoByGeoIP) ip_info = [] for getIPInfo in getIPInfoMethods: # lookup the ip by give methods info = getIPInfo(ip) ip_info.append(info) if IPInfo.foundIPLocation(info): return info # No method finds the ip, return the one which has the longest length if DEBUG: print >> sys.stderr,"ipinfo:",ip, "cannot be located" maxlen = 0 for info in ip_info: info_len = len(info) if info_len > maxlen: best_info = info maxlen = info_len return info lookupIPInfo = staticmethod(lookupIPInfo) # used by python 2.2 def setIPInfo(self): self.ip_info = IPInfo.lookupIPInfo(self.ip) def getIPInfo(self): if not self.ip_info: # postpone ip lookup until it's required self.setIPInfo() return self.ip_info if __name__ == '__main__': test_ip = [ '208.44.252.21', '140.160.136.72', '194.231.189.161', '58.69.8.35', '367.345.645.3743'] for ip in test_ip: # peer = IPInfo(ip) # ip_info = peer.getIPInfo() ip_info = IPInfo.lookupIPInfo(ip) print ip_info