geoip-lite
Advanced tools
Comparing version
@@ -80,3 +80,3 @@ var fs = require('fs'); | ||
city: '', | ||
ll: [0, 0] | ||
ll: [null, null] | ||
}; | ||
@@ -109,11 +109,14 @@ | ||
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.*/, ''); | ||
} | ||
} | ||
@@ -187,11 +190,14 @@ | ||
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.*/, ''); | ||
} | ||
} | ||
@@ -198,0 +204,0 @@ // We do not currently have detailed region/city info for IPv6, but finally have coords |
{ | ||
"name" : "geoip-lite", | ||
"version" : "1.4.7", | ||
"version" : "1.4.8", | ||
"description" : "A light weight native JavaScript implementation of GeoIP API from MaxMind", | ||
@@ -11,3 +11,3 @@ "keywords" : ["geo", "geoip", "ip", "ipv4", "ipv6", "geolookup", "maxmind", "geolite"], | ||
"repository" : { "type": "git", "url": "git://github.com/geoip-lite/node-geoip.git" }, | ||
"engines" : { "node": ">=5.10.0" }, | ||
"engines" : { "node": ">=18.18.0" }, | ||
"scripts": { | ||
@@ -14,0 +14,0 @@ "pretest": "eslint .", |
@@ -8,3 +8,5 @@ GeoIP-lite | ||
[](https://travis-ci.org/bluesmoon/node-geoip) | ||
**NOTE** You MUST update the data files after installation. The MaxMind license does not allow us to distribute | ||
the latest version of the data files with this package. Follow the instructions under [update the datafiles](#2-update-the-datafiles-optional) | ||
for details. | ||
@@ -69,3 +71,3 @@ introduction | ||
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) | ||
@@ -182,2 +184,14 @@ **NOTE** that this requires a lot of RAM. It is known to fail on on a Digital Ocean or AWS micro instance. | ||
#### Environment variables | ||
The following environment variables can be set. | ||
```bash | ||
# Override the default node_modules/geoip-lite/data dir | ||
GEOTMPDIR=/some/path | ||
# Override the default node_modules/geoip-lite/tmp dir | ||
GEODATADIR=/some/path | ||
``` | ||
Caveats | ||
@@ -184,0 +198,0 @@ ------- |
@@ -13,2 +13,3 @@ // fetches and converts maxmind lite databases | ||
var zlib = require('zlib'); | ||
var readline = require('readline'); | ||
@@ -48,5 +49,5 @@ fs.existsSync = fs.existsSync || path.existsSync; | ||
} | ||
var tmpPath = path.resolve(__dirname, '..', 'tmp'); | ||
var tmpPath = process.env.GEOTMPDIR ? process.env.GEOTMPDIR : path.resolve(__dirname, '..', 'tmp'); | ||
var countryLookup = {}; | ||
var cityLookup = {}; | ||
var cityLookup = {NaN: -1}; | ||
var databases = [ | ||
@@ -189,3 +190,3 @@ { | ||
client.abort(); | ||
process.exit(); | ||
process.exit(1); | ||
} | ||
@@ -213,3 +214,3 @@ | ||
client.abort(); | ||
process.exit(); | ||
process.exit(1); | ||
} | ||
@@ -252,3 +253,3 @@ cb(null, database); | ||
client.abort(); | ||
process.exit(); | ||
process.exit(1); | ||
} | ||
@@ -348,5 +349,5 @@ | ||
function processCountryData(src, dest, cb) { | ||
async function processCountryData(src, dest) { | ||
var lines=0; | ||
function processLine(line) { | ||
async function processLine(line) { | ||
var fields = CSVtoArray(line); | ||
@@ -398,4 +399,2 @@ | ||
b.write(cc, bsz - 2); | ||
fs.writeSync(datFile, b, 0, bsz, null); | ||
if(Date.now() - tstart > 5000) { | ||
@@ -405,2 +404,10 @@ tstart = Date.now(); | ||
} | ||
if(datFile._writableState.needDrain) { | ||
return new Promise((resolve) => { | ||
datFile.write(b, resolve); | ||
}); | ||
} else { | ||
return datFile.write(b); | ||
} | ||
} | ||
@@ -417,20 +424,21 @@ } | ||
var tstart = Date.now(); | ||
var datFile = fs.openSync(dataFile, "w"); | ||
var datFile = fs.createWriteStream(dataFile); | ||
lazy(fs.createReadStream(tmpDataFile)) | ||
.lines | ||
.map(function(byteArray) { | ||
return iconv.decode(byteArray, 'latin1'); | ||
}) | ||
.skip(1) | ||
.map(processLine) | ||
.on('pipe', function() { | ||
console.log(chalk.green(' DONE')); | ||
cb(); | ||
}); | ||
var rl = readline.createInterface({ | ||
input: fs.createReadStream(tmpDataFile), | ||
crlfDelay: Infinity | ||
}); | ||
var i = 0; | ||
for await (var line of rl) { | ||
i++; | ||
if(i == 1) continue; | ||
await processLine(line); | ||
} | ||
datFile.close(); | ||
console.log(' DONE'.green); | ||
} | ||
function processCityData(src, dest, cb) { | ||
async function processCityData(src, dest) { | ||
var lines = 0; | ||
function processLine(line) { | ||
async function processLine(line) { | ||
if (line.match(/^Copyright/) || !line.match(/\d/)) { | ||
@@ -512,3 +520,2 @@ return; | ||
fs.writeSync(datFile, b, 0, b.length, null); | ||
if(Date.now() - tstart > 5000) { | ||
@@ -518,2 +525,10 @@ tstart = Date.now(); | ||
} | ||
if(datFile._writableState.needDrain) { | ||
return new Promise((resolve) => { | ||
datFile.write(b, resolve); | ||
}); | ||
} else { | ||
return datFile.write(b); | ||
} | ||
} | ||
@@ -528,12 +543,15 @@ | ||
var tstart = Date.now(); | ||
var datFile = fs.openSync(dataFile, "w"); | ||
var datFile = fs.createWriteStream(dataFile); | ||
lazy(fs.createReadStream(tmpDataFile)) | ||
.lines | ||
.map(function(byteArray) { | ||
return iconv.decode(byteArray, 'latin1'); | ||
}) | ||
.skip(1) | ||
.map(processLine) | ||
.on('pipe', cb); | ||
var rl = readline.createInterface({ | ||
input: fs.createReadStream(tmpDataFile), | ||
crlfDelay: Infinity | ||
}); | ||
var i = 0; | ||
for await (var line of rl) { | ||
i++; | ||
if(i == 1) continue; | ||
await processLine(line); | ||
} | ||
datFile.close(); | ||
} | ||
@@ -553,3 +571,3 @@ | ||
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); | ||
@@ -615,6 +633,6 @@ return; | ||
processLookupCountry(src[0], function() { | ||
processCountryData(src[1], dest[1], function() { | ||
processCountryData(src[2], dest[2], function() { | ||
cb(null, database); | ||
}); | ||
processCountryData(src[1], dest[1]).then(() => { | ||
return processCountryData(src[2], dest[2]); | ||
}).then(() => { | ||
cb(null, database); | ||
}); | ||
@@ -630,8 +648,8 @@ }); | ||
processCityDataNames(src[0], dest[0], function() { | ||
processCityData(src[1], dest[1], function() { | ||
processCityData(src[1], dest[1]).then(() => { | ||
console.log("city data processed"); | ||
processCityData(src[2], dest[2], function() { | ||
console.log(chalk.green(' DONE')); | ||
cb(null, database); | ||
}); | ||
return processCityData(src[2], dest[2]); | ||
}).then(() => { | ||
console.log(chalk.green(' DONE')); | ||
cb(null, database); | ||
}); | ||
@@ -638,0 +656,0 @@ }); |
@@ -29,17 +29,17 @@ var geoip = require('../lib/geoip'); | ||
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"); | ||
@@ -58,17 +58,17 @@ | ||
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"); | ||
@@ -120,9 +120,9 @@ | ||
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 | ||
@@ -133,6 +133,6 @@ var none4 = geoip.lookup("75.82.117.180"); | ||
test.equal(none6, null); | ||
//reload data synchronized | ||
geoip.reloadDataSync(); | ||
//make sure we have value from before | ||
@@ -155,6 +155,6 @@ var after4 = geoip.lookup("75.82.117.180"); | ||
test.notEqual(before6, null); | ||
//clear data; | ||
geoip.clear(); | ||
//make sure data is cleared | ||
@@ -165,3 +165,3 @@ var none4 = geoip.lookup("75.82.117.180"); | ||
test.equal(none6, null); | ||
//reload data asynchronously | ||
@@ -177,3 +177,28 @@ geoip.reloadData(function(){ | ||
}); | ||
}, | ||
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(); | ||
} | ||
}; |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
115398670
01373
2.77%244
6.09%14
16.67%