~ubuntu-branches/ubuntu/saucy/horde3/saucy

« back to all changes in this revision

Viewing changes to lib/Horde/NLS/GeoIP.php

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2005-05-04 23:08:08 UTC
  • Revision ID: james.westby@ubuntu.com-20050504230808-p4hf3hk28o3v7wir
Tags: upstream-3.0.4
ImportĀ upstreamĀ versionĀ 3.0.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
/**
 
3
 * Horde optimized interface to the MaxMind IP Address->Country
 
4
 * listing.
 
5
 *
 
6
 * $Horde: framework/NLS/NLS/GeoIP.php,v 1.10.10.1 2005/01/03 12:19:08 jan Exp $
 
7
 *
 
8
 * Based on PHP geoip.inc library by MaxMind LLC:
 
9
 *   http://www.maxmind.com/download/geoip/api/php/
 
10
 *
 
11
 * Originally based on php version of the geoip library written in May
 
12
 * 2002 by jim winstead <jimw@apache.org>
 
13
 *
 
14
 * Copyright (C) 2003 MaxMind LLC
 
15
 * Copyright 2003-2005 Michael Slusarz <slusarz@bigworm.colorado.edu>
 
16
 *
 
17
 * This library is free software; you can redistribute it and/or
 
18
 * modify it under the terms of the GNU Lesser General Public
 
19
 * License as published by the Free Software Foundation; either
 
20
 * version 2.1 of the License, or (at your option) any later version.
 
21
 *
 
22
 * See the enclosed file COPYING for license information (LGPL). If you
 
23
 * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
 
24
 *
 
25
 * @author  Michael Slusarz <slusarz@bigworm.colorado.edu>
 
26
 * @version $Revision: 1.10.10.1 $
 
27
 * @since   Horde 3.0
 
28
 * @package Horde_NLS
 
29
 */
 
30
 
 
31
/* Country list. */
 
32
$GLOBALS['GEOIP_COUNTRY_CODES'] = array(
 
33
'', 'AP', 'EU', 'AD', 'AE', 'AF', 'AG', 'AI', 'AL', 'AM', 'AN', 'AO', 'AQ',
 
34
'AR', 'AS', 'AT', 'AU', 'AW', 'AZ', 'BA', 'BB', 'BD', 'BE', 'BF', 'BG', 'BH',
 
35
'BI', 'BJ', 'BM', 'BN', 'BO', 'BR', 'BS', 'BT', 'BV', 'BW', 'BY', 'BZ', 'CA',
 
36
'CC', 'CD', 'CF', 'CG', 'CH', 'CI', 'CK', 'CL', 'CM', 'CN', 'CO', 'CR', 'CU',
 
37
'CV', 'CX', 'CY', 'CZ', 'DE', 'DJ', 'DK', 'DM', 'DO', 'DZ', 'EC', 'EE', 'EG',
 
38
'EH', 'ER', 'ES', 'ET', 'FI', 'FJ', 'FK', 'FM', 'FO', 'FR', 'FX', 'GA', 'UK',
 
39
'GD', 'GE', 'GF', 'GH', 'GI', 'GL', 'GM', 'GN', 'GP', 'GQ', 'GR', 'GS', 'GT',
 
40
'GU', 'GW', 'GY', 'HK', 'HM', 'HN', 'HR', 'HT', 'HU', 'ID', 'IE', 'IL', 'IN',
 
41
'IO', 'IQ', 'IR', 'IS', 'IT', 'JM', 'JO', 'JP', 'KE', 'KG', 'KH', 'KI', 'KM',
 
42
'KN', 'KP', 'KR', 'KW', 'KY', 'KZ', 'LA', 'LB', 'LC', 'LI', 'LK', 'LR', 'LS',
 
43
'LT', 'LU', 'LV', 'LY', 'MA', 'MC', 'MD', 'MG', 'MH', 'MK', 'ML', 'MM', 'MN',
 
44
'MO', 'MP', 'MQ', 'MR', 'MS', 'MT', 'MU', 'MV', 'MW', 'MX', 'MY', 'MZ', 'NA',
 
45
'NC', 'NE', 'NF', 'NG', 'NI', 'NL', 'NO', 'NP', 'NR', 'NU', 'NZ', 'OM', 'PA',
 
46
'PE', 'PF', 'PG', 'PH', 'PK', 'PL', 'PM', 'PN', 'PR', 'PS', 'PT', 'PW', 'PY',
 
47
'QA', 'RE', 'RO', 'RU', 'RW', 'SA', 'SB', 'SC', 'SD', 'SE', 'SG', 'SH', 'SI',
 
48
'SJ', 'SK', 'SL', 'SM', 'SN', 'SO', 'SR', 'ST', 'SV', 'SY', 'SZ', 'TC', 'TD',
 
49
'TF', 'TG', 'TH', 'TJ', 'TK', 'TM', 'TN', 'TO', 'TP', 'TR', 'TT', 'TV', 'TW',
 
50
'TZ', 'UA', 'UG', 'UM', 'US', 'UY', 'UZ', 'VA', 'VC', 'VE', 'VG', 'VI', 'VN',
 
51
'VU', 'WF', 'WS', 'YE', 'YT', 'YU', 'ZA', 'ZM', 'ZR', 'ZW', 'A1', 'A2', 'O1'
 
52
);
 
