UNPKG

ipdb

Version:

IP lookup using IPIP.net database (Node.js & Browser)

297 lines (239 loc) 7.54 kB
'use strict'; var require$$0 = require('fs'); function getDefaultExportFromCjs (x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; } var src = {exports: {}}; var hasRequiredSrc; function requireSrc () { if (hasRequiredSrc) return src.exports; hasRequiredSrc = 1; (function (module, exports$1) { // Pure JavaScript IP validation (replaces net.isIP) function isIP(ip) { // IPv4 validation const ipv4Regex = /^(25[0-5]|2[0-4]\d|[01]?\d{1,2})\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})$/; if (ipv4Regex.test(ip)) { const parts = ip.split('.'); for (const part of parts) { const num = parseInt(part, 10); if (num > 255) { return 0 } } return 4 } // IPv6 validation (supports :: compression) if (ip.includes(':')) { const parts = ip.split(':'); const hasDoubleColon = ip.includes('::'); // Check basic format validity if (!hasDoubleColon && parts.length !== 8) { return 0 } if (hasDoubleColon && parts.length > 8) { return 0 } for (const part of parts) { if (part === '') { continue } if (!/^[\da-f]{1,4}$/i.test(part)) { return 0 } } return 6 } return 0 } // Buffer-compatible read functions using DataView function readInt32BE(buffer, offset) { if (buffer.readInt32BE) { return buffer.readInt32BE(offset) } // False = Big Endian const view = new DataView(buffer.buffer, buffer.byteOffset + offset, 4); return view.getInt32(0, false) } function readUInt16BE(buffer, offset) { if (buffer.readUInt16BE) { return buffer.readUInt16BE(offset) } const view = new DataView(buffer.buffer, buffer.byteOffset + offset, 2); return view.getUint16(0, false) } function readUInt32BE(buffer, offset) { if (buffer.readUInt32BE) { return buffer.readUInt32BE(offset) } const view = new DataView(buffer.buffer, buffer.byteOffset + offset, 4); return view.getUint32(0, false) } const isBuffer = obj => { // Support both Node.js Buffer and Uint8Array if (obj instanceof Uint8Array) { return true } return obj !== null && obj.constructor !== null && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) }; class Parse { constructor(filename, options = {}) { let data; // Environment detection: file path only supported in Node.js if (typeof filename === 'string') { if (typeof process !== 'undefined' && process.versions && process.versions.node) { // Node.js environment const fs = require$$0; data = fs.readFileSync(filename); } else { throw new Error('File path is only supported in Node.js environment. In browser, please pass ArrayBuffer or Uint8Array.') } } else if (isBuffer(filename)) { data = filename; } else if (filename instanceof ArrayBuffer) { data = new Uint8Array(filename); } else if (filename instanceof Uint8Array) { data = filename; } else { throw new TypeError('Invalid input type. Expected: file path (Node.js only), Buffer, ArrayBuffer, or Uint8Array') } const metaLen = readInt32BE(data, 0); const meta = data.slice(4, 4 + metaLen); // Convert Uint8Array to string let metaStr; if (typeof TextDecoder === 'undefined') { metaStr = meta.toString(); } else { metaStr = new TextDecoder().decode(meta); } this.meta = JSON.parse(metaStr); this.data = data.slice(4 + metaLen); if (options.patches) { this.patches = options.patches; } if (this.meta.v4node === undefined && this.meta.ip_version & 0x01) { this._initv4node(); } } _initv4node() { let node = 0; for (let i = 0; i < 80; i += 1) { node = this._node(node, 0); } for (let i = 80; i < 96; i += 1) { node = this._node(node, 1); } this.meta.v4node = node; } find(ip, options = {}) { const result = {}; try { result.data = this._find(ip, options.language); result.code = 0; if (this.patches || options.patches) { const patches = options.patches || this.patches; for (const patch of patches) { patch(result.data); } } } catch (error) { result.code = -1; result.message = error.message; } return result } _find(ip, language) { const bits = this._toBits(ip); let node = bits.length === 32 ? this.meta.v4node : 0; let cidr = 0; while (cidr < bits.length) { node = this._node(node, bits[cidr]); cidr += 1; if (node >= this.meta.node_count) { break } } const data = this._resolve(node); let offset = 0; if (this.meta.languages[language]) { offset = this.meta.languages[language]; } const result = {}; for (let i = 0; i < this.meta.fields.length; i += 1) { result[this.meta.fields[i]] = data[offset + i]; } result.ip = ip; result.bitmask = cidr; return result } _resolve(node) { const offset = node + (this.meta.node_count << 3) - this.meta.node_count; const len = readUInt16BE(this.data, offset); const buf = this.data.slice(offset + 2, offset + 2 + len); // Convert to string let str; if (typeof TextDecoder === 'undefined') { str = buf.toString(); } else { str = new TextDecoder().decode(buf); } return str.split('\t') } _node(id, idx) { return readUInt32BE(this.data, (id << 3) | (idx << 2)) } _toBits(ip) { const version = isIP(ip); if (!version) { throw new Error('ip format error') } if (version === 4 && !(this.meta.ip_version & 0x01)) { throw new Error('no support ipv4') } if (version === 6 && !(this.meta.ip_version & 0x02)) { throw new Error('no support ipv6') } return version === 4 ? this._toBits4(ip) : this._toBits6(ip) } _toBits4(ip) { const result = []; const items = ip.split('.'); for (const item of items) { const num = parseInt(item, 10); for (let i = 7; i >= 0; i -= 1) { result.push((num >> i) & 1); } } return result } _toBits6(ip) { const result = [[], []]; const parts = ip.split('::', 2); for (let index = 0; index < 2; index += 1) { if (parts[index]) { const items = parts[index].split(':'); for (const item of items) { const num = parseInt(item, 16); for (let i = 15; i >= 0; i -= 1) { result[index].push((num >> i) & 1); } } } } const pad = 128 - result[0].length - result[1].length; return [...result[0], ...(new Array(pad).fill(0)), ...result[1]] } } module.exports = Parse; // ESM export support { exports$1.default = Parse; exports$1.Parse = Parse; } } (src, src.exports)); return src.exports; } var srcExports = requireSrc(); var index = /*@__PURE__*/getDefaultExportFromCjs(srcExports); module.exports = index;