#!/usr/bin/python
+import IPy
import re
-from databases import Databases
-from memcached import Memcached
-from misc import Singleton
+import countries
-class GeoIP(object):
- __metaclass__ = Singleton
+from misc import Object
- @property
- def db(self):
- return Databases().geoip
+class GeoIP(Object):
+ def guess_address_family(self, addr):
+ if ":" in addr:
+ return 6
- def _encode_ip(self, addr):
- # We get a tuple if there were proxy headers.
- addr = addr.split(", ")
- if addr:
- addr = addr[-1]
+ return 4
- # ip is calculated as described in http://dev.maxmind.com/geoip/csv
- a1, a2, a3, a4 = addr.split(".")
+ def get_country(self, addr):
+ ret = self.get_all(addr)
- try:
- a1 = int(a1)
- a2 = int(a2)
- a3 = int(a3)
- a4 = int(a4)
- except ValueError:
- return 0
+ if ret:
+ return ret.country
- return (16777216 * a1) + (65536 * a2) + (256 * a3) + a4
+ def get_location(self, addr):
+ family = self.guess_address_family(addr)
- def get_country(self, addr):
- addr = self._encode_ip(addr)
+ if family == 6:
+ query = "SELECT *, NULL AS city, NULL AS postal_code FROM geoip_ipv6 WHERE %s \
+ BETWEEN start_ip AND end_ip LIMIT 1"
+ elif family == 4:
+ query = "SELECT * FROM geoip_ipv4 WHERE inet_to_bigint(%s) \
+ BETWEEN start_ip AND end_ip LIMIT 1"
- ret = self.db.get("SELECT locations.country_code AS country_code FROM addresses \
- JOIN locations ON locations.id = addresses.location \
- WHERE %s BETWEEN start_ip_num AND end_ip_num LIMIT 1", addr)
+ return self.db.get(query, addr)
- if ret:
- return ret.country_code
+ def get_asn(self, addr):
+ family = self.guess_address_family(addr)
- def get_all(self, addr):
- addr = self._encode_ip(addr)
- if not addr:
- return
+ if family == 6:
+ query = "SELECT asn FROM geoip_asnv6 WHERE %s \
+ BETWEEN start_ip AND end_ip LIMIT 1"
+ elif family == 4:
+ query = "SELECT asn FROM geoip_asnv4 WHERE inet_to_bigint(%s) \
+ BETWEEN start_ip AND end_ip LIMIT 1"
- ret = self.db.get("SELECT locations.* FROM addresses \
- JOIN locations ON locations.id = addresses.location \
- WHERE %s BETWEEN start_ip_num AND end_ip_num LIMIT 1", addr)
+ ret = self.db.get(query, addr)
- if not ret:
- return
+ if ret:
+ return ret.asn
- # If location was not determinable
- if ret.latitude == 0 and ret.longitude == 0:
- return None
+ def get_all(self, addr):
+ location = self.get_location(addr)
- return ret
+ if location:
+ location["asn"] = self.get_asn(addr)
- def get_country_name(self, code):
- name = "Unkown"
+ return location
- codes = {
- "A1" : "Anonymous Proxy",
- "A2" : "Satellite Provider",
- "EU" : "Europe",
- "AP" : "Asia/Pacific Region",
- }
+ _countries = {
+ "A1" : "Anonymous Proxy",
+ "A2" : "Satellite Provider",
+ "AP" : "Asia/Pacific Region",
+ "EU" : "Europe",
+ }
+ def get_country_name(self, code):
# Return description of some exceptional codes.
try:
- return codes[code]
+ return self._countries[code]
except KeyError:
pass
- ret = self.db.get("SELECT name FROM iso3166_countries WHERE code = %s LIMIT 1", code)
- if ret:
- name = ret.name
-
- # Fix some weird strings
- name = re.sub(r"(.*) (.* Republic of)", r"\2 \1", name)
-
- return name
-
-
-if __name__ == "__main__":
- g = GeoIP()
+ country = countries.get_by_code(code)
+ if not country:
+ return code
- print g.get_country("123.123.123.123")
- print g.get_all("123.123.123.123")
+ return country