ip2proxy-nodejs
Advanced tools
+2
-2
| { | ||
| "name": "ip2proxy-nodejs", | ||
| "version": "4.2.3", | ||
| "version": "4.3.0", | ||
| "description": "IP2Proxy proxy detection component", | ||
@@ -32,3 +32,3 @@ "keywords": [ | ||
| "type": "git", | ||
| "url": "https://github.com/ip2location/ip2proxy-nodejs" | ||
| "url": "git+https://github.com/ip2location/ip2proxy-nodejs.git" | ||
| }, | ||
@@ -35,0 +35,0 @@ "devDependencies": { |
+50
-0
@@ -33,2 +33,3 @@ [](http://npm.im/ip2proxy-nodejs) | ||
| |open|Open the IP2Proxy BIN data for lookup.| | ||
| |openAsync|Open the IP2Proxy BIN data for lookup asynchronously.| | ||
| |close|Close and clean up the file pointer.| | ||
@@ -39,16 +40,31 @@ |getPackageVersion|Get the package version (1 to 11 for PX1 to PX11 respectively).| | ||
| |isProxy|Check whether if an IP address was a proxy. Returned value:<ul><li>-1 : errors</li><li>0 : not a proxy</li><li>1 : a proxy</li><li>2 : a data center IP address or search engine robot</li></ul>| | ||
| |isProxyAsync|Check whether if an IP address was a proxy asynchronously. Returned value:<ul><li>-1 : errors</li><li>0 : not a proxy</li><li>1 : a proxy</li><li>2 : a data center IP address or search engine robot</li></ul>| | ||
| |getAll|Return the proxy information in an object.| | ||
| |getAllAsync|Return the proxy information in an object asynchronously.| | ||
| |getProxyType|Return the proxy type. Please visit <a href="https://www.ip2location.com/database/px10-ip-proxytype-country-region-city-isp-domain-usagetype-asn-lastseen-threat-residential" target="_blank">IP2Location</a> for the list of proxy types supported| | ||
| |getProxyTypeAsync|Return the proxy type asynchronously. Please visit <a href="https://www.ip2location.com/database/px10-ip-proxytype-country-region-city-isp-domain-usagetype-asn-lastseen-threat-residential" target="_blank">IP2Location</a> for the list of proxy types supported| | ||
| |getCountryShort|Return the ISO3166-1 country code (2-digits) of the proxy.| | ||
| |getCountryShortAsync|Return the ISO3166-1 country code (2-digits) of the proxy asynchronously.| | ||
| |getCountryLong|Return the ISO3166-1 country name of the proxy.| | ||
| |getCountryLongAsync|Return the ISO3166-1 country name of the proxy asynchronously.| | ||
| |getRegion|Return the ISO3166-2 region name of the proxy. Please visit <a href="https://www.ip2location.com/free/iso3166-2" target="_blank">ISO3166-2 Subdivision Code</a> for the information of ISO3166-2 supported| | ||
| |getRegionAsync|Return the ISO3166-2 region name of the proxy asynchronously. Please visit <a href="https://www.ip2location.com/free/iso3166-2" target="_blank">ISO3166-2 Subdivision Code</a> for the information of ISO3166-2 supported| | ||
| |getCity|Return the city name of the proxy.| | ||
| |getCityAsync|Return the city name of the proxy asynchronously.| | ||
| |getISP|Return the ISP name of the proxy.| | ||
| |getISPAsync|Return the ISP name of the proxy asynchronously.| | ||
| |getDomain|Return the domain name of the proxy.| | ||
| |getDomainAsync|Return the domain name of the proxy asynchronously.| | ||
| |getUsageType|Return the usage type classification of the proxy. Please visit <a href="https://www.ip2location.com/database/px10-ip-proxytype-country-region-city-isp-domain-usagetype-asn-lastseen-threat-residential" target="_blank">IP2Location</a> for the list of usage types supported.| | ||
| |getUsageTypeAsync|Return the usage type classification of the proxy asynchronously. Please visit <a href="https://www.ip2location.com/database/px10-ip-proxytype-country-region-city-isp-domain-usagetype-asn-lastseen-threat-residential" target="_blank">IP2Location</a> for the list of usage types supported.| | ||
| |getASN|Return the autonomous system number of the proxy.| | ||
| |getASNAsync|Return the autonomous system number of the proxy asynchronously.| | ||
| |getAS|Return the autonomous system name of the proxy.| | ||
| |getASAsync|Return the autonomous system name of the proxy asynchronously.| | ||
| |getLastSeen|Return the number of days that the proxy was last seen.| | ||
| |getLastSeenAsync|Return the number of days that the proxy was last seen asynchronously.| | ||
| |getThreat|Return the threat type of the proxy.| | ||
| |getThreatAsync|Return the threat type of the proxy asynchronously.| | ||
| |getProvider|Return the provider of the proxy.| | ||
| |getProviderAsync|Return the provider of the proxy asynchronously.| | ||
@@ -109,2 +125,36 @@ ## Usage | ||
| ## Asynchronously Usage | ||
| ```javascript | ||
| const {IP2Proxy} = require("ip2proxy-nodejs"); | ||
| let ip2proxy = new IP2Proxy(); | ||
| ip2proxy.openAsync("./IP2PROXY-IP-PROXYTYPE-COUNTRY-REGION-CITY-ISP-DOMAIN-USAGETYPE-ASN-LASTSEEN-THREAT-RESIDENTIAL-PROVIDER.BIN").then((status) => { | ||
| if (status == 0) { | ||
| ip = '199.83.103.79'; | ||
| ip2proxy.getAllAsync(ip).then(all => { | ||
| console.log("isProxy: " + all.isProxy); | ||
| console.log("proxyType: " + all.proxyType); | ||
| console.log("countryShort: " + all.countryShort); | ||
| console.log("countryLong: " + all.countryLong); | ||
| console.log("region: " + all.region); | ||
| console.log("city: " + all.city); | ||
| console.log("isp: " + all.isp); | ||
| console.log("domain: " + all.domain); | ||
| console.log("usagetype: " + all.usageType); | ||
| console.log("asn: " + all.asn); | ||
| console.log("as: " + all.as); | ||
| console.log("lastSeen: " + all.lastSeen); | ||
| console.log("threat: " + all.threat); | ||
| console.log("provider: " + all.provider); | ||
| }); | ||
| } | ||
| else { | ||
| console.log("Error reading BIN."); | ||
| } | ||
| }); | ||
| ``` | ||
| ## QUERY USING THE IP2PROXY PROXY DETECTION WEB SERVICE | ||
@@ -111,0 +161,0 @@ |
+184
-0
@@ -11,2 +11,10 @@ export class IP2Proxy { | ||
| /** | ||
| * Reads bytes from file into buffer asynchronously. | ||
| * | ||
| * @param readBytes The number of bytes to read. | ||
| * @param position The file offset to start reading. | ||
| * @returns The promise of the buffer containing the read bytes. | ||
| */ | ||
| readRowAsync(readBytes: number, position: number): Promise<any>; | ||
| /** | ||
| * Reads bytes from file and convert to specified data type. | ||
@@ -92,2 +100,9 @@ * | ||
| /** | ||
| * Reads string from file asynchronously. | ||
| * | ||
| * @param position The file offset to start reading. | ||
| * @returns The promise of the string. | ||
| */ | ||
| readStrAsync(position: number): Promise<string>; | ||
| /** | ||
| * Reads BIN file metadata. | ||
@@ -99,2 +114,8 @@ * | ||
| /** | ||
| * Reads BIN file metadata asynchronously. | ||
| * | ||
| * @returns The promise of whether metadata read successfully. | ||
| */ | ||
| loadBinAsync(): Promise<boolean>; | ||
| /** | ||
| * Initializes with BIN file path and pre-loads metadata. | ||
@@ -107,2 +128,9 @@ * | ||
| /** | ||
| * Initializes with BIN file path and pre-loads metadata asynchronously. | ||
| * | ||
| * @param binPath The path to the BIN file. | ||
| * @returns Promise of 0 if successful else -1 for errors. | ||
| */ | ||
| openAsync(binPath: string): Promise<0 | -1>; | ||
| /** | ||
| * Resets metadata and closes file handle. | ||
@@ -123,2 +151,11 @@ * | ||
| /** | ||
| * Retrieves proxy data into supplied object asynchronously. | ||
| * | ||
| * @param myIP The IP address to query. | ||
| * @param ipType 4 for IPv4 or 6 for IPv6. | ||
| * @param data The object to store the results. | ||
| * @param mode The fields to read. | ||
| */ | ||
| proxyQueryDataAsync(myIP: string, ipType: number, data: any, mode: any): Promise<void>; | ||
| /** | ||
| * Performs validations and returns proxy data. | ||
@@ -149,2 +186,27 @@ * | ||
| /** | ||
| * Performs validations and returns proxy data asynchronously. | ||
| * | ||
| * @param myIP The IP address to query. | ||
| * @param mode The fields to read. | ||
| * @returns The promise of the proxy data. | ||
| */ | ||
| proxyQueryAsync(myIP: string, mode: any): Promise<{ | ||
| ip: string; | ||
| ipNo: string; | ||
| isProxy: number; | ||
| proxyType: string; | ||
| countryShort: string; | ||
| countryLong: string; | ||
| region: string; | ||
| city: string; | ||
| isp: string; | ||
| domain: string; | ||
| usageType: string; | ||
| asn: string; | ||
| as: string; | ||
| lastSeen: string; | ||
| threat: string; | ||
| provider: string; | ||
| }>; | ||
| /** | ||
| * Returns the module version. | ||
@@ -175,2 +237,9 @@ * | ||
| /** | ||
| * Whether IP is a proxy server asynchronously. | ||
| * | ||
| * @param myIP The IP address to query. | ||
| * @returns Promise of -1 if error, 0 if not a proxy, 1 if proxy except DCH and SES, 2 if proxy and DCH or SES | ||
| */ | ||
| isProxyAsync(myIP: string): Promise<number>; | ||
| /** | ||
| * Returns the ISO 3166 country code. | ||
@@ -183,2 +252,9 @@ * | ||
| /** | ||
| * Returns the ISO 3166 country code asynchronously. | ||
| * | ||
| * @param myIP The IP address to query. | ||
| * @returns The promise of the country code. | ||
| */ | ||
| getCountryShortAsync(myIP: string): Promise<string>; | ||
| /** | ||
| * Returns the country name. | ||
@@ -191,2 +267,9 @@ * | ||
| /** | ||
| * Returns the country name asynchronously. | ||
| * | ||
| * @param myIP The IP address to query. | ||
| * @returns The promise of the country name. | ||
| */ | ||
| getCountryLongAsync(myIP: string): Promise<string>; | ||
| /** | ||
| * Returns the region or state. | ||
@@ -199,2 +282,9 @@ * | ||
| /** | ||
| * Returns the region or state asynchronously. | ||
| * | ||
| * @param myIP The IP address to query. | ||
| * @returns The promise of the region or state. | ||
| */ | ||
| getRegionAsync(myIP: string): Promise<string>; | ||
| /** | ||
| * Returns the city. | ||
@@ -207,2 +297,9 @@ * | ||
| /** | ||
| * Returns the city asynchronously. | ||
| * | ||
| * @param myIP The IP address to query. | ||
| * @returns The promise of the city. | ||
| */ | ||
| getCityAsync(myIP: string): Promise<string>; | ||
| /** | ||
| * Returns the Internet Service Provider. | ||
@@ -215,2 +312,9 @@ * | ||
| /** | ||
| * Returns the Internet Service Provider asynchronously. | ||
| * | ||
| * @param myIP The IP address to query. | ||
| * @returns The promise of the ISP. | ||
| */ | ||
| getISPAsync(myIP: string): Promise<string>; | ||
| /** | ||
| * Returns the proxy type. | ||
@@ -223,2 +327,9 @@ * | ||
| /** | ||
| * Returns the proxy type asynchronously. | ||
| * | ||
| * @param myIP The IP address to query. | ||
| * @returns The promise of the proxy type. | ||
| */ | ||
| getProxyTypeAsync(myIP: string): Promise<string>; | ||
| /** | ||
| * Returns the domain name. | ||
@@ -231,2 +342,9 @@ * | ||
| /** | ||
| * Returns the domain name asynchronously. | ||
| * | ||
| * @param myIP The IP address to query. | ||
| * @returns The promise of the domain name. | ||
| */ | ||
| getDomainAsync(myIP: string): Promise<string>; | ||
| /** | ||
| * Returns the usage type. | ||
@@ -239,2 +357,9 @@ * | ||
| /** | ||
| * Returns the usage type asynchronously. | ||
| * | ||
| * @param myIP The IP address to query. | ||
| * @returns The promise of the usage type. | ||
| */ | ||
| getUsageTypeAsync(myIP: string): Promise<string>; | ||
| /** | ||
| * Returns the autonomous system number. | ||
@@ -247,2 +372,9 @@ * | ||
| /** | ||
| * Returns the autonomous system number asynchronously. | ||
| * | ||
| * @param myIP The IP address to query. | ||
| * @returns The promise of the ASN. | ||
| */ | ||
| getASNAsync(myIP: string): Promise<string>; | ||
| /** | ||
| * Returns the autonomous system name. | ||
@@ -255,2 +387,9 @@ * | ||
| /** | ||
| * Returns the autonomous system name asynchronously. | ||
| * | ||
| * @param myIP The IP address to query. | ||
| * @returns The promise of the AS. | ||
| */ | ||
| getASAsync(myIP: string): Promise<string>; | ||
| /** | ||
| * Returns the number of days ago the proxy was last seen. | ||
@@ -263,2 +402,9 @@ * | ||
| /** | ||
| * Returns the number of days ago the proxy was last seen asynchronously. | ||
| * | ||
| * @param myIP The IP address to query. | ||
| * @returns The promise of the number of days ago the proxy was last seen. | ||
| */ | ||
| getLastSeenAsync(myIP: string): Promise<string>; | ||
| /** | ||
| * Returns the security threat reported. | ||
@@ -271,2 +417,9 @@ * | ||
| /** | ||
| * Returns the security threat reported asynchronously. | ||
| * | ||
| * @param myIP The IP address to query. | ||
| * @returns The promise of SPAM if spammer, SCANNER if network scanner, BOTNET if malware infected device. | ||
| */ | ||
| getThreatAsync(myIP: string): Promise<string>; | ||
| /** | ||
| * Returns the name of the VPN provider. | ||
@@ -279,2 +432,9 @@ * | ||
| /** | ||
| * Returns the name of the VPN provider asynchronously. | ||
| * | ||
| * @param myIP The IP address to query. | ||
| * @returns The promise of the name of the VPN provider. | ||
| */ | ||
| getProviderAsync(myIP: string): Provider<string>; | ||
| /** | ||
| * Returns all fields. | ||
@@ -303,2 +463,26 @@ * | ||
| }; | ||
| /** | ||
| * Returns all fields asynchronously. | ||
| * | ||
| * @param myIP The IP address to query. | ||
| * @returns The promise of all proxy fields. | ||
| */ | ||
| getAllAsync(myIP: string): Promise<{ | ||
| ip: string; | ||
| ipNo: string; | ||
| isProxy: number; | ||
| proxyType: string; | ||
| countryShort: string; | ||
| countryLong: string; | ||
| region: string; | ||
| city: string; | ||
| isp: string; | ||
| domain: string; | ||
| usageType: string; | ||
| asn: string; | ||
| as: string; | ||
| lastSeen: string; | ||
| threat: string; | ||
| provider: string; | ||
| }>; | ||
| #private; | ||
@@ -305,0 +489,0 @@ } |
+549
-5
@@ -1,7 +0,8 @@ | ||
| var net = require("net"); | ||
| var fs = require("fs"); | ||
| var https = require("https"); | ||
| const net = require("net"); | ||
| const fs = require("fs"); | ||
| const fsp = fs.promises; | ||
| const https = require("https"); | ||
| // For BIN queries | ||
| const VERSION = "4.2.3"; | ||
| const VERSION = "4.3.0"; | ||
| const MAX_INDEX = 65536; | ||
@@ -63,2 +64,15 @@ const COUNTRY_POSITION = [0, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]; | ||
| // Promise for fs.read since not provided by Node.js | ||
| const readPromise = (...args) => { | ||
| return new Promise((resolve, reject) => { | ||
| fs.read(...args, (err, bytesRead, buffer) => { | ||
| if (err) { | ||
| reject(err); | ||
| } else { | ||
| resolve({ bytesRead: bytesRead, buffer: buffer }); | ||
| } | ||
| }); | ||
| }); | ||
| }; | ||
| // BIN query class | ||
@@ -127,2 +141,14 @@ class IP2Proxy { | ||
| // Read row data async | ||
| async readRowAsync(readBytes, position) { | ||
| let buffer = new Buffer.alloc(readBytes); | ||
| var data; | ||
| try { | ||
| data = await readPromise(this.#fd, buffer, 0, readBytes, position - 1); | ||
| } catch (e) { | ||
| console.error(e); | ||
| } | ||
| return buffer; | ||
| } | ||
| // Read binary data | ||
@@ -235,2 +261,10 @@ readBin(readBytes, position, readType, isBigInt) { | ||
| // Read strings in the database async | ||
| async readStrAsync(position) { | ||
| let readBytes = 256; // max size of string field + 1 byte for the length | ||
| let row = await this.readRowAsync(readBytes, position + 1); | ||
| let len = this.read8Row(0, row); | ||
| return row.toString("utf8", 1, len + 1); | ||
| } | ||
| // Read metadata and indexes | ||
@@ -362,2 +396,129 @@ loadBin() { | ||
| // Read metadata and indexes async | ||
| async loadBinAsync() { | ||
| let loadOK = false; | ||
| try { | ||
| if (this.#binFile && this.#binFile != "") { | ||
| let fh = await fsp.open(this.#binFile, "r"); | ||
| this.#fd = fh.fd; | ||
| let len = 64; // 64-byte header | ||
| let row = await this.readRowAsync(len, 1); | ||
| this.#myDB.dbType = this.read8Row(0, row); | ||
| this.#myDB.dbColumn = this.read8Row(1, row); | ||
| this.#myDB.dbYear = this.read8Row(2, row); | ||
| this.#myDB.dbMonth = this.read8Row(3, row); | ||
| this.#myDB.dbDay = this.read8Row(4, row); | ||
| this.#myDB.dbCount = this.read32Row(5, row); | ||
| this.#myDB.baseAddress = this.read32Row(9, row); | ||
| this.#myDB.dbCountIPV6 = this.read32Row(13, row); | ||
| this.#myDB.baseAddressIPV6 = this.read32Row(17, row); | ||
| this.#myDB.indexBaseAddress = this.read32Row(21, row); | ||
| this.#myDB.indexBaseAddressIPV6 = this.read32Row(25, row); | ||
| this.#myDB.productCode = this.read8Row(29, row); | ||
| // below 2 fields just read for now, not being used yet | ||
| this.#myDB.productType = this.read8Row(30, row); | ||
| this.#myDB.fileSize = this.read32Row(31, row); | ||
| // check if is correct BIN (should be 2 for IP2Proxy BIN file), also checking for zipped file (PK being the first 2 chars) | ||
| if ( | ||
| (this.#myDB.productCode != 2 && this.#myDB.dbYear >= 21) || | ||
| (this.#myDB.dbType == 80 && this.#myDB.dbColumn == 75) | ||
| ) { | ||
| // only BINs from Jan 2021 onwards have this byte set | ||
| throw new Error(MSG_INVALID_BIN); | ||
| } | ||
| if (this.#myDB.indexBaseAddress > 0) { | ||
| this.#myDB.indexed = 1; | ||
| } | ||
| if (this.#myDB.dbCountIPV6 > 0 && this.#myDB.indexBaseAddressIPV6 > 0) { | ||
| this.#myDB.indexedIPV6 = 1; | ||
| } | ||
| this.#ipV4ColumnSize = this.#myDB.dbColumn << 2; // 4 bytes each column | ||
| this.#ipV6ColumnSize = 16 + ((this.#myDB.dbColumn - 1) << 2); // 4 bytes each column, except IPFrom column which is 16 bytes | ||
| let dbt = this.#myDB.dbType; | ||
| this.#countryPositionOffset = | ||
| COUNTRY_POSITION[dbt] != 0 ? (COUNTRY_POSITION[dbt] - 2) << 2 : 0; | ||
| this.#regionPositionOffset = | ||
| REGION_POSITION[dbt] != 0 ? (REGION_POSITION[dbt] - 2) << 2 : 0; | ||
| this.#cityPositionOffset = | ||
| CITY_POSITION[dbt] != 0 ? (CITY_POSITION[dbt] - 2) << 2 : 0; | ||
| this.#ispPositionOffset = | ||
| ISP_POSITION[dbt] != 0 ? (ISP_POSITION[dbt] - 2) << 2 : 0; | ||
| this.#proxyTypePositionOffset = | ||
| PROXY_TYPE_POSITION[dbt] != 0 | ||
| ? (PROXY_TYPE_POSITION[dbt] - 2) << 2 | ||
| : 0; | ||
| this.#domainPositionOffset = | ||
| DOMAIN_POSITION[dbt] != 0 ? (DOMAIN_POSITION[dbt] - 2) << 2 : 0; | ||
| this.#usageTypePositionOffset = | ||
| USAGE_TYPE_POSITION[dbt] != 0 | ||
| ? (USAGE_TYPE_POSITION[dbt] - 2) << 2 | ||
| : 0; | ||
| this.#asnPositionOffset = | ||
| ASN_POSITION[dbt] != 0 ? (ASN_POSITION[dbt] - 2) << 2 : 0; | ||
| this.#asPositionOffset = | ||
| AS_POSITION[dbt] != 0 ? (AS_POSITION[dbt] - 2) << 2 : 0; | ||
| this.#lastSeenPositionOffset = | ||
| LAST_SEEN_POSITION[dbt] != 0 ? (LAST_SEEN_POSITION[dbt] - 2) << 2 : 0; | ||
| this.#threatPositionOffset = | ||
| THREAT_POSITION[dbt] != 0 ? (THREAT_POSITION[dbt] - 2) << 2 : 0; | ||
| this.#providerPositionOffset = | ||
| PROVIDER_POSITION[dbt] != 0 ? (PROVIDER_POSITION[dbt] - 2) << 2 : 0; | ||
| this.#countryEnabled = COUNTRY_POSITION[dbt] != 0 ? 1 : 0; | ||
| this.#regionEnabled = REGION_POSITION[dbt] != 0 ? 1 : 0; | ||
| this.#cityEnabled = CITY_POSITION[dbt] != 0 ? 1 : 0; | ||
| this.#ispEnabled = ISP_POSITION[dbt] != 0 ? 1 : 0; | ||
| this.#proxyTypeEnabled = PROXY_TYPE_POSITION[dbt] != 0 ? 1 : 0; | ||
| this.#domainEnabled = DOMAIN_POSITION[dbt] != 0 ? 1 : 0; | ||
| this.#usageTypeEnabled = USAGE_TYPE_POSITION[dbt] != 0 ? 1 : 0; | ||
| this.#asnEnabled = ASN_POSITION[dbt] != 0 ? 1 : 0; | ||
| this.#asEnabled = AS_POSITION[dbt] != 0 ? 1 : 0; | ||
| this.#lastSeenEnabled = LAST_SEEN_POSITION[dbt] != 0 ? 1 : 0; | ||
| this.#threatEnabled = THREAT_POSITION[dbt] != 0 ? 1 : 0; | ||
| this.#providerEnabled = PROVIDER_POSITION[dbt] != 0 ? 1 : 0; | ||
| if (this.#myDB.indexed == 1) { | ||
| len = MAX_INDEX; | ||
| if (this.#myDB.indexedIPV6 == 1) { | ||
| len += MAX_INDEX; | ||
| } | ||
| len *= 8; // 4 bytes for both From/To | ||
| row = await this.readRowAsync(len, this.#myDB.indexBaseAddress); | ||
| let pointer = 0; | ||
| for (let x = 0; x < MAX_INDEX; x++) { | ||
| this.#indexArrayIPV4[x] = Array(2); | ||
| this.#indexArrayIPV4[x][0] = this.read32Row(pointer, row); | ||
| this.#indexArrayIPV4[x][1] = this.read32Row(pointer + 4, row); | ||
| pointer += 8; | ||
| } | ||
| if (this.#myDB.indexedIPV6 == 1) { | ||
| for (let x = 0; x < MAX_INDEX; x++) { | ||
| this.#indexArrayIPV6[x] = Array(2); | ||
| this.#indexArrayIPV6[x][0] = this.read32Row(pointer, row); | ||
| this.#indexArrayIPV6[x][1] = this.read32Row(pointer + 4, row); | ||
| pointer += 8; | ||
| } | ||
| } | ||
| } | ||
| loadOK = true; | ||
| } | ||
| } catch (err) { | ||
| // do nothing for now | ||
| } | ||
| return loadOK; | ||
| } | ||
| // Initialize the module with the path to the IP2Proxy BIN file | ||
@@ -379,3 +540,19 @@ open(binPath) { | ||
| // Reset everything | ||
| // Initialize the module with the path to the IP2Proxy BIN file async | ||
| async openAsync(binPath) { | ||
| if (this.#myDB.dbType == 0) { | ||
| this.#binFile = binPath; | ||
| if (!(await this.loadBinAsync())) { | ||
| // problems reading BIN | ||
| return -1; | ||
| } else { | ||
| return 0; | ||
| } | ||
| } else { | ||
| return 0; | ||
| } | ||
| } | ||
| // Reset everything (do not use in async case due to race conditions) | ||
| close() { | ||
@@ -626,2 +803,224 @@ try { | ||
| // Search BIN for the data async | ||
| async proxyQueryDataAsync(myIP, ipType, data, mode) { | ||
| let MAX_IP_RANGE; | ||
| let low; | ||
| let mid; | ||
| let high; | ||
| let countryPosition; | ||
| let baseAddress; | ||
| let columnSize; | ||
| let ipNumber; | ||
| let indexAddress; | ||
| let rowOffset; | ||
| let rowOffset2; | ||
| let ipFrom; | ||
| let ipTo; | ||
| let firstCol = 4; // IP From is 4 bytes | ||
| let row; | ||
| let fullRow; | ||
| if (ipType == 4) { | ||
| MAX_IP_RANGE = MAX_IPV4_RANGE; | ||
| high = this.#myDB.dbCount; | ||
| baseAddress = this.#myDB.baseAddress; | ||
| columnSize = this.#ipV4ColumnSize; | ||
| ipNumber = dot2Num(myIP); | ||
| if (this.#myDB.indexed == 1) { | ||
| indexAddress = ipNumber >>> 16; | ||
| low = this.#indexArrayIPV4[indexAddress][0]; | ||
| high = this.#indexArrayIPV4[indexAddress][1]; | ||
| } | ||
| } else if (ipType == 6) { | ||
| MAX_IP_RANGE = MAX_IPV6_RANGE; | ||
| high = this.#myDB.dbCountIPV6; | ||
| baseAddress = this.#myDB.baseAddressIPV6; | ||
| columnSize = this.#ipV6ColumnSize; | ||
| ipNumber = ip2No(myIP); | ||
| if ( | ||
| (ipNumber >= FROM_6TO4 && ipNumber <= TO_6TO4) || | ||
| (ipNumber >= FROM_TEREDO && ipNumber <= TO_TEREDO) | ||
| ) { | ||
| ipType = 4; | ||
| MAX_IP_RANGE = MAX_IPV4_RANGE; | ||
| high = this.#myDB.dbCount; | ||
| baseAddress = this.#myDB.baseAddress; | ||
| columnSize = this.#ipV4ColumnSize; | ||
| if (ipNumber >= FROM_6TO4 && ipNumber <= TO_6TO4) { | ||
| ipNumber = Number((ipNumber >> BigInt(80)) & LAST_32_BITS); | ||
| } else { | ||
| ipNumber = Number(~ipNumber & LAST_32_BITS); | ||
| } | ||
| if (this.#myDB.indexed == 1) { | ||
| indexAddress = ipNumber >>> 16; | ||
| low = this.#indexArrayIPV4[indexAddress][0]; | ||
| high = this.#indexArrayIPV4[indexAddress][1]; | ||
| } | ||
| } else { | ||
| firstCol = 16; // IPv6 is 16 bytes | ||
| if (this.#myDB.indexedIPV6 == 1) { | ||
| indexAddress = Number(ipNumber >> BigInt(112)); | ||
| low = this.#indexArrayIPV6[indexAddress][0]; | ||
| high = this.#indexArrayIPV6[indexAddress][1]; | ||
| } | ||
| } | ||
| } | ||
| data.ip = myIP; | ||
| ipNumber = BigInt(ipNumber); | ||
| if (ipNumber >= MAX_IP_RANGE) { | ||
| ipNumber = MAX_IP_RANGE - BigInt(1); | ||
| } | ||
| data.ipNo = ipNumber.toString(); | ||
| while (low <= high) { | ||
| mid = Math.trunc((low + high) / 2); | ||
| rowOffset = baseAddress + mid * columnSize; | ||
| rowOffset2 = rowOffset + columnSize; | ||
| // reading IP From + whole row + next IP From | ||
| fullRow = await this.readRowAsync(columnSize + firstCol, rowOffset); | ||
| ipFrom = this.read32Or128Row(0, fullRow, firstCol); | ||
| ipTo = this.read32Or128Row(columnSize, fullRow, firstCol); | ||
| ipFrom = BigInt(ipFrom); | ||
| ipTo = BigInt(ipTo); | ||
| if (ipFrom <= ipNumber && ipTo > ipNumber) { | ||
| loadMesg(data, MSG_NOT_SUPPORTED); // load default message | ||
| let rowLen = columnSize - firstCol; | ||
| row = fullRow.subarray(firstCol, firstCol + rowLen); // extract the actual row data | ||
| if (this.#proxyTypeEnabled) { | ||
| if ( | ||
| mode == MODES.ALL || | ||
| mode == MODES.PROXY_TYPE || | ||
| mode == MODES.IS_PROXY | ||
| ) { | ||
| data.proxyType = await this.readStrAsync( | ||
| this.read32Row(this.#proxyTypePositionOffset, row) | ||
| ); | ||
| } | ||
| } | ||
| if (this.#countryEnabled) { | ||
| if ( | ||
| mode == MODES.ALL || | ||
| mode == MODES.COUNTRY_SHORT || | ||
| mode == MODES.COUNTRY_LONG || | ||
| mode == MODES.IS_PROXY | ||
| ) { | ||
| countryPosition = this.read32Row(this.#countryPositionOffset, row); | ||
| } | ||
| if ( | ||
| mode == MODES.ALL || | ||
| mode == MODES.COUNTRY_SHORT || | ||
| mode == MODES.IS_PROXY | ||
| ) { | ||
| data.countryShort = await this.readStrAsync(countryPosition); | ||
| } | ||
| if (mode == MODES.ALL || mode == MODES.COUNTRY_LONG) { | ||
| data.countryLong = await this.readStrAsync(countryPosition + 3); | ||
| } | ||
| } | ||
| if (this.#regionEnabled) { | ||
| if (mode == MODES.ALL || mode == MODES.REGION) { | ||
| data.region = await this.readStrAsync( | ||
| this.read32Row(this.#regionPositionOffset, row) | ||
| ); | ||
| } | ||
| } | ||
| if (this.#cityEnabled) { | ||
| if (mode == MODES.ALL || mode == MODES.CITY) { | ||
| data.city = await this.readStrAsync( | ||
| this.read32Row(this.#cityPositionOffset, row) | ||
| ); | ||
| } | ||
| } | ||
| if (this.#ispEnabled) { | ||
| if (mode == MODES.ALL || mode == MODES.ISP) { | ||
| data.isp = await this.readStrAsync( | ||
| this.read32Row(this.#ispPositionOffset, row) | ||
| ); | ||
| } | ||
| } | ||
| if (this.#domainEnabled) { | ||
| if (mode == MODES.ALL || mode == MODES.DOMAIN) { | ||
| data.domain = await this.readStrAsync( | ||
| this.read32Row(this.#domainPositionOffset, row) | ||
| ); | ||
| } | ||
| } | ||
| if (this.#usageTypeEnabled) { | ||
| if (mode == MODES.ALL || mode == MODES.USAGE_TYPE) { | ||
| data.usageType = await this.readStrAsync( | ||
| this.read32Row(this.#usageTypePositionOffset, row) | ||
| ); | ||
| } | ||
| } | ||
| if (this.#asnEnabled) { | ||
| if (mode == MODES.ALL || mode == MODES.ASN) { | ||
| data.asn = await this.readStrAsync( | ||
| this.read32Row(this.#asnPositionOffset, row) | ||
| ); | ||
| } | ||
| } | ||
| if (this.#asEnabled) { | ||
| if (mode == MODES.ALL || mode == MODES.AS) { | ||
| data.as = await this.readStrAsync( | ||
| this.read32Row(this.#asPositionOffset, row) | ||
| ); | ||
| } | ||
| } | ||
| if (this.#lastSeenEnabled) { | ||
| if (mode == MODES.ALL || mode == MODES.LAST_SEEN) { | ||
| data.lastSeen = await this.readStrAsync( | ||
| this.read32Row(this.#lastSeenPositionOffset, row) | ||
| ); | ||
| } | ||
| } | ||
| if (this.#threatEnabled) { | ||
| if (mode == MODES.ALL || mode == MODES.THREAT) { | ||
| data.threat = await this.readStrAsync( | ||
| this.read32Row(this.#threatPositionOffset, row) | ||
| ); | ||
| } | ||
| } | ||
| if (this.#providerEnabled) { | ||
| if (mode == MODES.ALL || mode == MODES.PROVIDER) { | ||
| data.provider = await this.readStrAsync( | ||
| this.read32Row(this.#providerPositionOffset, row) | ||
| ); | ||
| } | ||
| } | ||
| if (data.countryShort == "-" || data.proxyType == "-") { | ||
| data.isProxy = 0; | ||
| } else { | ||
| if (data.proxyType == "DCH" || data.proxyType == "SES") { | ||
| data.isProxy = 2; | ||
| } else { | ||
| data.isProxy = 1; | ||
| } | ||
| } | ||
| return; | ||
| } else { | ||
| if (ipFrom > ipNumber) { | ||
| high = mid - 1; | ||
| } else { | ||
| low = mid + 1; | ||
| } | ||
| } | ||
| } | ||
| loadMesg(data, MSG_INVALID_IP); | ||
| } | ||
| // Query IP for proxy info | ||
@@ -678,2 +1077,53 @@ proxyQuery(myIP, mode) { | ||
| // Query IP for proxy info async | ||
| async proxyQueryAsync(myIP, mode) { | ||
| let data = { | ||
| ip: "?", | ||
| ipNo: "?", | ||
| isProxy: -1, | ||
| proxyType: "?", | ||
| countryShort: "?", | ||
| countryLong: "?", | ||
| region: "?", | ||
| city: "?", | ||
| isp: "?", | ||
| domain: "?", | ||
| usageType: "?", | ||
| asn: "?", | ||
| as: "?", | ||
| lastSeen: "?", | ||
| threat: "?", | ||
| provider: "?", | ||
| }; | ||
| if (REGEX_IPV4_1_MATCH.test(myIP)) { | ||
| myIP = myIP.replace(REGEX_IPV4_1_REPLACE, ""); | ||
| } else if (REGEX_IPV4_2_MATCH.test(myIP)) { | ||
| myIP = myIP.replace(REGEX_IPV4_2_REPLACE, ""); | ||
| } | ||
| let ipType = net.isIP(myIP); | ||
| if (ipType == 0) { | ||
| loadMesg(data, MSG_INVALID_IP); | ||
| return data; | ||
| } else if ( | ||
| !this.#binFile || | ||
| this.#binFile == "" || | ||
| !fs.existsSync(this.#binFile) // don't use async equivalent to test, not recommended by Node.js as it leads to race conditions | ||
| ) { | ||
| loadMesg(data, MSG_MISSING_FILE); | ||
| return data; | ||
| } else if (this.#myDB.dbType == 0) { | ||
| loadMesg(data, MSG_MISSING_FILE); | ||
| return data; | ||
| } else if (ipType == 6 && this.#myDB.dbCountIPV6 == 0) { | ||
| loadMesg(data, MSG_IPV6_UNSUPPORTED); | ||
| return data; | ||
| } else { | ||
| await this.proxyQueryDataAsync(myIP, ipType, data, mode); | ||
| return data; | ||
| } | ||
| } | ||
| // Return the module version | ||
@@ -711,2 +1161,12 @@ getModuleVersion() { | ||
| // Return an integer to state if is proxy async | ||
| async isProxyAsync(myIP) { | ||
| // -1 is error | ||
| // 0 is not a proxy | ||
| // 1 is proxy except DCH and SES | ||
| // 2 is proxy and DCH or SES | ||
| let data = await this.proxyQueryAsync(myIP, MODES.IS_PROXY); | ||
| return data.isProxy; | ||
| } | ||
| // Return a string for the country code | ||
@@ -718,2 +1178,8 @@ getCountryShort(myIP) { | ||
| // Return a string for the country code async | ||
| async getCountryShortAsync(myIP) { | ||
| let data = await this.proxyQueryAsync(myIP, MODES.COUNTRY_SHORT); | ||
| return data.countryShort; | ||
| } | ||
| // Return a string for the country name | ||
@@ -725,2 +1191,8 @@ getCountryLong(myIP) { | ||
| // Return a string for the country name async | ||
| async getCountryLongAsync(myIP) { | ||
| let data = await this.proxyQueryAsync(myIP, MODES.COUNTRY_LONG); | ||
| return data.countryLong; | ||
| } | ||
| // Return a string for the region name | ||
@@ -732,2 +1204,8 @@ getRegion(myIP) { | ||
| // Return a string for the region name async | ||
| async getRegionAsync(myIP) { | ||
| let data = await this.proxyQueryAsync(myIP, MODES.REGION); | ||
| return data.region; | ||
| } | ||
| // Return a string for the city name | ||
@@ -739,2 +1217,8 @@ getCity(myIP) { | ||
| // Return a string for the city name async | ||
| async getCityAsync(myIP) { | ||
| let data = await this.proxyQueryAsync(myIP, MODES.CITY); | ||
| return data.city; | ||
| } | ||
| // Return a string for the ISP name | ||
@@ -746,2 +1230,8 @@ getISP(myIP) { | ||
| // Return a string for the ISP name async | ||
| async getISPAsync(myIP) { | ||
| let data = await this.proxyQueryAsync(myIP, MODES.ISP); | ||
| return data.isp; | ||
| } | ||
| // Return a string for the proxy type | ||
@@ -753,2 +1243,8 @@ getProxyType(myIP) { | ||
| // Return a string for the proxy type async | ||
| async getProxyTypeAsync(myIP) { | ||
| let data = await this.proxyQueryAsync(myIP, MODES.PROXY_TYPE); | ||
| return data.proxyType; | ||
| } | ||
| // Return a string for the domain | ||
@@ -760,2 +1256,8 @@ getDomain(myIP) { | ||
| // Return a string for the domain async | ||
| async getDomainAsync(myIP) { | ||
| let data = await this.proxyQueryAsync(myIP, MODES.DOMAIN); | ||
| return data.domain; | ||
| } | ||
| // Return a string for the usage type | ||
@@ -767,2 +1269,8 @@ getUsageType(myIP) { | ||
| // Return a string for the usage type async | ||
| async getUsageTypeAsync(myIP) { | ||
| let data = await this.proxyQueryAsync(myIP, MODES.USAGE_TYPE); | ||
| return data.usageType; | ||
| } | ||
| // Return a string for the ASN | ||
@@ -774,2 +1282,8 @@ getASN(myIP) { | ||
| // Return a string for the ASN async | ||
| async getASNAsync(myIP) { | ||
| let data = await this.proxyQueryAsync(myIP, MODES.ASN); | ||
| return data.asn; | ||
| } | ||
| // Return a string for the AS | ||
@@ -781,2 +1295,8 @@ getAS(myIP) { | ||
| // Return a string for the AS async | ||
| async getASAsync(myIP) { | ||
| let data = await this.proxyQueryAsync(myIP, MODES.AS); | ||
| return data.as; | ||
| } | ||
| // Return a string for the last seen | ||
@@ -788,2 +1308,8 @@ getLastSeen(myIP) { | ||
| // Return a string for the last seen async | ||
| async getLastSeenAsync(myIP) { | ||
| let data = await this.proxyQueryAsync(myIP, MODES.LAST_SEEN); | ||
| return data.lastSeen; | ||
| } | ||
| // Return a string for the threat | ||
@@ -795,2 +1321,8 @@ getThreat(myIP) { | ||
| // Return a string for the threat async | ||
| async getThreatAsync(myIP) { | ||
| let data = await this.proxyQueryAsync(myIP, MODES.THREAT); | ||
| return data.threat; | ||
| } | ||
| // Return a string for the provider | ||
@@ -802,2 +1334,8 @@ getProvider(myIP) { | ||
| // Return a string for the provider async | ||
| async getProviderAsync(myIP) { | ||
| let data = await this.proxyQueryAsync(myIP, MODES.PROVIDER); | ||
| return data.provider; | ||
| } | ||
| // Return all results | ||
@@ -808,2 +1346,8 @@ getAll(myIP) { | ||
| } | ||
| // Return all results async | ||
| async getAllAsync(myIP) { | ||
| let data = await this.proxyQueryAsync(myIP, MODES.ALL); | ||
| return data; | ||
| } | ||
| } | ||
@@ -810,0 +1354,0 @@ |
Network access
Supply chain riskThis module accesses the network.
Found 2 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 2 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
71258
58.66%1848
56.88%231
27.62%3
50%