File Coverage

blib/lib/Geo/IP2Location.pm
Criterion Covered Total %
statement 451 966 46.6
branch 88 432 20.3
condition 61 168 36.3
subroutine 81 108 75.0
pod 27 44 61.3
total 708 1718 41.2


line stmt bran cond sub pod time code
1             #MIT License
2             #
3             #Copyright (c) 2021 IP2Location.com
4             #
5             #Permission is hereby granted, free of charge, to any person obtaining a copy
6             #of this software and associated documentation files (the "Software"), to deal
7             #in the Software without restriction, including without limitation the rights
8             #to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9             #copies of the Software, and to permit persons to whom the Software is
10             #furnished to do so, subject to the following conditions:
11             #
12             #The above copyright notice and this permission notice shall be included in all
13             #copies or substantial portions of the Software.
14             #
15             #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16             #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17             #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18             #AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19             #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20             #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21             #SOFTWARE.
22              
23             package Geo::IP2Location;
24              
25 3     3   12882 use strict;
  3         19  
  3         110  
26 3     3   19 use vars qw(@ISA $VERSION @EXPORT);
  3         4  
  3         208  
27 3     3   3691 use Math::BigInt;
  3         86088  
  3         15  
28 3     3   78136 use bigint;
  3         10459  
  3         15  
29              
30             $VERSION = '8.51';
31             require Exporter;
32             @ISA = qw(Exporter);
33              
34 3     3   2211 use constant UNKNOWN => "UNKNOWN IP ADDRESS";
  3         6  
  3         201  
35 3     3   19 use constant IPV6_ADDRESS_IN_IPV4_BIN => "IPV6 ADDRESS MISSING IN IPV4 BIN";
  3         6  
  3         144  
36 3     3   17 use constant NO_IP => "MISSING IP ADDRESS";
  3         4  
  3         183  
37 3     3   46 use constant INVALID_IPV6_ADDRESS => "INVALID IPV6 ADDRESS";
  3         8  
  3         147  
38 3     3   17 use constant INVALID_IPV4_ADDRESS => "INVALID IPV4 ADDRESS";
  3         5  
  3         182  
39 3     3   23 use constant INVALID_IP_ADDRESS => "INVALID IP ADDRESS";
  3         6  
  3         191  
40 3     3   19 use constant INVALID_BIN_DATABASE => "Incorrect IP2Location BIN file format. Please make sure that you are using the latest IP2Location BIN file.";
  3         5  
  3         129  
41 3     3   16 use constant NOT_SUPPORTED => "This parameter is unavailable in selected .BIN data file. Please upgrade data file.";
  3         6  
  3         141  
42 3     3   421 use constant MAX_IPV4_RANGE => 4294967295;
  3         7  
  3         175  
43 3     3   338 use constant MAX_IPV6_RANGE => 340282366920938463463374607431768211455;
  3         6  
  3         125  
44 3     3   284 use constant IP_COUNTRY => 1;
  3         8  
  3         117  
45 3     3   194 use constant IP_COUNTRY_ISP => 2;
  3         16  
  3         145  
46 3     3   202 use constant IP_COUNTRY_REGION_CITY => 3;
  3         4  
  3         113  
47 3     3   206 use constant IP_COUNTRY_REGION_CITY_ISP => 4;
  3         8  
  3         107  
48 3     3   171 use constant IP_COUNTRY_REGION_CITY_LATITUDE_LONGITUDE => 5;
  3         6  
  3         145  
49 3     3   177 use constant IP_COUNTRY_REGION_CITY_LATITUDE_LONGITUDE_ISP => 6;
  3         5  
  3         124  
50 3     3   233 use constant IP_COUNTRY_REGION_CITY_ISP_DOMAIN => 7;
  3         22  
  3         109  
51 3     3   213 use constant IP_COUNTRY_REGION_CITY_LATITUDE_LONGITUDE_ISP_DOMAIN => 8;
  3         6  
  3         2155  
52 3     3   194 use constant IP_COUNTRY_REGION_CITY_LATITUDE_LONGITUDE_ZIPCODE => 9;
  3         6  
  3         99  
53 3     3   165 use constant IP_COUNTRY_REGION_CITY_LATITUDE_LONGITUDE_ZIPCODE_ISP_DOMAIN => 10;
  3         5  
  3         140  
54 3     3   275 use constant IP_COUNTRY_REGION_CITY_LATITUDE_LONGITUDE_ZIPCODE_TIMEZONE => 11;
  3         6  
  3         113  
55 3     3   187 use constant IP_COUNTRY_REGION_CITY_LATITUDE_LONGITUDE_ZIPCODE_TIMEZONE_ISP_DOMAIN => 12;
  3         4  
  3         118  
56 3     3   204 use constant IP_COUNTRY_REGION_CITY_LATITUDE_LONGITUDE_TIMEZONE_NETSPEED => 13;
  3         5  
  3         115  
57 3     3   233 use constant IP_COUNTRY_REGION_CITY_LATITUDE_LONGITUDE_ZIPCODE_TIMEZONE_ISP_DOMAIN_NETSPEED => 14;
  3         6  
  3         109  
58 3     3   201 use constant IP_COUNTRY_REGION_CITY_LATITUDE_LONGITUDE_ZIPCODE_TIMEZONE_AREACODE => 15;
  3         5  
  3         107  
59 3     3   171 use constant IP_COUNTRY_REGION_CITY_LATITUDE_LONGITUDE_ZIPCODE_TIMEZONE_ISP_DOMAIN_NETSPEED_AREACODE => 16;
  3         6  
  3         184  
60 3     3   182 use constant IP_COUNTRY_REGION_CITY_LATITUDE_LONGITUDE_TIMEZONE_NETSPEED_WEATHER => 17;
  3         11  
  3         126  
61 3     3   195 use constant IP_COUNTRY_REGION_CITY_LATITUDE_LONGITUDE_ZIPCODE_TIMEZONE_ISP_DOMAIN_NETSPEED_AREACODE_WEATHER => 18;
  3         4  
  3         120  
62 3     3   219 use constant IP_COUNTRY_REGION_CITY_LATITUDE_LONGITUDE_ISP_DOMAIN_MOBILE => 19;
  3         4  
  3         161  
63 3     3   195 use constant IP_COUNTRY_REGION_CITY_LATITUDE_LONGITUDE_ZIPCODE_TIMEZONE_ISP_DOMAIN_NETSPEED_AREACODE_WEATHER_MOBILE => 20;
  3         5  
  3         137  
64 3     3   180 use constant IP_COUNTRY_REGION_CITY_LATITUDE_LONGITUDE_ZIPCODE_TIMEZONE_AREACODE_ELEVATION => 21;
  3         5  
  3         101  
65 3     3   202 use constant IP_COUNTRY_REGION_CITY_LATITUDE_LONGITUDE_ZIPCODE_TIMEZONE_ISP_DOMAIN_NETSPEED_AREACODE_WEATHER_MOBILE_ELEVATION => 22;
  3         6  
  3         493  
66 3     3   173 use constant IP_COUNTRY_REGION_CITY_LATITUDE_LONGITUDE_ISP_DOMAIN_MOBILE_USAGETYPE => 23;
  3         5  
  3         139  
67 3     3   180 use constant IP_COUNTRY_REGION_CITY_LATITUDE_LONGITUDE_ZIPCODE_TIMEZONE_ISP_DOMAIN_NETSPEED_AREACODE_WEATHER_MOBILE_ELEVATION_USAGETYPE => 24;
  3         4  
  3         143  
68 3     3   211 use constant IP_COUNTRY_REGION_CITY_LATITUDE_LONGITUDE_ZIPCODE_TIMEZONE_ISP_DOMAIN_NETSPEED_AREACODE_WEATHER_MOBILE_ELEVATION_USAGETYPE_ADDRESSTYPE_CATEGORY => 25;
  3         6  
  3         131  
69              
70 3     3   188 use constant COUNTRYSHORT => 1;
  3         5  
  3         127  
71 3     3   177 use constant COUNTRYLONG => 2;
  3         5  
  3         115  
72 3     3   199 use constant REGION => 3;
  3         5  
  3         123  
73 3     3   203 use constant CITY => 4;
  3         5  
  3         117  
74 3     3   174 use constant ISP => 5;
  3         4  
  3         118  
75 3     3   229 use constant LATITUDE => 6;
  3         4  
  3         105  
76 3     3   239 use constant LONGITUDE => 7;
  3         6  
  3         139  
77 3     3   206 use constant DOMAIN => 8;
  3         6  
  3         105  
78 3     3   242 use constant ZIPCODE => 9;
  3         6  
  3         104  
79 3     3   197 use constant TIMEZONE => 10;
  3         6  
  3         123  
80 3     3   181 use constant NETSPEED => 11;
  3         3  
  3         94  
81 3     3   262 use constant IDDCODE => 12;
  3         5  
  3         105  
82 3     3   170 use constant AREACODE => 13;
  3         6  
  3         128  
83 3     3   182 use constant WEATHERSTATIONCODE => 14;
  3         6  
  3         95  
84 3     3   203 use constant WEATHERSTATIONNAME => 15;
  3         5  
  3         106  
85 3     3   182 use constant MCC => 16;
  3         6  
  3         128  
86 3     3   177 use constant MNC => 17;
  3         5  
  3         92  
87 3     3   239 use constant MOBILEBRAND => 18;
  3         6  
  3         108  
88 3     3   170 use constant ELEVATION => 19;
  3         6  
  3         119  
89 3     3   218 use constant USAGETYPE => 20;
  3         6  
  3         102  
90 3     3   196 use constant ADDRESSTYPE => 21;
  3         5  
  3         115  
91 3     3   170 use constant CATEGORY => 22;
  3         6  
  3         163  
92              
93 3     3   195 use constant ALL => 100;
  3         5  
  3         144  
94 3     3   526 use constant IPV4 => 0;
  3         6  
  3         107  
