diff --git a/LICENSE b/LICENSE index 6a1c214..c55783c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018 ip2location +Copyright (c) 2019 ip2location Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 6bb94e5..b0f239d 100644 --- a/README.md +++ b/README.md @@ -73,4 +73,4 @@ Use the IPv6 BIN file if you need to query BOTH IPv4 and IPv6 addresses. Copyright ========= -Copyright (C) 2018 by IP2Location.com, support@ip2location.com +Copyright (C) 2019 by IP2Location.com, support@ip2location.com diff --git a/ip2location-8.0.3-1.rockspec b/ip2location-8.2.0-1.rockspec similarity index 91% rename from ip2location-8.0.3-1.rockspec rename to ip2location-8.2.0-1.rockspec index 5f632a3..f7b73e7 100644 --- a/ip2location-8.0.3-1.rockspec +++ b/ip2location-8.2.0-1.rockspec @@ -1,5 +1,5 @@ package = "ip2location" -version = "8.0.3-1" +version = "8.2.0-1" source = { url = "git://github.com/ip2location/ip2location-lua.git" } @@ -14,7 +14,7 @@ description = { time zone, ISP, domain name, connection type, IDD code, area code, weather station code, station name, mcc, mnc, mobile brand, elevation, and usage type as values. It supports both IP address in IPv4 and IPv6. ]], - homepage = "https://www.ip2location.com/developers/lua", + homepage = "https://www.ip2location.com/development-libraries/ip2location/lua", license = "MIT", maintainer = "support@ip2location.com" } diff --git a/ip2location.lua b/ip2location.lua index eaca9a1..1f718e7 100644 --- a/ip2location.lua +++ b/ip2location.lua @@ -15,6 +15,7 @@ ip2location = { ipv6indexbaseaddr = 0, ipv4columnsize = 0, ipv6columnsize = 0, + columnsize_without_ip = 0, country_position_offset = 0, region_position_offset = 0, city_position_offset = 0, @@ -82,6 +83,13 @@ ip2locationrecord.__index = ip2locationrecord local max_ipv4_range = bn(4294967295) local max_ipv6_range= bn("340282366920938463463374607431768211455") +local from_v4mapped = bn("281470681743360") +local to_v4mapped = bn("281474976710655") +local from_6to4 = bn("42545680458834377588178886921629466624") +local to_6to4 = bn("42550872755692912415807417417958686719") +local from_teredo = bn("42540488161975842760550356425300246528") +local to_teredo = bn("42540488241204005274814694018844196863") +local last_32bits = bn(4294967295) local country_position = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2} local region_position = {0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3} @@ -103,7 +111,7 @@ local mobilebrand_position = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, local elevation_position = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 19, 0, 19} local usagetype_position = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 20} -local api_version = "8.0.3" +local api_version = "8.2.0" local modes = { countryshort = 0x00001, @@ -135,10 +143,10 @@ local missing_file = "Invalid database file." local not_supported = "This parameter is unavailable for selected data file. Please upgrade the data file." -- for debugging purposes ---local function printme(stuff) --- local inspect = require('inspect') --- print(inspect(stuff)) ---end +local function printme(stuff) + local inspect = require('inspect') + print(inspect(stuff)) +end -- read byte local function readuint8(pos, myfile) @@ -157,10 +165,22 @@ local function readuint32(pos, myfile) local bytestr = myfile:read(4) local value = bn.ZERO if bytestr ~= nil then - bytestr = string.reverse(bytestr) - for x=1,4 do - value = (value << 8) + bn(bytestr:byte(x)) - end + -- bytestr = string.reverse(bytestr) + -- for x=1,4 do + -- value = (value << 8) + bn(bytestr:byte(x)) + -- end + value = bn(string.unpack(" 0 and part > 65535 then return R.ERROR end ipnum = ipnum + (bn(part) << (16 * (8 - x))) end - + + local override = 0 + + -- special cases which should convert to equivalent IPv4 + if ipnum >= from_v4mapped and ipnum <= to_v4mapped then -- ipv4-mapped ipv6 + override = 1 + ipnum = ipnum - from_v4mapped + elseif ipnum >= from_6to4 and ipnum <= to_6to4 then -- 6to4 + override = 1 + ipnum = ipnum >> 80 + ipnum = ipnum & last_32bits + elseif ipnum >= from_teredo and ipnum <= to_teredo then -- Teredo + override = 1 + ipnum = ~ipnum + ipnum = ipnum & last_32bits + end + local ipindex = 0; - if self.ipv6indexbaseaddr > 0 then - ipindex = ((ipnum >> 112) << 3):asnumber() + self.ipv6indexbaseaddr + if override == 1 then + if self.ipv4indexbaseaddr > 0 then + ipindex = ((ipnum >> 16) << 3):asnumber() + self.ipv4indexbaseaddr + end + return R.IPV4, ipnum, ipindex + else + if self.ipv6indexbaseaddr > 0 then + ipindex = ((ipnum >> 112) << 3):asnumber() + self.ipv6indexbaseaddr + end + return R.IPV6, ipnum, ipindex end - return R.IPV6, ipnum, ipindex end return R.ERROR @@ -438,6 +513,8 @@ function ip2location:query(ipaddress, mode) local ipfrom = bn.ZERO local ipto = bn.ZERO local maxip = bn.ZERO + local firstcol = 4 + -- local row = "" -- printme(self) @@ -478,87 +555,111 @@ function ip2location:query(ipaddress, mode) if (ipno >= ipfrom) and (ipno < ipto) then if iptype == 6 then - rowoffset = rowoffset + 12 -- coz below is assuming all columns are 4 bytes, so got 12 left to go to make 16 bytes total + firstcol = 16 + -- rowoffset = rowoffset + 12 -- coz below is assuming all columns are 4 bytes, so got 12 left to go to make 16 bytes total end + self.f:seek("set", rowoffset + firstcol - 1) + local row = self.f:read(self.columnsize_without_ip) + if (mode&modes.countryshort == 1) and (self.country_enabled == true) then - result.country_short = readstr(readuint32(rowoffset + self.country_position_offset, self.f):asnumber(), self.f) + -- result.country_short = readstr(readuint32(rowoffset + self.country_position_offset, self.f):asnumber(), self.f) + result.country_short = readstr(readuint32row(self.country_position_offset, row):asnumber(), self.f) end if (mode&modes.countrylong ~= 0) and (self.country_enabled == true) then - result.country_long = readstr(readuint32(rowoffset + self.country_position_offset, self.f):asnumber() + 3, self.f) + -- result.country_long = readstr(readuint32(rowoffset + self.country_position_offset, self.f):asnumber() + 3, self.f) + result.country_long = readstr(readuint32row(self.country_position_offset, row):asnumber() + 3, self.f) end if (mode&modes.region ~= 0) and (self.region_enabled == true) then - result.region = readstr(readuint32(rowoffset + self.region_position_offset, self.f):asnumber(), self.f) + -- result.region = readstr(readuint32(rowoffset + self.region_position_offset, self.f):asnumber(), self.f) + result.region = readstr(readuint32row(self.region_position_offset, row):asnumber(), self.f) end if (mode&modes.city ~= 0) and (self.city_enabled == true) then - result.city = readstr(readuint32(rowoffset + self.city_position_offset, self.f):asnumber(), self.f) + -- result.city = readstr(readuint32(rowoffset + self.city_position_offset, self.f):asnumber(), self.f) + result.city = readstr(readuint32row(self.city_position_offset, row):asnumber(), self.f) end if (mode&modes.isp ~= 0) and (self.isp_enabled == true) then - result.isp = readstr(readuint32(rowoffset + self.isp_position_offset, self.f):asnumber(), self.f) + -- result.isp = readstr(readuint32(rowoffset + self.isp_position_offset, self.f):asnumber(), self.f) + result.isp = readstr(readuint32row(self.isp_position_offset, row):asnumber(), self.f) end if (mode&modes.latitude ~= 0) and (self.latitude_enabled == true) then - result.latitude = roundup(readfloat(rowoffset + self.latitude_position_offset, self.f), 6) + -- result.latitude = roundup(readfloat(rowoffset + self.latitude_position_offset, self.f), 6) + result.latitude = roundup(readfloatrow(self.latitude_position_offset, row), 6) end if (mode&modes.longitude ~= 0) and (self.longitude_enabled == true) then - result.longitude = roundup(readfloat(rowoffset + self.longitude_position_offset, self.f), 6) + -- result.longitude = roundup(readfloat(rowoffset + self.longitude_position_offset, self.f), 6) + result.longitude = roundup(readfloatrow(self.longitude_position_offset, row), 6) end if (mode&modes.domain ~= 0) and (self.domain_enabled == true) then - result.domain = readstr(readuint32(rowoffset + self.domain_position_offset, self.f):asnumber(), self.f) + -- result.domain = readstr(readuint32(rowoffset + self.domain_position_offset, self.f):asnumber(), self.f) + result.domain = readstr(readuint32row(self.domain_position_offset, row):asnumber(), self.f) end if (mode&modes.zipcode ~= 0) and (self.zipcode_enabled == true) then - result.zipcode = readstr(readuint32(rowoffset + self.zipcode_position_offset, self.f):asnumber(), self.f) + -- result.zipcode = readstr(readuint32(rowoffset + self.zipcode_position_offset, self.f):asnumber(), self.f) + result.zipcode = readstr(readuint32row(self.zipcode_position_offset, row):asnumber(), self.f) end if (mode&modes.timezone ~= 0) and (self.timezone_enabled == true) then - result.timezone = readstr(readuint32(rowoffset + self.timezone_position_offset, self.f):asnumber(), self.f) + -- result.timezone = readstr(readuint32(rowoffset + self.timezone_position_offset, self.f):asnumber(), self.f) + result.timezone = readstr(readuint32row(self.timezone_position_offset, row):asnumber(), self.f) end if (mode&modes.netspeed ~= 0) and (self.netspeed_enabled == true) then - result.netspeed = readstr(readuint32(rowoffset + self.netspeed_position_offset, self.f):asnumber(), self.f) + -- result.netspeed = readstr(readuint32(rowoffset + self.netspeed_position_offset, self.f):asnumber(), self.f) + result.netspeed = readstr(readuint32row(self.netspeed_position_offset, row):asnumber(), self.f) end if (mode&modes.iddcode ~= 0) and (self.iddcode_enabled == true) then - result.iddcode = readstr(readuint32(rowoffset + self.iddcode_position_offset, self.f):asnumber(), self.f) + -- result.iddcode = readstr(readuint32(rowoffset + self.iddcode_position_offset, self.f):asnumber(), self.f) + result.iddcode = readstr(readuint32row(self.iddcode_position_offset, row):asnumber(), self.f) end if (mode&modes.areacode ~= 0) and (self.areacode_enabled == true) then - result.areacode = readstr(readuint32(rowoffset + self.areacode_position_offset, self.f):asnumber(), self.f) + -- result.areacode = readstr(readuint32(rowoffset + self.areacode_position_offset, self.f):asnumber(), self.f) + result.areacode = readstr(readuint32row(self.areacode_position_offset, row):asnumber(), self.f) end if (mode&modes.weatherstationcode ~= 0) and (self.weatherstationcode_enabled == true) then - result.weatherstationcode = readstr(readuint32(rowoffset + self.weatherstationcode_position_offset, self.f):asnumber(), self.f) + -- result.weatherstationcode = readstr(readuint32(rowoffset + self.weatherstationcode_position_offset, self.f):asnumber(), self.f) + result.weatherstationcode = readstr(readuint32row(self.weatherstationcode_position_offset, row):asnumber(), self.f) end if (mode&modes.weatherstationname ~= 0) and (self.weatherstationname_enabled == true) then - result.weatherstationname = readstr(readuint32(rowoffset + self.weatherstationname_position_offset, self.f):asnumber(), self.f) + -- result.weatherstationname = readstr(readuint32(rowoffset + self.weatherstationname_position_offset, self.f):asnumber(), self.f) + result.weatherstationname = readstr(readuint32row(self.weatherstationname_position_offset, row):asnumber(), self.f) end if (mode&modes.mcc ~= 0) and (self.mcc_enabled == true) then - result.mcc = readstr(readuint32(rowoffset + self.mcc_position_offset, self.f):asnumber(), self.f) + -- result.mcc = readstr(readuint32(rowoffset + self.mcc_position_offset, self.f):asnumber(), self.f) + result.mcc = readstr(readuint32row(self.mcc_position_offset, row):asnumber(), self.f) end if (mode&modes.mnc ~= 0) and (self.mnc_enabled == true) then - result.mnc = readstr(readuint32(rowoffset + self.mnc_position_offset, self.f):asnumber(), self.f) + -- result.mnc = readstr(readuint32(rowoffset + self.mnc_position_offset, self.f):asnumber(), self.f) + result.mnc = readstr(readuint32row(self.mnc_position_offset, row):asnumber(), self.f) end if (mode&modes.mobilebrand ~= 0) and (self.mobilebrand_enabled == true) then - result.mobilebrand = readstr(readuint32(rowoffset + self.mobilebrand_position_offset, self.f):asnumber(), self.f) + -- result.mobilebrand = readstr(readuint32(rowoffset + self.mobilebrand_position_offset, self.f):asnumber(), self.f) + result.mobilebrand = readstr(readuint32row(self.mobilebrand_position_offset, row):asnumber(), self.f) end if (mode&modes.elevation ~= 0) and (self.elevation_enabled == true) then - result.elevation = tonumber(readstr(readuint32(rowoffset + self.elevation_position_offset, self.f):asnumber(), self.f)) + -- result.elevation = tonumber(readstr(readuint32(rowoffset + self.elevation_position_offset, self.f):asnumber(), self.f)) + result.elevation = tonumber(readstr(readuint32row(self.elevation_position_offset, row):asnumber(), self.f)) end if (mode&modes.usagetype ~= 0) and (self.usagetype_enabled == true) then - result.usagetype = readstr(readuint32(rowoffset + self.usagetype_position_offset, self.f):asnumber(), self.f) + -- result.usagetype = readstr(readuint32(rowoffset + self.usagetype_position_offset, self.f):asnumber(), self.f) + result.usagetype = readstr(readuint32row(self.usagetype_position_offset, row):asnumber(), self.f) end -- printme(result)