IP-to-Country plugin

You can find a Serbo-Croatian translation of this article here (not my translation nor webpage). It was created by Andrijana Nikolic (thanks!).

There are many WordPress plugins for geolocation (assinging a country and possibly a city to a given IP address). Unfortunately, all of them are intended for users of WordPress, not for plugin programmers. I tried to remedy this situation with my new plugin IP-to-Country, which doesn’t provide any visual output – it just publishes methods which may be used by other programmers in their plugins. Which I immediately did in my Simple Download Manager plugin.

Installation and update

To install this plugin, follow standard WordPress steps: Download the distribution archive from WordPress repository or directly this page, extract it to some directory and upload it to your blog. Then activate the plugin from administrator’s Plugins menu.

Update works the same way, you can also use the automatic update from WordPress plugin repository.

Importing data

Geolocation in its most common form uses a list of IP addresses with countries assigned to each. My plugin also uses this kind of data. There is a number of possible sources, after an „exahausting research“ (=running a Google search and choosing the first acceptable result) I have decided to use data from ip-to-country.webhosting.info, which have a stable download address (which allows easy updating) and an easily-parsed file: it’s a standard CSV file with 5 columns: starting IP address, ending IP address (both define an interval of addresses which belong to the same country), two-letter ISO code of the country, three-letter ISO code of the country and full ISO name of the country. Columns are quoted by straight quotes " and separated by a comma ,, line-separator is LF (ASCII code 10, PHP representation \n). Example:

"100663296","121195295","US","USA","UNITED STATES"
"121195296","121195327","IT","ITA","ITALY"
"121195328","134693119","US","USA","UNITED STATES"
"134693120","134693375","CA","CAN","CANADA"

Unlike the usual representation of IP addresses as four 8-bit numbers separated by dots, the file uses a representation of one 32-bit integer. In PHP you can convert between the two representations with functions ip2long (4x8bit to 32bit) and long2ip (back). Or you can calculate by hand – you can reach address EEEE from address A.B.C.D by following this formula: EEEE = 2563*A + 2562*B + 2561*C + 2560*D = 16777216*A + 65536*B + 256*C + D.

Once you have the data in a supported format, uploading it to your database is extremely simple: Open the plugin’s configuration menu, select the source of data („official“ URL, your own URL, or a file located on your computer) and click the „Save settings and Upload data“ button. It should hopefully work with any server; however, you will need the php_zip extension enabled if you want to use a zipped source (such as the one from the official URL).

Plugin settings

Using the plugin

The plugin supports following tasks. If you would like another feature, just drop me a line.

  • Test, whether the plugin is active: If the plugin is active, class PepakIpToCountry is defined:

    if (class_exists('PepakIpToCountry'))
      echo "Geolocation is available";
    else
      echo "Please activate Ip-to-Country plugin";
  • Find in which country lies a given IP address: If the plugin is active, you can call one of the five defined static methods. All of them expect an IP address in numerical form as a parameter and return a particular piece of data:

    $country = PepakIpToCountry::IP_to_Country_Full('8.8.8.8');
    // $country = 'UNITED STATES';
    $code2 = PepakIpToCountry::IP_to_Country_XX('8.8.8.8');
    $code2a = PepakIpToCountry::IP_to_Country('8.8.8.8');
    // $code2 = $code2a == 'US';
    $code3 = PepakIpToCountry::IP_to_Country_XXX('8.8.8.8');
    // $code3 = 'USA';
    $info = PepakIpToCountry::IP_to_Country_Info('8.8.8.8');
    // $info = Array('iso_name'=>'UNITED STATES', 'iso_code2'=>'US', 'iso_code3'=>'USA')`;

    All requests are cached, so it makes little difference whether you read info for a particular address from one call to IP_to_Country_Info or whether you call all the other functions.

    You don’t need to provide an IP address if you are only interested in current user’s country:

    echo "Welcome, visitor from " . PepakIpToCountry::IP_to_Country_Full();

    These functions are useful if your script has an IP address and needs to know its country.

  • Add a country information to SQL query: If the plugin is active, you can use its method PepakIpToCountry::Subselect(...), which can include a country info in just about any SQL query. Suppose you have the following query (taken from my Simple Download Monitor)::

    $sql = "SELECT id, download_date, ip, referer, userid, username
    FROM wp_sdmon_details
    WHERE download=123
    ORDER BY download_date DESC
    LIMIT 20";

    Now you want to add country info to each row in this query. You could do that by 20 calls to IP_to_Country... methods, but that would put an unnecessary strain on your database server. Using Subselect you can easily add a new field to the resultset:

    if (class_exists('PepakIpToCountry'))
      $zeme2 = PepakIpToCountry::Subselect('INET_ATON(wp_sdmon_details.ip)', 'iso_code2');
    else
      $zeme2 = 'NULL';
    $sql = "SELECT id, download_date, ip, referer, userid, username, $code2 code2
    FROM wp_sdmon_details
    WHERE download=123
    ORDER BY download_date DESC
    LIMIT 20";

    Method PepakIpToCountry::SubSelect($field, $resultfield) accepts two arguments:

    1. $field defines a source field for IP address. It can be any field in your query (in my case field ip in table wp_sdmon_details), it;s just important to make sure it is fully-qualified – that is, instead of using just field_name, try table_name.field_name. The other requirement is that the field must be in a 32bit-number form. If your tables use the more common A.B.C.D form, you can use a MySQL function INET_ATON, to convert A.B.C.D into the one number. You can use the code above as an example.

    2. $resultfield defines which field will be returned by the subselect. Possible values are: iso_name (returns full ISO name of the country, such as „UNITED STATES“), iso_code2 (returns a two-letter ISO code, e.g. „US“), iso_code3 (returns a three-letter ISO code, e.g. „USA“).

    Important security notice: The method Subselect cannot validate its input parameters against SQL-injection attacks (that is, the $resultfield could be validated as it can only contain one of a few string values, but $field can’t be validated at all). It’s critically important that you make sure to never send anything that a user could have defined to the function! If you do not take this precaution, you give your users an ability to do anything they like with your database. I recommend only sending literal strings or constants (well, and $wpdb->prefix) and their combinations into the method.

