@@ -7,9 +7,9 @@ package ip2proxy
77import (
88 "bytes"
99 "encoding/binary"
10+ "errors"
1011 "fmt"
1112 "io"
12- "math"
1313 "math/big"
1414 "net"
1515 "os"
@@ -35,6 +35,9 @@ type ip2proxymeta struct {
3535 ipv6indexbaseaddr uint32
3636 ipv4columnsize uint32
3737 ipv6columnsize uint32
38+ productcode uint8
39+ producttype uint8
40+ filesize uint32
3841}
3942
4043// The IP2Proxyrecord struct stores all of the available
@@ -52,6 +55,7 @@ type IP2Proxyrecord struct {
5255 As string
5356 Last_seen string
5457 Threat string
58+ Provider string
5559 Is_proxy int8
5660}
5761
@@ -70,6 +74,7 @@ type DB struct {
7074 as_position_offset uint32
7175 lastseen_position_offset uint32
7276 threat_position_offset uint32
77+ provider_position_offset uint32
7378
7479 country_enabled bool
7580 region_enabled bool
@@ -82,25 +87,27 @@ type DB struct {
8287 as_enabled bool
8388 lastseen_enabled bool
8489 threat_enabled bool
90+ provider_enabled bool
8591
8692 metaok bool
8793}
8894
8995var defaultDB = & DB {}
9096
91- var country_position = [11 ]uint8 {0 , 2 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 }
92- var region_position = [11 ]uint8 {0 , 0 , 0 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 }
93- var city_position = [11 ]uint8 {0 , 0 , 0 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 }
94- var isp_position = [11 ]uint8 {0 , 0 , 0 , 0 , 6 , 6 , 6 , 6 , 6 , 6 , 6 }
95- var proxytype_position = [11 ]uint8 {0 , 0 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 }
96- var domain_position = [11 ]uint8 {0 , 0 , 0 , 0 , 0 , 7 , 7 , 7 , 7 , 7 , 7 }
97- var usagetype_position = [11 ]uint8 {0 , 0 , 0 , 0 , 0 , 0 , 8 , 8 , 8 , 8 , 8 }
98- var asn_position = [11 ]uint8 {0 , 0 , 0 , 0 , 0 , 0 , 0 , 9 , 9 , 9 , 9 }
99- var as_position = [11 ]uint8 {0 , 0 , 0 , 0 , 0 , 0 , 0 , 10 , 10 , 10 , 10 }
100- var lastseen_position = [11 ]uint8 {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 11 , 11 , 11 }
101- var threat_position = [11 ]uint8 {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 12 , 12 }
102-
103- const module_version string = "3.1.0"
97+ var country_position = [12 ]uint8 {0 , 2 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 }
98+ var region_position = [12 ]uint8 {0 , 0 , 0 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 }
99+ var city_position = [12 ]uint8 {0 , 0 , 0 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 }
100+ var isp_position = [12 ]uint8 {0 , 0 , 0 , 0 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 }
101+ var proxytype_position = [12 ]uint8 {0 , 0 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 }
102+ var domain_position = [12 ]uint8 {0 , 0 , 0 , 0 , 0 , 7 , 7 , 7 , 7 , 7 , 7 , 7 }
103+ var usagetype_position = [12 ]uint8 {0 , 0 , 0 , 0 , 0 , 0 , 8 , 8 , 8 , 8 , 8 , 8 }
104+ var asn_position = [12 ]uint8 {0 , 0 , 0 , 0 , 0 , 0 , 0 , 9 , 9 , 9 , 9 , 9 }
105+ var as_position = [12 ]uint8 {0 , 0 , 0 , 0 , 0 , 0 , 0 , 10 , 10 , 10 , 10 , 10 }
106+ var lastseen_position = [12 ]uint8 {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 11 , 11 , 11 , 11 }
107+ var threat_position = [12 ]uint8 {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 12 , 12 , 12 }
108+ var provider_position = [12 ]uint8 {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 13 }
109+
110+ const module_version string = "3.2.0"
104111
105112var max_ipv4_range = big .NewInt (4294967295 )
106113var max_ipv6_range = big .NewInt (0 )
@@ -125,13 +132,15 @@ const asn uint32 = 0x00200
125132const as uint32 = 0x00400
126133const lastseen uint32 = 0x00800
127134const threat uint32 = 0x01000
135+ const provider uint32 = 0x02000
128136
129- const all uint32 = countryshort | countrylong | region | city | isp | proxytype | isproxy | domain | usagetype | asn | as | lastseen | threat
137+ const all uint32 = countryshort | countrylong | region | city | isp | proxytype | isproxy | domain | usagetype | asn | as | lastseen | threat | provider
130138
131139const msg_not_supported string = "NOT SUPPORTED"
132140const msg_invalid_ip string = "INVALID IP ADDRESS"
133141const msg_missing_file string = "MISSING FILE"
134142const msg_ipv6_unsupported string = "IPV6 ADDRESS MISSING IN IPV4 BIN"
143+ const msg_invalid_bin string = "Incorrect IP2Proxy BIN file format. Please make sure that you are using the latest IP2Proxy BIN file."
135144
136145// get IP type and calculate IP number; calculates index too if exists
137146func (d * DB ) checkip (ip string ) (iptype uint32 , ipnum * big.Int , ipindex uint32 ) {
@@ -262,32 +271,6 @@ func (d *DB) readstr(pos uint32) (string, error) {
262271 return retval , nil
263272}
264273
265- // read float from slices
266- func (d * DB ) readfloat_row (row []byte , pos uint32 ) float32 {
267- var retval float32
268- data := row [pos : pos + 4 ]
269- bits := binary .LittleEndian .Uint32 (data )
270- retval = math .Float32frombits (bits )
271- return retval
272- }
273-
274- // read float
275- func (d * DB ) readfloat (pos uint32 ) (float32 , error ) {
276- pos2 := int64 (pos )
277- var retval float32
278- data := make ([]byte , 4 )
279- _ , err := d .f .ReadAt (data , pos2 - 1 )
280- if err != nil {
281- return 0 , err
282- }
283- buf := bytes .NewReader (data )
284- err = binary .Read (buf , binary .LittleEndian , & retval )
285- if err != nil {
286- fmt .Printf ("binary read failed: %v" , err )
287- }
288- return retval , nil
289- }
290-
291274func fatal (db * DB , err error ) (* DB , error ) {
292275 _ = db .f .Close ()
293276 return nil , err
@@ -362,6 +345,22 @@ func OpenDBWithReader(reader DBReader) (*DB, error) {
362345 if err != nil {
363346 return fatal (db , err )
364347 }
348+ db .meta .productcode , err = db .readuint8 (30 )
349+ if err != nil {
350+ return fatal (db , err )
351+ }
352+ db .meta .producttype , err = db .readuint8 (31 )
353+ if err != nil {
354+ return fatal (db , err )
355+ }
356+ db .meta .filesize , err = db .readuint32 (32 )
357+ if err != nil {
358+ return fatal (db , err )
359+ }
360+ // check if is correct BIN (should be 2 for IP2Proxy BIN file), also checking for zipped file (PK being the first 2 chars)
361+ if (db .meta .productcode != 2 && db .meta .databaseyear >= 21 ) || (db .meta .databasetype == 80 && db .meta .databasecolumn == 75 ) { // only BINs from Jan 2021 onwards have this byte set
362+ return fatal (db , errors .New (msg_invalid_bin ))
363+ }
365364 db .meta .ipv4columnsize = uint32 (db .meta .databasecolumn << 2 ) // 4 bytes each column
366365 db .meta .ipv6columnsize = uint32 (16 + ((db .meta .databasecolumn - 1 ) << 2 )) // 4 bytes each column, except IPFrom column which is 16 bytes
367366
@@ -411,6 +410,10 @@ func OpenDBWithReader(reader DBReader) (*DB, error) {
411410 db .threat_position_offset = uint32 (threat_position [dbt ]- 2 ) << 2
412411 db .threat_enabled = true
413412 }
413+ if provider_position [dbt ] != 0 {
414+ db .provider_position_offset = uint32 (provider_position [dbt ]- 2 ) << 2
415+ db .provider_enabled = true
416+ }
414417
415418 db .metaok = true
416419
@@ -523,6 +526,7 @@ func loadmessage(mesg string) IP2Proxyrecord {
523526 x .As = mesg
524527 x .Last_seen = mesg
525528 x .Threat = mesg
529+ x .Provider = mesg
526530 x .Is_proxy = - 1
527531
528532 return x
@@ -674,6 +678,7 @@ func (d *DB) GetAll(ipaddress string) (map[string]string, error) {
674678 x ["AS" ] = data .As
675679 x ["LastSeen" ] = data .Last_seen
676680 x ["Threat" ] = data .Threat
681+ x ["Provider" ] = data .Provider
677682
678683 return x , err
679684}
@@ -750,6 +755,12 @@ func (d *DB) GetThreat(ipaddress string) (string, error) {
750755 return data .Threat , err
751756}
752757
758+ // GetProvider will return the provider of the proxy.
759+ func (d * DB ) GetProvider (ipaddress string ) (string , error ) {
760+ data , err := d .query (ipaddress , provider )
761+ return data .Provider , err
762+ }
763+
753764// IsProxy checks whether the queried IP address was a proxy. Returned value: -1 (errors), 0 (not a proxy), 1 (a proxy), 2 (a data center IP address or search engine robot).
754765func (d * DB ) IsProxy (ipaddress string ) (int8 , error ) {
755766 data , err := d .query (ipaddress , isproxy )
@@ -852,7 +863,6 @@ func (d *DB) query(ipaddress string, mode uint32) (IP2Proxyrecord, error) {
852863 var firstcol uint32 = 4 // 4 bytes for ip from
853864 if iptype == 6 {
854865 firstcol = 16 // 16 bytes for ipv6
855- // rowoffset = rowoffset + 12 // coz below is assuming all columns are 4 bytes, so got 12 left to go to make 16 bytes total
856866 }
857867
858868 row := make ([]byte , colsize - firstcol ) // exclude the ip from field
@@ -863,8 +873,6 @@ func (d *DB) query(ipaddress string, mode uint32) (IP2Proxyrecord, error) {
863873
864874 if d .proxytype_enabled {
865875 if mode & proxytype != 0 || mode & isproxy != 0 {
866- // x.Proxy_type = readstr(readuint32(rowoffset + proxytype_position_offset))
867- // x.Proxy_type = readstr(readuint32_row(row, proxytype_position_offset))
868876 if x .Proxy_type , err = d .readstr (d .readuint32_row (row , d .proxytype_position_offset )); err != nil {
869877 return x , err
870878 }
@@ -873,96 +881,80 @@ func (d *DB) query(ipaddress string, mode uint32) (IP2Proxyrecord, error) {
873881
874882 if d .country_enabled {
875883 if mode & countryshort != 0 || mode & countrylong != 0 || mode & isproxy != 0 {
876- // countrypos = readuint32(rowoffset + country_position_offset)
877- // countrypos = readuint32_row(row, country_position_offset)
878884 countrypos = d .readuint32_row (row , d .country_position_offset )
879885 }
880886 if mode & countryshort != 0 || mode & isproxy != 0 {
881- // x.Country_short = readstr(countrypos)
882887 if x .Country_short , err = d .readstr (countrypos ); err != nil {
883888 return x , err
884889 }
885890 }
886891 if mode & countrylong != 0 {
887- // x.Country_long = readstr(countrypos + 3)
888892 if x .Country_long , err = d .readstr (countrypos + 3 ); err != nil {
889893 return x , err
890894 }
891895 }
892896 }
893897
894898 if mode & region != 0 && d .region_enabled {
895- // x.Region = readstr(readuint32(rowoffset + region_position_offset))
896- // x.Region = readstr(readuint32_row(row, region_position_offset))
897899 if x .Region , err = d .readstr (d .readuint32_row (row , d .region_position_offset )); err != nil {
898900 return x , err
899901 }
900902 }
901903
902904 if mode & city != 0 && d .city_enabled {
903- // x.City = readstr(readuint32(rowoffset + city_position_offset))
904- // x.City = readstr(readuint32_row(row, city_position_offset))
905905 if x .City , err = d .readstr (d .readuint32_row (row , d .city_position_offset )); err != nil {
906906 return x , err
907907 }
908908 }
909909
910910 if mode & isp != 0 && d .isp_enabled {
911- // x.Isp = readstr(readuint32(rowoffset + isp_position_offset))
912- // x.Isp = readstr(readuint32_row(row, isp_position_offset))
913911 if x .Isp , err = d .readstr (d .readuint32_row (row , d .isp_position_offset )); err != nil {
914912 return x , err
915913 }
916914 }
917915
918916 if mode & domain != 0 && d .domain_enabled {
919- // x.Domain = readstr(readuint32(rowoffset + domain_position_offset))
920- // x.Domain = readstr(readuint32_row(row, domain_position_offset))
921917 if x .Domain , err = d .readstr (d .readuint32_row (row , d .domain_position_offset )); err != nil {
922918 return x , err
923919 }
924920 }
925921
926922 if mode & usagetype != 0 && d .usagetype_enabled {
927- // x.Usage_type = readstr(readuint32(rowoffset + usagetype_position_offset))
928- // x.Usage_type = readstr(readuint32_row(row, usagetype_position_offset))
929923 if x .Usage_type , err = d .readstr (d .readuint32_row (row , d .usagetype_position_offset )); err != nil {
930924 return x , err
931925 }
932926 }
933927
934928 if mode & asn != 0 && d .asn_enabled {
935- // x.Asn = readstr(readuint32(rowoffset + asn_position_offset))
936- // x.Asn = readstr(readuint32_row(row, asn_position_offset))
937929 if x .Asn , err = d .readstr (d .readuint32_row (row , d .asn_position_offset )); err != nil {
938930 return x , err
939931 }
940932 }
941933
942934 if mode & as != 0 && d .as_enabled {
943- // x.As = readstr(readuint32(rowoffset + as_position_offset))
944- // x.As = readstr(readuint32_row(row, as_position_offset))
945935 if x .As , err = d .readstr (d .readuint32_row (row , d .as_position_offset )); err != nil {
946936 return x , err
947937 }
948938 }
949939
950940 if mode & lastseen != 0 && d .lastseen_enabled {
951- // x.Last_seen = readstr(readuint32(rowoffset + lastseen_position_offset))
952- // x.Last_seen = readstr(readuint32_row(row, lastseen_position_offset))
953941 if x .Last_seen , err = d .readstr (d .readuint32_row (row , d .lastseen_position_offset )); err != nil {
954942 return x , err
955943 }
956944 }
957945
958946 if mode & threat != 0 && d .threat_enabled {
959- // x.Threat = readstr(readuint32(rowoffset + threat_position_offset))
960- // x.Threat = readstr(readuint32_row(row, threat_position_offset))
961947 if x .Threat , err = d .readstr (d .readuint32_row (row , d .threat_position_offset )); err != nil {
962948 return x , err
963949 }
964950 }
965951
952+ if mode & provider != 0 && d .provider_enabled {
953+ if x .Provider , err = d .readstr (d .readuint32_row (row , d .provider_position_offset )); err != nil {
954+ return x , err
955+ }
956+ }
957+
966958 if x .Country_short == "-" || x .Proxy_type == "-" {
967959 x .Is_proxy = 0
968960 } else {
@@ -1004,5 +996,6 @@ func Printrecord(x IP2Proxyrecord) {
1004996 fmt .Printf ("as: %s\n " , x .As )
1005997 fmt .Printf ("last_seen: %s\n " , x .Last_seen )
1006998 fmt .Printf ("threat: %s\n " , x .Threat )
999+ fmt .Printf ("provider: %s\n " , x .Provider )
10071000 fmt .Printf ("is_proxy: %d\n " , x .Is_proxy )
10081001}
0 commit comments