Skip to content

Commit

Permalink
Remove country detection from IP
Browse files Browse the repository at this point in the history
The database that this depended on hasn't been available for quite some time now.
  • Loading branch information
derickr committed Nov 27, 2024
1 parent 67a8e1b commit 7023ed3
Show file tree
Hide file tree
Showing 4 changed files with 2 additions and 208 deletions.
4 changes: 1 addition & 3 deletions cal.php
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ function date_for_recur($recur, $day, $bom, $eom)
function display_events_for_day($day, $events): void
{
// For preservation of state in the links
global $cm, $cy, $COUNTRY;
global $cm, $cy;

// For all events, try to find the events for this day
foreach ($events as $event) {
Expand All @@ -241,12 +241,10 @@ function display_events_for_day($day, $events): void
if (($event['type'] == 2 && $event['start'] <= $day && $event['end'] >= $day)
|| ($event['start'] == $day)) {
echo '<div class="event">',
($COUNTRY == $event['country'] ? "<strong>" : ""),
'<a class="cat' . $event['category'] . '" href="/cal.php',
"?id=$event[id]&amp;cm=$cm&amp;cy=$cy", '">',
stripslashes(htmlentities($event['sdesc'], ENT_QUOTES | ENT_IGNORE, 'UTF-8')),
'</a>',
($COUNTRY == $event['country'] ? "</strong>" : ""),
'</div>';
}
}
Expand Down
184 changes: 0 additions & 184 deletions include/ip-to-country.inc
Original file line number Diff line number Diff line change
@@ -1,188 +1,4 @@
<?php

/*
This script uses the local copy of the ip-to-country.com
database available on all php.net mirror sites to find
out what country the user is in. This data is stored in
a cookie for future usage, and another check is only done,
if the cookie is expired.
We have an index to speed up the search. The first line of
the index file contains the step value used to create the
index. The IP should be divided by this number, when an
appropriate index entry is searched for. Then CSV formatted
lines are placed in the file with the division results and
starting indexes (pointing to the data file).
The data file has a fixed record size format to ease
fseek()ing. The format of the database is:
n records representing IP range and country relations
the format of a record is:
- starting IP number [10 bytes, padded with zeros from left]
- ending IP number [10 bytes, padded with zeros from left]
- ISO country code [3 bytes / letters]
- newline [1 byte: \n]
IP numbers can be created with i2c_ip2num().
Some things to consider:
- Now 'NA' is stored in the cookie (no country detected).
This is partly for safety reasons, not to bog down the
server with country detection in case the data files are
not there, or they are bogus, or the user has a non listed
IP.
*/

// Start the detection
i2c_go();

// Try to find out the country of the user and
// set a cookie in the browser (in case there is no
// cookie already storing this information)
function i2c_go()
{
global $COUNTRY;

// Get the real IP of the user
$ipnum = i2c_realip();

// User already has a country detected with this IP stored
if (!empty($_COOKIE['COUNTRY']) && strpos($_COOKIE['COUNTRY'], ',') !== false) {
list($COUNTRY, $storedip) = explode(",", $_COOKIE['COUNTRY']);
if ($storedip == $ipnum) { return true; }
}

// Convert the IP number to some useable form for searching
$ipn = (float) sprintf("%u", ip2long($ipnum));

// Find the index to start search from
$idx = i2c_search_in_index($ipn);

// If we were unable to find any helpful entry
// in the index do not search, as it would take
// a very long time. It is an error, if we have
// not found anything in the index
if ($idx !== false) {
$country = i2c_search_in_db($ipn, $idx);
} else {
$country = 'NA';
}

// Set global variable for further usage
$COUNTRY = $country;

// Set the country in a cookie for a week
return mirror_setcookie("COUNTRY", "$country,$ipnum", 60 * 60 * 24 * 7);

}

// Find nearest index entry for IP number
function i2c_search_in_index($ip)
{
// Indexed part and record number to jump to
$idxpart = 0; $recnum = 0;

// Open the index file for reading
$dbidx = fopen(
__DIR__ . "/../backend/ip-to-country.idx",
"r",
);
if (!$dbidx) { return false; }

// Read in granularity from index file and
// convert current IP to something useful
$granularity = (int) fgets($dbidx, 64);
if (!$granularity) {
// The file is empty (demo file)
return false;
}
$ip_chunk = (int) ($ip / $granularity);

// Loop till we can read the file
while (!feof($dbidx)) {

// Get CSV data from index file
$data = fgetcsv($dbidx, 100);

// Compare current index part with our IP
if ($ip_chunk >= $idxpart && $ip_chunk < (int) $data[0]) {
return [$recnum, (int) $data[1]];
}

// Store for next compare
$idxpart = (int) $data[0];
$recnum = (int) $data[1];
}

// Return record number found
return [$recnum, -1];
}

// Find the country searching from record $idx
// $ip should be an IP number and not an IP address
function i2c_search_in_db($ip, $idx)
{
// Default range and country
$range_start = 0; $range_end = 0;
$country = "NA";

// Open DB for reading
$ipdb = fopen(
$_SERVER['DOCUMENT_ROOT'] . "/backend/ip-to-country.db",
"r",
);

// Return with "NA" in case of we cannot open the db
if (!$ipdb) { return $country; }

// Jump to record $idx
fseek($ipdb, ($idx[0] ? (($idx[0] - 1) * 24) : 0));

// Read records until we hit the end of the file,
// or we find the range where this IP is, or we
// reach the next indexed part [where the IP should
// not be found, so there is no point in searching further]
while (!feof($ipdb) && !($range_start <= $ip && $range_end >= $ip)) {

// We had run out of the indexed region,
// where we expected to find the IP
if ($idx[1] != -1 && $idx[0] > $idx[1]) {
$country = "NA"; break;
}

// Try to read record
$record = fread($ipdb, 24);

// Unable to read the record => error
if (strlen($record) != 24) { $country = "NA"; break; }

// Split the record to it's parts
$range_start = (float) substr($record, 0, 10);
$range_end = (float) substr($record, 10, 10);
$country = substr($record, 20, 3);

// Getting closer to the end of the indexed region
$idx[0] += 1;
}

// Close datafile
fclose($ipdb);

// Return with the country found
return $country;
}

// Check if the current country is valid
function i2c_valid_country()
{
global $COUNTRY, $COUNTRIES;
return (!empty($COUNTRY) && $COUNTRY != "NA" && isset($COUNTRIES[$COUNTRY]));
}

// Returns the real IP address of the user
function i2c_realip()
{
Expand Down
3 changes: 1 addition & 2 deletions include/prepend.inc
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ unset($RSIDEBAR_DATA);
unset($SIDEBAR_DATA);
unset($SEARCH_BASE);
unset($LANG);
unset($COUNTRY);
unset($ONLOAD);
unset($LAST_UPDATED);

Expand All @@ -86,7 +85,7 @@ include __DIR__ . '/site.inc';
// Choose language used for translated parts
include __DIR__ . '/langchooser.inc';

// Get country of the user and set it in a cookie
// Import function to get the real IP address
include __DIR__ . '/ip-to-country.inc';

// Common layout functions
Expand Down
19 changes: 0 additions & 19 deletions my.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,25 +146,6 @@
<a href="/docs.php">language selection</a> pages, etc.
</p>

<h2>Your country</h2>

<p>
The PHP.net site tries to detect your country
using the <a href="http://www.directi.com/?site=ip-to-country">Directi
Ip-to-Country Database</a>. This information is used to mark
the events in your country specially.
</p>

<div class="indent">
<?php
if (i2c_valid_country()) {
echo "We detected that you are from <b>" . $COUNTRIES[$COUNTRY] . "</b>";
} else {
echo "We were unable to detect your country";
}
?>
</div>

<h2>URL search fallback</h2>

<p>
Expand Down

0 comments on commit 7023ed3

Please sign in to comment.