auto-patch 280-dev-dev01-2024-01-19T16_41_58 * auto-patch 280-dev-dev01-2024-01-19T16_41_58
479 lines
18 KiB
PHP
479 lines
18 KiB
PHP
<?php
|
|
/* This file is modified for IP Geo Block based on pre 1.15 (15 Feb, 2014) */
|
|
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */
|
|
/* geoip.inc
|
|
*
|
|
* Copyright (C) 2007 MaxMind LLC
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
define("GEOIP_COUNTRY_BEGIN", 16776960);
|
|
define("GEOIP_STATE_BEGIN_REV0", 16700000);
|
|
define("GEOIP_STATE_BEGIN_REV1", 16000000);
|
|
define("GEOIP_STANDARD", 0);
|
|
define("GEOIP_MEMORY_CACHE", 1);
|
|
define("GEOIP_SHARED_MEMORY", 2);
|
|
define("STRUCTURE_INFO_MAX_SIZE", 20);
|
|
define("DATABASE_INFO_MAX_SIZE", 100);
|
|
define("GEOIP_COUNTRY_EDITION", 1);
|
|
define("GEOIP_PROXY_EDITION", 8);
|
|
define("GEOIP_ASNUM_EDITION", 9);
|
|
define("GEOIP_NETSPEED_EDITION", 10);
|
|
define("GEOIP_REGION_EDITION_REV0", 7);
|
|
define("GEOIP_REGION_EDITION_REV1", 3);
|
|
define("GEOIP_CITY_EDITION_REV0", 6);
|
|
define("GEOIP_CITY_EDITION_REV1", 2);
|
|
define("GEOIP_ORG_EDITION", 5);
|
|
define("GEOIP_ISP_EDITION", 4);
|
|
define("SEGMENT_RECORD_LENGTH", 3);
|
|
define("STANDARD_RECORD_LENGTH", 3);
|
|
define("ORG_RECORD_LENGTH", 4);
|
|
define("MAX_RECORD_LENGTH", 4);
|
|
define("MAX_ORG_RECORD_LENGTH", 300);
|
|
define("GEOIP_SHM_KEY", 0x4f415401);
|
|
define("US_OFFSET", 1);
|
|
define("CANADA_OFFSET", 677);
|
|
define("WORLD_OFFSET", 1353);
|
|
define("FIPS_RANGE", 360);
|
|
define("GEOIP_UNKNOWN_SPEED", 0);
|
|
define("GEOIP_DIALUP_SPEED", 1);
|
|
define("GEOIP_CABLEDSL_SPEED", 2);
|
|
define("GEOIP_CORPORATE_SPEED", 3);
|
|
define("GEOIP_DOMAIN_EDITION", 11);
|
|
define("GEOIP_COUNTRY_EDITION_V6", 12);
|
|
define("GEOIP_LOCATIONA_EDITION", 13);
|
|
define("GEOIP_ACCURACYRADIUS_EDITION", 14);
|
|
define("GEOIP_CITYCOMBINED_EDITION", 15);
|
|
define("GEOIP_CITY_EDITION_REV1_V6", 30);
|
|
define("GEOIP_CITY_EDITION_REV0_V6", 31);
|
|
define("GEOIP_NETSPEED_EDITION_REV1", 32);
|
|
define("GEOIP_NETSPEED_EDITION_REV1_V6", 33);
|
|
define("GEOIP_USERTYPE_EDITION", 28);
|
|
define("GEOIP_USERTYPE_EDITION_V6", 29);
|
|
define("GEOIP_ASNUM_EDITION_V6", 21);
|
|
define("GEOIP_ISP_EDITION_V6", 22);
|
|
define("GEOIP_ORG_EDITION_V6", 23);
|
|
define("GEOIP_DOMAIN_EDITION_V6", 24);
|
|
|
|
define("CITYCOMBINED_FIXED_RECORD", 7);
|
|
|
|
class GeoIP
|
|
{
|
|
public $flags;
|
|
public $filehandle;
|
|
public $memory_buffer;
|
|
public $databaseType;
|
|
public $databaseSegments;
|
|
public $record_length;
|
|
public $shmid;
|
|
public $GEOIP_COUNTRY_CODES = array(
|
|
"", "AP", "EU", "AD", "AE", "AF", "AG", "AI",
|
|
"AL", "AM", "CW", "AO", "AQ", "AR", "AS", "AT",
|
|
"AU", "AW", "AZ", "BA", "BB", "BD", "BE", "BF",
|
|
"BG", "BH", "BI", "BJ", "BM", "BN", "BO", "BR",
|
|
"BS", "BT", "BV", "BW", "BY", "BZ", "CA", "CC",
|
|
"CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM",
|
|
"CN", "CO", "CR", "CU", "CV", "CX", "CY", "CZ",
|
|
"DE", "DJ", "DK", "DM", "DO", "DZ", "EC", "EE",
|
|
"EG", "EH", "ER", "ES", "ET", "FI", "FJ", "FK",
|
|
"FM", "FO", "FR", "SX", "GA", "GB", "GD", "GE",
|
|
"GF", "GH", "GI", "GL", "GM", "GN", "GP", "GQ",
|
|
"GR", "GS", "GT", "GU", "GW", "GY", "HK", "HM",
|
|
"HN", "HR", "HT", "HU", "ID", "IE", "IL", "IN",
|
|
"IO", "IQ", "IR", "IS", "IT", "JM", "JO", "JP",
|
|
"KE", "KG", "KH", "KI", "KM", "KN", "KP", "KR",
|
|
"KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK",
|
|
"LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC",
|
|
"MD", "MG", "MH", "MK", "ML", "MM", "MN", "MO",
|
|
"MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW",
|
|
"MX", "MY", "MZ", "NA", "NC", "NE", "NF", "NG",
|
|
"NI", "NL", "NO", "NP", "NR", "NU", "NZ", "OM",
|
|
"PA", "PE", "PF", "PG", "PH", "PK", "PL", "PM",
|
|
"PN", "PR", "PS", "PT", "PW", "PY", "QA", "RE",
|
|
"RO", "RU", "RW", "SA", "SB", "SC", "SD", "SE",
|
|
"SG", "SH", "SI", "SJ", "SK", "SL", "SM", "SN",
|
|
"SO", "SR", "ST", "SV", "SY", "SZ", "TC", "TD",
|
|
"TF", "TG", "TH", "TJ", "TK", "TM", "TN", "TO",
|
|
"TL", "TR", "TT", "TV", "TW", "TZ", "UA", "UG",
|
|
"UM", "US", "UY", "UZ", "VA", "VC", "VE", "VG",
|
|
"VI", "VN", "VU", "WF", "WS", "YE", "YT", "RS",
|
|
"ZA", "ZM", "ME", "ZW", "A1", "A2", "O1", "AX",
|
|
"GG", "IM", "JE", "BL", "MF", "BQ", "SS", "O1"
|
|
);
|
|
}
|
|
|
|
function _setup_segments($gi)
|
|
{
|
|
$gi->databaseType = GEOIP_COUNTRY_EDITION;
|
|
$gi->record_length = STANDARD_RECORD_LENGTH;
|
|
if ($gi->flags & GEOIP_SHARED_MEMORY) {
|
|
$offset = @shmop_size($gi->shmid) - 3;
|
|
for ($i = 0; $i < STRUCTURE_INFO_MAX_SIZE; $i++) {
|
|
$delim = @shmop_read($gi->shmid, $offset, 3);
|
|
$offset += 3;
|
|
if ($delim == (chr(255) . chr(255) . chr(255))) {
|
|
$gi->databaseType = ord(@shmop_read($gi->shmid, $offset, 1));
|
|
if ($gi->databaseType >= 106) {
|
|
$gi->databaseType -= 105;
|
|
}
|
|
$offset++;
|
|
|
|
if ($gi->databaseType == GEOIP_REGION_EDITION_REV0) {
|
|
$gi->databaseSegments = GEOIP_STATE_BEGIN_REV0;
|
|
} elseif ($gi->databaseType == GEOIP_REGION_EDITION_REV1) {
|
|
$gi->databaseSegments = GEOIP_STATE_BEGIN_REV1;
|
|
} elseif (($gi->databaseType == GEOIP_CITY_EDITION_REV0)
|
|
|| ($gi->databaseType == GEOIP_CITY_EDITION_REV1)
|
|
|| ($gi->databaseType == GEOIP_ORG_EDITION)
|
|
|| ($gi->databaseType == GEOIP_ORG_EDITION_V6)
|
|
|| ($gi->databaseType == GEOIP_DOMAIN_EDITION)
|
|
|| ($gi->databaseType == GEOIP_DOMAIN_EDITION_V6)
|
|
|| ($gi->databaseType == GEOIP_ISP_EDITION)
|
|
|| ($gi->databaseType == GEOIP_ISP_EDITION_V6)
|
|
|| ($gi->databaseType == GEOIP_USERTYPE_EDITION)
|
|
|| ($gi->databaseType == GEOIP_USERTYPE_EDITION_V6)
|
|
|| ($gi->databaseType == GEOIP_LOCATIONA_EDITION)
|
|
|| ($gi->databaseType == GEOIP_ACCURACYRADIUS_EDITION)
|
|
|| ($gi->databaseType == GEOIP_CITY_EDITION_REV0_V6)
|
|
|| ($gi->databaseType == GEOIP_CITY_EDITION_REV1_V6)
|
|
|| ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1)
|
|
|| ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1_V6)
|
|
|| ($gi->databaseType == GEOIP_ASNUM_EDITION)
|
|
|| ($gi->databaseType == GEOIP_ASNUM_EDITION_V6)
|
|
) {
|
|
$gi->databaseSegments = 0;
|
|
$buf = @shmop_read($gi->shmid, $offset, SEGMENT_RECORD_LENGTH);
|
|
for ($j = 0; $j < SEGMENT_RECORD_LENGTH; $j++) {
|
|
$gi->databaseSegments += (ord($buf[$j]) << ($j * 8));
|
|
}
|
|
if (($gi->databaseType == GEOIP_ORG_EDITION)
|
|
|| ($gi->databaseType == GEOIP_ORG_EDITION_V6)
|
|
|| ($gi->databaseType == GEOIP_DOMAIN_EDITION)
|
|
|| ($gi->databaseType == GEOIP_DOMAIN_EDITION_V6)
|
|
|| ($gi->databaseType == GEOIP_ISP_EDITION)
|
|
|| ($gi->databaseType == GEOIP_ISP_EDITION_V6)
|
|
) {
|
|
$gi->record_length = ORG_RECORD_LENGTH;
|
|
}
|
|
}
|
|
break;
|
|
} else {
|
|
$offset -= 4;
|
|
}
|
|
}
|
|
if (($gi->databaseType == GEOIP_COUNTRY_EDITION) ||
|
|
($gi->databaseType == GEOIP_COUNTRY_EDITION_V6) ||
|
|
($gi->databaseType == GEOIP_PROXY_EDITION) ||
|
|
($gi->databaseType == GEOIP_NETSPEED_EDITION)
|
|
) {
|
|
$gi->databaseSegments = GEOIP_COUNTRY_BEGIN;
|
|
}
|
|
} else {
|
|
$filepos = ftell($gi->filehandle);
|
|
fseek($gi->filehandle, -3, SEEK_END);
|
|
for ($i = 0; $i < STRUCTURE_INFO_MAX_SIZE; $i++) {
|
|
$delim = fread($gi->filehandle, 3);
|
|
if ($delim == (chr(255) . chr(255) . chr(255))) {
|
|
$gi->databaseType = ord(fread($gi->filehandle, 1));
|
|
if ($gi->databaseType >= 106) {
|
|
$gi->databaseType -= 105;
|
|
}
|
|
if ($gi->databaseType == GEOIP_REGION_EDITION_REV0) {
|
|
$gi->databaseSegments = GEOIP_STATE_BEGIN_REV0;
|
|
} elseif ($gi->databaseType == GEOIP_REGION_EDITION_REV1) {
|
|
$gi->databaseSegments = GEOIP_STATE_BEGIN_REV1;
|
|
} elseif (($gi->databaseType == GEOIP_CITY_EDITION_REV0)
|
|
|| ($gi->databaseType == GEOIP_CITY_EDITION_REV1)
|
|
|| ($gi->databaseType == GEOIP_CITY_EDITION_REV0_V6)
|
|
|| ($gi->databaseType == GEOIP_CITY_EDITION_REV1_V6)
|
|
|| ($gi->databaseType == GEOIP_ORG_EDITION)
|
|
|| ($gi->databaseType == GEOIP_DOMAIN_EDITION)
|
|
|| ($gi->databaseType == GEOIP_ISP_EDITION)
|
|
|| ($gi->databaseType == GEOIP_ORG_EDITION_V6)
|
|
|| ($gi->databaseType == GEOIP_DOMAIN_EDITION_V6)
|
|
|| ($gi->databaseType == GEOIP_ISP_EDITION_V6)
|
|
|| ($gi->databaseType == GEOIP_LOCATIONA_EDITION)
|
|
|| ($gi->databaseType == GEOIP_ACCURACYRADIUS_EDITION)
|
|
|| ($gi->databaseType == GEOIP_CITY_EDITION_REV0_V6)
|
|
|| ($gi->databaseType == GEOIP_CITY_EDITION_REV1_V6)
|
|
|| ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1)
|
|
|| ($gi->databaseType == GEOIP_NETSPEED_EDITION_REV1_V6)
|
|
|| ($gi->databaseType == GEOIP_USERTYPE_EDITION)
|
|
|| ($gi->databaseType == GEOIP_USERTYPE_EDITION_V6)
|
|
|| ($gi->databaseType == GEOIP_ASNUM_EDITION)
|
|
|| ($gi->databaseType == GEOIP_ASNUM_EDITION_V6)
|
|
) {
|
|
$gi->databaseSegments = 0;
|
|
$buf = fread($gi->filehandle, SEGMENT_RECORD_LENGTH);
|
|
for ($j = 0; $j < SEGMENT_RECORD_LENGTH; $j++) {
|
|
$gi->databaseSegments += (ord($buf[$j]) << ($j * 8));
|
|
}
|
|
if (($gi->databaseType == GEOIP_ORG_EDITION)
|
|
|| ($gi->databaseType == GEOIP_DOMAIN_EDITION)
|
|
|| ($gi->databaseType == GEOIP_ISP_EDITION)
|
|
|| ($gi->databaseType == GEOIP_ORG_EDITION_V6)
|
|
|| ($gi->databaseType == GEOIP_DOMAIN_EDITION_V6)
|
|
|| ($gi->databaseType == GEOIP_ISP_EDITION_V6)
|
|
) {
|
|
$gi->record_length = ORG_RECORD_LENGTH;
|
|
}
|
|
}
|
|
break;
|
|
} else {
|
|
fseek($gi->filehandle, -4, SEEK_CUR);
|
|
}
|
|
}
|
|
if (($gi->databaseType == GEOIP_COUNTRY_EDITION) ||
|
|
($gi->databaseType == GEOIP_COUNTRY_EDITION_V6) ||
|
|
($gi->databaseType == GEOIP_PROXY_EDITION) ||
|
|
($gi->databaseType == GEOIP_NETSPEED_EDITION)
|
|
) {
|
|
$gi->databaseSegments = GEOIP_COUNTRY_BEGIN;
|
|
}
|
|
fseek($gi->filehandle, $filepos, SEEK_SET);
|
|
}
|
|
return $gi;
|
|
}
|
|
|
|
function geoip_open($filename, $flags)
|
|
{
|
|
$gi = new GeoIP;
|
|
$gi->flags = $flags;
|
|
if ($gi->flags & GEOIP_SHARED_MEMORY) {
|
|
$gi->shmid = @shmop_open(GEOIP_SHM_KEY, "a", 0, 0);
|
|
} else {
|
|
$gi->filehandle = fopen($filename, "rb"); if (!$gi->filehandle) return FALSE; // or die("Can not open $filename\n");
|
|
flock($gi->filehandle, LOCK_SH); // @since 1.1.6
|
|
if ($gi->flags & GEOIP_MEMORY_CACHE) {
|
|
$s_array = fstat($gi->filehandle);
|
|
$gi->memory_buffer = fread($gi->filehandle, $s_array['size']);
|
|
}
|
|
}
|
|
|
|
$gi = _setup_segments($gi);
|
|
return $gi;
|
|
}
|
|
|
|
function geoip_close($gi)
|
|
{
|
|
if ($gi->flags & GEOIP_SHARED_MEMORY) {
|
|
return true;
|
|
}
|
|
|
|
return flock($gi->filehandle, LOCK_UN) and fclose($gi->filehandle); // @since 1.1.6
|
|
}
|
|
|
|
function geoip_country_id_by_addr_v6($gi, $addr)
|
|
{
|
|
$ipnum = inet_pton($addr);
|
|
return _geoip_seek_country_v6($gi, $ipnum) - GEOIP_COUNTRY_BEGIN;
|
|
}
|
|
|
|
function geoip_country_id_by_addr($gi, $addr)
|
|
{
|
|
$ipnum = ip2long($addr);
|
|
return _geoip_seek_country($gi, $ipnum) - GEOIP_COUNTRY_BEGIN;
|
|
}
|
|
|
|
function geoip_country_code_by_addr_v6($gi, $addr)
|
|
{
|
|
$country_id = geoip_country_id_by_addr_v6($gi, $addr);
|
|
if ($country_id !== false) {
|
|
return $gi->GEOIP_COUNTRY_CODES[$country_id];
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function geoip_country_code_by_addr($gi, $addr)
|
|
{
|
|
if ($gi->databaseType == GEOIP_CITY_EDITION_REV1) {
|
|
$record = geoip_record_by_addr($gi, $addr);
|
|
if ($record !== false) {
|
|
return $record->country_code;
|
|
}
|
|
} else {
|
|
$country_id = geoip_country_id_by_addr($gi, $addr);
|
|
if ($country_id !== false) {
|
|
return $gi->GEOIP_COUNTRY_CODES[$country_id];
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function _geoip_seek_country_v6($gi, $ipnum)
|
|
{
|
|
# arrays from unpack start with offset 1
|
|
# yet another php mystery. array_merge work around
|
|
# this broken behaviour
|
|
$v6vec = array_merge(unpack("C16", $ipnum));
|
|
|
|
$offset = 0;
|
|
for ($depth = 127; $depth >= 0; --$depth) {
|
|
if ($gi->flags & GEOIP_MEMORY_CACHE) {
|
|
$buf = _safe_substr(
|
|
$gi->memory_buffer,
|
|
2 * $gi->record_length * $offset,
|
|
2 * $gi->record_length
|
|
);
|
|
} elseif ($gi->flags & GEOIP_SHARED_MEMORY) {
|
|
$buf = @shmop_read(
|
|
$gi->shmid,
|
|
2 * $gi->record_length * $offset,
|
|
2 * $gi->record_length
|
|
);
|
|
} else {
|
|
fseek($gi->filehandle, 2 * $gi->record_length * $offset, SEEK_SET) == 0
|
|
or die("fseek failed");
|
|
$buf = fread($gi->filehandle, 2 * $gi->record_length);
|
|
}
|
|
$x = array(0, 0);
|
|
for ($i = 0; $i < 2; ++$i) {
|
|
for ($j = 0; $j < $gi->record_length; ++$j) {
|
|
$x[$i] += ord($buf[$gi->record_length * $i + $j]) << ($j * 8);
|
|
}
|
|
}
|
|
|
|
$bnum = 127 - $depth;
|
|
$idx = $bnum >> 3;
|
|
$b_mask = 1 << ($bnum & 7 ^ 7);
|
|
if (($v6vec[$idx] & $b_mask) > 0) {
|
|
if ($x[1] >= $gi->databaseSegments) {
|
|
return $x[1];
|
|
}
|
|
$offset = $x[1];
|
|
} else {
|
|
if ($x[0] >= $gi->databaseSegments) {
|
|
return $x[0];
|
|
}
|
|
$offset = $x[0];
|
|
}
|
|
}
|
|
trigger_error("error traversing database - perhaps it is corrupt?", E_USER_ERROR);
|
|
return false;
|
|
}
|
|
|
|
function _geoip_seek_country($gi, $ipnum)
|
|
{
|
|
$offset = 0;
|
|
for ($depth = 31; $depth >= 0; --$depth) {
|
|
if ($gi->flags & GEOIP_MEMORY_CACHE) {
|
|
$buf = _safe_substr(
|
|
$gi->memory_buffer,
|
|
2 * $gi->record_length * $offset,
|
|
2 * $gi->record_length
|
|
);
|
|
} elseif ($gi->flags & GEOIP_SHARED_MEMORY) {
|
|
$buf = @shmop_read(
|
|
$gi->shmid,
|
|
2 * $gi->record_length * $offset,
|
|
2 * $gi->record_length
|
|
);
|
|
} else {
|
|
fseek($gi->filehandle, 2 * $gi->record_length * $offset, SEEK_SET) == 0
|
|
or die("fseek failed");
|
|
$buf = fread($gi->filehandle, 2 * $gi->record_length);
|
|
}
|
|
$x = array(0, 0);
|
|
for ($i = 0; $i < 2; ++$i) {
|
|
for ($j = 0; $j < $gi->record_length; ++$j) {
|
|
$x[$i] += ord($buf[$gi->record_length * $i + $j]) << ($j * 8);
|
|
}
|
|
}
|
|
if ($ipnum & (1 << $depth)) {
|
|
if ($x[1] >= $gi->databaseSegments) {
|
|
return $x[1];
|
|
}
|
|
$offset = $x[1];
|
|
} else {
|
|
if ($x[0] >= $gi->databaseSegments) {
|
|
return $x[0];
|
|
}
|
|
$offset = $x[0];
|
|
}
|
|
}
|
|
trigger_error("error traversing database - perhaps it is corrupt?", E_USER_ERROR);
|
|
return false;
|
|
}
|
|
function _common_get_org($gi, $seek_org)
|
|
{
|
|
$record_pointer = $seek_org + (2 * $gi->record_length - 1) * $gi->databaseSegments;
|
|
if ($gi->flags & GEOIP_SHARED_MEMORY) {
|
|
$org_buf = _sharedMemRead($gi, $record_pointer, MAX_ORG_RECORD_LENGTH);
|
|
} else {
|
|
fseek($gi->filehandle, $record_pointer, SEEK_SET);
|
|
$org_buf = fread($gi->filehandle, MAX_ORG_RECORD_LENGTH);
|
|
}
|
|
$org_buf = _safe_substr($org_buf, 0, strpos($org_buf, "\0"));
|
|
return $org_buf;
|
|
}
|
|
|
|
function _get_org_v6($gi, $ipnum)
|
|
{
|
|
$seek_org = _geoip_seek_country_v6($gi, $ipnum);
|
|
if ($seek_org == $gi->databaseSegments) {
|
|
return null;
|
|
}
|
|
return _common_get_org($gi, $seek_org);
|
|
}
|
|
|
|
function _get_org($gi, $ipnum)
|
|
{
|
|
$seek_org = _geoip_seek_country($gi, $ipnum);
|
|
if ($seek_org == $gi->databaseSegments) {
|
|
return null;
|
|
}
|
|
return _common_get_org($gi, $seek_org);
|
|
}
|
|
|
|
|
|
function geoip_name_by_addr_v6($gi, $addr)
|
|
{
|
|
if ($addr == null) {
|
|
return 0;
|
|
}
|
|
$ipnum = inet_pton($addr);
|
|
return _get_org_v6($gi, $ipnum);
|
|
}
|
|
|
|
function geoip_name_by_addr($gi, $addr)
|
|
{
|
|
if ($addr == null) {
|
|
return 0;
|
|
}
|
|
$ipnum = ip2long($addr);
|
|
return _get_org($gi, $ipnum);
|
|
}
|
|
|
|
function _safe_substr($string, $start, $length)
|
|
{
|
|
// workaround php's broken substr, strpos, etc handling with
|
|
// mbstring.func_overload and mbstring.internal_encoding
|
|
$mbExists = extension_loaded('mbstring');
|
|
|
|
if ($mbExists) {
|
|
$enc = mb_internal_encoding();
|
|
mb_internal_encoding('ISO-8859-1');
|
|
}
|
|
|
|
$buf = substr($string, $start, $length);
|
|
|
|
if ($mbExists) {
|
|
mb_internal_encoding($enc);
|
|
}
|
|
|
|
return $buf;
|
|
}
|