Skip to content

Commit 831d77c

Browse files
Added provider field and exception handling for incorrect BIN database.
1 parent e11d1bb commit 831d77c

File tree

5 files changed

+72
-77
lines changed

5 files changed

+72
-77
lines changed

LICENSE.TXT

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2020 IP2Location.com
3+
Copyright (c) 2021 IP2Location.com
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,16 @@ Below are the methods supported in this library.
4040
|get_as|Return the autonomous system name of the proxy.|
4141
|get_last_seen|Return the number of days that the proxy was last seen.|
4242
|get_threat|Return the threat type of the proxy.|
43+
|get_provider|Return the provider of the proxy.|
4344

4445
## Usage
4546

4647
```d
4748
import std.stdio;
48-
import ip2proxy;
49+
import ip2proxy : ip2proxy;
4950
5051
int main() {
51-
string db = "./IP2PROXY-IP-PROXYTYPE-COUNTRY-REGION-CITY-ISP-DOMAIN-USAGETYPE-ASN-LASTSEEN-THREAT-RESIDENTIAL.BIN";
52+
string db = "./IP2PROXY-IP-PROXYTYPE-COUNTRY-REGION-CITY-ISP-DOMAIN-USAGETYPE-ASN-LASTSEEN-THREAT-RESIDENTIAL-PROVIDER.BIN";
5253
auto prox = new ip2proxy();
5354
5455
if (prox.open(db) == 0) {
@@ -72,6 +73,7 @@ int main() {
7273
writeln("AS: ", prox.get_as(ip));
7374
writeln("LastSeen: ", prox.get_last_seen(ip));
7475
writeln("Threat: ", prox.get_threat(ip));
76+
writeln("Provider: ", prox.get_provider(ip));
7577
7678
// function for all fields
7779
auto all = prox.get_all(ip);
@@ -88,6 +90,7 @@ int main() {
8890
writeln("AS: ", all["AS"]);
8991
writeln("LastSeen: ", all["LastSeen"]);
9092
writeln("Threat: ", all["Threat"]);
93+
writeln("Provider: ", all["Provider"]);
9194
}
9295
else {
9396
writeln("Error reading BIN file.");

dub.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
],
66
"description": "IP2Proxy D Library",
77
"homepage": "https://www.ip2location.com/development-libraries/ip2proxy/d",
8-
"copyright": "Copyright © 2020, IP2Location",
8+
"copyright": "Copyright © 2021, IP2Location",
99
"license": "MIT",
1010
"targetType": "library"
1111
}

source/app.d

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import std.stdio;
2-
import ip2proxy;
2+
import ip2proxy : ip2proxy;
33

44
int main() {
5-
string db = "./IP2PROXY-IP-PROXYTYPE-COUNTRY-REGION-CITY-ISP-DOMAIN-USAGETYPE-ASN-LASTSEEN-THREAT-RESIDENTIAL.BIN";
5+
string db = "./IP2PROXY-IP-PROXYTYPE-COUNTRY-REGION-CITY-ISP-DOMAIN-USAGETYPE-ASN-LASTSEEN-THREAT-RESIDENTIAL-PROVIDER.BIN";
66
auto prox = new ip2proxy();
77

88
if (prox.open(db) == 0) {
@@ -26,6 +26,7 @@ int main() {
2626
writeln("AS: ", prox.get_as(ip));
2727
writeln("LastSeen: ", prox.get_last_seen(ip));
2828
writeln("Threat: ", prox.get_threat(ip));
29+
writeln("Provider: ", prox.get_provider(ip));
2930

3031
// function for all fields
3132
auto all = prox.get_all(ip);
@@ -42,6 +43,7 @@ int main() {
4243
writeln("AS: ", all["AS"]);
4344
writeln("LastSeen: ", all["LastSeen"]);
4445
writeln("Threat: ", all["Threat"]);
46+
writeln("Provider: ", all["Provider"]);
4547
}
4648
else {
4749
writeln("Error reading BIN file.");

source/ip2proxy-d/ip2proxy.d

Lines changed: 61 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ protected struct ip2proxymeta {
2121
uint ipv6indexbaseaddr;
2222
uint ipv4columnsize;
2323
uint ipv6columnsize;
24+
ubyte productcode;
25+
ubyte producttype;
26+
uint filesize;
2427
}
2528

2629
protected struct ip2proxyrecord {
@@ -36,6 +39,7 @@ protected struct ip2proxyrecord {
3639
string as = "-";
3740
string last_seen = "-";
3841
string threat = "-";
42+
string provider = "-";
3943
byte is_proxy = -1;
4044
}
4145

@@ -45,19 +49,20 @@ protected struct ipv {
4549
uint ipindex = 0;
4650
}
4751

48-
const ubyte[11] COUNTRY_POSITION = [0, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3];
49-
const ubyte[11] REGION_POSITION = [0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4];
50-
const ubyte[11] CITY_POSITION = [0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5];
51-
const ubyte[11] ISP_POSITION = [0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6];
52-
const ubyte[11] PROXYTYPE_POSITION = [0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2];
53-
const ubyte[11] DOMAIN_POSITION = [0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7];
54-
const ubyte[11] USAGETYPE_POSITION = [0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8];
55-
const ubyte[11] ASN_POSITION = [0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9];
56-
const ubyte[11] AS_POSITION = [0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10];
57-
const ubyte[11] LASTSEEN_POSITION = [0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 11];
58-
const ubyte[11] THREAT_POSITION = [0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12];
52+
const ubyte[12] COUNTRY_POSITION = [0, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3];
53+
const ubyte[12] REGION_POSITION = [0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4];
54+
const ubyte[12] CITY_POSITION = [0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5];
55+
const ubyte[12] ISP_POSITION = [0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6];
56+
const ubyte[12] PROXYTYPE_POSITION = [0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2];
57+
const ubyte[12] DOMAIN_POSITION = [0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7];
58+
const ubyte[12] USAGETYPE_POSITION = [0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8];
59+
const ubyte[12] ASN_POSITION = [0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9];
60+
const ubyte[12] AS_POSITION = [0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10];
61+
const ubyte[12] LASTSEEN_POSITION = [0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 11, 11];
62+
const ubyte[12] THREAT_POSITION = [0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12];
63+
const ubyte[12] PROVIDER_POSITION = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13];
5964

60-
protected const string MODULE_VERSION = "3.0.0";
65+
protected const string MODULE_VERSION = "3.1.0";
6166

6267
protected const BigInt MAX_IPV4_RANGE = BigInt("4294967295");
6368
protected const BigInt MAX_IPV6_RANGE = BigInt("340282366920938463463374607431768211455");
@@ -80,13 +85,15 @@ protected const uint ASN = 0X00200;
8085
protected const uint AS = 0X00400;
8186
protected const uint LASTSEEN = 0X00800;
8287
protected const uint THREAT = 0X01000;
88+
protected const uint PROVIDER = 0X02000;
8389

84-
protected const uint ALL = COUNTRYSHORT | COUNTRYLONG | REGION | CITY | ISP | PROXYTYPE | ISPROXY | DOMAIN | USAGETYPE | ASN | AS | LASTSEEN | THREAT;
90+
protected const uint ALL = COUNTRYSHORT | COUNTRYLONG | REGION | CITY | ISP | PROXYTYPE | ISPROXY | DOMAIN | USAGETYPE | ASN | AS | LASTSEEN | THREAT | PROVIDER;
8591

8692
protected const string MSG_NOT_SUPPORTED = "NOT SUPPORTED";
8793
protected const string MSG_INVALID_IP = "INVALID IP ADDRESS";
8894
protected const string MSG_MISSING_FILE = "MISSING FILE";
8995
protected const string MSG_IPV6_UNSUPPORTED = "IPV6 ADDRESS MISSING IN IPV4 BIN";
96+
protected const string MSG_INVALID_BIN = "Incorrect IP2Proxy BIN file format. Please make sure that you are using the latest IP2Proxy BIN file.";
9097

9198
class ip2proxy {
9299
protected MmFile db;
@@ -105,6 +112,7 @@ class ip2proxy {
105112
private uint as_position_offset;
106113
private uint lastseen_position_offset;
107114
private uint threat_position_offset;
115+
private uint provider_position_offset;
108116

109117
private bool country_enabled;
110118
private bool region_enabled;
@@ -117,6 +125,7 @@ class ip2proxy {
117125
private bool as_enabled;
118126
private bool lastseen_enabled;
119127
private bool threat_enabled;
128+
private bool provider_enabled;
120129

121130
// constructor
122131
public this() {
@@ -159,6 +168,9 @@ class ip2proxy {
159168
meta.ipv6indexbaseaddr = 0;
160169
meta.ipv4columnsize = 0;
161170
meta.ipv6columnsize = 0;
171+
meta.productcode = 0;
172+
meta.producttype = 0;
173+
meta.filesize = 0;
162174
metaok = false;
163175
country_position_offset = 0;
164176
region_position_offset = 0;
@@ -171,6 +183,7 @@ class ip2proxy {
171183
as_position_offset = 0;
172184
lastseen_position_offset = 0;
173185
threat_position_offset = 0;
186+
provider_position_offset = 0;
174187
country_enabled = false;
175188
region_enabled = false;
176189
city_enabled = false;
@@ -182,6 +195,7 @@ class ip2proxy {
182195
as_enabled = false;
183196
lastseen_enabled = false;
184197
threat_enabled = false;
198+
provider_enabled = false;
185199

186200
destroy(db);
187201

@@ -228,27 +242,6 @@ class ip2proxy {
228242
return result;
229243
}
230244

231-
// read float from row
232-
private float readfloat_row(ref ubyte[] row, uint index) {
233-
ubyte[4] buf = row[index .. (index + 4)];
234-
float result = 0.0;
235-
result = littleEndianToNative!float(buf);
236-
return result;
237-
}
238-
239-
// read float
240-
private float readfloat(uint index) {
241-
uint pos = index - 1;
242-
ubyte[4] fl;
243-
float result = 0.0;
244-
for (int x = 0; x < 4; x++) {
245-
fl[x] = cast(ubyte)db[pos + x];
246-
}
247-
248-
result = littleEndianToNative!float(fl);
249-
return result;
250-
}
251-
252245
// read BIN file metadata
253246
private byte readmeta() {
254247
if (binfile.length == 0) {
@@ -273,25 +266,21 @@ class ip2proxy {
273266
meta.ipv6databaseaddr = readuint(18);
274267
meta.ipv4indexbaseaddr = readuint(22);
275268
meta.ipv6indexbaseaddr = readuint(26);
269+
meta.productcode = db[29];
270+
// below 2 fields just read for now, not being used yet
271+
meta.producttype = db[30];
272+
meta.filesize = readuint(32);
273+
274+
// check if is correct BIN (should be 2 for IP2Proxy BIN file), also checking for zipped file (PK being the first 2 chars)
275+
if ((meta.productcode != 2 && meta.databaseyear >= 21) || (meta.databasetype == 80 && meta.databasecolumn == 75)) { // only BINs from Jan 2021 onwards have this byte set
276+
throw new Exception(MSG_INVALID_BIN);
277+
}
278+
276279
meta.ipv4columnsize = meta.databasecolumn << 2; // 4 bytes each column
277280
meta.ipv6columnsize = 16 + ((meta.databasecolumn - 1) << 2); // 4 bytes each column, except IPFrom column which is 16 bytes
278281

279282
uint dbt = meta.databasetype;
280283

281-
// since both IPv4 and IPv6 use 4 bytes for the below columns, can just do it once here
282-
// country_position_offset = (COUNTRY_POSITION[dbt] != 0) ? (COUNTRY_POSITION[dbt] - 1) << 2 : 0;
283-
// region_position_offset = (REGION_POSITION[dbt] != 0) ? (REGION_POSITION[dbt] - 1) << 2 : 0;
284-
// city_position_offset = (CITY_POSITION[dbt] != 0) ? (CITY_POSITION[dbt] - 1) << 2 : 0;
285-
// isp_position_offset = (ISP_POSITION[dbt] != 0) ? (ISP_POSITION[dbt] - 1) << 2 : 0;
286-
// proxytype_position_offset = (PROXYTYPE_POSITION[dbt] != 0) ? (PROXYTYPE_POSITION[dbt] - 1) << 2 : 0;
287-
// domain_position_offset = (DOMAIN_POSITION[dbt] != 0) ? (DOMAIN_POSITION[dbt] - 1) << 2 : 0;
288-
// usagetype_position_offset = (USAGETYPE_POSITION[dbt] != 0) ? (USAGETYPE_POSITION[dbt] - 1) << 2 : 0;
289-
// asn_position_offset = (ASN_POSITION[dbt] != 0) ? (ASN_POSITION[dbt] - 1) << 2 : 0;
290-
// as_position_offset = (AS_POSITION[dbt] != 0) ? (AS_POSITION[dbt] - 1) << 2 : 0;
291-
// lastseen_position_offset = (LASTSEEN_POSITION[dbt] != 0) ? (LASTSEEN_POSITION[dbt] - 1) << 2 : 0;
292-
// threat_position_offset = (THREAT_POSITION[dbt] != 0) ? (THREAT_POSITION[dbt] - 1) << 2 : 0;
293-
294-
// offset slightly different when reading by row
295284
country_position_offset = (COUNTRY_POSITION[dbt] != 0) ? (COUNTRY_POSITION[dbt] - 2) << 2 : 0;
296285
region_position_offset = (REGION_POSITION[dbt] != 0) ? (REGION_POSITION[dbt] - 2) << 2 : 0;
297286
city_position_offset = (CITY_POSITION[dbt] != 0) ? (CITY_POSITION[dbt] - 2) << 2 : 0;
@@ -303,18 +292,20 @@ class ip2proxy {
303292
as_position_offset = (AS_POSITION[dbt] != 0) ? (AS_POSITION[dbt] - 2) << 2 : 0;
304293
lastseen_position_offset = (LASTSEEN_POSITION[dbt] != 0) ? (LASTSEEN_POSITION[dbt] - 2) << 2 : 0;
305294
threat_position_offset = (THREAT_POSITION[dbt] != 0) ? (THREAT_POSITION[dbt] - 2) << 2 : 0;
295+
provider_position_offset = (PROVIDER_POSITION[dbt] != 0) ? (PROVIDER_POSITION[dbt] - 2) << 2 : 0;
306296

307-
country_enabled = (COUNTRY_POSITION[dbt] != 0) ? true : false;
308-
region_enabled = (REGION_POSITION[dbt] != 0) ? true : false;
309-
city_enabled = (CITY_POSITION[dbt] != 0) ? true : false;
310-
isp_enabled = (ISP_POSITION[dbt] != 0) ? true : false;
311-
proxytype_enabled = (PROXYTYPE_POSITION[dbt] != 0) ? true : false;
312-
domain_enabled = (DOMAIN_POSITION[dbt] != 0) ? true : false;
313-
usagetype_enabled = (USAGETYPE_POSITION[dbt] != 0) ? true : false;
314-
asn_enabled = (ASN_POSITION[dbt] != 0) ? true : false;
315-
as_enabled = (AS_POSITION[dbt] != 0) ? true : false;
316-
lastseen_enabled = (LASTSEEN_POSITION[dbt] != 0) ? true : false;
317-
threat_enabled = (THREAT_POSITION[dbt] != 0) ? true : false;
297+
country_enabled = (COUNTRY_POSITION[dbt] != 0);
298+
region_enabled = (REGION_POSITION[dbt] != 0);
299+
city_enabled = (CITY_POSITION[dbt] != 0);
300+
isp_enabled = (ISP_POSITION[dbt] != 0);
301+
proxytype_enabled = (PROXYTYPE_POSITION[dbt] != 0);
302+
domain_enabled = (DOMAIN_POSITION[dbt] != 0);
303+
usagetype_enabled = (USAGETYPE_POSITION[dbt] != 0);
304+
asn_enabled = (ASN_POSITION[dbt] != 0);
305+
as_enabled = (AS_POSITION[dbt] != 0);
306+
lastseen_enabled = (LASTSEEN_POSITION[dbt] != 0);
307+
threat_enabled = (THREAT_POSITION[dbt] != 0);
308+
provider_enabled = (PROVIDER_POSITION[dbt] != 0);
318309

319310
metaok = true;
320311
}
@@ -436,6 +427,7 @@ class ip2proxy {
436427
x["AS"] = data.as;
437428
x["LastSeen"] = data.last_seen;
438429
x["Threat"] = data.threat;
430+
x["Provider"] = data.provider;
439431

440432
return x;
441433
}
@@ -512,6 +504,12 @@ class ip2proxy {
512504
return data.threat;
513505
}
514506

507+
// get provider
508+
public auto get_provider(const string ipaddress) {
509+
auto data = query(ipaddress, PROVIDER);
510+
return data.provider;
511+
}
512+
515513
// is proxy
516514
public auto is_proxy(const string ipaddress) {
517515
auto data = query(ipaddress, ISPROXY);
@@ -594,20 +592,17 @@ class ip2proxy {
594592
uint firstcol = 4; // 4 bytes for ip from
595593
if (ipdata.iptype == 6) {
596594
firstcol = 16; // 16 bytes for ipv6
597-
// rowoffset = rowoffset + 12; // coz below is assuming all columns are 4 bytes, so got 12 left to go to make 16 bytes total
598595
}
599596
ubyte[] row = cast(ubyte[])db[(rowoffset + firstcol - 1) .. (rowoffset + colsize - 1)];
600597

601598
if (proxytype_enabled) {
602599
if ((mode & PROXYTYPE) || (mode & ISPROXY)) {
603-
// x.proxy_type = readstr(readuint(rowoffset + proxytype_position_offset));
604600
x.proxy_type = readstr(readuint_row(row, proxytype_position_offset));
605601
}
606602
}
607603

608604
if (country_enabled) {
609605
if ((mode & COUNTRYSHORT) || (mode & COUNTRYLONG) || (mode & ISPROXY)) {
610-
// countrypos = readuint(rowoffset + country_position_offset);
611606
countrypos = readuint_row(row, country_position_offset);
612607
}
613608
if ((mode & COUNTRYSHORT) || (mode & ISPROXY)) {
@@ -619,50 +614,45 @@ class ip2proxy {
619614
}
620615

621616
if ((mode & REGION) && (region_enabled)) {
622-
// x.region = readstr(readuint(rowoffset + region_position_offset));
623617
x.region = readstr(readuint_row(row, region_position_offset));
624618
}
625619

626620
if ((mode & CITY) && (city_enabled)) {
627-
// x.city = readstr(readuint(rowoffset + city_position_offset));
628621
x.city = readstr(readuint_row(row, city_position_offset));
629622
}
630623

631624
if ((mode & ISP) && (isp_enabled)) {
632-
// x.isp = readstr(readuint(rowoffset + isp_position_offset));
633625
x.isp = readstr(readuint_row(row, isp_position_offset));
634626
}
635627

636628
if ((mode & DOMAIN) && (domain_enabled)) {
637-
// x.domain = readstr(readuint(rowoffset + domain_position_offset));
638629
x.domain = readstr(readuint_row(row, domain_position_offset));
639630
}
640631

641632
if ((mode & USAGETYPE) && (usagetype_enabled)) {
642-
// x.usage_type = readstr(readuint(rowoffset + usagetype_position_offset));
643633
x.usage_type = readstr(readuint_row(row, usagetype_position_offset));
644634
}
645635

646636
if ((mode & ASN) && (asn_enabled)) {
647-
// x.asn = readstr(readuint(rowoffset + asn_position_offset));
648637
x.asn = readstr(readuint_row(row, asn_position_offset));
649638
}
650639

651640
if ((mode & AS) && (as_enabled)) {
652-
// x.as = readstr(readuint(rowoffset + as_position_offset));
653641
x.as = readstr(readuint_row(row, as_position_offset));
654642
}
655643

656644
if ((mode & LASTSEEN) && (lastseen_enabled)) {
657-
// x.last_seen = readstr(readuint(rowoffset + lastseen_position_offset));
658645
x.last_seen = readstr(readuint_row(row, lastseen_position_offset));
659646
}
660647

661648
if ((mode & THREAT) && (threat_enabled)) {
662-
// x.threat = readstr(readuint(rowoffset + threat_position_offset));
663649
x.threat = readstr(readuint_row(row, threat_position_offset));
664650
}
665651

652+
if ((mode & PROVIDER) && (provider_enabled)) {
653+
x.provider = readstr(readuint_row(row, provider_position_offset));
654+
}
655+
666656
if ((x.country_short == "-") || (x.proxy_type == "-")) {
667657
x.is_proxy = 0;
668658
}

0 commit comments

Comments
 (0)