Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

maxmind-db-reader

Package Overview
Dependencies
Maintainers
2
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

maxmind-db-reader - npm Package Compare versions

Comparing version 0.0.2 to 0.2.0

lib/IPParser.js

35

index.js

@@ -6,12 +6,31 @@ 'use strict';

MaxmindDBReader = module.exports = function (database) {
if (database === undefined) {
throw new Error('MaxmindDBReader: No Database given');
}
MaxmindDBReader = module.exports = function () {
// allow creation without 'new' keyword
if (!(this instanceof MaxmindDBReader))
return new MaxmindDBReader();
};
this.reader = new Reader(database);
MaxmindDBReader.open = function(database,callback){
Reader.open(database,function(err, reader){
if(err){
return callback(err);
}
var mmdbreader = MaxmindDBReader();
mmdbreader.reader = reader;
callback(null,mmdbreader);
});
}
MaxmindDBReader.openSync = function(database){
var mmdbreader = MaxmindDBReader();
mmdbreader.reader = Reader.openSync(database);
return mmdbreader
}
MaxmindDBReader.prototype.getGeoData = function getGeoData(ipAddress,callback) {
this.reader.get(ipAddress,callback);
};
MaxmindDBReader.prototype.getGeoData = function getGeoData(ipAddress) {
return this.reader.get(ipAddress);
MaxmindDBReader.prototype.getGeoDataSync = function getGeoDataSync(ipAddress) {
return this.reader.getSync(ipAddress);
};

@@ -21,2 +40,2 @@

return this.reader.getMetadata();
};
};

@@ -30,4 +30,5 @@ 'use strict';