95 3     3   293 use constant IPV6 => 1;
  3         15  
  3         134  
96              
97             my @COUNTRY_POSITION = (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);
98             my @REGION_POSITION = (0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3);
99             my @CITY_POSITION = (0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4);
100             my @LATITUDE_POSITION = (0, 0, 0, 0, 0, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5);
101             my @LONGITUDE_POSITION = (0, 0, 0, 0, 0, 6, 6, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6);
102             my @ZIPCODE_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 0, 7, 7, 7, 0, 7, 0, 7, 7, 7, 0, 7, 7);
103             my @TIMEZONE_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 7, 8, 8, 8, 7, 8, 0, 8, 8, 8, 0, 8, 8);
104             my @ISP_POSITION = (0, 0, 3, 0, 5, 0, 7, 5, 7, 0, 8, 0, 9, 0, 9, 0, 9, 0, 9, 7, 9, 0, 9, 7, 9, 9);
105             my @DOMAIN_POSITION = (0, 0, 0, 0, 0, 0, 0, 6, 8, 0, 9, 0, 10, 0, 10, 0, 10, 0, 10, 8, 10, 0, 10, 8, 10, 10);
106             my @NETSPEED_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 11, 0, 11, 8, 11, 0, 11, 0, 11, 0, 11, 11);
107             my @IDDCODE_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 12, 0, 12, 0, 12, 9, 12, 0, 12, 12);
108             my @AREACODE_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 13, 0, 13, 0, 13, 10, 13, 0, 13, 13);
109             my @WEATHERSTATIONCODE_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 14, 0, 14, 0, 14, 0, 14, 14);
110             my @WEATHERSTATIONNAME_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 15, 0, 15, 0, 15, 0, 15, 15);
111             my @MCC_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 16, 0, 16, 9, 16, 16);
112             my @MNC_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 17, 0, 17, 10, 17, 17);
113             my @MOBILEBRAND_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 18, 0, 18, 11, 18, 18);
114             my @ELEVATION_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 19, 0, 19, 19);
115             my @USAGETYPE_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 20, 20);
116             my @ADDRESSTYPE_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21);
117             my @CATEGORY_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22);
118              
119             my @IPV6_COUNTRY_POSITION = (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);
120             my @IPV6_REGION_POSITION = (0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3);
121             my @IPV6_CITY_POSITION = (0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4);
122             my @IPV6_LATITUDE_POSITION = (0, 0, 0, 0, 0, 5, 5, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5);
123             my @IPV6_LONGITUDE_POSITION = (0, 0, 0, 0, 0, 6, 6, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6);
124             my @IPV6_ZIPCODE_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 0, 7, 7, 7, 0, 7, 0, 7, 7, 7, 0, 7, 7);
125             my @IPV6_TIMEZONE_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 7, 8, 8, 8, 7, 8, 0, 8, 8, 8, 0, 8, 8);
126             my @IPV6_ISP_POSITION = (0, 0, 3, 0, 5, 0, 7, 5, 7, 0, 8, 0, 9, 0, 9, 0, 9, 0, 9, 7, 9, 0, 9, 7, 9, 9);
127             my @IPV6_DOMAIN_POSITION = (0, 0, 0, 0, 0, 0, 0, 6, 8, 0, 9, 0, 10, 0, 10, 0, 10, 0, 10, 8, 10, 0, 10, 8, 10, 10);
128             my @IPV6_NETSPEED_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 11, 0, 11, 8, 11, 0, 11, 0, 11, 0, 11, 11);
129             my @IPV6_IDDCODE_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 12, 0, 12, 0, 12, 9, 12, 0, 12, 12);
130             my @IPV6_AREACODE_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 13, 0, 13, 0, 13, 10, 13, 0, 13, 13);
131             my @IPV6_WEATHERSTATIONCODE_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 14, 0, 14, 0, 14, 0, 14, 14);
132             my @IPV6_WEATHERSTATIONNAME_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 15, 0, 15, 0, 15, 0, 15, 15);
133             my @IPV6_MCC_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 16, 0, 16, 9, 16, 16);
134             my @IPV6_MNC_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 17, 0, 17, 10, 17, 17);
135             my @IPV6_MOBILEBRAND_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 18, 0, 18, 11, 18, 18);
136             my @IPV6_ELEVATION_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 19, 0, 19, 19);
137             my @IPV6_USAGETYPE_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 20, 20);
138             my @IPV6_ADDRESSTYPE_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21);
139             my @IPV6_CATEGORY_POSITION = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22);
140              
141              
142             my $IPv6_re = qr/:(?::[0-9a-fA-F]{1,4}){0,5}(?:(?::[0-9a-fA-F]{1,4}){1,2}|:(?:(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})))|[0-9a-fA-F]{1,4}:(?:[0-9a-fA-F]{1,4}:(?:[0-9a-fA-F]{1,4}:(?:[0-9a-fA-F]{1,4}:(?:[0-9a-fA-F]{1,4}:(?:[0-9a-fA-F]{1,4}:(?:[0-9a-fA-F]{1,4}:(?:[0-9a-fA-F]{1,4}|:)|(?::(?:[0-9a-fA-F]{1,4})?|(?:(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2}))))|:(?:(?:(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2}))|[0-9a-fA-F]{1,4}(?::[0-9a-fA-F]{1,4})?|))|(?::(?:(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2}))|:[0-9a-fA-F]{1,4}(?::(?:(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2}))|(?::[0-9a-fA-F]{1,4}){0,2})|:))|(?:(?::[0-9a-fA-F]{1,4}){0,2}(?::(?:(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2}))|(?::[0-9a-fA-F]{1,4}){1,2})|:))|(?:(?::[0-9a-fA-F]{1,4}){0,3}(?::(?:(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2}))|(?::[0-9a-fA-F]{1,4}){1,2})|:))|(?:(?::[0-9a-fA-F]{1,4}){0,4}(?::(?:(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})[.](?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2}))|(?::[0-9a-fA-F]{1,4}){1,2})|:))/;
143             my $IPv4_re = qr/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/;
144              
145             my $getLastErrorMessage = "";
146              
147             sub open {
148 2 50 33 2 1 103 unless( (@_ > 1) && ($_[1]) ) {
149 0         0 $getLastErrorMessage = "Geo::IP2Location::open() requires a database path name.";
150 0         0 die "Geo::IP2Location::open() requires a database path name";
151             }
152 2         347 my ($class, $db_file) = @_;
153 2         6 my $handle;
154             my $obj;
155 2 50       94 unless (CORE::open $handle, "$db_file") {
156 0         0 $getLastErrorMessage = "Geo::IP2Location::open() error in opening $db_file" . ".";
157 0         0 die "Geo::IP2Location::open() error in opening $db_file";
158             }
159 2         10 binmode($handle);
160 2         12 $obj = bless {filehandle => $handle}, $class;
161 2         9 $obj->initialize();
162 2 50       10 if ($obj->{"productcode"} == 1) {
163             } else {
164 2 50 33     484 if (($obj->{"databaseyear"} <= 20) && ($obj->{"productcode"} == 0)) {
165             } else {
166 0         0 $obj->close();
167 0         0 undef $obj;
168 0         0 $getLastErrorMessage = INVALID_BIN_DATABASE;
169 0         0 die INVALID_BIN_DATABASE;
170             }
171             }
172 2         476 return $obj;
173             }
174              
175             sub close {
176 0     0 0 0 my ($class) = @_;
177 0 0       0 if (CORE::close($class->{filehandle})) {
178 0         0 return 0;
179             } else {
180 0         0 return 1;
181             }
182             }
183              
184             sub initialize {
185 2     2 0 7 my ($obj) = @_;
186 2         18 $obj->{"databasetype"} = $obj->read8($obj->{filehandle}, 1);
187 2         12 $obj->{"databasecolumn"} = $obj->read8($obj->{filehandle}, 2);
188 2         8 $obj->{"databaseyear"} = $obj->read8($obj->{filehandle}, 3);
189 2         9 $obj->{"databasemonth"} = $obj->read8($obj->{filehandle}, 4);
190 2         10 $obj->{"databaseday"} = $obj->read8($obj->{filehandle}, 5);
191 2         12 $obj->{"ipv4databasecount"} = $obj->read32($obj->{filehandle}, 6);
192 2         7 $obj->{"ipv4databaseaddr"} = $obj->read32($obj->{filehandle}, 10);
193 2         9 $obj->{"ipv6databasecount"} = $obj->read32($obj->{filehandle}, 14);
194 2         10 $obj->{"ipv6databaseaddr"} = $obj->read32($obj->{filehandle}, 18);
195 2         10 $obj->{"ipv4indexbaseaddr"} = $obj->read32($obj->{filehandle}, 22);
196 2         8 $obj->{"ipv6indexbaseaddr"} = $obj->read32($obj->{filehandle}, 26);
197 2         8 $obj->{"productcode"} = $obj->read8($obj->{filehandle}, 30);
198 2         17 $obj->{"licensecode"} = $obj->read8($obj->{filehandle}, 31);
199 2         18 $obj->{"databasesize"} = $obj->read32($obj->{filehandle}, 32);
200 2         6 return $obj;
201             }
202              
203             sub get_last_error_message {
204 0     0 1 0 my $class = shift(@_);
205 0         0 return ($getLastErrorMessage);
206             }
207              
208             sub get_module_version {
209 0     0 1 0 my $obj = shift(@_);
210 0         0 return $VERSION;
211             }
212              
213             sub get_database_version {
214 0     0 1 0 my $obj = shift(@_);
215 0         0 return $obj->{"databaseyear"} . "." . $obj->{"databasemonth"} . "." . $obj->{"databaseday"};
216             }
217              
218             sub get_country_short {
219 20     20 1 2224 my $obj = shift(@_);
220 20         39 my $ipaddr = shift(@_);
221 20         57 my ($ipv, $ipnum) = $obj->validate_ip($ipaddr);
222 20 100       53 if ($ipv == 4) {
223 10         354 return $obj->get_ipv4_record($ipnum, COUNTRYSHORT);
224             } else {
225 10 50       300 if ($ipv == 6) {
226 10         292 return $obj->get_ipv6_record($ipnum, COUNTRYSHORT);
227             } else {
228 0         0 return INVALID_IP_ADDRESS;
229             }
230             }
231             }
232              
233             sub get_country_long {
234 0     0 1 0 my $obj = shift(@_);
235 0         0 my $ipaddr = shift(@_);
236 0         0 my ($ipv, $ipnum) = $obj->validate_ip($ipaddr);
237 0 0       0 if ($ipv == 4) {
238 0         0 return $obj->get_ipv4_record($ipnum, COUNTRYLONG);
239             } else {
240 0 0       0 if ($ipv == 6) {
241 0         0 return $obj->get_ipv6_record($ipnum, COUNTRYLONG);
242             } else {
243 0         0 return INVALID_IP_ADDRESS;
244             }
245             }
246             }
247              
248             sub get_region {
249 0     0 1 0 my $obj = shift(@_);
250 0         0 my $ipaddr = shift(@_);
251 0         0 my ($ipv, $ipnum) = $obj->validate_ip($ipaddr);
252 0 0       0 if ($ipv == 4) {
253 0         0 return $obj->get_ipv4_record($ipnum, REGION);
254             } else {
255 0 0       0 if ($ipv == 6) {
256 0         0 return $obj->get_ipv6_record($ipnum, REGION);
257             } else {
258 0         0 return INVALID_IP_ADDRESS;
259             }
260             }
261             }
262              
263             sub get_city {
264 0     0 1 0 my $obj = shift(@_);
265 0         0 my $ipaddr = shift(@_);
266 0         0 my ($ipv, $ipnum) = $obj->validate_ip($ipaddr);
267 0 0       0 if ($ipv == 4) {
268 0         0 return $obj->get_ipv4_record($ipnum, CITY);
269             } else {
270 0 0       0 if ($ipv == 6) {
271 0         0 return $obj->get_ipv6_record($ipnum, CITY);
272             } else {
273 0         0 return INVALID_IP_ADDRESS;
274             }
275             }
276             }
277              
278             sub get_isp {
279 0     0 1 0 my $obj = shift(@_);
280 0         0 my $ipaddr = shift(@_);
281 0         0 my ($ipv, $ipnum) = $obj->validate_ip($ipaddr);
282 0 0       0 if ($ipv == 4) {
283 0         0 return $obj->get_ipv4_record($ipnum, ISP);
284             } else {
285 0 0       0 if ($ipv == 6) {
286 0         0 return $obj->get_ipv6_record($ipnum, ISP);
287             } else {
288 0         0 return INVALID_IP_ADDRESS;
289             }
290             }
291             }
292              
293             sub get_latitude {
294 0     0 1 0 my $obj = shift(@_);
295 0         0 my $ipaddr = shift(@_);
296 0         0 my ($ipv, $ipnum) = $obj->validate_ip($ipaddr);
297 0 0       0 if ($ipv == 4) {
298 0         0 return $obj->get_ipv4_record($ipnum, LATITUDE);
299             } else {
300 0 0       0 if ($ipv == 6) {
301 0         0 return $obj->get_ipv6_record($ipnum, LATITUDE);
302             } else {
303 0         0 return INVALID_IP_ADDRESS;
304             }
305             }
306             }
307              
308             sub get_zipcode {
309 0     0 1 0 my $obj = shift(@_);
310 0         0 my $ipaddr = shift(@_);
311 0         0 my ($ipv, $ipnum) = $obj->validate_ip($ipaddr);
312 0 0       0 if ($ipv == 4) {
313 0         0 return $obj->get_ipv4_record($ipnum, ZIPCODE);
314             } else {
315 0 0       0 if ($ipv == 6) {
316 0         0 return $obj->get_ipv6_record($ipnum, ZIPCODE);
317             } else {
318 0         0 return INVALID_IP_ADDRESS;
319             }
320             }
321             }
322              
323             sub get_longitude {
324 0     0 1 0 my $obj = shift(@_);
325 0         0 my $ipaddr = shift(@_);
326 0         0 my ($ipv, $ipnum) = $obj->validate_ip($ipaddr);
327 0 0       0 if ($ipv == 4) {
328 0         0 return $obj->get_ipv4_record($ipnum, LONGITUDE);
329             } else {
330 0 0       0 if ($ipv == 6) {
331 0         0 return $obj->get_ipv6_record($ipnum, LONGITUDE);
332             } else {
333 0         0 return INVALID_IP_ADDRESS;
334             }
335             }
336             }
337              
338             sub get_domain {
339 0     0 1 0 my $obj = shift(@_);
340 0         0 my $ipaddr = shift(@_);
341 0         0 my ($ipv, $ipnum) = $obj->validate_ip($ipaddr);
342 0 0       0 if ($ipv == 4) {
343 0         0 return $obj->get_ipv4_record($ipnum, DOMAIN);
344             } else {
345 0 0       0 if ($ipv == 6) {
346 0         0 return $obj->get_ipv6_record($ipnum, DOMAIN);
347             } else {
348 0         0 return INVALID_IP_ADDRESS;
349             }
350             }
351             }
352              
353             sub get_timezone {
354 0     0 1 0 my $obj = shift(@_);
355 0         0 my $ipaddr = shift(@_);
356 0         0 my ($ipv, $ipnum) = $obj->validate_ip($ipaddr);
357 0 0       0 if ($ipv == 4) {
358 0         0 return $obj->get_ipv4_record($ipnum, TIMEZONE);
359             } else {
360 0 0       0 if ($ipv == 6) {
361 0         0 return $obj->get_ipv6_record($ipnum, TIMEZONE);
362             } else {
363 0         0 return INVALID_IP_ADDRESS;
364             }
365             }
366             }
367              
368             sub get_netspeed {
369 0     0 1 0 my $obj = shift(@_);
370 0         0 my $ipaddr = shift(@_);
371 0         0 my ($ipv, $ipnum) = $obj->validate_ip($ipaddr);
372 0 0       0 if ($ipv == 4) {
373 0         0 return $obj->get_ipv4_record($ipnum, NETSPEED);
374             } else {
375 0 0       0 if ($ipv == 6) {
376 0         0 return $obj->get_ipv6_record($ipnum, NETSPEED);
377             } else {
378 0         0 return INVALID_IP_ADDRESS;
379             }
380             }
381             }
382              
383             sub get_iddcode {
384 0     0 1 0 my $obj = shift(@_);
385 0         0 my $ipaddr = shift(@_);
386 0         0 my ($ipv, $ipnum) = $obj->validate_ip($ipaddr);
387 0 0       0 if ($ipv == 4) {
388 0         0 return $obj->get_ipv4_record($ipnum, IDDCODE);
389             } else {
390 0 0       0 if ($ipv == 6) {
391 0         0 return $obj->get_ipv6_record($ipnum, IDDCODE);
392             } else {
393 0         0 return INVALID_IP_ADDRESS;
394             }
395             }
396             }
397              
398             sub get_areacode {
399 0     0 1 0 my $obj = shift(@_);
400 0         0 my $ipaddr = shift(@_);
401 0         0 my ($ipv, $ipnum) = $obj->validate_ip($ipaddr);
402 0 0       0 if ($ipv == 4) {
403 0         0 return $obj->get_ipv4_record($ipnum, AREACODE);
404             } else {
405 0 0       0 if ($ipv == 6) {
406 0         0 return $obj->get_ipv6_record($ipnum, AREACODE);
407             } else {
408 0         0 return INVALID_IP_ADDRESS;
409             }
410             }
411             }
412              
413             sub get_weatherstationcode {
414 0     0 1 0 my $obj = shift(@_);
415 0         0 my $ipaddr = shift(@_);
416 0         0 my ($ipv, $ipnum) = $obj->validate_ip($ipaddr);
417 0 0       0 if ($ipv == 4) {
418 0         0 return $obj->get_ipv4_record($ipnum, WEATHERSTATIONCODE);
419             } else {
420 0 0       0 if ($ipv == 6) {
421 0         0 return $obj->get_ipv6_record($ipnum, WEATHERSTATIONCODE);
422             } else {
423 0         0 return INVALID_IP_ADDRESS;
424             }
425             }
426             }
427              
428             sub get_weatherstationname {
429 0     0 1 0 my $obj = shift(@_);
430 0         0 my $ipaddr = shift(@_);
431 0         0 my ($ipv, $ipnum) = $obj->validate_ip($ipaddr);
432 0 0       0 if ($ipv == 4) {
433 0         0 return $obj->get_ipv4_record($ipnum, WEATHERSTATIONNAME);
434             } else {
435 0 0       0 if ($ipv == 6) {
436 0         0 return $obj->get_ipv6_record($ipnum, WEATHERSTATIONNAME);
437             } else {
438 0         0 return INVALID_IP_ADDRESS;
439             }
440             }
441             }
442              
443             sub get_mcc {
444 0     0 1 0 my $obj = shift(@_);
445 0         0 my $ipaddr = shift(@_);
446 0         0 my ($ipv, $ipnum) = $obj->validate_ip($ipaddr);
447 0 0       0 if ($ipv == 4) {
448 0         0 return $obj->get_ipv4_record($ipnum, MCC);
449             } else {
450 0 0       0 if ($ipv == 6) {
451 0         0 return $obj->get_ipv6_record($ipnum, MCC);
452             } else {
453 0         0 return INVALID_IP_ADDRESS;
454             }
455             }
456             }
457              
458             sub get_mnc {
459 0     0 1 0 my $obj = shift(@_);
460 0         0 my $ipaddr = shift(@_);
461 0         0 my ($ipv, $ipnum) = $obj->validate_ip($ipaddr);
462 0 0       0 if ($ipv == 4) {
463 0         0 return $obj->get_ipv4_record($ipnum, MNC);
464             } else {
465 0 0       0 if ($ipv == 6) {
466 0         0 return $obj->get_ipv6_record($ipnum, MNC);
467             } else {
468 0         0 return INVALID_IP_ADDRESS;
469             }
470             }
471             }
472              
473             sub get_mobilebrand {
474 0     0 1 0 my $obj = shift(@_);
475 0         0 my $ipaddr = shift(@_);
476 0         0 my ($ipv, $ipnum) = $obj->validate_ip($ipaddr);
477 0 0       0 if ($ipv == 4) {
478 0         0 return $obj->get_ipv4_record($ipnum, MOBILEBRAND);
479             } else {
480 0 0       0 if ($ipv == 6) {
481 0         0 return $obj->get_ipv6_record($ipnum, MOBILEBRAND);
482             } else {
483 0         0 return INVALID_IP_ADDRESS;
484             }
485             }
486             }
487              
488             sub get_elevation {
489 0     0 1 0 my $obj = shift(@_);
490 0         0 my $ipaddr = shift(@_);
491 0         0 my ($ipv, $ipnum) = $obj->validate_ip($ipaddr);
492 0 0       0 if ($ipv == 4) {
493 0         0 return $obj->get_ipv4_record($ipnum, ELEVATION);
494             } else {
495 0 0       0 if ($ipv == 6) {
496 0         0 return $obj->get_ipv6_record($ipnum, ELEVATION);
497             } else {
498 0         0 return INVALID_IP_ADDRESS;
499             }
500             }
501             }
502              
503             sub get_usagetype {
504 0     0 1 0 my $obj = shift(@_);
505 0         0 my $ipaddr = shift(@_);
506 0         0 my ($ipv, $ipnum) = $obj->validate_ip($ipaddr);
507 0 0       0 if ($ipv == 4) {
508 0         0 return $obj->get_ipv4_record($ipnum, USAGETYPE);
509             } else {
510 0 0       0 if ($ipv == 6) {
511 0         0 return $obj->get_ipv6_record($ipnum, USAGETYPE);
512             } else {
513 0         0 return INVALID_IP_ADDRESS;
514             }
515             }
516             }
517              
518             sub get_addresstype {
519 0     0 1 0 my $obj = shift(@_);
520 0         0 my $ipaddr = shift(@_);
521 0         0 my ($ipv, $ipnum) = $obj->validate_ip($ipaddr);
522 0 0       0 if ($ipv == 4) {
523 0         0 return $obj->get_ipv4_record($ipnum, ADDRESSTYPE);
524             } else {
525 0 0       0 if ($ipv == 6) {
526 0         0 return $obj->get_ipv6_record($ipnum, ADDRESSTYPE);
527             } else {
528 0         0 return INVALID_IP_ADDRESS;
529             }
530             }
531             }
532              
533             sub get_category {
534 0     0 1 0 my $obj = shift(@_);
535 0         0 my $ipaddr = shift(@_);
536 0         0 my ($ipv, $ipnum) = $obj->validate_ip($ipaddr);
537 0 0       0 if ($ipv == 4) {
538 0         0 return $obj->get_ipv4_record($ipnum, CATEGORY);
539             } else {
540 0 0       0 if ($ipv == 6) {
541 0         0 return $obj->get_ipv6_record($ipnum, CATEGORY);
542             } else {
543 0         0 return INVALID_IP_ADDRESS;
544             }
545             }
546             }
547              
548             sub get_all {
549 0     0 1 0 my $obj = shift(@_);
550 0         0 my $ipaddr = shift(@_);
551 0         0 my ($ipv, $ipnum) = $obj->validate_ip($ipaddr);
552 0 0       0 if ($ipv == 4) {
553 0         0 return $obj->get_ipv4_record($ipnum, ALL);
554             } else {
555 0 0       0 if ($ipv == 6) {
556 0         0 return $obj->get_ipv6_record($ipnum, ALL);
557             } else {
558 0         0 return (INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS, INVALID_IP_ADDRESS);
559             }
560             }
561             }
562              
563             sub get_ipv6_record {
564 10     10 0 21 my $obj = shift(@_);
565 10         18 my $ipnum = shift(@_);
566 10         13 my $mode = shift(@_);
567 10         23 my $dbtype = $obj->{"databasetype"};
568              
569 10 50       33 if ($ipnum eq "") {
570 0 0       0 if ($mode == ALL) {
571 0         0 return (NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP);
572             } else {
573 0         0 return NO_IP;
574             }
575             }
576              
577 10 50 33     318 if (($mode == COUNTRYSHORT) && ($IPV6_COUNTRY_POSITION[$dbtype] == 0)) {
578 0         0 return NOT_SUPPORTED;
579             }
580 10 50 33     580 if (($mode == COUNTRYLONG) && ($IPV6_COUNTRY_POSITION[$dbtype] == 0)) {
581 0         0 return NOT_SUPPORTED;
582             }
583 10 50 33     330 if (($mode == REGION) && ($IPV6_REGION_POSITION[$dbtype] == 0)) {
584 0         0 return NOT_SUPPORTED;
585             }
586 10 50 33     325 if (($mode == CITY) && ($IPV6_CITY_POSITION[$dbtype] == 0)) {
587 0         0 return NOT_SUPPORTED;
588             }
589 10 50 33     317 if (($mode == ISP) && ($IPV6_ISP_POSITION[$dbtype] == 0)) {
590 0         0 return NOT_SUPPORTED;
591             }
592 10 50 33     280 if (($mode == LATITUDE) && ($IPV6_LATITUDE_POSITION[$dbtype] == 0)) {
593 0         0 return NOT_SUPPORTED;
594             }
595 10 50 33     273 if (($mode == LONGITUDE) && ($IPV6_LONGITUDE_POSITION[$dbtype] == 0)) {
596 0         0 return NOT_SUPPORTED;
597             }
598 10 50 33     292 if (($mode == DOMAIN) && ($IPV6_DOMAIN_POSITION[$dbtype] == 0)) {
599 0         0 return NOT_SUPPORTED;
600             }
601 10 50 33     281 if (($mode == ZIPCODE) && ($IPV6_ZIPCODE_POSITION[$dbtype] == 0)) {
602 0         0 return NOT_SUPPORTED;
603             }
604 10 50 33     273 if (($mode == TIMEZONE) && ($IPV6_TIMEZONE_POSITION[$dbtype] == 0)) {
605 0         0 return NOT_SUPPORTED;
606             }
607 10 50 33     272 if (($mode == NETSPEED) && ($IPV6_NETSPEED_POSITION[$dbtype] == 0)) {
608 0         0 return NOT_SUPPORTED;
609             }
610 10 50 33     269 if (($mode == IDDCODE) && ($IPV6_IDDCODE_POSITION[$dbtype] == 0)) {
611 0         0 return NOT_SUPPORTED;
612             }
613 10 50 33     289 if (($mode == AREACODE) && ($IPV6_AREACODE_POSITION[$dbtype] == 0)) {
614 0         0 return NOT_SUPPORTED;
615             }
616 10 50 33     286 if (($mode == WEATHERSTATIONCODE) && ($IPV6_WEATHERSTATIONCODE_POSITION[$dbtype] == 0)) {
617 0         0 return NOT_SUPPORTED;
618             }
619 10 50 33     271 if (($mode == WEATHERSTATIONNAME) && ($IPV6_WEATHERSTATIONNAME_POSITION[$dbtype] == 0)) {
620 0         0 return NOT_SUPPORTED;
621             }
622 10 50 33     274 if (($mode == MCC) && ($IPV6_MCC_POSITION[$dbtype] == 0)) {
623 0         0 return NOT_SUPPORTED;
624             }
625 10 50 33     279 if (($mode == MNC) && ($IPV6_MNC_POSITION[$dbtype] == 0)) {
626 0         0 return NOT_SUPPORTED;
627             }
628 10 50 33     275 if (($mode == MOBILEBRAND) && ($IPV6_MOBILEBRAND_POSITION[$dbtype] == 0)) {
629 0         0 return NOT_SUPPORTED;
630             }
631 10 50 33     285 if (($mode == ELEVATION) && ($IPV6_ELEVATION_POSITION[$dbtype] == 0)) {
632 0         0 return NOT_SUPPORTED;
633             }
634 10 50 33     271 if (($mode == USAGETYPE) && ($IPV6_USAGETYPE_POSITION[$dbtype] == 0)) {
635 0         0 return NOT_SUPPORTED;
636             }
637 10 50 33     273 if (($mode == ADDRESSTYPE) && ($IPV6_ADDRESSTYPE_POSITION[$dbtype] == 0)) {
638 0         0 return NOT_SUPPORTED;
639             }
640 10 50 33     308 if (($mode == CATEGORY) && ($IPV6_CATEGORY_POSITION[$dbtype] == 0)) {
641 0         0 return NOT_SUPPORTED;
642             }
643              
644 10         271 my $realipno = $ipnum;
645 10         22 my $handle = $obj->{"filehandle"};
646 10         16 my $baseaddr = $obj->{"ipv6databaseaddr"};
647 10         18 my $dbcount = $obj->{"ipv6databasecount"};
648 10         15 my $dbcolumn = $obj->{"databasecolumn"};
649 10         20 my $indexbaseaddr = $obj->{"ipv6indexbaseaddr"};
650              
651 10 50       22 if ($dbcount == 0) {
652 0 0       0 if ($mode == ALL) {
653 0         0 return (IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN, IPV6_ADDRESS_IN_IPV4_BIN);
654             } else {
655 0         0 return IPV6_ADDRESS_IN_IPV4_BIN;
656             }
657             }
658              
659 10         1112 my $ipnum1_2 = new Math::BigInt($ipnum);
660 10         366 my $remainder = 0;
661 10         29 ($ipnum1_2, $remainder) = $ipnum1_2->bdiv(2**112);
662 10         3028 my $indexaddr = $indexbaseaddr + ($ipnum1_2 << 3);
663              
664 10         3152 my $low = 0;
665 10         17 my $high = $dbcount;
666 10 50       29 if ($indexbaseaddr > 0) {
667 10         718 $low = $obj->read32($handle, $indexaddr);
668 10         41 $high = $obj->read32($handle, $indexaddr + 4);
669             }
670              
671 10         44 my $mid = 0;
672 10         19 my $ipfrom = 0;
673 10         14 my $ipto = 0;
674 10         19 my $ipno = 0;
675              
676 10         17 $ipno = $realipno;
677 10 50       35 if ($realipno == "340282366920938463463374607431768211455") {
678 0         0 $ipno = $ipno->bsub(1);
679             }
680              
681 10         1407 while ($low <= $high) {
682 104         16077 $mid = int(($low + $high)/2);
683 104         31443 $ipfrom = $obj->read128($handle, $baseaddr + $mid * (($dbcolumn * 4) + 12));
684 104         3864 $ipto = $obj->read128($handle, $baseaddr + ($mid + 1) * (($dbcolumn * 4) + 12));
685 104 100 100     3929 if (($ipno >= $ipfrom) && ($ipno < $ipto)) {
686 10         2675 my $row_pointer = $baseaddr + $mid * (($dbcolumn * 4) + 12);
687             # read whole results string into temp string and parse results from memory
688 10         4319 my $raw_positions_row;
689 10         34 seek($handle, $row_pointer - 1, 0);
690 10         1801 read($handle, $raw_positions_row, $dbcolumn * 4 + 12);
691            
692 10 50       2739 if ($mode == ALL) {
693 0         0 my $country_short = NOT_SUPPORTED;
694 0         0 my $country_long = NOT_SUPPORTED;
695 0         0 my $region = NOT_SUPPORTED;
696 0         0 my $city = NOT_SUPPORTED;
697 0         0 my $isp = NOT_SUPPORTED;
698 0         0 my $latitude = NOT_SUPPORTED;
699 0         0 my $longitude = NOT_SUPPORTED;
700 0         0 my $domain = NOT_SUPPORTED;
701 0         0 my $zipcode = NOT_SUPPORTED;
702 0         0 my $timezone = NOT_SUPPORTED;
703 0         0 my $netspeed = NOT_SUPPORTED;
704 0         0 my $iddcode = NOT_SUPPORTED;
705 0         0 my $areacode = NOT_SUPPORTED;
706 0         0 my $weatherstationcode = NOT_SUPPORTED;
707 0         0 my $weatherstationname = NOT_SUPPORTED;
708 0         0 my $mcc = NOT_SUPPORTED;
709 0         0 my $mnc = NOT_SUPPORTED;
710 0         0 my $mobilebrand = NOT_SUPPORTED;
711 0         0 my $elevation = NOT_SUPPORTED;
712 0         0 my $usagetype = NOT_SUPPORTED;
713 0         0 my $addresstype = NOT_SUPPORTED;
714 0         0 my $category = NOT_SUPPORTED;
715            
716 0 0       0 if ($IPV6_COUNTRY_POSITION[$dbtype] != 0) {
717 0         0 $country_short = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_COUNTRY_POSITION[$dbtype]+2), 4)));
718 0         0 $country_long = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_COUNTRY_POSITION[$dbtype]+2), 4)) + 3);
719             }
720 0 0       0 if ($IPV6_REGION_POSITION[$dbtype] != 0) {
721 0         0 $region = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_REGION_POSITION[$dbtype]+2), 4)));
722             }
723 0 0       0 if ($IPV6_CITY_POSITION[$dbtype] != 0) {
724 0         0 $city = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_CITY_POSITION[$dbtype]+2), 4)));
725             }
726 0 0       0 if ($IPV6_ISP_POSITION[$dbtype] != 0) {
727 0         0 $isp = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_ISP_POSITION[$dbtype]+2), 4)));
728             }
729 0 0       0 if ($IPV6_LATITUDE_POSITION[$dbtype] != 0) {
730 0         0 $latitude = $obj->readFloat(substr($raw_positions_row, 4 * ($IPV6_LATITUDE_POSITION[$dbtype]+2)));
731 0         0 $latitude = sprintf("%.6f", $latitude);
732             }
733 0 0       0 if ($IPV6_LONGITUDE_POSITION[$dbtype] != 0) {
734 0         0 $longitude = $obj->readFloat(substr($raw_positions_row, 4 * ($IPV6_LONGITUDE_POSITION[$dbtype]+2)));
735 0         0 $longitude = sprintf("%.6f", $longitude);
736             }
737 0 0       0 if ($IPV6_DOMAIN_POSITION[$dbtype] != 0) {
738 0         0 $domain = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_DOMAIN_POSITION[$dbtype]+2), 4)));
739             }
740 0 0       0 if ($IPV6_ZIPCODE_POSITION[$dbtype] != 0) {
741 0         0 $zipcode = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_ZIPCODE_POSITION[$dbtype]+2), 4)));
742             }
743 0 0       0 if ($IPV6_TIMEZONE_POSITION[$dbtype] != 0) {
744 0         0 $timezone = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_TIMEZONE_POSITION[$dbtype]+2), 4)));
745             }
746 0 0       0 if ($IPV6_NETSPEED_POSITION[$dbtype] != 0) {
747 0         0 $netspeed = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_NETSPEED_POSITION[$dbtype]+2), 4)));
748             }
749 0 0       0 if ($IPV6_IDDCODE_POSITION[$dbtype] != 0) {
750 0         0 $iddcode = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_IDDCODE_POSITION[$dbtype]+2), 4)));
751             }
752 0 0       0 if ($IPV6_AREACODE_POSITION[$dbtype] != 0) {
753 0         0 $areacode = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_AREACODE_POSITION[$dbtype]+2), 4)));
754             }
755 0 0       0 if ($IPV6_WEATHERSTATIONCODE_POSITION[$dbtype] != 0) {
756 0         0 $weatherstationcode = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_WEATHERSTATIONCODE_POSITION[$dbtype]+2), 4)));
757             }
758 0 0       0 if ($IPV6_WEATHERSTATIONNAME_POSITION[$dbtype] != 0) {
759 0         0 $weatherstationname = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_WEATHERSTATIONNAME_POSITION[$dbtype]+2), 4)));
760             }
761 0 0       0 if ($IPV6_MCC_POSITION[$dbtype] != 0) {
762 0         0 $mcc = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_MCC_POSITION[$dbtype]+2), 4)));
763             }
764 0 0       0 if ($IPV6_MNC_POSITION[$dbtype] != 0) {
765 0         0 $mnc = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_MNC_POSITION[$dbtype]+2), 4)));
766             }
767 0 0       0 if ($IPV6_MOBILEBRAND_POSITION[$dbtype] != 0) {
768 0         0 $mobilebrand = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_MOBILEBRAND_POSITION[$dbtype]+2), 4)));
769             }
770 0 0       0 if ($IPV6_ELEVATION_POSITION[$dbtype] != 0) {
771 0         0 $elevation = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_ELEVATION_POSITION[$dbtype]+2), 4)));
772             }
773 0 0       0 if ($IPV6_USAGETYPE_POSITION[$dbtype] != 0) {
774 0         0 $usagetype = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_USAGETYPE_POSITION[$dbtype]+2), 4)));
775             }
776 0 0       0 if ($IPV6_ADDRESSTYPE_POSITION[$dbtype] != 0) {
777 0         0 $addresstype = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_ADDRESSTYPE_POSITION[$dbtype]+2), 4)));
778             }
779 0 0       0 if ($IPV6_CATEGORY_POSITION[$dbtype] != 0) {
780 0         0 $category = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_CATEGORY_POSITION[$dbtype]+2), 4)));
781             }
782 0         0 return ($country_short, $country_long, $region, $city, $latitude, $longitude, $zipcode, $timezone, $isp, $domain, $netspeed, $iddcode, $areacode, $weatherstationcode, $weatherstationname, $mcc, $mnc, $mobilebrand, $elevation, $usagetype, $addresstype, $category);
783             }
784 10 50       395 if ($mode == COUNTRYSHORT) {
785 10         294 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_COUNTRY_POSITION[$dbtype]+2), 4)));
786             }
787 0 0       0 if ($mode == COUNTRYLONG) {
788 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_COUNTRY_POSITION[$dbtype]+2), 4)) + 3);
789             }
790 0 0       0 if ($mode == REGION) {
791 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_REGION_POSITION[$dbtype]+2), 4)));
792             }
793 0 0       0 if ($mode == CITY) {
794 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_CITY_POSITION[$dbtype]+2), 4)));
795             }
796 0 0       0 if ($mode == ISP) {
797 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_ISP_POSITION[$dbtype]+2), 4)));
798             }
799 0 0       0 if ($mode == LATITUDE) {
800 0         0 my $lat = $obj->readFloat(substr($raw_positions_row, 4 * ($IPV6_LATITUDE_POSITION[$dbtype]+2)));
801 0         0 $lat = sprintf("%.6f", $lat);
802 0         0 return $lat;
803             }
804 0 0       0 if ($mode == LONGITUDE) {
805 0         0 my $lon = $obj->readFloat(substr($raw_positions_row, 4 * ($IPV6_LONGITUDE_POSITION[$dbtype]+2)));
806 0         0 $lon = sprintf("%.6f", $lon);
807 0         0 return $lon;
808             }
809 0 0       0 if ($mode == DOMAIN) {
810 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_DOMAIN_POSITION[$dbtype]+2), 4)));
811             }
812 0 0       0 if ($mode == ZIPCODE) {
813 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_ZIPCODE_POSITION[$dbtype]+2), 4)));
814             }
815 0 0       0 if ($mode == TIMEZONE) {
816 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_TIMEZONE_POSITION[$dbtype]+2), 4)));
817             }
818 0 0       0 if ($mode == NETSPEED) {
819 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_NETSPEED_POSITION[$dbtype]+2), 4)));
820             }
821 0 0       0 if ($mode == IDDCODE) {
822 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_IDDCODE_POSITION[$dbtype]+2), 4)));
823             }
824 0 0       0 if ($mode == AREACODE) {
825 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_AREACODE_POSITION[$dbtype]+2), 4)));
826             }
827 0 0       0 if ($mode == WEATHERSTATIONCODE) {
828 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_WEATHERSTATIONCODE_POSITION[$dbtype]+2), 4)));
829             }
830 0 0       0 if ($mode == WEATHERSTATIONNAME) {
831 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_WEATHERSTATIONNAME_POSITION[$dbtype]+2), 4)));
832             }
833 0 0       0 if ($mode == MCC) {
834 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_MCC_POSITION[$dbtype]+2), 4)));
835             }
836 0 0       0 if ($mode == MNC) {
837 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_MNC_POSITION[$dbtype]+2), 4)));
838             }
839 0 0       0 if ($mode == MOBILEBRAND) {
840 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_MOBILEBRAND_POSITION[$dbtype]+2), 4)));
841             }
842 0 0       0 if ($mode == ELEVATION) {
843 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_ELEVATION_POSITION[$dbtype]+2), 4)));
844             }
845 0 0       0 if ($mode == USAGETYPE) {
846 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_USAGETYPE_POSITION[$dbtype]+2), 4)));
847             }
848 0 0       0 if ($mode == ADDRESSTYPE) {
849 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_ADDRESSTYPE_POSITION[$dbtype]+2), 4)));
850             }
851 0 0       0 if ($mode == CATEGORY) {
852 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IPV6_CATEGORY_POSITION[$dbtype]+2), 4)));
853             }
854             } else {
855 94 100       14507 if ($ipno < $ipfrom) {
856 82         10669 $high = $mid - 1;
857             } else {
858 12         1541 $low = $mid + 1;
859             }
860             }
861             }
862 0 0       0 if ($mode == ALL) {
863 0         0 return (UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN);
864             } else {
865 0         0 return UNKNOWN;
866             }
867             }
868              
869             sub get_ipv4_record {
870 10     10 0 19 my $obj = shift(@_);
871 10         14 my $ipnum = shift(@_);
872 10         15 my $mode = shift(@_);
873 10         18 my $dbtype= $obj->{"databasetype"};
874            
875 10 50       25 if ($ipnum eq "") {
876 0 0       0 if ($mode == ALL) {
877 0         0 return (NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP, NO_IP);
878             } else {
879 0         0 return NO_IP;
880             }
881             }
882            
883 10 50 33     256 if (($mode == COUNTRYSHORT) && ($COUNTRY_POSITION[$dbtype] == 0)) {
884 0         0 return NOT_SUPPORTED;
885             }
886 10 50 33     571 if (($mode == COUNTRYLONG) && ($COUNTRY_POSITION[$dbtype] == 0)) {
887 0         0 return NOT_SUPPORTED;
888             }
889 10 50 33     290 if (($mode == REGION) && ($REGION_POSITION[$dbtype] == 0)) {
890 0         0 return NOT_SUPPORTED;
891             }
892 10 50 33     277 if (($mode == CITY) && ($CITY_POSITION[$dbtype] == 0)) {
893 0         0 return NOT_SUPPORTED;
894             }
895 10 50 33     271 if (($mode == ISP) && ($ISP_POSITION[$dbtype] == 0)) {
896 0         0 return NOT_SUPPORTED;
897             }
898 10 50 33     271 if (($mode == LATITUDE) && ($LATITUDE_POSITION[$dbtype] == 0)) {
899 0         0 return NOT_SUPPORTED;
900             }
901 10 50 33     266 if (($mode == LONGITUDE) && ($LONGITUDE_POSITION[$dbtype] == 0)) {
902 0         0 return NOT_SUPPORTED;
903             }
904 10 50 33     288 if (($mode == DOMAIN) && ($DOMAIN_POSITION[$dbtype] == 0)) {
905 0         0 return NOT_SUPPORTED;
906             }
907 10 50 33     275 if (($mode == ZIPCODE) && ($ZIPCODE_POSITION[$dbtype] == 0)) {
908 0         0 return NOT_SUPPORTED;
909             }
910 10 50 33     341 if (($mode == TIMEZONE) && ($TIMEZONE_POSITION[$dbtype] == 0)) {
911 0         0 return NOT_SUPPORTED;
912             }
913 10 50 33     272 if (($mode == NETSPEED) && ($NETSPEED_POSITION[$dbtype] == 0)) {
914 0         0 return NOT_SUPPORTED;
915             }
916 10 50 33     282 if (($mode == IDDCODE) && ($IDDCODE_POSITION[$dbtype] == 0)) {
917 0         0 return NOT_SUPPORTED;
918             }
919 10 50 33     276 if (($mode == AREACODE) && ($AREACODE_POSITION[$dbtype] == 0)) {
920 0         0 return NOT_SUPPORTED;
921             }
922 10 50 33     265 if (($mode == WEATHERSTATIONCODE) && ($WEATHERSTATIONCODE_POSITION[$dbtype] == 0)) {
923 0         0 return NOT_SUPPORTED;
924             }
925 10 50 33     306 if (($mode == WEATHERSTATIONNAME) && ($WEATHERSTATIONNAME_POSITION[$dbtype] == 0)) {
926 0         0 return NOT_SUPPORTED;
927             }
928 10 50 33     280 if (($mode == MCC) && ($MCC_POSITION[$dbtype] == 0)) {
929 0         0 return NOT_SUPPORTED;
930             }
931 10 50 33     274 if (($mode == MNC) && ($MNC_POSITION[$dbtype] == 0)) {
932 0         0 return NOT_SUPPORTED;
933             }
934 10 50 33     268 if (($mode == MOBILEBRAND) && ($MOBILEBRAND_POSITION[$dbtype] == 0)) {
935 0         0 return NOT_SUPPORTED;
936             }
937 10 50 33     284 if (($mode == ELEVATION) && ($ELEVATION_POSITION[$dbtype] == 0)) {
938 0         0 return NOT_SUPPORTED;
939             }
940 10 50 33     285 if (($mode == USAGETYPE) && ($USAGETYPE_POSITION[$dbtype] == 0)) {
941 0         0 return NOT_SUPPORTED;
942             }
943 10 50 33     280 if (($mode == ADDRESSTYPE) && ($ADDRESSTYPE_POSITION[$dbtype] == 0)) {
944 0         0 return NOT_SUPPORTED;
945             }
946 10 50 33     280 if (($mode == CATEGORY) && ($CATEGORY_POSITION[$dbtype] == 0)) {
947 0         0 return NOT_SUPPORTED;
948             }
949            
950 10         275 my $realipno = $ipnum;
951 10         18 my $handle = $obj->{"filehandle"};
952 10         15 my $baseaddr = $obj->{"ipv4databaseaddr"};
953 10         15 my $dbcount = $obj->{"ipv4databasecount"};
954 10         15 my $dbcolumn = $obj->{"databasecolumn"};
955 10         13 my $indexbaseaddr = $obj->{"ipv4indexbaseaddr"};
956              
957 10         24 my $ipnum1_2 = int($ipnum >> 16);
958 10         2386 my $indexaddr = $indexbaseaddr + ($ipnum1_2 << 3);
959              
960 10         3032 my $low = 0;
961 10         16 my $high = $dbcount;
962 10 50       24 if ($indexbaseaddr > 0) {
963 10         687 $low = $obj->read32($handle, $indexaddr);
964 10         39 $high = $obj->read32($handle, $indexaddr + 4);
965             }
966 10         47 my $mid = 0;
967 10         17 my $ipfrom = 0;
968 10         14 my $ipto = 0;
969 10         15 my $ipno = 0;
970              
971 10 50       27 if ($realipno == MAX_IPV4_RANGE) {
972 0         0 $ipno = $realipno - 1;
973             } else {
974 10         407 $ipno = $realipno;
975             }
976              
977 10         39 while ($low <= $high) {
978 15         928 $mid = int(($low + $high) >> 1);
979 15         3187 $ipfrom = $obj->read32($handle, $baseaddr + $mid * $dbcolumn * 4);
980 15         84 $ipto = $obj->read32($handle, $baseaddr + ($mid + 1) * $dbcolumn * 4);
981 15 100 100     87 if (($ipno >= $ipfrom) && ($ipno < $ipto)) {
982             # read whole results string into temp string and parse results from memory
983 10         2311 my $raw_positions_row;
984 10         31 seek($handle, ($baseaddr + $mid * $dbcolumn * 4) - 1, 0);
985 10         5233 read($handle, $raw_positions_row, $dbcolumn * 4);
986              
987 10 50       1904 if ($mode == ALL) {
988 0         0 my $country_short = NOT_SUPPORTED;
989 0         0 my $country_long = NOT_SUPPORTED;
990 0         0 my $region = NOT_SUPPORTED;
991 0         0 my $city = NOT_SUPPORTED;
992 0         0 my $isp = NOT_SUPPORTED;
993 0         0 my $latitude = NOT_SUPPORTED;
994 0         0 my $longitude = NOT_SUPPORTED;
995 0         0 my $domain = NOT_SUPPORTED;
996 0         0 my $zipcode = NOT_SUPPORTED;
997 0         0 my $timezone = NOT_SUPPORTED;
998 0         0 my $netspeed = NOT_SUPPORTED;
999 0         0 my $iddcode = NOT_SUPPORTED;
1000 0         0 my $areacode = NOT_SUPPORTED;
1001 0         0 my $weatherstationcode = NOT_SUPPORTED;
1002 0         0 my $weatherstationname = NOT_SUPPORTED;
1003 0         0 my $mcc = NOT_SUPPORTED;
1004 0         0 my $mnc = NOT_SUPPORTED;
1005 0         0 my $mobilebrand = NOT_SUPPORTED;
1006 0         0 my $elevation = NOT_SUPPORTED;
1007 0         0 my $usagetype = NOT_SUPPORTED;
1008 0         0 my $addresstype = NOT_SUPPORTED;
1009 0         0 my $category = NOT_SUPPORTED;
1010            
1011 0 0       0 if ($COUNTRY_POSITION[$dbtype] != 0) {
1012 0         0 $country_short = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($COUNTRY_POSITION[$dbtype]-1), 4)));
1013 0         0 $country_long = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($COUNTRY_POSITION[$dbtype]-1), 4)) + 3);
1014             }
1015              
1016 0 0       0 if ($REGION_POSITION[$dbtype] != 0) {
1017 0         0 $region = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($REGION_POSITION[$dbtype]-1), 4)));
1018             }
1019 0 0       0 if ($CITY_POSITION[$dbtype] != 0) {
1020 0         0 $city = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($CITY_POSITION[$dbtype]-1), 4)));
1021             }
1022 0 0       0 if ($ISP_POSITION[$dbtype] != 0) {
1023 0         0 $isp = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($ISP_POSITION[$dbtype]-1), 4)));
1024             }
1025 0 0       0 if ($LATITUDE_POSITION[$dbtype] != 0) {
1026 0         0 $latitude = $obj->readFloat(substr($raw_positions_row, 4 * ($LATITUDE_POSITION[$dbtype]-1), 4));
1027 0         0 $latitude = sprintf("%.6f", $latitude);
1028             }
1029 0 0       0 if ($LONGITUDE_POSITION[$dbtype] != 0) {
1030 0         0 $longitude = $obj->readFloat(substr($raw_positions_row, 4 * ($LONGITUDE_POSITION[$dbtype]-1), 4));
1031 0         0 $longitude = sprintf("%.6f", $longitude);
1032             }
1033 0 0       0 if ($DOMAIN_POSITION[$dbtype] != 0) {
1034 0         0 $domain = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($DOMAIN_POSITION[$dbtype]-1), 4)));
1035             }
1036 0 0       0 if ($ZIPCODE_POSITION[$dbtype] != 0) {
1037 0         0 $zipcode = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($ZIPCODE_POSITION[$dbtype]-1), 4)));
1038             }
1039 0 0       0 if ($TIMEZONE_POSITION[$dbtype] != 0) {
1040 0         0 $timezone = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($TIMEZONE_POSITION[$dbtype]-1), 4)));
1041             }
1042 0 0       0 if ($NETSPEED_POSITION[$dbtype] != 0) {
1043 0         0 $netspeed = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($NETSPEED_POSITION[$dbtype]-1), 4)));
1044             }
1045 0 0       0 if ($IDDCODE_POSITION[$dbtype] != 0) {
1046 0         0 $iddcode = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IDDCODE_POSITION[$dbtype]-1), 4)));
1047             }
1048 0 0       0 if ($AREACODE_POSITION[$dbtype] != 0) {
1049 0         0 $areacode = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($AREACODE_POSITION[$dbtype]-1), 4)));
1050             }
1051 0 0       0 if ($WEATHERSTATIONCODE_POSITION[$dbtype] != 0) {
1052 0         0 $weatherstationcode = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($WEATHERSTATIONCODE_POSITION[$dbtype]-1), 4)));
1053             }
1054 0 0       0 if ($WEATHERSTATIONNAME_POSITION[$dbtype] != 0) {
1055 0         0 $weatherstationname = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($WEATHERSTATIONNAME_POSITION[$dbtype]-1), 4)));
1056             }
1057 0 0       0 if ($MCC_POSITION[$dbtype] != 0) {
1058 0         0 $mcc = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($MCC_POSITION[$dbtype]-1), 4)));
1059             }
1060 0 0       0 if ($MNC_POSITION[$dbtype] != 0) {
1061 0         0 $mnc = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($MNC_POSITION[$dbtype]-1), 4)));
1062             }
1063 0 0       0 if ($MOBILEBRAND_POSITION[$dbtype] != 0) {
1064 0         0 $mobilebrand = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($MOBILEBRAND_POSITION[$dbtype]-1), 4)));
1065             }
1066 0 0       0 if ($ELEVATION_POSITION[$dbtype] != 0) {
1067 0         0 $elevation = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($ELEVATION_POSITION[$dbtype]-1), 4)));
1068             }
1069 0 0       0 if ($USAGETYPE_POSITION[$dbtype] != 0) {
1070 0         0 $usagetype = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($USAGETYPE_POSITION[$dbtype]-1), 4)));
1071             }
1072 0 0       0 if ($ADDRESSTYPE_POSITION[$dbtype] != 0) {
1073 0         0 $addresstype = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($ADDRESSTYPE_POSITION[$dbtype]-1), 4)));
1074             }
1075 0 0       0 if ($CATEGORY_POSITION[$dbtype] != 0) {
1076 0         0 $category = $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($CATEGORY_POSITION[$dbtype]-1), 4)));
1077             }
1078 0         0 return ($country_short, $country_long, $region, $city, $latitude, $longitude, $zipcode, $timezone, $isp, $domain, $netspeed, $iddcode, $areacode, $weatherstationcode, $weatherstationname, $mcc, $mnc, $mobilebrand, $elevation, $usagetype, $addresstype, $category);
1079             }
1080 10 50       370 if ($mode == COUNTRYSHORT) {
1081 10         293 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($COUNTRY_POSITION[$dbtype]-1), 4)));
1082             }
1083 0 0       0 if ($mode == COUNTRYLONG) {
1084 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($COUNTRY_POSITION[$dbtype]-1), 4)) + 3);
1085             }
1086 0 0       0 if ($mode == REGION) {
1087 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($REGION_POSITION[$dbtype]-1), 4)));
1088             }
1089 0 0       0 if ($mode == CITY) {
1090 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($CITY_POSITION[$dbtype]-1), 4)));
1091             }
1092 0 0       0 if ($mode == ISP) {
1093 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($ISP_POSITION[$dbtype]-1), 4)));
1094             }
1095 0 0       0 if ($mode == LATITUDE) {
1096 0         0 my $lat = $obj->readFloat(substr($raw_positions_row, 4 * ($LATITUDE_POSITION[$dbtype]-1), 4));
1097 0         0 $lat = sprintf("%.6f", $lat);
1098 0         0 return $lat;
1099             }
1100 0 0       0 if ($mode == LONGITUDE) {
1101 0         0 my $lon = $obj->readFloat(substr($raw_positions_row, 4 * ($LONGITUDE_POSITION[$dbtype]-1), 4));
1102 0         0 $lon = sprintf("%.6f", $lon);
1103 0         0 return $lon;
1104             }
1105 0 0       0 if ($mode == DOMAIN) {
1106 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($DOMAIN_POSITION[$dbtype]-1), 4)));
1107             }
1108 0 0       0 if ($mode == ZIPCODE) {
1109 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($ZIPCODE_POSITION[$dbtype]-1), 4)));
1110             }
1111 0 0       0 if ($mode == TIMEZONE) {
1112 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($TIMEZONE_POSITION[$dbtype]-1), 4)));
1113             }
1114 0 0       0 if ($mode == NETSPEED) {
1115 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($NETSPEED_POSITION[$dbtype]-1), 4)));
1116             }
1117 0 0       0 if ($mode == IDDCODE) {
1118 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($IDDCODE_POSITION[$dbtype]-1), 4)));
1119             }
1120 0 0       0 if ($mode == AREACODE) {
1121 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($AREACODE_POSITION[$dbtype]-1), 4)));
1122             }
1123 0 0       0 if ($mode == WEATHERSTATIONCODE) {
1124 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($WEATHERSTATIONCODE_POSITION[$dbtype]-1), 4)));
1125             }
1126 0 0       0 if ($mode == WEATHERSTATIONNAME) {
1127 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($WEATHERSTATIONNAME_POSITION[$dbtype]-1), 4)));
1128             }
1129 0 0       0 if ($mode == MCC) {
1130 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($MCC_POSITION[$dbtype]-1), 4)));
1131             }
1132 0 0       0 if ($mode == MNC) {
1133 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($MNC_POSITION[$dbtype]-1), 4)));
1134             }
1135 0 0       0 if ($mode == MOBILEBRAND) {
1136 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($MOBILEBRAND_POSITION[$dbtype]-1), 4)));
1137             }
1138 0 0       0 if ($mode == ELEVATION) {
1139 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($ELEVATION_POSITION[$dbtype]-1), 4)));
1140             }
1141 0 0       0 if ($mode == USAGETYPE) {
1142 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($USAGETYPE_POSITION[$dbtype]-1), 4)));
1143             }
1144 0 0       0 if ($mode == ADDRESSTYPE) {
1145 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($ADDRESSTYPE_POSITION[$dbtype]-1), 4)));
1146             }
1147 0 0       0 if ($mode == CATEGORY) {
1148 0         0 return $obj->readStr($handle, unpack("V", substr($raw_positions_row, 4 * ($CATEGORY_POSITION[$dbtype]-1), 4)));
1149             }
1150             } else {
1151 5 100       689 if ($ipno < $ipfrom) {
1152 4         418 $high = $mid - 1;
1153             } else {
1154 1         98 $low = $mid + 1;
1155             }
1156             }
1157             }
1158 0 0       0 if ($mode == ALL) {
1159 0         0 return (UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN);
1160             } else {
1161 0         0 return UNKNOWN;
1162             }
1163             }
1164              
1165             sub read128 {
1166 208     208 0 97246 my ($obj, $handle, $position) = @_;
1167 208         380 my $data = "";
1168 208         534 seek($handle, $position-1, 0);
1169 208         35584 read($handle, $data, 16);
1170 208         8048 return &bytes2int($data);
1171             }
1172              
1173             sub read32 {
1174 84     84 0 14023 my ($obj, $handle, $position) = @_;
1175 84         146 my $data = "";
1176 84         233 seek($handle, $position-1, 0);
1177 84         14370 read($handle, $data, 4);
1178 84         3342 return unpack("V", $data);
1179             }
1180              
1181             sub read8 {
1182 14     14 0 34 my ($obj, $handle, $position) = @_;
1183 14         24 my $data = "";
1184 14         47 seek($handle, $position-1, 0);
1185 14         2570 read($handle, $data, 1);
1186 14         542 return unpack("C", $data);
1187             }
1188              
1189             sub readStr {
1190 20     20 0 4318 my ($obj, $handle, $position) = @_;
1191 20         92 my $data = "";
1192 20         32 my $string = "";
1193 20         51 seek($handle, $position, 0);
1194 20         727 read($handle, $data, 1);
1195 20         768 read($handle, $string, unpack("C", $data));
1196 20         264 return $string;
1197             }
1198              
1199             sub readFloat {
1200 0     0 0 0 my ($obj, $data) = @_;
1201 0         0 my $is_little_endian = unpack("h*", pack("s", 1));
1202 0 0       0 if ($is_little_endian =~ m/^1/) {
1203             # "LITTLE ENDIAN - x86\n";
1204 0         0 return unpack("f", $data);
1205             } else {
1206             # "BIG ENDIAN - MAC\n";
1207 0         0 return unpack("f", reverse($data));
1208             }
1209             }
1210              
1211             sub bytes2int {
1212 208     208 0 421 my $binip = shift(@_);
1213 208         1084 my @array = split(//, $binip);
1214 208 50       690 return 0 if ($#array != 15);
1215 208         23678 my $ip96_127 = unpack("V", $array[0] . $array[1] . $array[2] . $array[3]);
1216 208         469 my $ip64_95 = unpack("V", $array[4] . $array[5] . $array[6] . $array[7]);
1217 208         398 my $ip32_63 = unpack("V", $array[8] . $array[9] . $array[10] . $array[11]);
1218 208         394 my $ip1_31 = unpack("V", $array[12] . $array[13] . $array[14] . $array[15]);
1219              
1220 208         625 my $big1 = Math::BigInt->new("$ip96_127");
1221 208         18857 my $big2 = Math::BigInt->new("$ip64_95")->blsft(32);
1222 208         28006 my $big3 = Math::BigInt->new("$ip32_63")->blsft(64);
1223 208         29378 my $big4 = Math::BigInt->new("$ip1_31")->blsft(96);
1224 208         83714 $big1 = $big1->badd($big2)->badd($big3)->badd($big4);
1225            
1226 208         27113 return $big1->bstr();
1227             }
1228              
1229             sub validate_ip {
1230 20     20 0 39 my $obj = shift(@_);
1231 20         35 my $ip = shift(@_);
1232 20         33 my $ipv = -1;
1233 20         32 my $ipnum = -1;
1234             #name server lookup if domain name
1235 20         52 $ip = $obj->name2ip($ip);
1236            
1237 20 100       58 if ($obj->ip_is_ipv4($ip)) {
1238             #ipv4 address
1239 10         248 $ipv = 4;
1240 10         23 $ipnum = $obj->ip2no($ip);
1241             } else {
1242             #expand ipv6 address
1243 10         302 $ip = $obj->expand_ipv6_address($ip);
1244 10 50       34 if ($obj->ip_is_ipv6($ip)) {
1245             #ipv6 address
1246 10         256 $ipv = 6;
1247 10         28 $ipnum = $obj->hex2int($ip);
1248            
1249             #reformat ipv4 address in ipv6
1250 10 50 33     30 if (($ipnum >= 281470681743360) && ($ipnum <= 281474976710655)) {
1251 0         0 $ipv = 4;
1252 0         0 $ipnum = $ipnum - 281470681743360;
1253             }
1254              
1255             #reformat 6to4 address to ipv4 address 2002:: to 2002:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF
1256 10 50 33     713 if (($ipnum >= 42545680458834377588178886921629466624) && ($ipnum <= 42550872755692912415807417417958686719)) {
1257 0         0 $ipv = 4;
1258             #bitshift right 80 bits
1259 0         0 $ipnum->brsft(80);
1260             #bitwise modulus to get the last 32 bit
1261 0         0 $ipnum->bmod(4294967296);
1262             }
1263              
1264             #reformat Teredo address to ipv4 address 2001:0000:: to 2001:0000:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:
1265 10 50 33     759 if (($ipnum >= 42540488161975842760550356425300246528) && ($ipnum <= 42540488241204005274814694018844196863)) {
1266 0         0 $ipv = 4;
1267 0         0 $ipnum = Math::BigInt->new($ipnum);
1268             #bitwise not to invert binary
1269 0         0 $ipnum->bnot();
1270             #bitwise modulus to get the last 32 bit
1271 0         0 $ipnum->bmod(4294967296);
1272             }
1273              
1274             } else {
1275             #not IPv4 and IPv6
1276             }
1277             }
1278 20         828 return ($ipv, $ipnum);
1279             }
1280              
1281             sub expand_ipv6_address {
1282 10     10 0 21 my $obj = shift(@_);
1283 10         17 my $ip = shift(@_);
1284 10         26 $ip =~ s/\:\:/\:Z\:/;
1285 10         51 my @ip = split(/\:/, $ip);
1286 10         23 my $num = scalar(@ip);
1287              
1288 10         19 my $l = 8;
1289 10 50       35 if ($ip[$#ip] =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) {
1290 0         0 my $a = sprintf("%x", ($1*256 + $2));
1291 0         0 my $b = sprintf("%x", ($3*256 + $4));
1292 0         0 $ip[$#ip] = $a;
1293 0         0 $ip[$#ip+1] = $b;
1294 0         0 $l--;
1295             }
1296              
1297 10 50       31 if ($#ip == 8) {
1298 0         0 shift(@ip);
1299 0         0 $l++;
1300             }
1301              
1302 10         1132 foreach (0..(scalar(@ip)-1)) {
1303 80         16478 $ip[$_] = ('0'x(4-length ($ip[$_]))).$ip[$_];
1304             }
1305              
1306 10         1928 foreach (0..(scalar(@ip)-1)) {
1307 80 50       2776 next unless ($ip[$_] eq '000Z');
1308 0         0 my @empty = map { $_ = '0'x4 } (0..7);
  0         0  
1309 0         0 $ip[$_] = join(':', @empty[0..$l-$num]);
1310 0         0 last;
1311             }
1312              
1313 10         70 return (uc(join ':', @ip));
1314             }
1315              
1316             sub hex2int {
1317 10     10 0 18 my $obj = shift(@_);
1318 10         20 my $hexip = shift(@_);
1319              
1320 10         54 $hexip =~ s/\://g;
1321              
1322 10 50       36 unless (length($hexip) == 32) {
1323 0         0 return 0;
1324             };
1325              
1326 10         1117 my $binip = unpack('B128', pack('H32', $hexip));
1327 10         29 my ($n, $dec) = (Math::BigInt->new(1), Math::BigInt->new(0));
1328              
1329 10         893 foreach (reverse (split('', $binip))) {
1330 1280 100       73527 $_ && ($dec += $n);
1331 1280         5703 $n *= 2;
1332             }
1333              
1334 10         738 $dec =~ s/^\+//;
1335 10         374 return $dec;
1336             }
1337              
1338             sub ip2no {
1339 10     10 0 17 my $obj = shift(@_);
1340 10         14 my $ip = shift(@_);
1341 10         32 my @block = split(/\./, $ip);
1342 10         19 my $no = 0;
1343 10         15 $no = $block[3];
1344 10         32 $no = $no + $block[2] * 256;
1345 10         3059 $no = $no + $block[1] * 256 * 256;
1346 10         2805 $no = $no + $block[0] * 256 * 256 * 256;
1347 10         3460 return $no;
1348             }
1349              
1350             sub name2ip {
1351 20     20 0 35 my $obj = shift(@_);
1352 20         34 my $host = shift(@_);
1353 20         35 my $ip_address = "";
1354 20 50 66     1007 if (($host =~ m/^$IPv4_re$/) || ($host =~ m/^$IPv6_re$/) || ($host =~ m/^\:\:$/)) {
      33        
1355 20         49 $ip_address = $host;
1356             } else {
1357             # TO_DO: Can we return IPv6 address too?
1358 0         0 my @hostname = gethostbyname($host);
1359 0 0       0 if ($#hostname < 4) {
1360 0         0 $ip_address = $host;
1361             } else {
1362 0         0 $ip_address = join('.', unpack('C4', $hostname[4]));
1363             }
1364             }
1365 20         70 return $ip_address;
1366             }
1367              
1368             sub ip_is_ipv4 {
1369 20     20 0 37 my $obj = shift(@_);
1370 20         31 my $ip = shift(@_);
1371 20 100       144 if ($ip =~ m/^$IPv4_re$/) {
1372 10         38 my @octet = split(/\./, $ip);
1373 10         42 foreach my $i (0 .. $#octet) {
1374 40 50 33     4449 return 0 if (($octet[$i] > 255) || ($octet[$i] < 0));
1375             }
1376 10         1362 return 1;
1377             } else {
1378 10         56 return 0;
1379             }
1380             }
1381              
1382             sub ip_is_ipv6 {
1383 10     10 0 18 my $obj = shift(@_);
1384 10         23 my $ip = shift(@_);
1385 10 50 33     609 if (($ip =~ m/^$IPv6_re$/) || ($ip =~ m/^$IPv4_re$/) || ($ip =~ m/^\:\:$/)) {
      33        
1386 10         49 return 1;
1387             } else {
1388 0           return 0;
1389             }
1390             }
1391              
1392             1;
1393             __END__