@@ -4,7 +4,7 @@ var bigInt = require("big-integer");
44var https = require ( "https" ) ;
55
66// For BIN queries
7- const VERSION = "4.1 .0" ;
7+ const VERSION = "4.2 .0" ;
88const MAX_INDEX = 65536 ;
99const COUNTRY_POSITION = [ 0 , 2 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 ] ;
1010const REGION_POSITION = [ 0 , 0 , 0 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 ] ;
@@ -105,6 +105,8 @@ class IP2Proxy {
105105 baseAddress : 0 ,
106106 dbCountIPV6 : 0 ,
107107 baseAddressIPV6 : 0 ,
108+ indexed : 0 ,
109+ indexedIPV6 : 0 ,
108110 indexBaseAddress : 0 ,
109111 indexBaseAddressIPV6 : 0 ,
110112 productCode : 0 ,
@@ -168,6 +170,11 @@ class IP2Proxy {
168170 return this . readBin ( readBytes , position - 1 , "int8" ) ;
169171 }
170172
173+ // Read 8 bits integer in the buffer
174+ read8Row ( position , buffer ) {
175+ return buffer . readUInt8 ( position ) ;
176+ }
177+
171178 // Read 32 bits integer in the database
172179 read32 ( position , isBigInt ) {
173180 let readBytes = 4 ;
@@ -179,6 +186,29 @@ class IP2Proxy {
179186 return buffer . readUInt32LE ( position ) ;
180187 }
181188
189+ // Read 128 bits integer in the buffer
190+ read128Row ( position , buffer ) {
191+ let myBig = bigInt ( ) ; // zero
192+ let bitShift = 8 ;
193+ for ( let x = 0 ; x < 16 ; x ++ ) {
194+ let pos = position + x ;
195+ myBig = myBig . add (
196+ bigInt ( this . read8Row ( pos , buffer ) ) . shiftLeft ( bitShift * x )
197+ ) ;
198+ }
199+ return myBig ;
200+ }
201+
202+ read32Or128Row ( position , buffer , len ) {
203+ if ( len == 4 ) {
204+ return this . read32Row ( position , buffer ) ;
205+ } else if ( len == 16 ) {
206+ return this . read128Row ( position , buffer ) ;
207+ } else {
208+ return 0 ;
209+ }
210+ }
211+
182212 read32Or128 ( position , ipType ) {
183213 if ( ipType == 4 ) {
184214 return this . read32 ( position , true ) ;
@@ -197,12 +227,10 @@ class IP2Proxy {
197227
198228 // Read strings in the database
199229 readStr ( position ) {
200- let readBytes = 1 ;
201- return this . readBin (
202- this . readBin ( readBytes , position , "int8" ) ,
203- position + 1 ,
204- "str"
205- ) ;
230+ let readBytes = 256 ; // max size of string field + 1 byte for the length
231+ let row = this . readRow ( readBytes , position + 1 ) ;
232+ let len = this . read8Row ( 0 , row ) ;
233+ return row . toString ( "utf8" , 1 , len + 1 ) ;
206234 }
207235
208236 // Read metadata and indexes
@@ -213,21 +241,24 @@ class IP2Proxy {
213241 if ( this . #binFile && this . #binFile != "" ) {
214242 this . #fd = fs . openSync ( this . #binFile, "r" ) ;
215243
216- this . #myDB. dbType = this . read8 ( 1 ) ;
217- this . #myDB. dbColumn = this . read8 ( 2 ) ;
218- this . #myDB. dbYear = this . read8 ( 3 ) ;
219- this . #myDB. dbMonth = this . read8 ( 4 ) ;
220- this . #myDB. dbDay = this . read8 ( 5 ) ;
221- this . #myDB. dbCount = this . read32 ( 6 ) ;
222- this . #myDB. baseAddress = this . read32 ( 10 ) ;
223- this . #myDB. dbCountIPV6 = this . read32 ( 14 ) ;
224- this . #myDB. baseAddressIPV6 = this . read32 ( 18 ) ;
225- this . #myDB. indexBaseAddress = this . read32 ( 22 ) ;
226- this . #myDB. indexBaseAddressIPV6 = this . read32 ( 26 ) ;
227- this . #myDB. productCode = this . read8 ( 30 ) ;
244+ let len = 64 ; // 64-byte header
245+ let row = this . readRow ( len , 1 ) ;
246+
247+ this . #myDB. dbType = this . read8Row ( 0 , row ) ;
248+ this . #myDB. dbColumn = this . read8Row ( 1 , row ) ;
249+ this . #myDB. dbYear = this . read8Row ( 2 , row ) ;
250+ this . #myDB. dbMonth = this . read8Row ( 3 , row ) ;
251+ this . #myDB. dbDay = this . read8Row ( 4 , row ) ;
252+ this . #myDB. dbCount = this . read32Row ( 5 , row ) ;
253+ this . #myDB. baseAddress = this . read32Row ( 9 , row ) ;
254+ this . #myDB. dbCountIPV6 = this . read32Row ( 13 , row ) ;
255+ this . #myDB. baseAddressIPV6 = this . read32Row ( 17 , row ) ;
256+ this . #myDB. indexBaseAddress = this . read32Row ( 21 , row ) ;
257+ this . #myDB. indexBaseAddressIPV6 = this . read32Row ( 25 , row ) ;
258+ this . #myDB. productCode = this . read8Row ( 29 , row ) ;
228259 // below 2 fields just read for now, not being used yet
229- this . #myDB. productType = this . read8 ( 31 ) ;
230- this . #myDB. fileSize = this . read32 ( 32 ) ;
260+ this . #myDB. productType = this . read8Row ( 30 , row ) ;
261+ this . #myDB. fileSize = this . read32Row ( 31 , row ) ;
231262
232263 // check if is correct BIN (should be 2 for IP2Proxy BIN file), also checking for zipped file (PK being the first 2 chars)
233264 if (
@@ -238,6 +269,14 @@ class IP2Proxy {
238269 throw new Error ( MSG_INVALID_BIN ) ;
239270 }
240271
272+ if ( this . #myDB. indexBaseAddress > 0 ) {
273+ this . #myDB. indexed = 1 ;
274+ }
275+
276+ if ( this . #myDB. dbCountIPV6 > 0 && this . #myDB. indexBaseAddressIPV6 > 0 ) {
277+ this . #myDB. indexedIPV6 = 1 ;
278+ }
279+
241280 this . #ipV4ColumnSize = this . #myDB. dbColumn << 2 ; // 4 bytes each column
242281 this . #ipV6ColumnSize = 16 + ( ( this . #myDB. dbColumn - 1 ) << 2 ) ; // 4 bytes each column, except IPFrom column which is 16 bytes
243282
@@ -285,22 +324,32 @@ class IP2Proxy {
285324 this . #threatEnabled = THREAT_POSITION [ dbt ] != 0 ? 1 : 0 ;
286325 this . #providerEnabled = PROVIDER_POSITION [ dbt ] != 0 ? 1 : 0 ;
287326
288- let pointer = this . #myDB. indexBaseAddress ;
327+ if ( this . #myDB. indexed == 1 ) {
328+ len = MAX_INDEX ;
329+ if ( this . #myDB. indexedIPV6 == 1 ) {
330+ len += MAX_INDEX ;
331+ }
332+ len *= 8 ; // 4 bytes for both From/To
289333
290- for ( let x = 0 ; x < MAX_INDEX ; x ++ ) {
291- this . #indexArrayIPV4[ x ] = Array ( 2 ) ;
292- this . #indexArrayIPV4[ x ] [ 0 ] = this . read32 ( pointer ) ;
293- this . #indexArrayIPV4[ x ] [ 1 ] = this . read32 ( pointer + 4 ) ;
294- pointer += 8 ;
295- }
334+ row = this . readRow ( len , this . #myDB. indexBaseAddress ) ;
335+
336+ let pointer = 0 ;
296337
297- if ( this . #myDB. indexBaseAddressIPV6 > 0 ) {
298338 for ( let x = 0 ; x < MAX_INDEX ; x ++ ) {
299- this . #indexArrayIPV6 [ x ] = Array ( 2 ) ;
300- this . #indexArrayIPV6 [ x ] [ 0 ] = this . read32 ( pointer ) ;
301- this . #indexArrayIPV6 [ x ] [ 1 ] = this . read32 ( pointer + 4 ) ;
339+ this . #indexArrayIPV4 [ x ] = Array ( 2 ) ;
340+ this . #indexArrayIPV4 [ x ] [ 0 ] = this . read32Row ( pointer , row ) ;
341+ this . #indexArrayIPV4 [ x ] [ 1 ] = this . read32Row ( pointer + 4 , row ) ;
302342 pointer += 8 ;
303343 }
344+
345+ if ( this . #myDB. indexedIPV6 == 1 ) {
346+ for ( let x = 0 ; x < MAX_INDEX ; x ++ ) {
347+ this . #indexArrayIPV6[ x ] = Array ( 2 ) ;
348+ this . #indexArrayIPV6[ x ] [ 0 ] = this . read32Row ( pointer , row ) ;
349+ this . #indexArrayIPV6[ x ] [ 1 ] = this . read32Row ( pointer + 4 , row ) ;
350+ pointer += 8 ;
351+ }
352+ }
304353 }
305354 loadOK = true ;
306355 }
@@ -338,6 +387,8 @@ class IP2Proxy {
338387 this . #myDB. dbYear = 0 ;
339388 this . #myDB. baseAddressIPV6 = 0 ;
340389 this . #myDB. dbCountIPV6 = 0 ;
390+ this . #myDB. indexed = 0 ;
391+ this . #myDB. indexedIPV6 = 0 ;
341392 this . #myDB. indexBaseAddress = 0 ;
342393 this . #myDB. indexBaseAddressIPV6 = 0 ;
343394 this . #myDB. productCode = 0 ;
@@ -365,8 +416,9 @@ class IP2Proxy {
365416 let rowOffset2 ;
366417 let ipFrom ;
367418 let ipTo ;
368- let firstCol ;
419+ let firstCol = 4 ; // IP From is 4 bytes
369420 let row ;
421+ let fullRow ;
370422
371423 if ( ipType == 4 ) {
372424 MAX_IP_RANGE = MAX_IPV4_RANGE ;
@@ -375,9 +427,11 @@ class IP2Proxy {
375427 columnSize = this . #ipV4ColumnSize;
376428 ipNumber = dot2Num ( myIP ) ;
377429
378- indexAddress = ipNumber >>> 16 ;
379- low = this . #indexArrayIPV4[ indexAddress ] [ 0 ] ;
380- high = this . #indexArrayIPV4[ indexAddress ] [ 1 ] ;
430+ if ( this . #myDB. indexed == 1 ) {
431+ indexAddress = ipNumber >>> 16 ;
432+ low = this . #indexArrayIPV4[ indexAddress ] [ 0 ] ;
433+ high = this . #indexArrayIPV4[ indexAddress ] [ 1 ] ;
434+ }
381435 } else if ( ipType == 6 ) {
382436 MAX_IP_RANGE = MAX_IPV6_RANGE ;
383437 high = this . #myDB. dbCountIPV6 ;
@@ -400,13 +454,18 @@ class IP2Proxy {
400454 } else {
401455 ipNumber = ipNumber . not ( ) . and ( LAST_32_BITS ) . toJSNumber ( ) ;
402456 }
403- indexAddress = ipNumber >>> 16 ;
404- low = this . #indexArrayIPV4[ indexAddress ] [ 0 ] ;
405- high = this . #indexArrayIPV4[ indexAddress ] [ 1 ] ;
457+ if ( this . #myDB. indexed == 1 ) {
458+ indexAddress = ipNumber >>> 16 ;
459+ low = this . #indexArrayIPV4[ indexAddress ] [ 0 ] ;
460+ high = this . #indexArrayIPV4[ indexAddress ] [ 1 ] ;
461+ }
406462 } else {
407- indexAddress = ipNumber . shiftRight ( 112 ) . toJSNumber ( ) ;
408- low = this . #indexArrayIPV6[ indexAddress ] [ 0 ] ;
409- high = this . #indexArrayIPV6[ indexAddress ] [ 1 ] ;
463+ firstCol = 16 ; // IPv6 is 16 bytes
464+ if ( this . #myDB. indexedIPV6 == 1 ) {
465+ indexAddress = ipNumber . shiftRight ( 112 ) . toJSNumber ( ) ;
466+ low = this . #indexArrayIPV6[ indexAddress ] [ 0 ] ;
467+ high = this . #indexArrayIPV6[ indexAddress ] [ 1 ] ;
468+ }
410469 }
411470 }
412471
@@ -420,25 +479,23 @@ class IP2Proxy {
420479 data . ipNo = ipNumber . toString ( ) ;
421480
422481 while ( low <= high ) {
423- mid = parseInt ( ( low + high ) / 2 ) ;
482+ mid = Math . trunc ( ( low + high ) / 2 ) ;
424483 rowOffset = baseAddress + mid * columnSize ;
425484 rowOffset2 = rowOffset + columnSize ;
426485
427- ipFrom = this . read32Or128 ( rowOffset , ipType ) ;
428- ipTo = this . read32Or128 ( rowOffset2 , ipType ) ;
486+ // reading IP From + whole row + next IP From
487+ fullRow = this . readRow ( columnSize + firstCol , rowOffset ) ;
488+ ipFrom = this . read32Or128Row ( 0 , fullRow , firstCol ) ;
489+ ipTo = this . read32Or128Row ( columnSize , fullRow , firstCol ) ;
429490
430491 ipFrom = bigInt ( ipFrom ) ;
431492 ipTo = bigInt ( ipTo ) ;
432493
433494 if ( ipFrom . leq ( ipNumber ) && ipTo . gt ( ipNumber ) ) {
434495 loadMesg ( data , MSG_NOT_SUPPORTED ) ; // load default message
435496
436- firstCol = 4 ;
437- if ( ipType == 6 ) {
438- firstCol = 16 ;
439- }
440-
441- row = this . readRow ( columnSize - firstCol , rowOffset + firstCol ) ;
497+ let rowLen = columnSize - firstCol ;
498+ row = fullRow . subarray ( firstCol , firstCol + rowLen ) ; // extract the actual row data
442499
443500 if ( this . #proxyTypeEnabled) {
444501 if (
0 commit comments