Decoder.prototype.decode = function decode(offset) {
Decoder.prototype.decode = function decode(offset,callback,nexttick) {
var tmp,
that = this,
ctrlByte = this.fileStream[offset++],

@@ -39,3 +40,7 @@ type = this.types[ctrlByte >> 5]

tmp = this.decodePointer(ctrlByte, offset);
return [this.decode(tmp[0])[0], tmp[1]];
this.decode(tmp[0],function(err,data){
if(err) return callback(err);
callback(null, [data[0], tmp[1]]);
},nexttick);
return;
}

@@ -47,2 +52,67 @@

if (tmp < 8) {
return callback(new Error('MaxmindDBReader: Invalid Extended Type at offset:' + offset));
}
type = this.types[tmp];
offset++;
}
tmp = this.sizeFromCtrlByte(ctrlByte, offset);
if(nexttick === false)
this.decodeByType(type, tmp[1], tmp[0],callback);
else
process.nextTick(function(){
that.decodeByType(type, tmp[1], tmp[0],callback);
});
};
Decoder.prototype.decodeByType = function decodeByType(type, offset, size,callback) {
var newOffset = offset + size,
bytes = this.read(offset, size)
;
switch (type) {
case 'map':
return this.decodeMap(size, offset,callback);
case 'array':
return this.decodeArray(size, offset,callback);
case 'boolean':
return callback(null,[this.decodeBoolean(size), offset]);
case 'utf8_string':
return callback(null,[this.decodeString(bytes), newOffset]);
case 'double':
return callback(null,[this.decodeDouble(bytes), newOffset]);
case 'float':
return callback(null,[this.decodeFloat(bytes), newOffset]);
case 'bytes':
return callback(null,[bytes, newOffset]);
case 'uint16':
return callback(null,[this.decodeUint16(bytes), newOffset]);
case 'uint32':
return callback(null,[this.decodeUint32(bytes), newOffset]);
case 'int32':
return callback(null,[this.decodeInt32(bytes), newOffset]);
case 'uint64':
return callback(null,[this.decodeUint64(bytes), newOffset]);
case 'uint128':
return callback(null,[this.decodeUint128(bytes), newOffset]);
}
callback(new Error("MaxmindDBReader: Unknown or unexpected type: " + type + ' at offset:' + offset));
};
Decoder.prototype.decodeSync = function decodeSync(offset) {
var tmp,
ctrlByte = this.fileStream[offset++],
type = this.types[ctrlByte >> 5]
;
if (type === 'pointer') {
tmp = this.decodePointer(ctrlByte, offset);
return [this.decodeSync(tmp[0])[0], tmp[1]];
}
if (type === 'extended') {
tmp = this.fileStream[offset] + 7;
if (tmp < 8) {
throw new Error('MaxmindDBReader: Invalid Extended Type at offset:' + offset);

@@ -57,6 +127,6 @@ }

return this.decodeByType(type, tmp[1], tmp[0]);
return this.decodeByTypeSync(type, tmp[1], tmp[0]);
};
Decoder.prototype.decodeByType = function decodeByType(type, offset, size) {
Decoder.prototype.decodeByTypeSync = function decodeByTypeSync(type, offset, size) {
var newOffset = offset + size,

@@ -67,4 +137,4 @@ bytes = this.read(offset, size)

switch (type) {
case 'map': return this.decodeMap(size, offset);
case 'array': return this.decodeArray(size, offset);
case 'map': return this.decodeMapSync(size, offset);
case 'array': return this.decodeArraySync(size, offset);
case 'boolean': return [this.decodeBoolean(size), offset];

@@ -136,3 +206,26 @@ case 'utf8_string': return [this.decodeString(bytes), newOffset];

Decoder.prototype.decodeArray = function decodeArray(size, offset) {
Decoder.prototype.decodeArray = function decodeArray(size, offset,callback) {
var that = this;
process.nextTick(function(){
var tmp,
i = 1,
array = [],
cb = function(err,tmp){
if(err){
return callback(err);
}
offset = tmp[1];
array.push(tmp[0]);
if(i++ < size){
that.decode(offset,cb,i%20===0);
}else{
callback(null, [array,offset]);
}
};
if(size === 0) callback(null,[[],offset]);
that.decode(offset,cb,false);
});
};
Decoder.prototype.decodeArraySync = function decodeArraySync(size, offset) {
var tmp,

@@ -144,3 +237,3 @@ i = 0,

for(i; i < size; i++) {
tmp = this.decode(offset);
tmp = this.decodeSync(offset);
offset = tmp[1];

@@ -165,3 +258,30 @@ array.push(tmp[0]);

Decoder.prototype.decodeMap = function decodeMap(size, offset) {
Decoder.prototype.decodeMap = function decodeMap(size, offset,callback) {
var that = this;
process.nextTick(function(){
var tmp, key,
map = {},
i = 1,
cb = function(err,tmp){
if(err){
return callback(err);
}
map[key] = tmp[0];
offset = tmp[1];
if(i++ < size){
tmp = that.decodeSync(offset);
key = tmp[0].toString();
that.decode(tmp[1],cb,i%20===0);
}else{
callback(null, [map,offset]);
}
};
if(size === 0) return callback(null,[{},offset]);
tmp = that.decodeSync(offset);
key = tmp[0].toString();
that.decode(tmp[1],cb,false);
});
};
Decoder.prototype.decodeMapSync = function decodeMapSync(size, offset) {
var tmp, key,

@@ -173,5 +293,5 @@ map = {},

for (i; i < size; i++) {
tmp = this.decode(offset);
tmp = this.decodeSync(offset);
key = tmp[0].toString();
tmp = this.decode(tmp[1]);
tmp = this.decodeSync(tmp[1]);
offset = tmp[1];

@@ -178,0 +298,0 @@ map[key] = tmp[0];

@@ -8,3 +8,3 @@ 'use strict';

this.binaryFormatMinorVersion = metadata.binary_format_minor_version;
this.buildEpoch = metadata.build_epoch;
this.buildEpoch = new Date(metadata.build_epoch*1000);
this.databaseType = metadata.database_type;

@@ -11,0 +11,0 @@ this.languages = metadata.languages;

@@ -8,15 +8,38 @@ 'use strict';

Decoder = require('./Decoder.js'),
IPParser = require('./IPParser.js'),
Reader;
Reader = module.exports = function (database) {
Reader = module.exports = function () {};
Reader.open = function(database, callback){
var reader = new Reader();
var start, metadataDecoder, metadataArray;
fs.readFile(database,function(err, data){
if(err){
callback && callback(err);
return;
}
reader.fileHandle =data;
start = reader.findMetadataStart(reader.fileHandle);
metadataDecoder = new Decoder(reader.fileHandle, 0);
metadataDecoder.decode(start,function(err,metadata){
reader.metadata = new Metadata(metadata[0]);
reader.decoder = new Decoder(reader.fileHandle, reader.metadata.getSearchTreeSize() + DATA_SECTION_SEPARATOR_SIZE);
callback && callback(null,reader);
});
});
}
this.fileHandle = fs.readFileSync(database);
Reader.openSync = function (database) {
var reader = new Reader();
var start, metadataDecoder, metadataArray;
start = this.findMetadataStart(this.fileHandle);
metadataDecoder = new Decoder(this.fileHandle, 0);
metadataArray = metadataDecoder.decode(start);
reader.fileHandle = fs.readFileSync(database);
this.metadata = new Metadata(metadataArray[0]);
this.decoder = new Decoder(this.fileHandle, this.metadata.getSearchTreeSize() + DATA_SECTION_SEPARATOR_SIZE);
start = reader.findMetadataStart(reader.fileHandle);
metadataDecoder = new Decoder(reader.fileHandle, 0);
metadataArray = metadataDecoder.decodeSync(start);
reader.metadata = new Metadata(metadataArray[0]);
reader.decoder = new Decoder(reader.fileHandle, reader.metadata.getSearchTreeSize() + DATA_SECTION_SEPARATOR_SIZE);
return reader;
};

@@ -29,3 +52,2 @@

;
while (found <= mlen && fsize--) {

@@ -38,6 +60,16 @@ found += (file[fsize] === METADATA_START_MARKER[mlen - found]) ? 1 : -found;

Reader.prototype.get = function get(ipAddress) {
Reader.prototype.getSync = function getSync(ipAddress) {
var pointer = this.findAddressInTree(ipAddress);
return (pointer === 0) ? null : this.resolveDataPointerSync(pointer);
};
return (pointer === 0) ? null : this.resolveDataPointer(pointer);
Reader.prototype.get = function get(ipAddress,callback) {
var pointer = this.findAddressInTree(ipAddress);
if(pointer === 0){
process.nextTick(function(){
callback(null,null);
});
}else{
this.resolveDataPointer(pointer,callback);
};
};

@@ -47,3 +79,3 @@

var bit, tempBit, record,
rawAddress = ipAddress.split('.').map(function(v) { return parseInt(v, 10); }),
rawAddress = IPParser(ipAddress),
countRaw = rawAddress.length,

@@ -78,3 +110,3 @@ isIp4AddressInIp6Db = (countRaw === 4 && this.metadata.getIpVersion() === 6),

throw new Error('MaxmindDBReader: Unable to find IP:' + ipAddress + ' in Database');
return null;
};

@@ -109,10 +141,19 @@

Reader.prototype.resolveDataPointer = function resolveDataPointer(pointer) {
Reader.prototype.resolveDataPointerSync = function resolveDataPointerSync(pointer) {
var resolved = pointer - this.metadata.getNodeCount() + this.metadata.getSearchTreeSize();
return this.decoder.decode(resolved)[0];
return this.decoder.decodeSync(resolved)[0];
};
Reader.prototype.resolveDataPointer = function resolveDataPointer(pointer,callback) {
var resolved = pointer - this.metadata.getNodeCount() + this.metadata.getSearchTreeSize();
this.decoder.decode(resolved,function(err,data){
if(err) return callback(err);
callback(null,data[0]);
});
};
Reader.prototype.getMetadata = function metadata() {
return this.metadata;
};
{
"name" : "maxmind-db-reader",
"version" : "0.0.2",
"description" : "This is the pure Node API for reading MaxMind DB files. MaxMind DB is a binary file format that stores data indexed by IP address subnets (IPv4 or IPv6).",
"main" : "./index.js",
"repository" : {
"type" : "git",
"url" : "https://github.com/PaddeK/node-maxmind-db"
"name": "maxmind-db-reader",
"version": "0.2.0",
"description": "This is the pure Node API for reading MaxMind DB files. MaxMind DB is a binary file format that stores data indexed by IP address subnets (IPv4 or IPv6).",
"main": "./index.js",
"contributors": [
{
"name": "Patrick Klös",
"email": "pkloes@web.de"
},
"keywords": [
"Maxmind",
"Maxmind DB",
"Maxmind DB Reader",
"GeoIP2",
"GeoIP2 Lite"
],
"author" : {
"name" : "Patrick Klös",
"email" : "pkloes@web.de"
},
"dependencies" : {
"big-integer" : ">=1.1.5"
},
"licenses": [
{
"type": "LGPL 2.1",
"url": "https://github.com/PaddeK/node-maxmind-db/blob/master/LICENSE"
}
],
"engine" : {
"node" : ">=0.8.0"
{
"name": "Corné 'EaterOfCode' Oppelaar",
"email": "hello@eaterofco.de"
}
}
],
"repository": {
"type": "git",
"url": "https://github.com/PaddeK/node-maxmind-db"
},
"bin": {
"mmdb-geoip": "./repl"
},
"keywords": [
"Maxmind",
"Maxmind DB",
"Maxmind DB Reader",
"GeoIP2",
"GeoIP2 Lite"
],
"author": {
"name": "Patrick Klös",
"email": "pkloes@web.de"
},
"dependencies": {
"big-integer": ">=1.1.5"
},
"licenses": [
{
"type": "LGPL 2.1",
"url": "https://github.com/PaddeK/node-maxmind-db/blob/master/LICENSE"
}
],
"engine": {
"node": ">=0.8.0"
}
}

@@ -1,4 +0,148 @@

node-maxmind-db
===============
# node-maxmind-db
This is the pure Node API for reading MaxMind DB files. MaxMind DB is a binary file format that stores data indexed by IP address subnets (IPv4 or IPv6).
# WARNING
* `.open(Sync)` needs to be called once before abusing `.getGeoData(Sync)`
* this is version 0.1.0! the API is not compitable with 0.0.*
* Most IP's don't seem to have city data in the GeoLite2 City database. Only american cities are present, if your IP is american but not returning a city try to replace the last number of your IP by a 0 (only with a IPv4 address. for IPv6 address it doesn't seem to work).
# Install
npm i https://github.com/EaterOfCode/node-maxmind-db/archive/master.tar.gz
# Example
## Async
```javascript
// require the db reader
var mmdbreader = require('maxmind-db-reader');
// open database
mmdbreader.open('./countries.mmdb',function(err,countries){
// get geodata
countries.getGeoData('128.101.101.101',function(err,geodata){
// log data :D
console.log(geodata);
});
});
```
## Sync
```javascript
// require the db reader
var mmdbreader = require('maxmind-db-reader');
// open database
var countries = mmdbreader.openSync('./countries.mmdb');
// get geodata
var geodata = countries.getGeoDataSync('128.101.101.101');
// log data :D
console.log(geodata);
```
## Mixed (Sync init, Async request)
```javascript
// require the db reader
var mmdbreader = require('maxmind-db-reader');
// open database
var countries = mmdbreader.openSync('./countries.mmdb');
// get geodata
countries.getGeoData('128.101.101.101',function(err,geodata){
// log data :D
console.log(geodata);
});
```
## Result
```javascript
{
"city": {
"geoname_id": 5037649,
"names": {
"de": "Minneapolis",
"en": "Minneapolis",
"es": "Mineápolis",
"fr": "Minneapolis",
"ja": "ミネアポリス",
"pt-BR": "Minneapolis",
"ru": "Миннеаполис",
"zh-CN": "明尼阿波利斯"
}
},
"continent": {
"code": "NA",
"geoname_id": 6255149,
"names": {
"de": "Nordamerika",
"en": "North America",
"es": "Norteamérica",
"fr": "Amérique du Nord",
"ja": "北アメリカ",
"pt-BR": "América do Norte",
"ru": "Северная Америка",
"zh-CN": "北美洲"
}
},
"country": {
"geoname_id": 6252001,
"iso_code": "US",
"names": {
"de": "USA",
"en": "United States",
"es": "Estados Unidos",
"fr": "États-Unis",
"ja": "アメリカ合衆国",
"pt-BR": "Estados Unidos",
"ru": "США",
"zh-CN": "美国"
}
},
"location": {
"latitude": 44.9759,
"longitude": -93.2166,
"metro_code": "613",
"time_zone": "America/Chicago"
},
"postal": {
"code": "55414"
},
"registered_country": {
"geoname_id": 6252001,
"iso_code": "US",
"names": {
"de": "USA",
"en": "United States",
"es": "Estados Unidos",
"fr": "États-Unis",
"ja": "アメリカ合衆国",
"pt-BR": "Estados Unidos",
"ru": "США",
"zh-CN": "美国"
}
},
"subdivisions": [
{
"geoname_id": 5037779,
"iso_code": "MN",
"names": {
"en": "Minnesota",
"es": "Minnesota",
"ja": "ミネソタ州",
"ru": "Миннесота"
}
}
]
}
```
# API
`maxmind-db-reader`
* `.open (databasePath, callback(err, maxmind-db-reader)) void`
* `.openSync (databasePath) maxmind-db-reader`
`maxmind-db-reader()`
* `.getGeoData (ip, callback(err,geodata)) void`
* `.getGeoDataSync (ip) geodata`
* `.getDatabaseMetadata() metadata`
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc