Skip to content

Commit

Permalink
Handle unassigned blocks. Issue #254
Browse files Browse the repository at this point in the history
  • Loading branch information
bluesmoon committed Oct 17, 2023
1 parent f273b48 commit b124cb3
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 47 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ installation

Run `cd node_modules/geoip-lite && npm run-script updatedb license_key=YOUR_LICENSE_KEY` to update the data files. (Replace `YOUR_LICENSE_KEY` with your license key obtained from [maxmind.com](https://support.maxmind.com/hc/en-us/articles/4407111582235-Generate-a-License-Key))

You can create maxmind account [here](https://www.maxmind.com/en/geolite2/signup)
You can create a maxmind account [here](https://www.maxmind.com/en/geolite2/signup)

**NOTE** that this requires a lot of RAM. It is known to fail on on a Digital Ocean or AWS micro instance.
There are no plans to change this. `geoip-lite` stores all data in RAM in order to be fast.
Expand Down
44 changes: 25 additions & 19 deletions lib/geoip.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ function lookup4(ip) {
eu:'',
timezone:'',
city: '',
ll: [0, 0]
ll: [null, null]
};

// outside IPv4 range
Expand Down Expand Up @@ -105,15 +105,18 @@ function lookup4(ip) {
} else {
locId = buffer.readUInt32BE((line * recordSize) + 8);

geodata.country = locBuffer.toString('utf8', (locId * locRecordSize) + 0, (locId * locRecordSize) + 2).replace(/\u0000.*/, '');
geodata.region = locBuffer.toString('utf8', (locId * locRecordSize) + 2, (locId * locRecordSize) + 5).replace(/\u0000.*/, '');
geodata.metro = locBuffer.readInt32BE((locId * locRecordSize) + 5);
geodata.ll[0] = buffer.readInt32BE((line * recordSize) + 12)/10000;//latitude
geodata.ll[1] = buffer.readInt32BE((line * recordSize) + 16)/10000; //longitude
geodata.area = buffer.readUInt32BE((line * recordSize) + 20); //longitude
geodata.eu = locBuffer.toString('utf8', (locId * locRecordSize) + 9, (locId * locRecordSize) + 10).replace(/\u0000.*/, '');
geodata.timezone = locBuffer.toString('utf8', (locId * locRecordSize) + 10, (locId * locRecordSize) + 42).replace(/\u0000.*/, '');
geodata.city = locBuffer.toString('utf8', (locId * locRecordSize) + 42, (locId * locRecordSize) + locRecordSize).replace(/\u0000.*/, '');
// -1>>>0 is a marker for "No Location Info"
if(-1>>>0 > locId) {
geodata.country = locBuffer.toString('utf8', (locId * locRecordSize) + 0, (locId * locRecordSize) + 2).replace(/\u0000.*/, '');
geodata.region = locBuffer.toString('utf8', (locId * locRecordSize) + 2, (locId * locRecordSize) + 5).replace(/\u0000.*/, '');
geodata.metro = locBuffer.readInt32BE((locId * locRecordSize) + 5);
geodata.ll[0] = buffer.readInt32BE((line * recordSize) + 12)/10000;//latitude
geodata.ll[1] = buffer.readInt32BE((line * recordSize) + 16)/10000; //longitude
geodata.area = buffer.readUInt32BE((line * recordSize) + 20); //longitude
geodata.eu = locBuffer.toString('utf8', (locId * locRecordSize) + 9, (locId * locRecordSize) + 10).replace(/\u0000.*/, '');
geodata.timezone = locBuffer.toString('utf8', (locId * locRecordSize) + 10, (locId * locRecordSize) + 42).replace(/\u0000.*/, '');
geodata.city = locBuffer.toString('utf8', (locId * locRecordSize) + 42, (locId * locRecordSize) + locRecordSize).replace(/\u0000.*/, '');
}
}

return geodata;
Expand Down Expand Up @@ -182,15 +185,18 @@ function lookup6(ip) {
} else {
locId = buffer.readUInt32BE((line * recordSize) + 32);

geodata.country = locBuffer.toString('utf8', (locId * locRecordSize) + 0, (locId * locRecordSize) + 2).replace(/\u0000.*/, '');
geodata.region = locBuffer.toString('utf8', (locId * locRecordSize) + 2, (locId * locRecordSize) + 5).replace(/\u0000.*/, '');
geodata.metro = locBuffer.readInt32BE((locId * locRecordSize) + 5);
geodata.ll[0] = buffer.readInt32BE((line * recordSize) + 36)/10000;//latitude
geodata.ll[1] = buffer.readInt32BE((line * recordSize) + 40)/10000; //longitude
geodata.area = buffer.readUInt32BE((line * recordSize) + 44); //area
geodata.eu = locBuffer.toString('utf8', (locId * locRecordSize) + 9, (locId * locRecordSize) + 10).replace(/\u0000.*/, '');
geodata.timezone = locBuffer.toString('utf8', (locId * locRecordSize) + 10, (locId * locRecordSize) + 42).replace(/\u0000.*/, '');
geodata.city = locBuffer.toString('utf8', (locId * locRecordSize) + 42, (locId * locRecordSize) + locRecordSize).replace(/\u0000.*/, '');
// -1>>>0 is a marker for "No Location Info"
if(-1>>>0 > locId) {
geodata.country = locBuffer.toString('utf8', (locId * locRecordSize) + 0, (locId * locRecordSize) + 2).replace(/\u0000.*/, '');
geodata.region = locBuffer.toString('utf8', (locId * locRecordSize) + 2, (locId * locRecordSize) + 5).replace(/\u0000.*/, '');
geodata.metro = locBuffer.readInt32BE((locId * locRecordSize) + 5);
geodata.ll[0] = buffer.readInt32BE((line * recordSize) + 36)/10000;//latitude
geodata.ll[1] = buffer.readInt32BE((line * recordSize) + 40)/10000; //longitude
geodata.area = buffer.readUInt32BE((line * recordSize) + 44); //area
geodata.eu = locBuffer.toString('utf8', (locId * locRecordSize) + 9, (locId * locRecordSize) + 10).replace(/\u0000.*/, '');
geodata.timezone = locBuffer.toString('utf8', (locId * locRecordSize) + 10, (locId * locRecordSize) + 42).replace(/\u0000.*/, '');
geodata.city = locBuffer.toString('utf8', (locId * locRecordSize) + 42, (locId * locRecordSize) + locRecordSize).replace(/\u0000.*/, '');
}
}
// We do not currently have detailed region/city info for IPv6, but finally have coords
return geodata;
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name" : "geoip-lite",
"version" : "1.4.7",
"version" : "1.4.8",
"description" : "A light weight native JavaScript implementation of GeoIP API from MaxMind",
"keywords" : ["geo", "geoip", "ip", "ipv4", "ipv6", "geolookup", "maxmind", "geolite"],
"homepage" : "https://github.com/geoip-lite/node-geoip",
Expand Down
4 changes: 2 additions & 2 deletions scripts/updatedb.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ if (typeof geodatadir !== 'undefined') {
}
var tmpPath = process.env.GEOTMPDIR ? process.env.GEOTMPDIR : path.resolve(__dirname, '..', 'tmp');
var countryLookup = {};
var cityLookup = {};
var cityLookup = {NaN: -1};
var databases = [
{
type: 'country',
Expand Down Expand Up @@ -538,7 +538,7 @@ function processCityDataNames(src, dest, cb) {
var sz = 88;
var fields = CSVtoArray(line);
if (!fields) {
//lot's of cities contain ` or ' in the name and can't be parsed correctly with current method
//lots of cities contain ` or ' in the name and can't be parsed correctly with current method
console.log("weird line: %s::", line);
return;
}
Expand Down
73 changes: 49 additions & 24 deletions test/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,21 @@ module.exports = {
var actual = geoip.lookup(ip);

test.notStrictEqual(actual.range, undefined, 'should contain IPv4 range');

test.strictEqual(actual.country, 'US', "should match country");

test.strictEqual(actual.region, 'NY', "should match region");

test.strictEqual(actual.eu, '0', "should match eu");

test.strictEqual(actual.timezone, 'America/New_York', "should match timezone");

test.strictEqual(actual.city, 'New York', "should match city");

test.ok(actual.ll, 'should contain coordinates');

test.strictEqual(actual.metro, 501, "should match metro");

test.strictEqual(actual.area, 1, "should match area");

test.done();
Expand All @@ -54,21 +54,21 @@ module.exports = {
var actual = geoip.lookup(ipv6);

test.notStrictEqual(actual.range, undefined, 'should contain IPv6 range');

test.strictEqual(actual.country, 'NL', "should match country");

test.strictEqual(actual.region, 'NH', "should match region");

test.strictEqual(actual.eu, '1', "should match eu");

test.strictEqual(actual.timezone, 'Europe/Amsterdam', "should match timezone");

test.strictEqual(actual.city, 'Amsterdam', "should match city");

test.ok(actual.ll, 'should contain coordinates');

test.strictEqual(actual.metro, 0, "should match metro");

test.strictEqual(actual.area, 5, "should match area");

test.done();
Expand Down Expand Up @@ -115,22 +115,22 @@ module.exports = {
//get original data
var before4 = geoip.lookup("75.82.117.180");
test.notEqual(before4, null);

var before6 = geoip.lookup("::ffff:173.185.182.82");
test.notEqual(before6, null);

//clear data;
geoip.clear();

//make sure data is cleared
var none4 = geoip.lookup("75.82.117.180");
test.equal(none4, null);
var none6 = geoip.lookup("::ffff:173.185.182.82");
test.equal(none6, null);

//reload data synchronized
geoip.reloadDataSync();

//make sure we have value from before
var after4 = geoip.lookup("75.82.117.180");
test.deepEqual(before4, after4);
Expand All @@ -148,16 +148,16 @@ module.exports = {
test.notEqual(before4, null);
var before6 = geoip.lookup("::ffff:173.185.182.82");
test.notEqual(before6, null);

//clear data;
geoip.clear();

//make sure data is cleared
var none4 = geoip.lookup("75.82.117.180");
test.equal(none4, null);
var none6 = geoip.lookup("::ffff:173.185.182.82");
test.equal(none6, null);

//reload data asynchronously
geoip.reloadData(function(){
//make sure we have value from before
Expand All @@ -168,5 +168,30 @@ module.exports = {

test.done();
});
},

testUnassigned: function (test) {
test.expect(8);

var ip = '1.1.1.1';

var actual = geoip.lookup(ip);

test.notStrictEqual(actual.range, undefined, 'should contain IPv4 range');

test.strictEqual(actual.country, '', "should match empty country");

test.strictEqual(actual.region, '', "should match empty region");

test.strictEqual(actual.eu, '', "should match empty eu");

test.strictEqual(actual.timezone, '', "should match empty timezone");

test.strictEqual(actual.city, '', "should match empty city");

test.strictEqual(actual.ll[0], null, 'should contain empty coordinates');
test.strictEqual(actual.ll[1], null, 'should contain empty coordinates');

test.done();
}
};

0 comments on commit b124cb3

Please sign in to comment.