diff --git a/django/contrib/gis/geoip/base.py b/django/contrib/gis/geoip/base.py
index 944240c..7ae846f 100644
|
a
|
b
|
import re
|
| 3 | 3 | from ctypes import c_char_p |
| 4 | 4 | |
| 5 | 5 | from django.core.validators import ipv4_re |
| | 6 | from django.utils.ipv6 import is_valid_ipv6_address |
| 6 | 7 | from django.contrib.gis.geoip.libgeoip import GEOIP_SETTINGS |
| 7 | 8 | from django.contrib.gis.geoip.prototypes import ( |
| 8 | 9 | GeoIPRecord, GeoIPTag, GeoIP_open, GeoIP_delete, GeoIP_database_info, |
| 9 | 10 | GeoIP_lib_version, GeoIP_record_by_addr, GeoIP_record_by_name, |
| 10 | 11 | GeoIP_country_code_by_addr, GeoIP_country_code_by_name, |
| 11 | | GeoIP_country_name_by_addr, GeoIP_country_name_by_name) |
| | 12 | GeoIP_country_name_by_addr, GeoIP_country_name_by_name, |
| | 13 | GeoIP_country_code_by_addr_v6, GeoIP_country_name_by_addr_v6, |
| | 14 | GeoIP_record_by_addr_v6) |
| 12 | 15 | |
| 13 | 16 | from django.utils import six |
| 14 | 17 | |
| … |
… |
class GeoIP(object):
|
| 48 | 51 | |
| 49 | 52 | # Paths to the city & country binary databases. |
| 50 | 53 | _city_file = '' |
| | 54 | _city6_file = '' |
| 51 | 55 | _country_file = '' |
| | 56 | _country6_file = '' |
| 52 | 57 | |
| 53 | 58 | # Initially, pointers to GeoIP file references are NULL. |
| 54 | 59 | _city = None |
| | 60 | _city6 = None |
| 55 | 61 | _country = None |
| 56 | 62 | |
| 57 | 63 | def __init__(self, path=None, cache=0, country=None, city=None): |
| … |
… |
class GeoIP(object):
|
| 100 | 106 | self._country = GeoIP_open(country_db, cache) |
| 101 | 107 | self._country_file = country_db |
| 102 | 108 | |
| | 109 | country6_db = os.path.join(path, country or GEOIP_SETTINGS.get('GEOIP_COUNTRY6', 'GeoIPv6.dat')) |
| | 110 | if os.path.isfile(country6_db): |
| | 111 | self._country6 = GeoIP_open(country6_db, cache) |
| | 112 | self._country6_file = country6_db |
| | 113 | |
| 103 | 114 | city_db = os.path.join(path, city or GEOIP_SETTINGS.get('GEOIP_CITY', 'GeoLiteCity.dat')) |
| 104 | 115 | if os.path.isfile(city_db): |
| 105 | 116 | self._city = GeoIP_open(city_db, cache) |
| 106 | 117 | self._city_file = city_db |
| | 118 | |
| | 119 | city6_db = os.path.join(path, city or GEOIP_SETTINGS.get('GEOIP_CITY6', 'GeoLiteCityv6.dat')) |
| | 120 | if os.path.isfile(city6_db): |
| | 121 | self._city6 = GeoIP_open(city6_db, cache) |
| | 122 | self._city6_file = city6_db |
| | 123 | |
| 107 | 124 | elif os.path.isfile(path): |
| 108 | 125 | # Otherwise, some detective work will be needed to figure |
| 109 | 126 | # out whether the given database path is for the GeoIP country |
| … |
… |
class GeoIP(object):
|
| 126 | 143 | def __del__(self): |
| 127 | 144 | # Cleaning any GeoIP file handles lying around. |
| 128 | 145 | if self._country: GeoIP_delete(self._country) |
| | 146 | if self._country6: GeoIP_delete(self._country6) |
| 129 | 147 | if self._city: GeoIP_delete(self._city) |
| | 148 | if self._city6: GeoIP_delete(self._city6) |
| 130 | 149 | |
| 131 | 150 | def _check_query(self, query, country=False, city=False, city_or_country=False): |
| 132 | 151 | "Helper routine for checking the query and database availability." |
| … |
… |
class GeoIP(object):
|
| 158 | 177 | if ipv4_re.match(query): |
| 159 | 178 | # If an IP address was passed in |
| 160 | 179 | return GeoIP_record_by_addr(self._city, c_char_p(query)) |
| | 180 | elif is_valid_ipv6_address(query) and self._city6: |
| | 181 | # If an IPv6 address was passed in |
| | 182 | return GeoIP_record_by_addr_v6(self._city6, c_char_p(query)) |
| 161 | 183 | else: |
| 162 | 184 | # If a FQDN was passed in. |
| 163 | 185 | return GeoIP_record_by_name(self._city, c_char_p(query)) |
| … |
… |
class GeoIP(object):
|
| 165 | 187 | def country_code(self, query): |
| 166 | 188 | "Returns the country code for the given IP Address or FQDN." |
| 167 | 189 | query = self._check_query(query, city_or_country=True) |
| 168 | | if self._country: |
| | 190 | if self._country6 and is_valid_ipv6_address(query): |
| | 191 | return GeoIP_country_code_by_addr_v6(self._country6, query) |
| | 192 | elif self._country: |
| 169 | 193 | if ipv4_re.match(query): |
| 170 | 194 | return GeoIP_country_code_by_addr(self._country, query) |
| 171 | 195 | else: |
| … |
… |
class GeoIP(object):
|
| 176 | 200 | def country_name(self, query): |
| 177 | 201 | "Returns the country name for the given IP Address or FQDN." |
| 178 | 202 | query = self._check_query(query, city_or_country=True) |
| 179 | | if self._country: |
| | 203 | if self._country6 and is_valid_ipv6_address(query): |
| | 204 | return GeoIP_country_name_by_addr_v6(self._country6, query) |
| | 205 | elif self._country: |
| 180 | 206 | if ipv4_re.match(query): |
| 181 | 207 | return GeoIP_country_name_by_addr(self._country, query) |
| 182 | 208 | else: |
diff --git a/django/contrib/gis/geoip/prototypes.py b/django/contrib/gis/geoip/prototypes.py
index 1cec0d5..0bbea3d 100644
|
a
|
b
|
def record_output(func):
|
| 73 | 73 | return func |
| 74 | 74 | GeoIP_record_by_addr = record_output(lgeoip.GeoIP_record_by_addr) |
| 75 | 75 | GeoIP_record_by_name = record_output(lgeoip.GeoIP_record_by_name) |
| 76 | | |
| | 76 | GeoIP_record_by_addr_v6 = record_output(lgeoip.GeoIP_record_by_addr_v6) |
| 77 | 77 | |
| 78 | 78 | # For opening & closing GeoIP database files. |
| 79 | 79 | GeoIP_open = lgeoip.GeoIP_open |
| … |
… |
def string_output(func):
|
| 106 | 106 | GeoIP_country_code_by_addr = string_output(lgeoip.GeoIP_country_code_by_addr) |
| 107 | 107 | GeoIP_country_code_by_name = string_output(lgeoip.GeoIP_country_code_by_name) |
| 108 | 108 | GeoIP_country_name_by_addr = string_output(lgeoip.GeoIP_country_name_by_addr) |
| | 109 | GeoIP_country_code_by_addr_v6 = string_output(lgeoip.GeoIP_country_code_by_addr_v6) |
| | 110 | GeoIP_country_name_by_addr_v6 = string_output(lgeoip.GeoIP_country_name_by_addr_v6) |
| 109 | 111 | GeoIP_country_name_by_name = string_output(lgeoip.GeoIP_country_name_by_name) |
diff --git a/django/contrib/gis/geoip/tests.py b/django/contrib/gis/geoip/tests.py
index e53230d..f20e363 100644
|
a
|
b
|
class GeoIPTest(unittest.TestCase):
|
| 105 | 105 | d = g.city('62.224.93.23') |
| 106 | 106 | self.assertEqual('Schümberg', d['city']) |
| 107 | 107 | |
| | 108 | def test07_ipv6_query(self): |
| | 109 | "Testing that GeoIP can lookup ipv6 addresses." |
| | 110 | g = GeoIP() |
| | 111 | d = g.city('2a03:2880:2110:3f01:face:b00c::') |
| | 112 | self.assertNotEqual(d, None) |
| | 113 | |
| 108 | 114 | def test06_unicode_query(self): |
| 109 | 115 | "Testing that GeoIP accepts unicode string queries, see #17059." |
| 110 | 116 | g = GeoIP() |