53
 
 
54
/* Country Names. */
 
55
$GLOBALS['GEOIP_COUNTRY_NAMES'] = array(
 
56
"", _("Asia/Pacific Region"), _("Europe"), _("Andorra"),
 
57
_("United Arab Emirates"), _("Afghanistan"), _("Antigua and Barbuda"),
 
58
_("Anguilla"), _("Albania"), _("Armenia"), _("Netherlands Antilles"),
 
59
_("Angola"), _("Antarctica"), _("Argentina"), _("American Samoa"),
 
60
_("Austria"), _("Australia"), _("Aruba"), _("Azerbaijan"),
 
61
_("Bosnia and Herzegovina"), _("Barbados"), _("Bangladesh"), _("Belgium"),
 
62
_("Burkina Faso"), _("Bulgaria"), _("Bahrain"), _("Burundi"), _("Benin"),
 
63
_("Bermuda"), _("Brunei Darussalam"), _("Bolivia"), _("Brazil"), _("Bahamas"),
 
64
_("Bhutan"), _("Bouvet Island"), _("Botswana"), _("Belarus"), _("Belize"),
 
65
_("Canada"), _("Cocos (Keeling) Islands"),
 
66
_("Congo, The Democratic Republic of the"), _("Central African Republic"),
 
67
_("Congo"), _("Switzerland"), _("Cote d'Ivoire"), _("Cook Islands"),
 
68
_("Chile"), _("Cameroon"), _("China"), _("Colombia"), _("Costa Rica"),
 
69
_("Cuba"), _("Cape Verde"), _("Christmas Island"), _("Cyprus"),
 
70
_("Czech Republic"), _("Germany"), _("Djibouti"), _("Denmark"), _("Dominica"),
 
71
_("Dominican Republic"), _("Algeria"), _("Ecuador"), _("Estonia"), _("Egypt"),
 
72
_("Western Sahara"), _("Eritrea"), _("Spain"), _("Ethiopia"), _("Finland"),
 
73
_("Fiji"), _("Falkland Islands (Malvinas)"), _("Micronesia, Federated States of"),
 
74
_("Faroe Islands"), _("France"), _("France, Metropolitan"), _("Gabon"),
 
75
_("United Kingdom"), _("Grenada"), _("Georgia"), _("French Guiana"),
 
76
_("Ghana"), _("Gibraltar"), _("Greenland"), _("Gambia"), _("Guinea"),
 
77
_("Guadeloupe"), _("Equatorial Guinea"), _("Greece"),
 
78
_("South Georgia and the South Sandwich Islands"), _("Guatemala"), _("Guam"),
 
79
_("Guinea-Bissau"), _("Guyana"), _("Hong Kong"),
 
80
_("Heard Island and McDonald Islands"), _("Honduras"), _("Croatia"),
 
81
_("Haiti"), _("Hungary"), _("Indonesia"), _("Ireland"), _("Israel"),
 
82
_("India"), _("British Indian Ocean Territory"), _("Iraq"),
 
83
_("Iran, Islamic Republic of"), _("Iceland"), _("Italy"), _("Jamaica"),
 
84
_("Jordan"), _("Japan"), _("Kenya"), _("Kyrgyzstan"), _("Cambodia"),
 
85
_("Kiribati"), _("Comoros"), _("Saint Kitts and Nevis"),
 
86
_("Korea, Democratic People's Republic of"), _("Korea, Republic of"),
 
87
_("Kuwait"), _("Cayman Islands"), _("Kazakhstan"),
 
88
_("Lao People's Democratic Republic"), _("Lebanon"), _("Saint Lucia"),
 
89
_("Liechtenstein"), _("Sri Lanka"), _("Liberia"), _("Lesotho"),
 
90
_("Lithuania"), _("Luxembourg"), _("Latvia"), _("Libyan Arab Jamahiriya"),
 
91
_("Morocco"), _("Monaco"), _("Moldova, Republic of"), _("Madagascar"),
 
92
_("Marshall Islands"), _("Macedonia, The Former Yugoslav Republic of"),
 
93
_("Mali"), _("Myanmar"), _("Mongolia"), _("Macao"),
 
94
_("Northern Mariana Islands"), _("Martinique"), _("Mauritania"),
 
95
_("Montserrat"), _("Malta"), _("Mauritius"), _("Maldives"), _("Malawi"),
 
96
_("Mexico"), _("Malaysia"), _("Mozambique"), _("Namibia"), _("New Caledonia"),
 
97
_("Niger"), _("Norfolk Island"), _("Nigeria"), _("Nicaragua"),
 
98
_("Netherlands"), _("Norway"), _("Nepal"), _("Nauru"), _("Niue"),
 
99
_("New Zealand"), _("Oman"), _("Panama"), _("Peru"), _("French Polynesia"),
 
100
_("Papua New Guinea"), _("Philippines"), _("Pakistan"), _("Poland"),
 
101
_("Saint Pierre and Miquelon"), _("Pitcairn"), _("Puerto Rico"),
 
102
_("Palestinian Territory, Occupied"), _("Portugal"), _("Palau"),
 
103
_("Paraguay"), _("Qatar"), _("Reunion"), _("Romania"),
 
104
_("Russian Federation"), _("Rwanda"), _("Saudi Arabia"), _("Solomon Islands"),
 
105
_("Seychelles"), _("Sudan"), _("Sweden"), _("Singapore"), _("Saint Helena"),
 
106
_("Slovenia"), _("Svalbard and Jan Mayen"), _("Slovakia"), _("Sierra Leone"),
 
107
_("San Marino"), _("Senegal"), _("Somalia"), _("Suriname"),
 
108
_("Sao Tome and Principe"), _("El Salvador"), _("Syrian Arab Republic"),
 
109
_("Swaziland"), _("Turks and Caicos Islands"), _("Chad"),
 
110
_("French Southern Territories"), _("Togo"), _("Thailand"), _("Tajikistan"),
 
111
_("Tokelau"), _("Turkmenistan"), _("Tunisia"), _("Tonga"), _("Timor-Leste"),
 
112
_("Turkey"), _("Trinidad and Tobago"), _("Tuvalu"), _("Taiwan"),
 
113
_("Tanzania, United Republic of"), _("Ukraine"), _("Uganda"),
 
114
_("United States Minor Outlying Islands"), _("United States"), _("Uruguay"),
 
115
_("Uzbekistan"), _("Holy See (Vatican City State)"),
 
116
_("Saint Vincent and the Grenadines"), _("Venezuela"),
 
117
_("Virgin Islands, British"), _("Virgin Islands, U.S."), _("Viet Nam"),
 
118
_("Vanuatu"), _("Wallis and Futuna"), _("Samoa"), _("Yemen"), _("Mayotte"),
 
119
_("Yugoslavia"), _("South Africa"), _("Zambia"), _("Zaire"), _("Zimbabwe"),
 
120
_("Anonymous Proxy"), _("Satellite Provider"), _("Other")
 
121
);
 
