File Coverage

blib/lib/Geo/IP2Location.pm
Criterion Covered Total %
statement 461 993 46.4
branch 89 434 20.5
condition 61 168 36.3
subroutine 82 112 73.2
pod 27 48 56.2
total 720 1755 41.0


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