@@ -4,7 +4,7 @@ var bigInt = require("big-integer");
44var https = require ( "https" ) ;
55
66// For BIN queries
7- const VERSION = "9.2 .0" ;
7+ const VERSION = "9.3 .0" ;
88const MAX_INDEX = 65536 ;
99const COUNTRY_POSITION = [
1010 0 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ,
@@ -269,6 +269,11 @@ class IP2Location {
269269 return this . readBin ( readBytes , position - 1 , "int8" ) ;
270270 }
271271
272+ // Read 8 bits integer in the buffer
273+ read8Row ( position , buffer ) {
274+ return buffer . readUInt8 ( position ) ;
275+ }
276+
272277 // Read 32 bits integer in the database
273278 read32 ( position , isBigInt ) {
274279 let readBytes = 4 ;
@@ -280,6 +285,29 @@ class IP2Location {
280285 return buffer . readUInt32LE ( position ) ;
281286 }
282287
288+ // Read 128 bits integer in the buffer
289+ read128Row ( position , buffer ) {
290+ let myBig = bigInt ( ) ; // zero
291+ let bitShift = 8 ;
292+ for ( let x = 0 ; x < 16 ; x ++ ) {
293+ let pos = position + x ;
294+ myBig = myBig . add (
295+ bigInt ( this . read8Row ( pos , buffer ) ) . shiftLeft ( bitShift * x )
296+ ) ;
297+ }
298+ return myBig ;
299+ }
300+
301+ read32Or128Row ( position , buffer , len ) {
302+ if ( len == 4 ) {
303+ return this . read32Row ( position , buffer ) ;
304+ } else if ( len == 16 ) {
305+ return this . read128Row ( position , buffer ) ;
306+ } else {
307+ return 0 ;
308+ }
309+ }
310+
283311 read32Or128 ( position , ipType ) {
284312 if ( ipType == 4 ) {
285313 return this . read32 ( position , true ) ;
@@ -303,12 +331,10 @@ class IP2Location {
303331
304332 // Read strings in the database
305333 readStr ( position ) {
306- let readBytes = 1 ;
307- return this . readBin (
308- this . readBin ( readBytes , position , "int8" ) ,
309- position + 1 ,
310- "str"
311- ) ;
334+ let readBytes = 256 ; // max size of string field + 1 byte for the length
335+ let row = this . readRow ( readBytes , position + 1 ) ;
336+ let len = this . read8Row ( 0 , row ) ;
337+ return row . toString ( "utf8" , 1 , len + 1 ) ;
312338 }
313339
314340 // Read metadata and indexes
@@ -319,21 +345,24 @@ class IP2Location {
319345 if ( this . #binFile && this . #binFile != "" ) {
320346 this . #fd = fs . openSync ( this . #binFile, "r" ) ;
321347
322- this . #myDB. dbType = this . read8 ( 1 ) ;
323- this . #myDB. dbColumn = this . read8 ( 2 ) ;
324- this . #myDB. dbYear = this . read8 ( 3 ) ;
325- this . #myDB. dbMonth = this . read8 ( 4 ) ;
326- this . #myDB. dbDay = this . read8 ( 5 ) ;
327- this . #myDB. dbCount = this . read32 ( 6 ) ;
328- this . #myDB. baseAddress = this . read32 ( 10 ) ;
329- this . #myDB. dbCountIPV6 = this . read32 ( 14 ) ;
330- this . #myDB. baseAddressIPV6 = this . read32 ( 18 ) ;
331- this . #myDB. indexBaseAddress = this . read32 ( 22 ) ;
332- this . #myDB. indexBaseAddressIPV6 = this . read32 ( 26 ) ;
333- this . #myDB. productCode = this . read8 ( 30 ) ;
348+ let len = 64 ; // 64-byte header
349+ let row = this . readRow ( len , 1 ) ;
350+
351+ this . #myDB. dbType = this . read8Row ( 0 , row ) ;
352+ this . #myDB. dbColumn = this . read8Row ( 1 , row ) ;
353+ this . #myDB. dbYear = this . read8Row ( 2 , row ) ;
354+ this . #myDB. dbMonth = this . read8Row ( 3 , row ) ;
355+ this . #myDB. dbDay = this . read8Row ( 4 , row ) ;
356+ this . #myDB. dbCount = this . read32Row ( 5 , row ) ;
357+ this . #myDB. baseAddress = this . read32Row ( 9 , row ) ;
358+ this . #myDB. dbCountIPV6 = this . read32Row ( 13 , row ) ;
359+ this . #myDB. baseAddressIPV6 = this . read32Row ( 17 , row ) ;
360+ this . #myDB. indexBaseAddress = this . read32Row ( 21 , row ) ;
361+ this . #myDB. indexBaseAddressIPV6 = this . read32Row ( 25 , row ) ;
362+ this . #myDB. productCode = this . read8Row ( 29 , row ) ;
334363 // below 2 fields just read for now, not being used yet
335- this . #myDB. productType = this . read8 ( 31 ) ;
336- this . #myDB. fileSize = this . read32 ( 32 ) ;
364+ this . #myDB. productType = this . read8Row ( 30 , row ) ;
365+ this . #myDB. fileSize = this . read32Row ( 31 , row ) ;
337366
338367 // check if is correct BIN (should be 1 for IP2Location BIN file), also checking for zipped file (PK being the first 2 chars)
339368 if (
@@ -434,20 +463,28 @@ class IP2Location {
434463 this . #categoryEnabled = CATEGORY_POSITION [ dbt ] != 0 ? 1 : 0 ;
435464
436465 if ( this . #myDB. indexed == 1 ) {
437- let pointer = this . #myDB. indexBaseAddress ;
466+ len = MAX_INDEX ;
467+ if ( this . #myDB. indexedIPV6 == 1 ) {
468+ len += MAX_INDEX ;
469+ }
470+ len *= 8 ; // 4 bytes for both From/To
471+
472+ row = this . readRow ( len , this . #myDB. indexBaseAddress ) ;
473+
474+ let pointer = 0 ;
438475
439476 for ( let x = 0 ; x < MAX_INDEX ; x ++ ) {
440477 this . #indexArrayIPV4[ x ] = Array ( 2 ) ;
441- this . #indexArrayIPV4[ x ] [ 0 ] = this . read32 ( pointer ) ;
442- this . #indexArrayIPV4[ x ] [ 1 ] = this . read32 ( pointer + 4 ) ;
478+ this . #indexArrayIPV4[ x ] [ 0 ] = this . read32Row ( pointer , row ) ;
479+ this . #indexArrayIPV4[ x ] [ 1 ] = this . read32Row ( pointer + 4 , row ) ;
443480 pointer += 8 ;
444481 }
445482
446- if ( this . #myDB. indexBaseAddressIPV6 > 0 ) {
483+ if ( this . #myDB. indexedIPV6 == 1 ) {
447484 for ( let x = 0 ; x < MAX_INDEX ; x ++ ) {
448485 this . #indexArrayIPV6[ x ] = Array ( 2 ) ;
449- this . #indexArrayIPV6[ x ] [ 0 ] = this . read32 ( pointer ) ;
450- this . #indexArrayIPV6[ x ] [ 1 ] = this . read32 ( pointer + 4 ) ;
486+ this . #indexArrayIPV6[ x ] [ 0 ] = this . read32Row ( pointer , row ) ;
487+ this . #indexArrayIPV6[ x ] [ 1 ] = this . read32Row ( pointer + 4 , row ) ;
451488 pointer += 8 ;
452489 }
453490 }
@@ -509,8 +546,9 @@ class IP2Location {
509546 let rowOffset2 ;
510547 let ipFrom ;
511548 let ipTo ;
512- let firstCol ;
549+ let firstCol = 4 ; // IP From is 4 bytes
513550 let row ;
551+ let fullRow ;
514552
515553 if ( ipType == 4 ) {
516554 MAX_IP_RANGE = MAX_IPV4_RANGE ;
@@ -519,9 +557,11 @@ class IP2Location {
519557 columnSize = this . #ipV4ColumnSize;
520558 ipNumber = dot2Num ( myIP ) ;
521559
522- indexAddress = ipNumber >>> 16 ;
523- low = this . #indexArrayIPV4[ indexAddress ] [ 0 ] ;
524- high = this . #indexArrayIPV4[ indexAddress ] [ 1 ] ;
560+ if ( this . #myDB. indexed == 1 ) {
561+ indexAddress = ipNumber >>> 16 ;
562+ low = this . #indexArrayIPV4[ indexAddress ] [ 0 ] ;
563+ high = this . #indexArrayIPV4[ indexAddress ] [ 1 ] ;
564+ }
525565 } else if ( ipType == 6 ) {
526566 MAX_IP_RANGE = MAX_IPV6_RANGE ;
527567 high = this . #myDB. dbCountIPV6 ;
@@ -544,16 +584,20 @@ class IP2Location {
544584 } else {
545585 ipNumber = ipNumber . not ( ) . and ( LAST_32_BITS ) . toJSNumber ( ) ;
546586 }
547- indexAddress = ipNumber >>> 16 ;
548- low = this . #indexArrayIPV4[ indexAddress ] [ 0 ] ;
549- high = this . #indexArrayIPV4[ indexAddress ] [ 1 ] ;
587+ if ( this . #myDB. indexed == 1 ) {
588+ indexAddress = ipNumber >>> 16 ;
589+ low = this . #indexArrayIPV4[ indexAddress ] [ 0 ] ;
590+ high = this . #indexArrayIPV4[ indexAddress ] [ 1 ] ;
591+ }
550592 } else {
551- indexAddress = ipNumber . shiftRight ( 112 ) . toJSNumber ( ) ;
552- low = this . #indexArrayIPV6[ indexAddress ] [ 0 ] ;
553- high = this . #indexArrayIPV6[ indexAddress ] [ 1 ] ;
593+ firstCol = 16 ; // IPv6 is 16 bytes
594+ if ( this . #myDB. indexedIPV6 == 1 ) {
595+ indexAddress = ipNumber . shiftRight ( 112 ) . toJSNumber ( ) ;
596+ low = this . #indexArrayIPV6[ indexAddress ] [ 0 ] ;
597+ high = this . #indexArrayIPV6[ indexAddress ] [ 1 ] ;
598+ }
554599 }
555600 }
556-
557601 data . ip = myIP ;
558602 ipNumber = bigInt ( ipNumber ) ;
559603
@@ -564,25 +608,23 @@ class IP2Location {
564608 data . ipNo = ipNumber . toString ( ) ;
565609
566610 while ( low <= high ) {
567- mid = parseInt ( ( low + high ) / 2 ) ;
611+ mid = Math . trunc ( ( low + high ) / 2 ) ;
568612 rowOffset = baseAddress + mid * columnSize ;
569613 rowOffset2 = rowOffset + columnSize ;
570614
571- ipFrom = this . read32Or128 ( rowOffset , ipType ) ;
572- ipTo = this . read32Or128 ( rowOffset2 , ipType ) ;
615+ // reading IP From + whole row + next IP From
616+ fullRow = this . readRow ( columnSize + firstCol , rowOffset ) ;
617+ ipFrom = this . read32Or128Row ( 0 , fullRow , firstCol ) ;
618+ ipTo = this . read32Or128Row ( columnSize , fullRow , firstCol ) ;
573619
574620 ipFrom = bigInt ( ipFrom ) ;
575621 ipTo = bigInt ( ipTo ) ;
576622
577623 if ( ipFrom . leq ( ipNumber ) && ipTo . gt ( ipNumber ) ) {
578624 loadMesg ( data , MSG_NOT_SUPPORTED ) ; // load default message
579625
580- firstCol = 4 ;
581- if ( ipType == 6 ) {
582- firstCol = 16 ;
583- }
584-
585- row = this . readRow ( columnSize - firstCol , rowOffset + firstCol ) ;
626+ let rowLen = columnSize - firstCol ;
627+ row = fullRow . subarray ( firstCol , firstCol + rowLen ) ; // extract the actual row data
586628
587629 if ( this . #countryEnabled) {
588630 if (
0 commit comments