UNPKG

ip-location-api

Version:
276 lines (234 loc) 7.02 kB
const path = require('path') const countryCodeToNum = (code) => { // 0~675 code = code.toUpperCase() return (code.charCodeAt(0)-65)*26 + (code.charCodeAt(1)-65) } const numToCountryCode = (num) => { return String.fromCharCode((num/26|0) + 65, num % 26 + 65) } const getFieldsSize = (types) => { var size = 0 for (const type of types) { switch (type) { case 'postcode': size += 5 break case 'area': size += 1 break case 'latitude': case 'longitude': case 'city': size += 4 break case 'eu': break default: size += 2 break } } return size } const ntoa4 = (n) => { return [n >>> 24, n >> 16 & 255, n >> 8 & 255, n & 255].join('.') } const aton4 = (a) => { a = a.split(/\./) return (a[0] << 24 | a[1] << 16 | a[2] << 8 | a[3]) >>> 0 } const aton6Start = (a) => { if(a.includes('.')){ return aton4(a.split(':').pop()) } a = a.split(/:/) const l = a.length - 1 var i, r = 0n if (l < 7) { const omitStart = a.indexOf('') if(omitStart < 4){ const omitted = 8 - a.length, omitEnd = omitStart + omitted for (i = 7; i >= omitStart; i--) { a[i] = i > omitEnd ? a[i - omitted] : 0 } } } for (i = 0; i < 4; i++) { if(a[i]) r += BigInt(parseInt(a[i], 16)) << BigInt(16 * (3 - i)) } return r } const aton6 = (a) => { a = a.replace(/"/g, '').split(/:/) const l = a.length - 1 var i if (a[l] === '') a[l] = 0 if (l < 7) { const omitted = 8 - a.length, omitStart = a.indexOf(''), omitEnd = omitStart + omitted for (i = 7; i >= omitStart; i--) { a[i] = i > omitEnd ? a[i - omitted] : 0 } } var r = 0n for (i = 0; i < 4; i++) { if (a[i]) { r += BigInt(parseInt(a[i], 16)) << BigInt(16 * (3 - i)) } } return r } const v4MappedReg = /^(?:0:0:0:0:0|:):ffff:(\d+\.\d+\.\d+\.\d+)$/i const v4Mapped = (addr) => { const match = v4MappedReg.exec(addr) return match && match[1] } const PrivateIpRegList = [ /^10\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/, /^192\.168\.([0-9]{1,3})\.([0-9]{1,3})/, /^172\.16\.([0-9]{1,3})\.([0-9]{1,3})/, /^127\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/, /^169\.254\.([0-9]{1,3})\.([0-9]{1,3})/, /^fc00:/, /^fe80:/ ] const isPrivateIP = function(addr) { for(const reg of PrivateIpRegList){ if(reg.test(addr)){ return true } } return false } const strToNum37 = (a) => { var num = 0 for(var i = 0; i < a.length; i++){ num = num * 37 + parseInt(a[i], 36) + 1 } return num } const num37ToStr = (num) => { var str = '' while(num > 0){ str = (num % 37 - 1).toString(36) + str num = Math.floor(num / 37) } return str.toUpperCase() } const getZeroFill = (num, len) => { return '0'.repeat(len - num.length) + num } const getUnderberFill = (num, len) => { if(num.length > len) return num return '_'.repeat(len - num.length) + num } const numberToDir = (num) => { return getUnderberFill(num.toString(36), 2) } const getSmallMemoryFile = (line, db, isTmp) => { const dbNumber = line / db.folderLineMax | 0 const fileNumber = (line - dbNumber * db.folderLineMax) / db.fileLineMax | 0 const lineOffset = line - dbNumber * db.folderLineMax - fileNumber * db.fileLineMax var dir = path.join(db.name + (isTmp ? '-tmp' : ''), getUnderberFill(dbNumber.toString(36), 2)) return [dir, getUnderberFill(fileNumber.toString(36), 2), lineOffset * db.recordSize] } const isPostNumReg = /^\d+$/ const isPostNumReg2 = /^(\d+)[-\s](\d+)$/ const isPostStrReg = /^([a-zA-Z\d]+)$/ const isPostStrReg2 = /^([a-zA-Z\d]+)[-\s]([a-zA-Z\d]+)$/ var postcodeDatabase const initPostcodeDatabase = () => { postcodeDatabase = [null] } const getPostcodeDatabase = () => { return postcodeDatabase } const Uint32Max = 0xFFFFFFFF // 4294967295 const createPostcodeDatabase = (postcode) => { var idx = postcodeDatabase.indexOf(postcode) if(idx === -1){ idx = postcodeDatabase.length postcodeDatabase.push(postcode) } return [-128, idx] } const zeroStartCount = (postcode) => { var count = 0 for(var i = 0; i < postcode.length; i++){ if(postcode[i] !== '0'){ break; } count++ } return count } /** * @param {number} idx (int8) * @param {number} num (uint32) * @param {object} database */ const getPostcodeFromDatabase = (idx, num, database) => { if(idx < 0) { if(idx === -128){ return database[num] } idx = -idx var str if(idx <= 6){ str = num.toString(36) } else { str = ((idx-6)%36).toString(36) + num.toString(36) idx = ((idx-6)/36|0) + 2 } return str.slice(0, idx) + '-' + str.slice(idx) } if(idx <= 10) { return '0'.repeat(idx-1) + num } if(idx <= 20) { return '0'.repeat(idx-11) + num.toString(36) } if(idx <= 56) { return (idx-21).toString(36) + num.toString(36) } idx -= 57 var zeroCount = idx & 7, r1length = (idx >> 3) + 1 var r = '0'.repeat(zeroCount) + num.toString(10) return r.slice(0, r1length) + '-' + r.slice(r1length) } /** * @param {string} postcode */ const getPostcodeDatabaseElement = (postcode) => { if(!postcode) return [0, 0]; var idx, num, r if(isPostNumReg.test(postcode)){ idx = zeroStartCount(postcode) + 1 // 1-10 num = parseInt(postcode, 10) if(num <= Uint32Max && idx <= 10) return [idx, num] } else if(isPostStrReg.test(postcode)){ idx = zeroStartCount(postcode) + 11 // 11-20 num = parseInt(postcode, 36) if(num <= Uint32Max && idx <= 20) return [idx, num] if(postcode[1] !== '0'){ idx = parseInt(postcode[0], 36) + 21 // 21-56 num = parseInt(postcode.slice(1), 36) if(num <= Uint32Max) return [idx, num] } } else if(r = isPostNumReg2.exec(postcode)) { idx = (((r[1].length-1) * 8) | zeroStartCount(r[1])) + 57 // 57-127 num = parseInt(r[1] + r[2], 10) if(zeroStartCount(r[1]) < 8 && idx <= 127 && num <= Uint32Max) return [idx, num] } else if(postcode[0] !== '0' && (r = isPostStrReg2.exec(postcode))){ idx = r[1].length // 1-6 num = parseInt(r[1] + r[2], 36) if(num <= Uint32Max && idx <= 6) return [-idx, num] num = r[1].slice(1) + r[2] if(num[0] !== '0' && r[1].length > 1){ idx = parseInt(postcode[0], 36) + (r[1].length-2)*36 + 6 // 1-35 + (0-3) * 36 + 6 num = parseInt(num, 36) if(num <= Uint32Max && idx < 128) return [-idx, num] } } return createPostcodeDatabase(postcode) } module.exports={countryCodeToNum:countryCodeToNum,numToCountryCode:numToCountryCode,getFieldsSize:getFieldsSize,ntoa4:ntoa4,aton4:aton4,aton6Start:aton6Start,aton6:aton6,v4Mapped:v4Mapped,isPrivateIP:isPrivateIP,strToNum37:strToNum37,num37ToStr:num37ToStr,getZeroFill:getZeroFill,numberToDir:numberToDir,getSmallMemoryFile:getSmallMemoryFile,initPostcodeDatabase:initPostcodeDatabase,getPostcodeDatabase:getPostcodeDatabase,getPostcodeFromDatabase:getPostcodeFromDatabase,getPostcodeDatabaseElement:getPostcodeDatabaseElement}