Skip to content

Commit eef081b

Browse files
committed
Added provider field and exception handling for incorrect BIN database.
1 parent 025c830 commit eef081b

File tree

10 files changed

+113
-54
lines changed

10 files changed

+113
-54
lines changed

LICENSE.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Copyright (c) 2019 IP2Location ( [email protected] )
1+
Copyright (c) 2021 IP2Location ( [email protected] )
22

33
Permission is hereby granted, free of charge, to any person obtaining
44
a copy of this software and associated documentation files (the

README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
# IP2Proxy Ruby Library
55

6-
This module allows user to reverse search of IP address to detect VPN servers, open proxies, web proxies, Tor exit nodes, search engine robots, data center ranges and residential proxies using IP2Proxy BIN database. Other information available includes proxy type, country, state, city, ISP, domain name, usage type, AS number, AS name, threats and last seen date.
6+
This module allows user to reverse search of IP address to detect VPN servers, open proxies, web proxies, Tor exit nodes, search engine robots, data center ranges and residential proxies using IP2Proxy BIN database. Other information available includes proxy type, country, state, city, ISP, domain name, usage type, AS number, AS name, threats, last seen date and provider names.
77

88
It lookup the proxy IP address from **IP2Proxy BIN Data** file. This data file can be downloaded at
99

@@ -22,12 +22,12 @@ Below are the methods supported in this module.
2222
|---|---|
2323
|open|Open the IP2Proxy BIN data with **File I/O** mode for lookup.|
2424
|close|Close and clean up the file pointer.|
25-
|get_package_version|Get the package version (1 to 10 for PX1 to PX10 respectively).|
25+
|get_package_version|Get the package version (1 to 10 for PX1 to PX11 respectively).|
2626
|get_module_version|Get the module version.|
2727
|get_database_version|Get the database version.|
2828
|is_proxy|Check whether if an IP address was a proxy. Please see [Proxy Type](#proxy-type) for details. 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</li></ul>|
2929
|get_all|Return the proxy information in array.|
30-
|get_proxytype|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|
30+
|get_proxytype|Return the proxy type. Please visit <a href="https://www.ip2location.com/database/px11-ip-proxytype-country-region-city-isp-domain-usagetype-asn-lastseen-threat-residential-provider" target="_blank">IP2Location</a> for the list of proxy types supported|
3131
|get_country_short|Return the ISO3166-1 country code (2-digits) of the proxy.|
3232
|get_country_long|Return the ISO3166-1 country name of the proxy.|
3333
|get_region|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|
@@ -39,14 +39,15 @@ Below are the methods supported in this module.
3939
|get_as|Return the autonomous system (AS) name of proxy's IP address or domain name.|
4040
|get_last_seen|Return the last seen days ago value of proxy's IP address or domain name.|
4141
|get_threat|Return the threat types reported to proxy's IP address or domain name. Please see [Threat Type](#threat-type) for details.|
42+
|get_provider|Returns the VPN service provider name if available.|
4243

4344
## Usage
4445

4546
```
4647
require 'ip2proxy_ruby'
4748
4849
# open IP2Proxy BIN database for proxy lookup
49-
i2p = Ip2proxy.new.open("./data/IP2PROXY-IP-PROXYTYPE-COUNTRY-REGION-CITY-ISP-DOMAIN-USAGETYPE-ASN-LASTSEEN-THREAT-RESIDENTIAL.BIN")
50+
i2p = Ip2proxy.new.open("./data/IP2PROXY-IP-PROXYTYPE-COUNTRY-REGION-CITY-ISP-DOMAIN-USAGETYPE-ASN-LASTSEEN-THREAT-RESIDENTIAL-PROVIDER.BIN")
5051
5152
# get versioning information
5253
print 'Module Version: ' + i2p.get_module_version + "\n"
@@ -67,6 +68,7 @@ print 'ASN: ' + i2p.get_asn('1.2.3.4') + "\n"
6768
print 'AS: ' + i2p.get_as('1.2.3.4') + "\n"
6869
print 'Last Seen: ' + i2p.get_last_seen('1.2.3.4') + "\n"
6970
print 'Threat: ' + i2p.get_threat('1.2.3.4') + "\n"
71+
print 'Provider: ' + i2p.get_provider('1.2.3.4') + "\n"
7072
7173
# single function to get all proxy data returned in array
7274
record = i2p.get_all('1.2.3.4')
@@ -83,6 +85,7 @@ print 'ASN: ' + record['asn'] + "\n"
8385
print 'AS: ' + record['as'] + "\n"
8486
print 'Last Seen: ' + record['last_seen'] + "\n"
8587
print 'Threat: ' + record['threat'] + "\n"
88+
print 'Provider: ' + record['provider'] + "\n"
8689
8790
# close IP2Proxy BIN database
8891
i2p.close()

example.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
require 'ip2proxy_ruby'
22

33
# open IP2Proxy BIN database for proxy lookup
4-
i2p = Ip2proxy.new.open("./data/IP2PROXY-LITE-PX1.BIN")
4+
i2p = Ip2proxy.new.open("./data/PX11.SAMPLE.BIN")
55

66
# get versioning information
77
print 'Module Version: ' + i2p.get_module_version + "\n"
@@ -22,6 +22,7 @@
2222
print 'AS: ' + i2p.get_as('1.2.3.4') + "\n"
2323
print 'Last Seen: ' + i2p.get_last_seen('1.2.3.4') + "\n"
2424
print 'Threat: ' + i2p.get_threat('1.2.3.4') + "\n"
25+
print 'Provider: ' + i2p.get_provider('1.2.3.4') + "\n"
2526

2627
# single function to get all proxy data returned in array
2728
record = i2p.get_all('1.2.3.4')
@@ -38,6 +39,7 @@
3839
print 'AS: ' + record['as'] + "\n"
3940
print 'Last Seen: ' + record['last_seen'] + "\n"
4041
print 'Threat: ' + record['threat'] + "\n"
42+
print 'Provider: ' + record['provider'] + "\n"
4143

4244
# close IP2Proxy BIN database
4345
i2p.close()

ip2proxy_ruby.gemspec

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
Gem::Specification.new do |s|
44
s.name = "ip2proxy_ruby"
5-
s.version = "3.0.1"
5+
s.version = "3.1.0"
66
s.authors = ["ip2location"]
77
s.email = ["[email protected]"]
88

99
s.summary = "IP2Proxy Ruby library"
10-
s.description = "The official IP2Proxy Ruby library to detect VPN servers, open proxies, web proxies, Tor exit nodes, search engine robots, data center ranges and residential proxies using IP2Proxy BIN database. Other information available includes proxy type, country, state, city, ISP, domain name, usage type, AS number, AS name, threats and last seen date."
10+
s.description = "The official IP2Proxy Ruby library to detect VPN servers, open proxies, web proxies, Tor exit nodes, search engine robots, data center ranges and residential proxies using IP2Proxy BIN database. Other information available includes proxy type, country, state, city, ISP, domain name, usage type, AS number, AS name, threats, last seen date and provider names."
1111
s.homepage = "https://github.com/ip2location/ip2proxy-ruby"
1212
s.licenses = ["MIT"]
1313
s.require_paths = ["lib"]
@@ -31,10 +31,10 @@ Gem::Specification.new do |s|
3131
"lib/ip2proxy_ruby/i2p_string_data.rb",
3232
"lib/ip2proxy_ruby/ip2proxy_config.rb",
3333
"lib/ip2proxy_ruby/ip2proxy_record.rb",
34-
"spec/assets/PX10.SAMPLE.BIN",
34+
"spec/assets/PX11.SAMPLE.BIN",
3535
"spec/ip2proxy_ruby_database_spec.rb",
3636
"spec/spec_helper.rb",
37-
"rb/data/PX10.SAMPLE.BIN"
37+
"rb/data/PX11.SAMPLE.BIN"
3838
]
3939

4040
if s.respond_to?(:metadata=)

lib/ip2proxy_ruby.rb

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,36 @@
77
require_relative 'ip2proxy_ruby/ip2proxy_record'
88

99
class Ip2proxy
10-
attr_accessor :record_class4, :record_class6, :v4, :file, :db_index, :count, :base_addr, :ipno, :record, :database, :columns, :ip_version, :ipv4databasecount, :ipv4databaseaddr, :ipv4indexbaseaddr, :ipv6databasecount, :ipv6databaseaddr, :ipv6indexbaseaddr, :databaseyear, :databasemonth, :databaseday
10+
attr_accessor :record_class4, :record_class6, :v4, :file, :db_index, :count, :base_addr, :ipno, :record, :database, :columns, :ip_version, :ipv4databasecount, :ipv4databaseaddr, :ipv4indexbaseaddr, :ipv6databasecount, :ipv6databaseaddr, :ipv6indexbaseaddr, :databaseyear, :databasemonth, :databaseday, :last_err_msg
1111

12-
VERSION = '3.0.1'
12+
VERSION = '3.1.0'
1313
FIELD_NOT_SUPPORTED = 'NOT SUPPORTED'
1414
INVALID_IP_ADDRESS = 'INVALID IP ADDRESS'
15+
INVALID_BIN_DATABASE = 'Incorrect IP2Proxy BIN file format. Please make sure that you are using the latest IP2Proxy BIN file.'
1516

1617
def open(url)
17-
self.file = File.open(File.expand_path url, 'rb')
18+
if url == ''
19+
self.last_err_msg = 'Ip2proxy.new.open() requires a database path name.'
20+
abort('Ip2proxy.new.open() requires a database path name.')
21+
end
22+
23+
begin
24+
self.file = File.open(File.expand_path url, 'rb')
25+
rescue
26+
self.last_err_msg = 'Ip2proxy.new.open() error in opening ' + url +'.'
27+
abort('Ip2proxy.new.open() error in opening ' + url +'.')
28+
else
29+
end
1830
i2p = Ip2proxyConfig.read(file)
31+
if i2p.productcode == 2
32+
else
33+
if i2p.databaseyear <= 20 && i2p.productcode == 0
34+
else
35+
self.file.close
36+
self.last_err_msg = INVALID_BIN_DATABASE
37+
abort(INVALID_BIN_DATABASE)
38+
end
39+
end
1940
self.db_index = i2p.databasetype
2041
self.columns = i2p.databasecolumn + 0
2142
self.databaseyear = 2000 + i2p.databaseyear
@@ -37,6 +58,10 @@ def close()
3758
self.file.close
3859
end
3960

61+
def get_last_error_message()
62+
return self.last_err_msg
63+
end
64+
4065
def get_module_version()
4166
return VERSION
4267
end
@@ -281,6 +306,21 @@ def is_proxy(ip)
281306
return isproxy
282307
end
283308

309+
def get_provider(ip)
310+
valid = !(IPAddr.new(ip) rescue nil).nil?
311+
if valid
312+
rec = get_record(ip)
313+
if !(rec.nil?)
314+
provider = (defined?(rec.provider) && rec.provider != '') ? rec.provider : FIELD_NOT_SUPPORTED
315+
else
316+
provider = INVALID_IP_ADDRESS
317+
end
318+
else
319+
provider = INVALID_IP_ADDRESS
320+
end
321+
return provider
322+
end
323+
284324
def get_all(ip)
285325
valid = !(IPAddr.new(ip) rescue nil).nil?
286326
if valid
@@ -298,6 +338,7 @@ def get_all(ip)
298338
as = (defined?(rec.as) && rec.as != '') ? rec.as : FIELD_NOT_SUPPORTED
299339
last_seen = (defined?(rec.lastseen) && rec.lastseen != '') ? rec.lastseen : FIELD_NOT_SUPPORTED
300340
threat = (defined?(rec.threat) && rec.threat != '') ? rec.threat : FIELD_NOT_SUPPORTED
341+
provider = (defined?(rec.provider) && rec.provider != '') ? rec.provider : FIELD_NOT_SUPPORTED
301342
if self.db_index == 1
302343
isproxy = (rec.country_short == '-') ? 0 : 1
303344
else
@@ -316,6 +357,7 @@ def get_all(ip)
316357
as = INVALID_IP_ADDRESS
317358
last_seen = INVALID_IP_ADDRESS
318359
threat = INVALID_IP_ADDRESS
360+
provider = INVALID_IP_ADDRESS
319361
isproxy = -1
320362
end
321363
else
@@ -331,6 +373,7 @@ def get_all(ip)
331373
as = INVALID_IP_ADDRESS
332374
last_seen = INVALID_IP_ADDRESS
333375
threat = INVALID_IP_ADDRESS
376+
provider = INVALID_IP_ADDRESS
334377
isproxy = -1
335378
end
336379
results = {}
@@ -347,6 +390,7 @@ def get_all(ip)
347390
results['as'] = as
348391
results['last_seen'] = last_seen
349392
results['threat'] = threat
393+
results['provider'] = provider
350394
return results
351395
end
352396

lib/ip2proxy_ruby/i2p_database_config.rb

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
class I2pDbConfig
22
COLUMNS = {
3-
:COUNTRY => [0, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3],
4-
:REGION => [0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4],
5-
:CITY => [0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5],
6-
:ISP => [0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6],
7-
:PROXYTYPE => [0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2],
8-
:DOMAIN => [0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7],
9-
:USAGETYPE => [0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8],
10-
:ASN => [0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9],
11-
:AS => [0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10],
12-
:LASTSEEN => [0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 11],
13-
:THREAT => [0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12]
3+
:COUNTRY => [0, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3],
4+
:REGION => [0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4],
5+
:CITY => [0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5],
6+
:ISP => [0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 6],
7+
:PROXYTYPE => [0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
8+
:DOMAIN => [0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7],
9+
:USAGETYPE => [0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8],
10+
:ASN => [0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9],
11+
:AS => [0, 0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10],
12+
:LASTSEEN => [0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 11, 11],
13+
:THREAT => [0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12],
14+
:PROVIDER => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13]
1415
}
1516

1617
def self.setup_database(db_index)
Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
11
class Ip2proxyConfig < BinData::Record
22
endian :little
3-
uint8 :databasetype
4-
uint8 :databasecolumn
5-
uint8 :databaseyear
6-
uint8 :databasemonth
7-
uint8 :databaseday
8-
# uint32 :databasecount
9-
# uint32 :databaseaddr
10-
# uint32 :ipversion
3+
uint8 :databasetype
4+
uint8 :databasecolumn
5+
uint8 :databaseyear
6+
uint8 :databasemonth
7+
uint8 :databaseday
8+
# uint32 :databasecount
9+
# uint32 :databaseaddr
10+
# uint32 :ipversion
1111
uint32 :ipv4databasecount
1212
uint32 :ipv4databaseaddr
1313
uint32 :ipv6databasecount
1414
uint32 :ipv6databaseaddr
1515
uint32 :ipv4indexbaseaddr
1616
uint32 :ipv6indexbaseaddr
17+
uint8 :productcode
18+
uint8 :licensecode
19+
uint32 :databasesize
1720
end

0 commit comments

Comments
 (0)