Several data-input functions are available as well, but I am sure that if you feel the need to use them, you will be able to locate them in the source code.

If you have any questions of feature requests, post a new comment here or in my forums (you don’t need to register to post there).

Download

Podobné příspěvky:

23 komentářů “IP-to-Country plugin”

  1. avatar pepak napsal:

    DeAlwis: I am sorry, my experience with plugins is limited. And because I don’t allow registration here, my experience with registration plugins is nonexistent.

  2. avatar DeAlwis napsal:

    Hi,

    I am looking for a plugin that will allow at registration and search to have country/city list. You mentioned early in the article that there are such which recognise IP and,country etc. Do you have any suggestions which I could use?

  3. avatar pepak napsal:

    OK. Done in my development version. Will have to build and release it sometime.

  4. avatar Mixo napsal:

    It worked, thanks! Somehow I totally neglected the importing part :“)

    Also, while we’re there, please see to correct the Serbo-Croatian translation of buttons from „S. podešenja“ to „S. podešavanja“ and from „S. p. i dopunu“ to „S. p. i ažuriraj“, and also „Otpremljen je“ to „Otpremi“. Makes much more sense ^^

    Cheers

  5. avatar pepak napsal:

    Mixo: Did you import a list of Geo-IP data? Without that there’s no way to match IP addresses to locations. You can import the data in the plugin’s configuration.

  6. avatar Mixo napsal:

    Hi,

    The plugin doesn’t seem to work for me for some reason :/ I installed it, enabled it, took the index.php of my theme, inserted the code, tested it, and everything functions alright, except that the function always returns nothing? No 2-char code, no 3-char code, no full name.

    I only tried it from my static IP adress, I’m on WordPress 5, and I don’t know what I should do?

    Thanks,
    Mixo

  7. avatar pepak napsal:

    Version 0.06: Serbo-Croatian translation by Andrijana Nikolic. Fixed warnings in WordPress 3.5.

  8. avatar pepak napsal:

    uzma: What are you looking for? There is no activation in the source code, you just need to activate the plugin in the WordPress’s Plugin options.

  9. avatar uzma napsal:

    if (class_exists(‚PepakIpToCountry‘))
    echo „Geolocation is available“;
    else
    echo „Please activate Ip-to-Country plugin“;

    where it is located i didn’t find it in iptocountry.php

  10. avatar pepak napsal:

    Version 0.05: Romanian translation by Alexander Ovsov.

  11. avatar pepak napsal:

    Dave: I am afraid I don’t know how to help you then. Your webhost is apparently powerful enough (more powerful than mine, anyway) to handle the import, and I have no idea why it fails. I guess your only option is to import the file to your local copy of your blog, and then copy the content of tables wp_ip2c_countries, wp_ip2c_addresses and wp_ip2c_ipv6 to your online version. There is no real setup, only the tables need to contain some data.

  12. avatar Dave napsal:

    Thanks for the reply, I tried that file now, it uploaded okay but I get a timeout error after 30s again.

    I tried setting

    fastcgi_read_timeout 600; in my server config,

    memory_limit = 256M
    max_execution_time = 600 in php.ini

    and set_time_limit(600); in the plugin file

    but it still times out (after 10 minutes).

  13. avatar pepak napsal:

    Dave: Are you sure you are downloading the right file? I have just checked the one from http://ip-to-country.webhosting.info/ (click „download“, then click „latest IP-to-Country Database“) and it seems to be short enough and quickly imported. Also rather old, but good enough for the starters.

    Note: If your webhost doesn’t work with zipped files, unzip the archive and upload it; you can even upload it to your own website and import it using the custom URL to overcome the tiny max_upload_size.

  14. avatar Dave napsal:

    Hi Pepak

    I can’t get the plugin to work. When I install and activate it, it creates the empty tables in the db. If I try and update the db from the IP-to-Country options page in the admin area, I get a timeout after 30s.

    I tried adding set_time_limit(120) to the plugin file just above the class declaration, but that makes a blank page load up after 30s, and the database tables still aren’t populated.

    I also tried downloading the file from http://software77.net/geo-ip/?DL=1 and then updating using the ‚Uploaded file with IPv4‘ option. But my server won’t let me upload files that large (I guess it’s probably set to a max upload size of 1MB or something).

    Any suggestions?

    Thanks

    Dave

  15. avatar pepak napsal:

    Version 0.04: Added a TITLE attribute to the HTML code of flag images.

  16. avatar Phillip napsal:

    This is great. It worked just as I hoped, and I’m now able to add per-country content to my client’s site.

    Thanks so much!

  17. avatar pepak napsal:

    That really depends on the plugin you use. You will almost certainly need to have at least some minimal knowledge of PHP, and like as not at least some basic knowledge of WordPress plugin programming.

    If you want to discuss a specific problem further, I’ll be glad to help you, depending on my free time of course, It would be better to discuss it in the forums, though – just go there and open a topic in the english section. (You don’t need to register to post, unless you want to.)

  18. avatar Sun napsal:

    Thanks for your quick response!
    But it seems too complicated to me 🙁
    I wanted to use it so much cause my website visitors major part are from 4-5 countries but the can see items only from amazon.com.

    Maybe I could try… Which is the file where I am supposed to make these changes? Thanks.

  19. avatar pepak napsal:

    Easy answers first: If you don’t know which database to download from software77.net, just download the predefined one.

    As to the question on „how to use it“: It won’t help you by itself. It does not perform any user-visible tasks. The point of the plugin is that it provides a simple interface which can be used by other plugins to provide geolocation. So, in your case, you would have to modify the Amazon Machine Tags plugin. Suppose that the plugin stores IP addresses somewhere and displays them with something like echo $ip_addr;. You could modify that to something like: echo $ip_addr; if (class_exists('PepakIpToCountry')) echo PepakIpToCountry::IP_to_Country_Flag($ip_addr); (which would add a country flag next to the IP address).

  20. avatar Sun napsal:

    Hi Pepak,
    I have downloaded the plugin to use it for a country detection with Amazon Machine Tags plugin.
    It sits downloaded on my wp blog and activated. What next? Sorry, but I am not sure what should I do know. I visited http://software77.net/geo-ip/?license for the files for upload but not sure which is the ones I need, and what’s their path (I can’t sort it out). At least I hope I have understood it correctly what needs to be done with all this. ?
    Your help is appreciated.

    Thank you in advance.

  21. avatar pepak napsal:

    Fixed the reported bug. Added support for IPv6. Added flag icons for use by other plugins.

  22. avatar pepak napsal:

    Thanks, it will be fixed.

  23. avatar Andrea napsal:

    there is a bug in the file „ip-to-country.php“ on line 111. ip2long() returns a signed integer, hence $ip<0 is valid. on line 118 you shuld change the sprint-format from %d to %u the get the right ip to look up in the database.

Leave a Reply

Themocracy iconWordPress Themes

css.php