122
 
 
123
define('GEOIP_COUNTRY_BEGIN', 16776960);
 
124
define('STRUCTURE_INFO_MAX_SIZE', 20);
 
125
define('STANDARD_RECORD_LENGTH', 3);
 
126
 
 
127
class NLS_GeoIP {
 
128
 
 
129
    /**
 
130
     * The location of the GeoIP database.
 
131
     *
 
132
     * @var string $_datafile
 
133
     */
 
134
    var $_datafile;
 
135
 
 
136
    /**
 
137
     * The open filehandle to the GeoIP database.
 
138
     *
 
139
     * @var resource $_filehandle
 
140
     */
 
141
    var $_filehandle;
 
142
 
 
143
    /**
 
144
     * Returns a reference to the global NLS_GeoIP object, only creating it
 
145
     * if it doesn't already exist.
 
146
     *
 
147
     * This method must be invoked as:
 
148
     *   $geoip = &GeoIP::singleton($datafile);
 
149
     *
 
150
     * @access public
 
151
     *
 
152
     * @param string $datafile  The location of the GeoIP database.
 
153
     *
 
154
     * @return object NLS_GeoIP  The NLS_GeoIP instance.
 
155
     */
 
156
    function &singleton($datafile)
 
157
    {
 
158
        static $instance;
 
159
 
 
160
        if (!isset($instance)) {
 
161
            $instance = new NLS_GeoIP($datafile);
 
162
        }
 
163
 
 
164
        return $instance;
 
165
    }
 
166
 
 
167
    /**
 
168
     * Create a NLS_GeoIP instance (Constructor).
 
169
     *
 
170
     * @access public
 
171
     *
 
172
     * @param string $datafile  The location of the GeoIP database.
 
173
     */
 
174
    function NLS_GeoIP($datafile)
 
175
    {
 
176
        $this->_datafile = $datafile;
 
177
    }
 
178
 
 
179
    /**
 
180
     * Open the GeoIP database.
 
181
     *
 
182
     * @access private
 
183
     *
 
184
     * @return boolean  False on error.
 
185
     */
 
186
    function _open()
 
187
    {
 
188
        /* Return if we already have an object. */
 
189
        if (!empty($this->_gi)) {
 
190
            return true;
 
191
        }
 
192
 
 
193
        /* Return if no datafile specified. */
 
194
        if (empty($this->_datafile)) {
 
195
            return false;
 
196
        }
 
197
 
 
198
        $this->_filehandle = fopen($this->_datafile, 'rb');
 
199
 
 
200
        $filepos = ftell($this->_filehandle);
 
201
        fseek($this->_filehandle, -3, SEEK_END);
 
202
        for ($i = 0; $i < STRUCTURE_INFO_MAX_SIZE; $i++) {
 
203
            $delim = fread($this->_filehandle, 3);
 
204
            if ($delim == (chr(255) . chr(255) . chr(255))) {
 
205
                break;
 
206
            } else {
 
207
                fseek($this->_filehandle, -4, SEEK_CUR);
 
208
            }
 
209
        }
 
210
        fseek($this->_filehandle, $filepos, SEEK_SET);
 
211
 
 
212
        return true;
 
213
    }
 
214
 
 
215
    /**
 
216
     * Returns the country ID for a hostname.
 
217
     *
 
218
     * @access public
 
219
     *
 
220
     * @param string $name  The hostname.
 
221
     *
 
222
     * @return integer  The GeoIP country ID.
 
223
     */
 
224
    function countryIdByName($name)
 
225
    {
 
226
        if (!$this->_open()) {
 
227
            return false;
 
228
        }
 
229
        $addr = gethostbyname($name);
 
230
        if (!$addr || $addr == $name) {
 
231
            return false;
 
232
        }
 
233
        return $this->countryIdByAddr($addr);
 
234
    }
 
235
 
 
236
    /**
 
237
     * Returns the country abbreviation (2-letter) for a hostname.
 
238
     *
 
239
     * @access public
 
240
     *
 
241
     * @param string $name  The hostname.
 
242
     *
 
243
     * @return integer  The country abbreviation.
 
244
     */
 
245
    function countryCodeByName($name)
 
246
    {
 
247
        if ($this->_open()) {
 
248
            $country_id = $this->countryIdByName($name);
 
249
            if ($country_id !== false) {
 
250
                return $GLOBALS['GEOIP_COUNTRY_CODES'][$country_id];
 
251
            }
 
252
        }
 
253
        return false;
 
254
    }
 
255
 
 
256
    /**
 
257
     * Returns the country name for a hostname.
 
258
     *
 
259
     * @access public
 
260
     *
 
261
     * @param string $name  The hostname.
 
262
     *
 
263
     * @return integer  The country name.
 
264
     */
 
265
    function countryNameByName($name)
 
266
    {
 
267
        if ($this->_open()) {
 
268
            $country_id = $this->countryIdByName($name);
 
269
            if ($country_id !== false) {
 
270
                return $GLOBALS['GEOIP_COUNTRY_NAMES'][$country_id];
 
271
            }
 
272
        }
 
273
        return false;
 
274
    }
 
275
 
 
276
    /**
 
277
     * Returns the country ID for an IP Address.
 
278
     *
 
279
     * @access public
 
280
     *
 
281
     * @param string $addr  The IP Address.
 
282
     *
 
283
     * @return integer  The GeoIP country ID.
 
284
     */
 
285
    function countryIdByAddr($addr)
 
286
    {
 
287
        if (!$this->_open()) {
 
288
            return false;
 
289
        }
 
290
        $ipnum = ip2long($addr);
 
291
        return ($this->_seekCountry($ipnum) - GEOIP_COUNTRY_BEGIN);
 
292
    }
 
293
 
 
294
    /**
 
295
     * Returns the country abbreviation (2-letter) for an IP Address.
 
296
     *
 
297
     * @access public
 
298
     *
 
299
     * @param string $addr  The IP Address.
 
300
     *
 
301
     * @return integer  The country abbreviation.
 
302
     */
 
303
    function countryCodeByAddr($addr)
 
304
    {
 
305
        if ($this->_open()) {
 
306
            $country_id = $this->countryIdByAddr($addr);
 
307
            if ($country_id !== false) {
 
308
                return $GLOBALS['GEOIP_COUNTRY_CODES'][$country_id];
 
309
            }
 
310
        }
 
311
        return false;
 
312
    }
 
313
 
 
314
    /**
 
315
     * Returns the country name for an IP address.
 
316
     *
 
317
     * @access public
 
318
     *
 
319
     * @param string $addr  The IP address.
 
320
     *
 
321
     * @return mixed  The country name.
 
322
     */
 
323
    function countryNameByAddr($addr)
 
324
    {
 
325
        if ($this->_open()) {
 
326
            $country_id = $this->countryIdByAddr($addr);
 
327
            if ($country_id !== false) {
 
328
                return $GLOBALS['GEOIP_COUNTRY_NAMES'][$country_id];
 
329
            }
 
330
        }
 
331
        return false;
 
332
    }
 
333
 
 
334
    /**
 
335
     * Finds a country by IP Address in the GeoIP database.
 
336
     *
 
337
     * @access private
 
338
     *
 
339
     * @param string $ipnum  The IP Address to search for.
 
340
     *
 
341
     * @return mixed  The country ID or false if not found.
 
342
     *                Returns PEAR_Error on error.
 
343
     */
 
344
    function _seekCountry($ipnum)
 
345
    {
 
346
        $offset = 0;
 
347
        for ($depth = 31; $depth >= 0; --$depth) {
 
348
            if (fseek($this->_filehandle, 2 * STANDARD_RECORD_LENGTH * $offset, SEEK_SET) != 0) {
 
349
                return PEAR::raiseError('fseek failed');
 
350
            }
 
351
            $buf = fread($this->_filehandle, 2 * STANDARD_RECORD_LENGTH);
 
352
            $x = array(0, 0);
 
353
            for ($i = 0; $i < 2; ++$i) {
 
354
                for ($j = 0; $j < STANDARD_RECORD_LENGTH; ++$j) {
 
355
                    $x[$i] += ord($buf[STANDARD_RECORD_LENGTH * $i + $j]) << ($j * 8);
 
356
                }
 
357
            }
 
358
            if ($ipnum & (1 << $depth)) {
 
359
                if ($x[1] >= GEOIP_COUNTRY_BEGIN) {
 
360
                    return $x[1];
 
361
                }
 
362
                $offset = $x[1];
 
363
            } else {
 
364
                if ($x[0] >= GEOIP_COUNTRY_BEGIN) {
 
365
                    return $x[0];
 
366
                }
 
367
                $offset = $x[0];
 
368
            }
 
369
        }
 
370
 
 
371
        return false;
 
372
    }
 
373
 
 
374
}