<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://bf2tech.uturista.pt/index.php?action=history&amp;feed=atom&amp;title=Scripts%3ACountryFilter</id>
	<title>Scripts:CountryFilter - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://bf2tech.uturista.pt/index.php?action=history&amp;feed=atom&amp;title=Scripts%3ACountryFilter"/>
	<link rel="alternate" type="text/html" href="https://bf2tech.uturista.pt/index.php?title=Scripts:CountryFilter&amp;action=history"/>
	<updated>2026-08-06T01:09:25Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.40.1</generator>
	<entry>
		<id>https://bf2tech.uturista.pt/index.php?title=Scripts:CountryFilter&amp;diff=101&amp;oldid=prev</id>
		<title>Pireax: Created page with &quot;== Description ==  The feature of CountryFilter is as follows.  * This script can display country name by finding the country from IP-address of the player. * This script prov...&quot;</title>
		<link rel="alternate" type="text/html" href="https://bf2tech.uturista.pt/index.php?title=Scripts:CountryFilter&amp;diff=101&amp;oldid=prev"/>
		<updated>2018-06-22T15:24:07Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;== Description ==  The feature of CountryFilter is as follows.  * This script can display country name by finding the country from IP-address of the player. * This script prov...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== Description ==&lt;br /&gt;
&lt;br /&gt;
The feature of CountryFilter is as follows.&lt;br /&gt;
&lt;br /&gt;
* This script can display country name by finding the country from IP-address of the player.&lt;br /&gt;
* This script provides access control (allow/deny) based on player country name.&lt;br /&gt;
* This script uses GeoIP Free Country, and its accuracy of conversion is approximately 97%.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== The Code ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt; &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt; &amp;lt;/code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
# CountryFilter.py&lt;br /&gt;
#&lt;br /&gt;
# Copyright (C) 2005 Guwashi &amp;lt;guwashi[AT]fooos[DOT]com&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
# This library is free software; you can redistribute it and/or&lt;br /&gt;
# modify it under the terms of the GNU General Public&lt;br /&gt;
# License as published by the Free Software Foundation; either&lt;br /&gt;
# version 2.1 of the License, or (at your option) any later version.&lt;br /&gt;
#&lt;br /&gt;
# This library is distributed in the hope that it will be useful,&lt;br /&gt;
# but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU&lt;br /&gt;
# General Public License for more details.&lt;br /&gt;
#&lt;br /&gt;
# You should have received a copy of the GNU General Public&lt;br /&gt;
# License along with this library; if not, write to the Free Software&lt;br /&gt;
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA&lt;br /&gt;
&lt;br /&gt;
# Description:&lt;br /&gt;
#&lt;br /&gt;
#   The feature of CountryFilter is as follows.&lt;br /&gt;
#&lt;br /&gt;
#     - This script can display country name by finding the country&lt;br /&gt;
#       from IP-address of the player.&lt;br /&gt;
#&lt;br /&gt;
#     - This script provides access control (allow/deny) based on&lt;br /&gt;
#       player country name.&lt;br /&gt;
#&lt;br /&gt;
#     - This script uses GeoIP Free Country, and its accuracy of&lt;br /&gt;
#       conversion is approximately 97%.&lt;br /&gt;
#&lt;br /&gt;
#   If you want to see latest information of this script, please&lt;br /&gt;
#   acccess this URL.&lt;br /&gt;
#   http://d3.jpn.org/&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# Download:&lt;br /&gt;
#&lt;br /&gt;
#   http://d3.jpn.org/bf2/CountryFilter-bf2-1.0.0.zip&lt;br /&gt;
#   http://www.maxmind.com/download/geoip/database/GeoIP.dat.gz&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# Install:&lt;br /&gt;
#&lt;br /&gt;
#   - Copy CountryFilter.py and PurePythonGeoIP.py to&lt;br /&gt;
#     &amp;#039;&amp;lt;bf2&amp;gt;/Admin/standard_admin&amp;#039; directory.&lt;br /&gt;
#&lt;br /&gt;
#   - Add the lines &amp;#039;import CountryFilter&amp;#039; and &amp;#039;CountryFilter.init()&amp;#039;&lt;br /&gt;
#     to the file &amp;#039;&amp;lt;bf2&amp;gt;/admin/standard_admin/__init__.py&amp;#039;.&lt;br /&gt;
#&lt;br /&gt;
#     ex.)&lt;br /&gt;
#       import autobalance&lt;br /&gt;
#       import tk_punish&lt;br /&gt;
#       import CountryFilter&lt;br /&gt;
#&lt;br /&gt;
#       autobalance.init()&lt;br /&gt;
#       tk_punish.init()   &lt;br /&gt;
#       CountryFilter.init()&lt;br /&gt;
#&lt;br /&gt;
#   - Download GeoIP.dat from&lt;br /&gt;
#     http://www.maxmind.com/download/geoip/database/GeoIP.dat.gz&lt;br /&gt;
#     and extract it.&lt;br /&gt;
#&lt;br /&gt;
#   - Copy GeoIP.dat to &amp;#039;&amp;lt;bf2&amp;gt;&amp;#039; directory.&lt;br /&gt;
#&lt;br /&gt;
#   - Finally, it must be the following.&lt;br /&gt;
#&lt;br /&gt;
#     ex.)&lt;br /&gt;
#       &amp;lt;bf2&amp;gt;/Admin/standard_admin/CountryFilter.py&lt;br /&gt;
#       &amp;lt;bf2&amp;gt;/Admin/standard_admin/PurePythonGeoIP.py&lt;br /&gt;
#       &amp;lt;bf2&amp;gt;/GeoIP.dat&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# Config:&lt;br /&gt;
#&lt;br /&gt;
#   see also&lt;br /&gt;
#   http://d3.jpn.org/hl2/CountryFilter-en.html (English)&lt;br /&gt;
#   http://d3.jpn.org/hl2/CountryFilter-jp.html (Japanese)&lt;br /&gt;
#&lt;br /&gt;
#   - You can customize the print format of country.&lt;br /&gt;
#&lt;br /&gt;
#     - Country code by two characters.  ex.) JP&lt;br /&gt;
#&lt;br /&gt;
cf_country_print_mode = &amp;#039;code&amp;#039;&lt;br /&gt;
#&lt;br /&gt;
#     - Country code by three characters.  ex.) JPN&lt;br /&gt;
#&lt;br /&gt;
#cf_country_print_mode = &amp;#039;code3&amp;#039;&lt;br /&gt;
#&lt;br /&gt;
#     - Long country name.  ex.) Japan&lt;br /&gt;
#&lt;br /&gt;
#cf_country_print_mode = &amp;#039;name&amp;#039;&lt;br /&gt;
#&lt;br /&gt;
#   - You can customize the message format when script allow/deny the&lt;br /&gt;
#     connection according to the country of the player.&lt;br /&gt;
#&lt;br /&gt;
#     - Message format when player was allowed to connect.&lt;br /&gt;
#       %(name)s is replaced with player name.&lt;br /&gt;
#       %(country)s is replaced with country name.&lt;br /&gt;
#       The message will not displayed when setting as&lt;br /&gt;
#       cf_allow_message = &amp;#039;&amp;#039;.&lt;br /&gt;
#&lt;br /&gt;
cf_allow_message = &amp;#039;%(name)s (Country: %(country)s) was allowed to connect.&amp;#039;&lt;br /&gt;
#&lt;br /&gt;
#     - Message format when player was denied to connect.&lt;br /&gt;
#       %(name)s is replaced with player name.&lt;br /&gt;
#       %(country)s is replaced with country name.&lt;br /&gt;
#       The message will not displayed when setting as&lt;br /&gt;
#       cf_deny_message = &amp;#039;&amp;#039;.&lt;br /&gt;
#&lt;br /&gt;
cf_deny_message =  &amp;#039;%(name)s (Country: %(country)s) was rejected by CountryFilter.&amp;#039;&lt;br /&gt;
#&lt;br /&gt;
#     - Specify the country(s) which is excluded from printing&lt;br /&gt;
#       messages.&lt;br /&gt;
#       Available value is same as cf_allow_from and cf_deny_from.&lt;br /&gt;
#&lt;br /&gt;
cf_message_exclude_from = &amp;#039;&amp;#039;&lt;br /&gt;
#&lt;br /&gt;
#   - Allowing/denying the connection according to the country of the&lt;br /&gt;
#     player.&lt;br /&gt;
#&lt;br /&gt;
#     You can limit the connection by using cf_allow_from,&lt;br /&gt;
#     cf_deny_from, and cf_order. Please specify this by the country&lt;br /&gt;
#     code of two characters. Basically, it is the same as the&lt;br /&gt;
#     mod_access module of Apache. See this URL.&lt;br /&gt;
#&lt;br /&gt;
#     http://httpd.apache.org/docs/mod/mod_access.html&lt;br /&gt;
#&lt;br /&gt;
#     - cf_allow_from&lt;br /&gt;
#&lt;br /&gt;
#       cf_allow_from specify the country(s) which is allowed to&lt;br /&gt;
#       connect. Available value of cf_allow_from is &amp;#039;all&amp;#039;, &amp;#039;&amp;#039;, &amp;#039;--&amp;#039;&lt;br /&gt;
#       and country code by 2 characters. If you want to specify&lt;br /&gt;
#       multiple value, use space as delimiter. Set &amp;#039;all&amp;#039;, if you want&lt;br /&gt;
#       to allow all countries. When &amp;#039;&amp;#039; (null string) is specified,&lt;br /&gt;
#       nothing is done. &amp;#039;--&amp;#039; is unknown country. Note: when you&lt;br /&gt;
#       connect to server from LAN, its IP-address is 192.168.xxx.xxx,&lt;br /&gt;
#       so this script cannot find valid country name. Therefore if&lt;br /&gt;
#       you want to allow to connect from LAN, you must specify &amp;#039;--&amp;#039;.&lt;br /&gt;
#&lt;br /&gt;
#       ex.1)&lt;br /&gt;
#         # Allowing all countries.&lt;br /&gt;
#         cf_allow_from = &amp;#039;all&amp;#039;&lt;br /&gt;
#&lt;br /&gt;
#       ex.2)&lt;br /&gt;
#         # Allowing only JP, US and LAN.&lt;br /&gt;
#         cf_allow_from = &amp;#039;JP US --&amp;#039;&lt;br /&gt;
#&lt;br /&gt;
#       ex.3)&lt;br /&gt;
#         # Doing nothing.&lt;br /&gt;
#         cf_allow_from = &amp;#039;&amp;#039;&lt;br /&gt;
#&lt;br /&gt;
#     - cf_deny_from&lt;br /&gt;
#&lt;br /&gt;
#       cf_deny_from specify the country(s) which is deny to&lt;br /&gt;
#       connect. Available value of cf_deny_from is quite the same as&lt;br /&gt;
#       cf_allow_from.&lt;br /&gt;
#&lt;br /&gt;
#     - cf_order&lt;br /&gt;
#&lt;br /&gt;
#       cf_order controls the default access state and the order in&lt;br /&gt;
#       which cf_allow_from and cf_deny_from are evaluated. The value&lt;br /&gt;
#       of cf_order must be &amp;quot;deny,allow&amp;quot; or &amp;quot;allow,deny&amp;quot;. The default&lt;br /&gt;
#       value is &amp;quot;deny,allow&amp;quot;.&lt;br /&gt;
#&lt;br /&gt;
#       ex.1)&lt;br /&gt;
#         # It is evaluated in order of deny and allow.&lt;br /&gt;
#         # Access is allowed by default.&lt;br /&gt;
#         cf_order = &amp;#039;deny,allow&amp;#039;&lt;br /&gt;
#&lt;br /&gt;
#       ex.2)&lt;br /&gt;
#         # It is evaluated in order of allow and deny.&lt;br /&gt;
#         # Access is denied by default.&lt;br /&gt;
#         cf_order = &amp;#039;allow,deny&amp;#039;&lt;br /&gt;
#&lt;br /&gt;
#     - Examples&lt;br /&gt;
#&lt;br /&gt;
#       Some typical usages are shown as follows.&lt;br /&gt;
#&lt;br /&gt;
#       - Allowing all countries. (default)&lt;br /&gt;
#&lt;br /&gt;
cf_order = &amp;#039;deny,allow&amp;#039;&lt;br /&gt;
cf_deny_from = &amp;#039;&amp;#039;&lt;br /&gt;
cf_allow_from = &amp;#039;all&amp;#039;&lt;br /&gt;
#&lt;br /&gt;
#       - Allowing only JP, US and LAN. Others are denied.&lt;br /&gt;
#&lt;br /&gt;
#cf_order = &amp;#039;deny,allow&amp;#039;&lt;br /&gt;
#cf_deny_from = &amp;#039;all&amp;#039;&lt;br /&gt;
#cf_allow_from = &amp;#039;JP US --&amp;#039;&lt;br /&gt;
#&lt;br /&gt;
#       - Denying only JP. Others are allowed.&lt;br /&gt;
#&lt;br /&gt;
#cf_order = &amp;#039;allow,deny&amp;#039;&lt;br /&gt;
#cf_allow_from = &amp;#039;all&amp;#039;&lt;br /&gt;
#cf_deny_from = &amp;#039;JP&amp;#039;&lt;br /&gt;
#&lt;br /&gt;
#       If you want to find country code, refer this page.&lt;br /&gt;
#       http://www.maxmind.com/app/iso3166&lt;br /&gt;
#&lt;br /&gt;
#   - Specify the path of GeoIP.dat file. Default path is&lt;br /&gt;
#     &amp;lt;bf2&amp;gt;/GeoIP.dat.&lt;br /&gt;
#&lt;br /&gt;
cf_geoipdat_path = &amp;#039;GeoIP.dat&amp;#039;&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# etc.:&lt;br /&gt;
#&lt;br /&gt;
#   - The CountryFilter is licensed under the GPL. For details see the&lt;br /&gt;
#     COPYING file.&lt;br /&gt;
#&lt;br /&gt;
#   - This product includes GeoIP data created by MaxMind, available&lt;br /&gt;
#     from http://maxmind.com/&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# Author:&lt;br /&gt;
#&lt;br /&gt;
#   Guwashi&lt;br /&gt;
#     - E-Mail&lt;br /&gt;
#       guwashi[AT]fooos[DOT]com&lt;br /&gt;
#     - Web&lt;br /&gt;
#       http://d3.jpn.org/&lt;br /&gt;
#     - Forums&lt;br /&gt;
#       not yet.&lt;br /&gt;
#&lt;br /&gt;
# ChangeLog:&lt;br /&gt;
#&lt;br /&gt;
#   - 1.0.0 2005/07/07&lt;br /&gt;
#     first public release.&lt;br /&gt;
#   - 1.0.0rc1 2005/07/06&lt;br /&gt;
#     added cf_country_print_mode, cf_message_exclude_from and&lt;br /&gt;
#     cf_geoipdat_path.&lt;br /&gt;
#   - 1.0.0b 2005/07/04&lt;br /&gt;
#     first beta.&lt;br /&gt;
&lt;br /&gt;
import sys&lt;br /&gt;
import re&lt;br /&gt;
import host&lt;br /&gt;
import bf2&lt;br /&gt;
import PurePythonGeoIP&lt;br /&gt;
from PurePythonGeoIP import GeoIP&lt;br /&gt;
&lt;br /&gt;
COUNTRYFILTER_VERSION = &amp;#039;1.0.0&amp;#039;&lt;br /&gt;
&lt;br /&gt;
gi = None&lt;br /&gt;
&lt;br /&gt;
def init():&lt;br /&gt;
   &amp;#039;&amp;#039;&amp;#039;Create a new GeoIP object and register callback functions.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
   global gi, cf_geoipdat_path&lt;br /&gt;
   printLog(&amp;#039;init&amp;#039;, &amp;#039;start...&amp;#039;)&lt;br /&gt;
   gi = GeoIP.open(cf_geoipdat_path, GeoIP.GEOIP_STANDARD)&lt;br /&gt;
   printLog(&amp;#039;init&amp;#039;, &amp;#039;testing: 133.1.1.1 ==&amp;gt; &amp;#039; + gi.country_code_by_addr(&amp;#039;133.1.1.1&amp;#039;))&lt;br /&gt;
   host.registerHandler(&amp;#039;PlayerConnect&amp;#039;, onPlayerConnect, 1)&lt;br /&gt;
   printLog(&amp;#039;init&amp;#039;, &amp;#039;done&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
def onPlayerConnect(player):&lt;br /&gt;
   &amp;#039;&amp;#039;&amp;#039;Examine players country and allow/deny to connect.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
   global cf_allow_message, cf_deny_message&lt;br /&gt;
   printLog(&amp;#039;onPlayerConnect&amp;#039;, &amp;#039;start...&amp;#039;)&lt;br /&gt;
   printLog(&amp;#039;onPlayerConnect&amp;#039;, &amp;#039;player.index == &amp;#039; + str(player.index))&lt;br /&gt;
   printLog(&amp;#039;onPlayerConnect&amp;#039;, &amp;#039;player.getName() == &amp;#039; + str(player.getName()))&lt;br /&gt;
   printLog(&amp;#039;onPlayerConnect&amp;#039;, &amp;#039;player.getAddress() == &amp;#039; + str(player.getAddress()))&lt;br /&gt;
   countryId = gi.id_by_addr(str(player.getAddress()))&lt;br /&gt;
   countryCode = GeoIP.id_to_country_code(countryId)&lt;br /&gt;
   country = idToCountry(countryId)&lt;br /&gt;
   printLog(&amp;#039;onPlayerConnect&amp;#039;, &amp;#039;country == &amp;#039; + country)&lt;br /&gt;
   if isAllowConnect(countryCode):&lt;br /&gt;
      if 0 &amp;lt; len(cf_allow_message) and (not isMessageExcludeFrom(countryCode)):&lt;br /&gt;
         message = cf_allow_message % {&amp;#039;name&amp;#039;:player.getName(), &amp;#039;country&amp;#039;:country}&lt;br /&gt;
         printConsole(message)&lt;br /&gt;
         sayAll(message)&lt;br /&gt;
      pass # do nothing&lt;br /&gt;
   else:&lt;br /&gt;
      if 0 &amp;lt; len(cf_deny_message) and (not isMessageExcludeFrom(countryCode)):&lt;br /&gt;
         message = cf_deny_message % {&amp;#039;name&amp;#039;:player.getName(), &amp;#039;country&amp;#039;:country}&lt;br /&gt;
         printConsole(message)&lt;br /&gt;
         sayAll(message)&lt;br /&gt;
      host.rcon_invoke(&amp;#039;admin.kickPlayer &amp;#039; + str(player.index)) # kick!&lt;br /&gt;
   printLog(&amp;#039;onPlayerConnect&amp;#039;, &amp;#039;done&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
def printLog(method_name, message):&lt;br /&gt;
   &amp;#039;&amp;#039;&amp;#039;Print log to stdout.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
   if bf2.g_debug:&lt;br /&gt;
      print &amp;#039;[CF]: &amp;#039; + str(method_name) + &amp;#039;: &amp;#039; + str(message)&lt;br /&gt;
      sys.stdout.flush()&lt;br /&gt;
&lt;br /&gt;
def printConsole(message):&lt;br /&gt;
   &amp;#039;&amp;#039;&amp;#039;Print log to server console.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
   host.rcon_invoke(&amp;#039;echo &amp;quot;&amp;#039; + str(message) + &amp;#039;&amp;quot;&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
def sayAll(message):&lt;br /&gt;
   &amp;#039;&amp;#039;&amp;#039;Say message to to all players.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
   host.rcon_invoke(&amp;#039;game.sayAll &amp;quot;&amp;#039; + str(message) + &amp;#039;&amp;quot;&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
def isAllowConnect(countryCode):&lt;br /&gt;
   &amp;#039;&amp;#039;&amp;#039;Is player allowed to connect?&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
   # http://httpd.apache.org/docs/mod/mod_access.html&lt;br /&gt;
   # TODO: use regular expressions&lt;br /&gt;
   global cf_order, cf_allow_from, cf_deny_from&lt;br /&gt;
   result = True&lt;br /&gt;
   if &amp;#039;allow,deny&amp;#039; == cf_order:&lt;br /&gt;
      result = False # deny&lt;br /&gt;
      if -1 != cf_allow_from.find(&amp;#039;all&amp;#039;):&lt;br /&gt;
         result = True&lt;br /&gt;
      if -1 != cf_allow_from.find(countryCode):&lt;br /&gt;
         result = True&lt;br /&gt;
      if -1 != cf_deny_from.find(&amp;#039;all&amp;#039;):&lt;br /&gt;
         result = False&lt;br /&gt;
      if -1 != cf_deny_from.find(countryCode):&lt;br /&gt;
         result = False&lt;br /&gt;
   else: # &amp;#039;deny,allow&amp;#039; (default)&lt;br /&gt;
      result = True; # allow&lt;br /&gt;
      if -1 != cf_deny_from.find(&amp;#039;all&amp;#039;):&lt;br /&gt;
         result = False&lt;br /&gt;
      if -1 != cf_deny_from.find(countryCode):&lt;br /&gt;
         result = False&lt;br /&gt;
      if -1 != cf_allow_from.find(&amp;#039;all&amp;#039;):&lt;br /&gt;
         result = True&lt;br /&gt;
      if -1 != cf_allow_from.find(countryCode):&lt;br /&gt;
         result = True&lt;br /&gt;
   return result;&lt;br /&gt;
&lt;br /&gt;
def isMessageExcludeFrom(countryCode):&lt;br /&gt;
   &amp;#039;&amp;#039;&amp;#039;Is message allowed to print?&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
   global cf_message_exclude_from&lt;br /&gt;
   result = False&lt;br /&gt;
   if -1 != cf_message_exclude_from.find(&amp;#039;all&amp;#039;):&lt;br /&gt;
      result = True&lt;br /&gt;
   if -1 != cf_message_exclude_from.find(countryCode):&lt;br /&gt;
      result = True&lt;br /&gt;
   return result&lt;br /&gt;
&lt;br /&gt;
def idToCountry(countryId):&lt;br /&gt;
   &amp;#039;&amp;#039;&amp;#039;Convert country id to country representation.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
   global cf_country_print_mode&lt;br /&gt;
   if &amp;#039;code3&amp;#039; == cf_country_print_mode:&lt;br /&gt;
      return GeoIP.id_to_country_code3(countryId)&lt;br /&gt;
   elif &amp;#039;name&amp;#039; == cf_country_print_mode:&lt;br /&gt;
      return GeoIP.id_to_country_name(countryId)&lt;br /&gt;
   else: # &amp;#039;code&amp;#039; (default)&lt;br /&gt;
      return GeoIP.id_to_country_code(countryId)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;/code&amp;gt; &amp;lt;code&amp;gt; &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt; &amp;lt;/code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
#! /usr/bin/python&lt;br /&gt;
&lt;br /&gt;
# PurePythonGeoIP.py&lt;br /&gt;
#&lt;br /&gt;
# Copyright (C) 2005 Guwashi &amp;lt;guwashi[AT]fooos[DOT]com&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
# This library is free software; you can redistribute it and/or&lt;br /&gt;
# modify it under the terms of the GNU General Public&lt;br /&gt;
# License as published by the Free Software Foundation; either&lt;br /&gt;
# version 2.1 of the License, or (at your option) any later version.&lt;br /&gt;
#&lt;br /&gt;
# This library is distributed in the hope that it will be useful,&lt;br /&gt;
# but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU&lt;br /&gt;
# General Public License for more details.&lt;br /&gt;
#&lt;br /&gt;
# You should have received a copy of the GNU General Public&lt;br /&gt;
# License along with this library; if not, write to the Free Software&lt;br /&gt;
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA&lt;br /&gt;
&lt;br /&gt;
# This code is based on&lt;br /&gt;
# http://www.maxmind.com/app/python&lt;br /&gt;
# http://www.maxmind.com/download/geoip/api/pureperl&lt;br /&gt;
&lt;br /&gt;
import re&lt;br /&gt;
import struct&lt;br /&gt;
&lt;br /&gt;
PUREPYTHONGEOIP_VERSION = &amp;#039;1.0.0&amp;#039;&lt;br /&gt;
&lt;br /&gt;
def nreverse(sequence):&lt;br /&gt;
    &amp;#039;&amp;#039;&amp;#039;nreverse in Common Lisp. :)&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
    sequence.reverse()&lt;br /&gt;
    return sequence&lt;br /&gt;
&lt;br /&gt;
class GeoIP:&lt;br /&gt;
    __STANDARD_RECORD_LENGTH = 3&lt;br /&gt;
    __GEOIP_COUNTRY_EDITION = 106&lt;br /&gt;
    __GEOIP_COUNTRY_BEGIN = 16776960&lt;br /&gt;
&lt;br /&gt;
    __COUNTRIES = (&amp;#039;--&amp;#039;,&amp;#039;AP&amp;#039;,&amp;#039;EU&amp;#039;,&amp;#039;AD&amp;#039;,&amp;#039;AE&amp;#039;,&amp;#039;AF&amp;#039;,&amp;#039;AG&amp;#039;,&amp;#039;AI&amp;#039;,&amp;#039;AL&amp;#039;,&amp;#039;AM&amp;#039;,&amp;#039;AN&amp;#039;,&amp;#039;AO&amp;#039;,&amp;#039;AQ&amp;#039;,&amp;#039;AR&amp;#039;,&amp;#039;AS&amp;#039;,&amp;#039;AT&amp;#039;,&amp;#039;AU&amp;#039;,&amp;#039;AW&amp;#039;,&amp;#039;AZ&amp;#039;,&amp;#039;BA&amp;#039;,&amp;#039;BB&amp;#039;,&amp;#039;BD&amp;#039;,&amp;#039;BE&amp;#039;,&amp;#039;BF&amp;#039;,&amp;#039;BG&amp;#039;,&amp;#039;BH&amp;#039;,&amp;#039;BI&amp;#039;,&amp;#039;BJ&amp;#039;,&amp;#039;BM&amp;#039;,&amp;#039;BN&amp;#039;,&amp;#039;BO&amp;#039;,&amp;#039;BR&amp;#039;,&amp;#039;BS&amp;#039;,&amp;#039;BT&amp;#039;,&amp;#039;BV&amp;#039;,&amp;#039;BW&amp;#039;,&amp;#039;BY&amp;#039;,&amp;#039;BZ&amp;#039;,&amp;#039;CA&amp;#039;,&amp;#039;CC&amp;#039;,&amp;#039;CD&amp;#039;,&amp;#039;CF&amp;#039;,&amp;#039;CG&amp;#039;,&amp;#039;CH&amp;#039;,&amp;#039;CI&amp;#039;,&amp;#039;CK&amp;#039;,&amp;#039;CL&amp;#039;,&amp;#039;CM&amp;#039;,&amp;#039;CN&amp;#039;,&amp;#039;CO&amp;#039;,&amp;#039;CR&amp;#039;,&amp;#039;CU&amp;#039;,&amp;#039;CV&amp;#039;,&amp;#039;CX&amp;#039;,&amp;#039;CY&amp;#039;,&amp;#039;CZ&amp;#039;,&amp;#039;DE&amp;#039;,&amp;#039;DJ&amp;#039;,&amp;#039;DK&amp;#039;,&amp;#039;DM&amp;#039;,&amp;#039;DO&amp;#039;,&amp;#039;DZ&amp;#039;,&amp;#039;EC&amp;#039;,&amp;#039;EE&amp;#039;,&amp;#039;EG&amp;#039;,&amp;#039;EH&amp;#039;,&amp;#039;ER&amp;#039;,&amp;#039;ES&amp;#039;,&amp;#039;ET&amp;#039;,&amp;#039;FI&amp;#039;,&amp;#039;FJ&amp;#039;,&amp;#039;FK&amp;#039;,&amp;#039;FM&amp;#039;,&amp;#039;FO&amp;#039;,&amp;#039;FR&amp;#039;,&amp;#039;FX&amp;#039;,&amp;#039;GA&amp;#039;,&amp;#039;GB&amp;#039;,&amp;#039;GD&amp;#039;,&amp;#039;GE&amp;#039;,&amp;#039;GF&amp;#039;,&amp;#039;GH&amp;#039;,&amp;#039;GI&amp;#039;,&amp;#039;GL&amp;#039;,&amp;#039;GM&amp;#039;,&amp;#039;GN&amp;#039;,&amp;#039;GP&amp;#039;,&amp;#039;GQ&amp;#039;,&amp;#039;GR&amp;#039;,&amp;#039;GS&amp;#039;,&amp;#039;GT&amp;#039;,&amp;#039;GU&amp;#039;,&amp;#039;GW&amp;#039;,&amp;#039;GY&amp;#039;,&amp;#039;HK&amp;#039;,&amp;#039;HM&amp;#039;,&amp;#039;HN&amp;#039;,&amp;#039;HR&amp;#039;,&amp;#039;HT&amp;#039;,&amp;#039;HU&amp;#039;,&amp;#039;ID&amp;#039;,&amp;#039;IE&amp;#039;,&amp;#039;IL&amp;#039;,&amp;#039;IN&amp;#039;,&amp;#039;IO&amp;#039;,&amp;#039;IQ&amp;#039;,&amp;#039;IR&amp;#039;,&amp;#039;IS&amp;#039;,&amp;#039;IT&amp;#039;,&amp;#039;JM&amp;#039;,&amp;#039;JO&amp;#039;,&amp;#039;JP&amp;#039;,&amp;#039;KE&amp;#039;,&amp;#039;KG&amp;#039;,&amp;#039;KH&amp;#039;,&amp;#039;KI&amp;#039;,&amp;#039;KM&amp;#039;,&amp;#039;KN&amp;#039;,&amp;#039;KP&amp;#039;,&amp;#039;KR&amp;#039;,&amp;#039;KW&amp;#039;,&amp;#039;KY&amp;#039;,&amp;#039;KZ&amp;#039;,&amp;#039;LA&amp;#039;,&amp;#039;LB&amp;#039;,&amp;#039;LC&amp;#039;,&amp;#039;LI&amp;#039;,&amp;#039;LK&amp;#039;,&amp;#039;LR&amp;#039;,&amp;#039;LS&amp;#039;,&amp;#039;LT&amp;#039;,&amp;#039;LU&amp;#039;,&amp;#039;LV&amp;#039;,&amp;#039;LY&amp;#039;,&amp;#039;MA&amp;#039;,&amp;#039;MC&amp;#039;,&amp;#039;MD&amp;#039;,&amp;#039;MG&amp;#039;,&amp;#039;MH&amp;#039;,&amp;#039;MK&amp;#039;,&amp;#039;ML&amp;#039;,&amp;#039;MM&amp;#039;,&amp;#039;MN&amp;#039;,&amp;#039;MO&amp;#039;,&amp;#039;MP&amp;#039;,&amp;#039;MQ&amp;#039;,&amp;#039;MR&amp;#039;,&amp;#039;MS&amp;#039;,&amp;#039;MT&amp;#039;,&amp;#039;MU&amp;#039;,&amp;#039;MV&amp;#039;,&amp;#039;MW&amp;#039;,&amp;#039;MX&amp;#039;,&amp;#039;MY&amp;#039;,&amp;#039;MZ&amp;#039;,&amp;#039;NA&amp;#039;,&amp;#039;NC&amp;#039;,&amp;#039;NE&amp;#039;,&amp;#039;NF&amp;#039;,&amp;#039;NG&amp;#039;,&amp;#039;NI&amp;#039;,&amp;#039;NL&amp;#039;,&amp;#039;NO&amp;#039;,&amp;#039;NP&amp;#039;,&amp;#039;NR&amp;#039;,&amp;#039;NU&amp;#039;,&amp;#039;NZ&amp;#039;,&amp;#039;OM&amp;#039;,&amp;#039;PA&amp;#039;,&amp;#039;PE&amp;#039;,&amp;#039;PF&amp;#039;,&amp;#039;PG&amp;#039;,&amp;#039;PH&amp;#039;,&amp;#039;PK&amp;#039;,&amp;#039;PL&amp;#039;,&amp;#039;PM&amp;#039;,&amp;#039;PN&amp;#039;,&amp;#039;PR&amp;#039;,&amp;#039;PS&amp;#039;,&amp;#039;PT&amp;#039;,&amp;#039;PW&amp;#039;,&amp;#039;PY&amp;#039;,&amp;#039;QA&amp;#039;,&amp;#039;RE&amp;#039;,&amp;#039;RO&amp;#039;,&amp;#039;RU&amp;#039;,&amp;#039;RW&amp;#039;,&amp;#039;SA&amp;#039;,&amp;#039;SB&amp;#039;,&amp;#039;SC&amp;#039;,&amp;#039;SD&amp;#039;,&amp;#039;SE&amp;#039;,&amp;#039;SG&amp;#039;,&amp;#039;SH&amp;#039;,&amp;#039;SI&amp;#039;,&amp;#039;SJ&amp;#039;,&amp;#039;SK&amp;#039;,&amp;#039;SL&amp;#039;,&amp;#039;SM&amp;#039;,&amp;#039;SN&amp;#039;,&amp;#039;SO&amp;#039;,&amp;#039;SR&amp;#039;,&amp;#039;ST&amp;#039;,&amp;#039;SV&amp;#039;,&amp;#039;SY&amp;#039;,&amp;#039;SZ&amp;#039;,&amp;#039;TC&amp;#039;,&amp;#039;TD&amp;#039;,&amp;#039;TF&amp;#039;,&amp;#039;TG&amp;#039;,&amp;#039;TH&amp;#039;,&amp;#039;TJ&amp;#039;,&amp;#039;TK&amp;#039;,&amp;#039;TM&amp;#039;,&amp;#039;TN&amp;#039;,&amp;#039;TO&amp;#039;,&amp;#039;TP&amp;#039;,&amp;#039;TR&amp;#039;,&amp;#039;TT&amp;#039;,&amp;#039;TV&amp;#039;,&amp;#039;TW&amp;#039;,&amp;#039;TZ&amp;#039;,&amp;#039;UA&amp;#039;,&amp;#039;UG&amp;#039;,&amp;#039;UM&amp;#039;,&amp;#039;US&amp;#039;,&amp;#039;UY&amp;#039;,&amp;#039;UZ&amp;#039;,&amp;#039;VA&amp;#039;,&amp;#039;VC&amp;#039;,&amp;#039;VE&amp;#039;,&amp;#039;VG&amp;#039;,&amp;#039;VI&amp;#039;,&amp;#039;VN&amp;#039;,&amp;#039;VU&amp;#039;,&amp;#039;WF&amp;#039;,&amp;#039;WS&amp;#039;,&amp;#039;YE&amp;#039;,&amp;#039;YT&amp;#039;,&amp;#039;YU&amp;#039;,&amp;#039;ZA&amp;#039;,&amp;#039;ZM&amp;#039;,&amp;#039;ZR&amp;#039;,&amp;#039;ZW&amp;#039;,&amp;#039;A1&amp;#039;,&amp;#039;A2&amp;#039;)&lt;br /&gt;
    __CODE3S = (&amp;#039;--&amp;#039;,&amp;#039;AP&amp;#039;,&amp;#039;EU&amp;#039;,&amp;#039;AND&amp;#039;,&amp;#039;ARE&amp;#039;,&amp;#039;AFG&amp;#039;,&amp;#039;ATG&amp;#039;,&amp;#039;AIA&amp;#039;,&amp;#039;ALB&amp;#039;,&amp;#039;ARM&amp;#039;,&amp;#039;ANT&amp;#039;,&amp;#039;AGO&amp;#039;,&amp;#039;AQ&amp;#039;,&amp;#039;ARG&amp;#039;,&amp;#039;ASM&amp;#039;,&amp;#039;AUT&amp;#039;,&amp;#039;AUS&amp;#039;,&amp;#039;ABW&amp;#039;,&amp;#039;AZE&amp;#039;,&amp;#039;BIH&amp;#039;,&amp;#039;BRB&amp;#039;,&amp;#039;BGD&amp;#039;,&amp;#039;BEL&amp;#039;,&amp;#039;BFA&amp;#039;,&amp;#039;BGR&amp;#039;,&amp;#039;BHR&amp;#039;,&amp;#039;BDI&amp;#039;,&amp;#039;BEN&amp;#039;,&amp;#039;BMU&amp;#039;,&amp;#039;BRN&amp;#039;,&amp;#039;BOL&amp;#039;,&amp;#039;BRA&amp;#039;,&amp;#039;BHS&amp;#039;,&amp;#039;BTN&amp;#039;,&amp;#039;BV&amp;#039;,&amp;#039;BWA&amp;#039;,&amp;#039;BLR&amp;#039;,&amp;#039;BLZ&amp;#039;,&amp;#039;CAN&amp;#039;,&amp;#039;CC&amp;#039;,&amp;#039;COD&amp;#039;,&amp;#039;CAF&amp;#039;,&amp;#039;COG&amp;#039;,&amp;#039;CHE&amp;#039;,&amp;#039;CIV&amp;#039;,&amp;#039;COK&amp;#039;,&amp;#039;CHL&amp;#039;,&amp;#039;CMR&amp;#039;,&amp;#039;CHN&amp;#039;,&amp;#039;COL&amp;#039;,&amp;#039;CRI&amp;#039;,&amp;#039;CUB&amp;#039;,&amp;#039;CPV&amp;#039;,&amp;#039;CX&amp;#039;,&amp;#039;CYP&amp;#039;,&amp;#039;CZE&amp;#039;,&amp;#039;DEU&amp;#039;,&amp;#039;DJI&amp;#039;,&amp;#039;DNK&amp;#039;,&amp;#039;DMA&amp;#039;,&amp;#039;DOM&amp;#039;,&amp;#039;DZA&amp;#039;,&amp;#039;ECU&amp;#039;,&amp;#039;EST&amp;#039;,&amp;#039;EGY&amp;#039;,&amp;#039;ESH&amp;#039;,&amp;#039;ERI&amp;#039;,&amp;#039;ESP&amp;#039;,&amp;#039;ETH&amp;#039;,&amp;#039;FIN&amp;#039;,&amp;#039;FJI&amp;#039;,&amp;#039;FLK&amp;#039;,&amp;#039;FSM&amp;#039;,&amp;#039;FRO&amp;#039;,&amp;#039;FRA&amp;#039;,&amp;#039;FX&amp;#039;,&amp;#039;GAB&amp;#039;,&amp;#039;GBR&amp;#039;,&amp;#039;GRD&amp;#039;,&amp;#039;GEO&amp;#039;,&amp;#039;GUF&amp;#039;,&amp;#039;GHA&amp;#039;,&amp;#039;GIB&amp;#039;,&amp;#039;GRL&amp;#039;,&amp;#039;GMB&amp;#039;,&amp;#039;GIN&amp;#039;,&amp;#039;GLP&amp;#039;,&amp;#039;GNQ&amp;#039;,&amp;#039;GRC&amp;#039;,&amp;#039;GS&amp;#039;,&amp;#039;GTM&amp;#039;,&amp;#039;GUM&amp;#039;,&amp;#039;GNB&amp;#039;,&amp;#039;GUY&amp;#039;,&amp;#039;HKG&amp;#039;,&amp;#039;HM&amp;#039;,&amp;#039;HND&amp;#039;,&amp;#039;HRV&amp;#039;,&amp;#039;HTI&amp;#039;,&amp;#039;HUN&amp;#039;,&amp;#039;IDN&amp;#039;,&amp;#039;IRL&amp;#039;,&amp;#039;ISR&amp;#039;,&amp;#039;IND&amp;#039;,&amp;#039;IO&amp;#039;,&amp;#039;IRQ&amp;#039;,&amp;#039;IRN&amp;#039;,&amp;#039;ISL&amp;#039;,&amp;#039;ITA&amp;#039;,&amp;#039;JAM&amp;#039;,&amp;#039;JOR&amp;#039;,&amp;#039;JPN&amp;#039;,&amp;#039;KEN&amp;#039;,&amp;#039;KGZ&amp;#039;,&amp;#039;KHM&amp;#039;,&amp;#039;KIR&amp;#039;,&amp;#039;COM&amp;#039;,&amp;#039;KNA&amp;#039;,&amp;#039;PRK&amp;#039;,&amp;#039;KOR&amp;#039;,&amp;#039;KWT&amp;#039;,&amp;#039;CYM&amp;#039;,&amp;#039;KAZ&amp;#039;,&amp;#039;LAO&amp;#039;,&amp;#039;LBN&amp;#039;,&amp;#039;LCA&amp;#039;,&amp;#039;LIE&amp;#039;,&amp;#039;LKA&amp;#039;,&amp;#039;LBR&amp;#039;,&amp;#039;LSO&amp;#039;,&amp;#039;LTU&amp;#039;,&amp;#039;LUX&amp;#039;,&amp;#039;LVA&amp;#039;,&amp;#039;LBY&amp;#039;,&amp;#039;MAR&amp;#039;,&amp;#039;MCO&amp;#039;,&amp;#039;MDA&amp;#039;,&amp;#039;MDG&amp;#039;,&amp;#039;MHL&amp;#039;,&amp;#039;MKD&amp;#039;,&amp;#039;MLI&amp;#039;,&amp;#039;MMR&amp;#039;,&amp;#039;MNG&amp;#039;,&amp;#039;MAC&amp;#039;,&amp;#039;MNP&amp;#039;,&amp;#039;MTQ&amp;#039;,&amp;#039;MRT&amp;#039;,&amp;#039;MSR&amp;#039;,&amp;#039;MLT&amp;#039;,&amp;#039;MUS&amp;#039;,&amp;#039;MDV&amp;#039;,&amp;#039;MWI&amp;#039;,&amp;#039;MEX&amp;#039;,&amp;#039;MYS&amp;#039;,&amp;#039;MOZ&amp;#039;,&amp;#039;NAM&amp;#039;,&amp;#039;NCL&amp;#039;,&amp;#039;NER&amp;#039;,&amp;#039;NFK&amp;#039;,&amp;#039;NGA&amp;#039;,&amp;#039;NIC&amp;#039;,&amp;#039;NLD&amp;#039;,&amp;#039;NOR&amp;#039;,&amp;#039;NPL&amp;#039;,&amp;#039;NRU&amp;#039;,&amp;#039;NIU&amp;#039;,&amp;#039;NZL&amp;#039;,&amp;#039;OMN&amp;#039;,&amp;#039;PAN&amp;#039;,&amp;#039;PER&amp;#039;,&amp;#039;PYF&amp;#039;,&amp;#039;PNG&amp;#039;,&amp;#039;PHL&amp;#039;,&amp;#039;PAK&amp;#039;,&amp;#039;POL&amp;#039;,&amp;#039;SPM&amp;#039;,&amp;#039;PCN&amp;#039;,&amp;#039;PRI&amp;#039;,&amp;#039;PSE&amp;#039;,&amp;#039;PRT&amp;#039;,&amp;#039;PLW&amp;#039;,&amp;#039;PRY&amp;#039;,&amp;#039;QAT&amp;#039;,&amp;#039;REU&amp;#039;,&amp;#039;ROM&amp;#039;,&amp;#039;RUS&amp;#039;,&amp;#039;RWA&amp;#039;,&amp;#039;SAU&amp;#039;,&amp;#039;SLB&amp;#039;,&amp;#039;SYC&amp;#039;,&amp;#039;SDN&amp;#039;,&amp;#039;SWE&amp;#039;,&amp;#039;SGP&amp;#039;,&amp;#039;SHN&amp;#039;,&amp;#039;SVN&amp;#039;,&amp;#039;SJM&amp;#039;,&amp;#039;SVK&amp;#039;,&amp;#039;SLE&amp;#039;,&amp;#039;SMR&amp;#039;,&amp;#039;SEN&amp;#039;,&amp;#039;SOM&amp;#039;,&amp;#039;SUR&amp;#039;,&amp;#039;STP&amp;#039;,&amp;#039;SLV&amp;#039;,&amp;#039;SYR&amp;#039;,&amp;#039;SWZ&amp;#039;,&amp;#039;TCA&amp;#039;,&amp;#039;TCD&amp;#039;,&amp;#039;TF&amp;#039;,&amp;#039;TGO&amp;#039;,&amp;#039;THA&amp;#039;,&amp;#039;TJK&amp;#039;,&amp;#039;TKL&amp;#039;,&amp;#039;TLS&amp;#039;,&amp;#039;TKM&amp;#039;,&amp;#039;TUN&amp;#039;,&amp;#039;TON&amp;#039;,&amp;#039;TUR&amp;#039;,&amp;#039;TTO&amp;#039;,&amp;#039;TUV&amp;#039;,&amp;#039;TWN&amp;#039;,&amp;#039;TZA&amp;#039;,&amp;#039;UKR&amp;#039;,&amp;#039;UGA&amp;#039;,&amp;#039;UM&amp;#039;,&amp;#039;USA&amp;#039;,&amp;#039;URY&amp;#039;,&amp;#039;UZB&amp;#039;,&amp;#039;VAT&amp;#039;,&amp;#039;VCT&amp;#039;,&amp;#039;VEN&amp;#039;,&amp;#039;VGB&amp;#039;,&amp;#039;VIR&amp;#039;,&amp;#039;VNM&amp;#039;,&amp;#039;VUT&amp;#039;,&amp;#039;WLF&amp;#039;,&amp;#039;WSM&amp;#039;,&amp;#039;YEM&amp;#039;,&amp;#039;YT&amp;#039;,&amp;#039;YUG&amp;#039;,&amp;#039;ZAF&amp;#039;,&amp;#039;ZMB&amp;#039;,&amp;#039;ZR&amp;#039;,&amp;#039;ZWE&amp;#039;,&amp;#039;A1&amp;#039;,&amp;#039;A2&amp;#039;)&lt;br /&gt;
    __NAMES = (&amp;quot;--&amp;quot;,&amp;quot;Asia/Pacific Region&amp;quot;,&amp;quot;Europe&amp;quot;,&amp;quot;Andorra&amp;quot;,&amp;quot;United Arab Emirates&amp;quot;,&amp;quot;Afghanistan&amp;quot;,&amp;quot;Antigua and Barbuda&amp;quot;,&amp;quot;Anguilla&amp;quot;,&amp;quot;Albania&amp;quot;,&amp;quot;Armenia&amp;quot;,&amp;quot;Netherlands Antilles&amp;quot;,&amp;quot;Angola&amp;quot;,&amp;quot;Antarctica&amp;quot;,&amp;quot;Argentina&amp;quot;,&amp;quot;American Samoa&amp;quot;,&amp;quot;Austria&amp;quot;,&amp;quot;Australia&amp;quot;,&amp;quot;Aruba&amp;quot;,&amp;quot;Azerbaijan&amp;quot;,&amp;quot;Bosnia and Herzegovina&amp;quot;,&amp;quot;Barbados&amp;quot;,&amp;quot;Bangladesh&amp;quot;,&amp;quot;Belgium&amp;quot;,&amp;quot;Burkina Faso&amp;quot;,&amp;quot;Bulgaria&amp;quot;,&amp;quot;Bahrain&amp;quot;,&amp;quot;Burundi&amp;quot;,&amp;quot;Benin&amp;quot;,&amp;quot;Bermuda&amp;quot;,&amp;quot;Brunei Darussalam&amp;quot;,&amp;quot;Bolivia&amp;quot;,&amp;quot;Brazil&amp;quot;,&amp;quot;Bahamas&amp;quot;,&amp;quot;Bhutan&amp;quot;,&amp;quot;Bouvet Island&amp;quot;,&amp;quot;Botswana&amp;quot;,&amp;quot;Belarus&amp;quot;,&amp;quot;Belize&amp;quot;,&amp;quot;Canada&amp;quot;,&amp;quot;Cocos (Keeling) Islands&amp;quot;,&amp;quot;Congo, The Democratic Republic of the&amp;quot;,&amp;quot;Central African Republic&amp;quot;,&amp;quot;Congo&amp;quot;,&amp;quot;Switzerland&amp;quot;,&amp;quot;Cote D&amp;#039;Ivoire&amp;quot;,&amp;quot;Cook Islands&amp;quot;,&amp;quot;Chile&amp;quot;,&amp;quot;Cameroon&amp;quot;,&amp;quot;China&amp;quot;,&amp;quot;Colombia&amp;quot;,&amp;quot;Costa Rica&amp;quot;,&amp;quot;Cuba&amp;quot;,&amp;quot;Cape Verde&amp;quot;,&amp;quot;Christmas Island&amp;quot;,&amp;quot;Cyprus&amp;quot;,&amp;quot;Czech Republic&amp;quot;,&amp;quot;Germany&amp;quot;,&amp;quot;Djibouti&amp;quot;,&amp;quot;Denmark&amp;quot;,&amp;quot;Dominica&amp;quot;,&amp;quot;Dominican Republic&amp;quot;,&amp;quot;Algeria&amp;quot;,&amp;quot;Ecuador&amp;quot;,&amp;quot;Estonia&amp;quot;,&amp;quot;Egypt&amp;quot;,&amp;quot;Western Sahara&amp;quot;,&amp;quot;Eritrea&amp;quot;,&amp;quot;Spain&amp;quot;,&amp;quot;Ethiopia&amp;quot;,&amp;quot;Finland&amp;quot;,&amp;quot;Fiji&amp;quot;,&amp;quot;Falkland Islands (Malvinas)&amp;quot;,&amp;quot;Micronesia, Federated States of&amp;quot;,&amp;quot;Faroe Islands&amp;quot;,&amp;quot;France&amp;quot;,&amp;quot;France, Metropolitan&amp;quot;,&amp;quot;Gabon&amp;quot;,&amp;quot;United Kingdom&amp;quot;,&amp;quot;Grenada&amp;quot;,&amp;quot;Georgia&amp;quot;,&amp;quot;French Guiana&amp;quot;,&amp;quot;Ghana&amp;quot;,&amp;quot;Gibraltar&amp;quot;,&amp;quot;Greenland&amp;quot;,&amp;quot;Gambia&amp;quot;,&amp;quot;Guinea&amp;quot;,&amp;quot;Guadeloupe&amp;quot;,&amp;quot;Equatorial Guinea&amp;quot;,&amp;quot;Greece&amp;quot;,&amp;quot;South Georgia and the South Sandwich Islands&amp;quot;,&amp;quot;Guatemala&amp;quot;,&amp;quot;Guam&amp;quot;,&amp;quot;Guinea-Bissau&amp;quot;,&amp;quot;Guyana&amp;quot;,&amp;quot;Hong Kong&amp;quot;,&amp;quot;Heard Island and McDonald Islands&amp;quot;,&amp;quot;Honduras&amp;quot;,&amp;quot;Croatia&amp;quot;,&amp;quot;Haiti&amp;quot;,&amp;quot;Hungary&amp;quot;,&amp;quot;Indonesia&amp;quot;,&amp;quot;Ireland&amp;quot;,&amp;quot;Israel&amp;quot;,&amp;quot;India&amp;quot;,&amp;quot;British Indian Ocean Territory&amp;quot;,&amp;quot;Iraq&amp;quot;,&amp;quot;Iran, Islamic Republic of&amp;quot;,&amp;quot;Iceland&amp;quot;,&amp;quot;Italy&amp;quot;,&amp;quot;Jamaica&amp;quot;,&amp;quot;Jordan&amp;quot;,&amp;quot;Japan&amp;quot;,&amp;quot;Kenya&amp;quot;,&amp;quot;Kyrgyzstan&amp;quot;,&amp;quot;Cambodia&amp;quot;,&amp;quot;Kiribati&amp;quot;,&amp;quot;Comoros&amp;quot;,&amp;quot;Saint Kitts and Nevis&amp;quot;,&lt;br /&gt;
&amp;quot;Korea, Democratic People&amp;#039;s Republic of&amp;quot;,&amp;quot;Korea, Republic of&amp;quot;,&amp;quot;Kuwait&amp;quot;,&amp;quot;Cayman Islands&amp;quot;,&amp;quot;Kazakhstan&amp;quot;,&amp;quot;Lao People&amp;#039;s Democratic Republic&amp;quot;,&amp;quot;Lebanon&amp;quot;,&amp;quot;Saint Lucia&amp;quot;,&amp;quot;Liechtenstein&amp;quot;,&amp;quot;Sri Lanka&amp;quot;,&amp;quot;Liberia&amp;quot;,&amp;quot;Lesotho&amp;quot;,&amp;quot;Lithuania&amp;quot;,&amp;quot;Luxembourg&amp;quot;,&amp;quot;Latvia&amp;quot;,&amp;quot;Libyan Arab Jamahiriya&amp;quot;,&amp;quot;Morocco&amp;quot;,&amp;quot;Monaco&amp;quot;,&amp;quot;Moldova, Republic of&amp;quot;,&amp;quot;Madagascar&amp;quot;,&amp;quot;Marshall Islands&amp;quot;,&amp;quot;Macedonia&amp;quot;,&amp;quot;Mali&amp;quot;,&amp;quot;Myanmar&amp;quot;,&amp;quot;Mongolia&amp;quot;,&amp;quot;Macau&amp;quot;,&amp;quot;Northern Mariana Islands&amp;quot;,&amp;quot;Martinique&amp;quot;,&amp;quot;Mauritania&amp;quot;,&amp;quot;Montserrat&amp;quot;,&amp;quot;Malta&amp;quot;,&amp;quot;Mauritius&amp;quot;,&amp;quot;Maldives&amp;quot;,&amp;quot;Malawi&amp;quot;,&amp;quot;Mexico&amp;quot;,&amp;quot;Malaysia&amp;quot;,&amp;quot;Mozambique&amp;quot;,&amp;quot;Namibia&amp;quot;,&amp;quot;New Caledonia&amp;quot;,&amp;quot;Niger&amp;quot;,&amp;quot;Norfolk Island&amp;quot;,&amp;quot;Nigeria&amp;quot;,&amp;quot;Nicaragua&amp;quot;,&amp;quot;Netherlands&amp;quot;,&amp;quot;Norway&amp;quot;,&amp;quot;Nepal&amp;quot;,&amp;quot;Nauru&amp;quot;,&amp;quot;Niue&amp;quot;,&amp;quot;New Zealand&amp;quot;,&amp;quot;Oman&amp;quot;,&amp;quot;Panama&amp;quot;,&amp;quot;Peru&amp;quot;,&amp;quot;French Polynesia&amp;quot;,&amp;quot;Papua New Guinea&amp;quot;,&amp;quot;Philippines&amp;quot;,&amp;quot;Pakistan&amp;quot;,&amp;quot;Poland&amp;quot;,&amp;quot;Saint Pierre and Miquelon&amp;quot;,&amp;quot;Pitcairn Islands&amp;quot;,&amp;quot;Puerto Rico&amp;quot;,&amp;quot;Palestinian Territory, Occupied&amp;quot;,&amp;quot;Portugal&amp;quot;,&amp;quot;Palau&amp;quot;,&amp;quot;Paraguay&amp;quot;,&amp;quot;Qatar&amp;quot;,&amp;quot;Reunion&amp;quot;,&amp;quot;Romania&amp;quot;,&amp;quot;Russian Federation&amp;quot;,&amp;quot;Rwanda&amp;quot;,&amp;quot;Saudi Arabia&amp;quot;,&amp;quot;Solomon Islands&amp;quot;,&amp;quot;Seychelles&amp;quot;,&amp;quot;Sudan&amp;quot;,&amp;quot;Sweden&amp;quot;,&amp;quot;Singapore&amp;quot;,&amp;quot;Saint Helena&amp;quot;,&amp;quot;Slovenia&amp;quot;,&amp;quot;Svalbard and Jan Mayen&amp;quot;,&amp;quot;Slovakia&amp;quot;,&amp;quot;Sierra Leone&amp;quot;,&amp;quot;San Marino&amp;quot;,&amp;quot;Senegal&amp;quot;,&amp;quot;Somalia&amp;quot;,&amp;quot;Suriname&amp;quot;,&amp;quot;Sao Tome and Principe&amp;quot;,&amp;quot;El Salvador&amp;quot;,&amp;quot;Syrian Arab Republic&amp;quot;,&amp;quot;Swaziland&amp;quot;,&amp;quot;Turks and Caicos Islands&amp;quot;,&amp;quot;Chad&amp;quot;,&amp;quot;French Southern Territories&amp;quot;,&amp;quot;Togo&amp;quot;,&amp;quot;Thailand&amp;quot;,&amp;quot;Tajikistan&amp;quot;,&amp;quot;Tokelau&amp;quot;,&amp;quot;Turkmenistan&amp;quot;,&amp;quot;Tunisia&amp;quot;,&amp;quot;Tonga&amp;quot;,&amp;quot;East Timor&amp;quot;,&amp;quot;Turkey&amp;quot;,&amp;quot;Trinidad and Tobago&amp;quot;,&amp;quot;Tuvalu&amp;quot;,&amp;quot;Taiwan&amp;quot;,&amp;quot;Tanzania, United Republic of&amp;quot;,&amp;quot;Ukraine&amp;quot;,&amp;quot;Uganda&amp;quot;,&amp;quot;United States Minor Outlying Islands&amp;quot;,&amp;quot;United States&amp;quot;,&amp;quot;Uruguay&amp;quot;,&amp;quot;Uzbekistan&amp;quot;,&amp;quot;Holy See (Vatican City State)&amp;quot;,&amp;quot;Saint Vincent and the Grenadines&amp;quot;,&amp;quot;Venezuela&amp;quot;,&amp;quot;Virgin Islands, British&amp;quot;,&amp;quot;Virgin Islands, U.S.&amp;quot;,&amp;quot;Vietnam&amp;quot;,&amp;quot;Vanuatu&amp;quot;,&amp;quot;Wallis and Futuna&amp;quot;,&amp;quot;Samoa&amp;quot;,&amp;quot;Yemen&amp;quot;,&amp;quot;Mayotte&amp;quot;,&amp;quot;Yugoslavia&amp;quot;,&amp;quot;South Africa&amp;quot;,&amp;quot;Zambia&amp;quot;,&amp;quot;Zaire&amp;quot;,&amp;quot;Zimbabwe&amp;quot;,&lt;br /&gt;
&amp;quot;Anonymous Proxy&amp;quot;,&amp;quot;Satellite Provider&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    __RE_IP_DOTTED_FORM = re.compile(&amp;quot;^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    GEOIP_STANDARD = 0 # TODO&lt;br /&gt;
&lt;br /&gt;
    def addr_to_num(ip_address):&lt;br /&gt;
        &amp;#039;&amp;#039;&amp;#039;Convert IP-address to number.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
        # a = [int(s) for s in re.split(&amp;#039;\.&amp;#039;, ip_address)]&lt;br /&gt;
        a = map(int, re.split(&amp;#039;\.&amp;#039;, ip_address))&lt;br /&gt;
        return a[0] * 16777216L + a[1] * 65536L + a[2] * 256L + a[3]&lt;br /&gt;
&lt;br /&gt;
    def open(db_file, flags):&lt;br /&gt;
        &amp;#039;&amp;#039;&amp;#039;Create a new GeoIP object.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
        gi = GeoIP()&lt;br /&gt;
        gi.db_file = db_file&lt;br /&gt;
        gi.flags = flags # TODO&lt;br /&gt;
        gi.fh = open(db_file, &amp;#039;rb&amp;#039;)&lt;br /&gt;
        gi.databaseType = GeoIP.__GEOIP_COUNTRY_EDITION # TODO&lt;br /&gt;
        gi.record_length = GeoIP.__STANDARD_RECORD_LENGTH # TODO&lt;br /&gt;
        gi.databaseSegments = GeoIP.__GEOIP_COUNTRY_BEGIN # TODO&lt;br /&gt;
        return gi&lt;br /&gt;
&lt;br /&gt;
    def new(flags):&lt;br /&gt;
        &amp;#039;&amp;#039;&amp;#039;Create a new GeoIP object.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
        return GeoIP.open(&amp;#039;/usr/local/share/GeoIP/GeoIP.dat&amp;#039;, flags)&lt;br /&gt;
&lt;br /&gt;
    def __seek_country(self, ipnum):&lt;br /&gt;
        &amp;#039;&amp;#039;&amp;#039;Seek GeoIP data file to find country id.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
        fh = self.fh&lt;br /&gt;
        record_length = self.record_length&lt;br /&gt;
        databaseSegments = self.databaseSegments&lt;br /&gt;
        offset = 0&lt;br /&gt;
        x0 = -1&lt;br /&gt;
        x1 = -1&lt;br /&gt;
        for depth in nreverse(range(32)):&lt;br /&gt;
            fh.seek(offset * 2 * record_length, 0)&lt;br /&gt;
            x0 = fh.read(record_length)&lt;br /&gt;
            x1 = fh.read(record_length)&lt;br /&gt;
            x0, = struct.unpack(&amp;quot;&amp;lt;1l&amp;quot;, x0 + &amp;quot;\0&amp;quot;)&lt;br /&gt;
            x1, = struct.unpack(&amp;quot;&amp;lt;1l&amp;quot;, x1 + &amp;quot;\0&amp;quot;)&lt;br /&gt;
            if ipnum &amp;amp; (1L &amp;lt;&amp;lt; depth):&lt;br /&gt;
                if x1 &amp;gt;= databaseSegments:&lt;br /&gt;
                    return x1&lt;br /&gt;
                offset = x1&lt;br /&gt;
            else:&lt;br /&gt;
                if x0 &amp;gt;= databaseSegments:&lt;br /&gt;
                    return x0&lt;br /&gt;
                offset = x0&lt;br /&gt;
        raise Exception(&amp;#039;Error Traversing Database for ipnum = %d - Perhaps database is corrupt?&amp;#039; % ipnum) # TODO&lt;br /&gt;
&lt;br /&gt;
    def id_by_addr(self, ip_address):&lt;br /&gt;
        &amp;#039;&amp;#039;&amp;#039;Find country id by IP-address.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
        if self.__RE_IP_DOTTED_FORM.match(ip_address):&lt;br /&gt;
            return self.__seek_country(self.addr_to_num(ip_address)) - self.__GEOIP_COUNTRY_BEGIN&lt;br /&gt;
        else:&lt;br /&gt;
            return 0&lt;br /&gt;
&lt;br /&gt;
    def id_to_country_code(id):&lt;br /&gt;
        &amp;#039;&amp;#039;&amp;#039;Convert country id to country code.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
        return GeoIP.__COUNTRIES[id]&lt;br /&gt;
&lt;br /&gt;
    def id_to_country_code3(id):&lt;br /&gt;
        &amp;#039;&amp;#039;&amp;#039;Convert country id to country code.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
        return GeoIP.__CODE3S[id]&lt;br /&gt;
&lt;br /&gt;
    def id_to_country_name(id):&lt;br /&gt;
        &amp;#039;&amp;#039;&amp;#039;Convert country id to country code.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
        return GeoIP.__NAMES[id]&lt;br /&gt;
&lt;br /&gt;
    def country_code_by_addr(self, ip_address):&lt;br /&gt;
        &amp;#039;&amp;#039;&amp;#039;Find country code by IP-address.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
        return GeoIP.id_to_country_code(self.id_by_addr(ip_address))&lt;br /&gt;
&lt;br /&gt;
    def country_code3_by_addr(self, ip_address):&lt;br /&gt;
        &amp;#039;&amp;#039;&amp;#039;Find country code3 by IP-address.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
        return GeoIP.id_to_country_code3(self.id_by_addr(ip_address))&lt;br /&gt;
&lt;br /&gt;
    def country_name_by_addr(self, ip_address):&lt;br /&gt;
        &amp;#039;&amp;#039;&amp;#039;Find country name by IP-address.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
        return GeoIP.id_to_country_name(self.id_by_addr(ip_address))&lt;br /&gt;
&lt;br /&gt;
    addr_to_num = staticmethod(addr_to_num)&lt;br /&gt;
    open = staticmethod(open)&lt;br /&gt;
    new = staticmethod(new)&lt;br /&gt;
    id_to_country_code = staticmethod(id_to_country_code)&lt;br /&gt;
    id_to_country_code3 = staticmethod(id_to_country_code3)&lt;br /&gt;
    id_to_country_name = staticmethod(id_to_country_name)&lt;br /&gt;
&lt;br /&gt;
if &amp;#039;__main__&amp;#039; == __name__:&lt;br /&gt;
    import sys&lt;br /&gt;
    import string&lt;br /&gt;
&lt;br /&gt;
    argc = len(sys.argv)&lt;br /&gt;
    gi = None&lt;br /&gt;
    if 2 == argc:&lt;br /&gt;
        gi = GeoIP.new(GeoIP.GEOIP_STANDARD)&lt;br /&gt;
    elif 3 == argc:&lt;br /&gt;
        gi = GeoIP.open(sys.argv[2], GeoIP.GEOIP_STANDARD)&lt;br /&gt;
    else:&lt;br /&gt;
        print &amp;quot;Usage:\n  %s &amp;lt;ipaddress&amp;gt; [geoipdatafile]&amp;quot; % sys.argv[0]&lt;br /&gt;
        sys.exit(1)&lt;br /&gt;
&lt;br /&gt;
    ip = sys.argv[1]&lt;br /&gt;
    id = str(gi.id_by_addr(ip))&lt;br /&gt;
    code = gi.country_code_by_addr(ip)&lt;br /&gt;
    code3 = gi.country_code3_by_addr(ip)&lt;br /&gt;
    name = gi.country_name_by_addr(ip)&lt;br /&gt;
&lt;br /&gt;
    print string.join([&amp;#039;ipaddress&amp;#039;, &amp;#039;id&amp;#039;, &amp;#039;code&amp;#039;, &amp;#039;code3&amp;#039;, &amp;#039;name&amp;#039;], &amp;quot;\t&amp;quot;)&lt;br /&gt;
    print string.join([ip, id, code, code3, name], &amp;quot;\t&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pireax</name></author>
	</entry>
</feed>