loyal_ipinfo 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/MIT-LICENSE +20 -0
- data/README.md +25 -0
- data/Rakefile +8 -0
- data/lib/loyal_ipinfo/array_util.rb +16 -0
- data/lib/loyal_ipinfo/config.rb +33 -0
- data/lib/loyal_ipinfo/version.rb +4 -0
- data/lib/loyal_ipinfo/worker.rb +226 -0
- data/lib/loyal_ipinfo.rb +9 -0
- data/lib/tasks/loyal_ipinfo_tasks.rake +4 -0
- data/resources/qqwry.dat +0 -0
- metadata +77 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2013 YOURNAME
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
= LoyalIpinfo
|
2
|
+
|
3
|
+
get ip info
|
4
|
+
|
5
|
+
eg:
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
# config
|
9
|
+
|
10
|
+
LoyalIpinfo.configure do |config|
|
11
|
+
# config.default_adapter = :qqwry
|
12
|
+
# config.default_library_file_path = '' # library_file_path
|
13
|
+
end
|
14
|
+
|
15
|
+
# usage:
|
16
|
+
|
17
|
+
worker = ::LoyalIpinfo::Worker.new
|
18
|
+
|
19
|
+
result = worker.find('127.0.0.1')
|
20
|
+
|
21
|
+
result.city # '本机地址'
|
22
|
+
result.area # ''
|
23
|
+
|
24
|
+
```
|
25
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module LoyalIpinfo
|
3
|
+
class ArrayUtil
|
4
|
+
def self.extract_options!(arr)
|
5
|
+
if arr.last.is_a?(Hash)
|
6
|
+
arr.pop
|
7
|
+
else
|
8
|
+
{}
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.init args
|
13
|
+
args.is_a?(Array) ? args : (args.nil? ? [] : [args])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module LoyalIpinfo
|
3
|
+
class << self
|
4
|
+
attr_writer :config
|
5
|
+
|
6
|
+
def config
|
7
|
+
@config ||= Config.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def configure
|
11
|
+
yield self.config ||= Config.new
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Config
|
16
|
+
def default_adapter
|
17
|
+
@default_adapter ||= :qqwry # 纯真qq
|
18
|
+
end
|
19
|
+
|
20
|
+
def default_adapter= _adapter
|
21
|
+
@default_adapter ||= _adapter
|
22
|
+
end
|
23
|
+
|
24
|
+
def default_library_file_path
|
25
|
+
@default_library_file_path ||= "#{File.dirname(__FILE__)}/../../resources/qqwry.dat"
|
26
|
+
end
|
27
|
+
|
28
|
+
def default_library_file_path= path
|
29
|
+
@default_library_file_path ||= path
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
@@ -0,0 +1,226 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'iconv' unless RUBY_VERSION.respond_to?(:encode)
|
3
|
+
|
4
|
+
module LoyalIpinfo
|
5
|
+
|
6
|
+
class Worker
|
7
|
+
attr_reader :adapter, :library_file_path
|
8
|
+
|
9
|
+
def initialize attrs={}
|
10
|
+
@adapter ||= (attrs[:adapter] || ::LoyalIpinfo.config.default_adapter)
|
11
|
+
@library_file_path ||= (attrs[:library_file_path] || ::LoyalIpinfo.config.default_library_file_path)
|
12
|
+
|
13
|
+
case self.adapter
|
14
|
+
when :qqwry
|
15
|
+
self.extend ::LoyalIpinfo::QQwryAdapter
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module QQwryAdapter
|
21
|
+
def find *args, &block
|
22
|
+
options = ::LoyalIpinfo::ArrayUtil.extract_options!(args)
|
23
|
+
|
24
|
+
@qqwry_db ||= QQWry::QQWryFile.new(self.library_file_path)
|
25
|
+
|
26
|
+
result = args.inject({}) do |_result, ip|
|
27
|
+
_result[ip] = @qqwry_db.find(ip)
|
28
|
+
_result
|
29
|
+
end
|
30
|
+
|
31
|
+
if block_given?
|
32
|
+
block.call result
|
33
|
+
end
|
34
|
+
|
35
|
+
if args.any?
|
36
|
+
if args.one?
|
37
|
+
result[args.first]
|
38
|
+
else
|
39
|
+
result
|
40
|
+
end
|
41
|
+
else
|
42
|
+
nil
|
43
|
+
end
|
44
|
+
end
|
45
|
+
module QQWry
|
46
|
+
module QQWryIO
|
47
|
+
def get_le32
|
48
|
+
arr = read(4).unpack("C4")
|
49
|
+
arr[0] | arr[1]<<8 | arr[2]<<16 | arr[3]<<24
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_le24
|
53
|
+
arr = read(3).unpack("C3")
|
54
|
+
arr[0] | arr[1]<<8 | arr[2]<<16
|
55
|
+
end
|
56
|
+
|
57
|
+
def get_string
|
58
|
+
str = ""
|
59
|
+
while ((ch = read(1).unpack("a")[0]) != "\x00")
|
60
|
+
str += ch
|
61
|
+
end
|
62
|
+
str
|
63
|
+
end
|
64
|
+
|
65
|
+
def get_u8
|
66
|
+
read(1).unpack("C")[0]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
module QQWryIpStr
|
71
|
+
def ip_str
|
72
|
+
[@ip].pack("L").unpack("C4").reverse.join(".")
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class QQWryHeader
|
77
|
+
def initialize(file)
|
78
|
+
file.seek(0)
|
79
|
+
@first = file.get_le32
|
80
|
+
@last = file.get_le32
|
81
|
+
end
|
82
|
+
attr_reader :first, :last
|
83
|
+
end
|
84
|
+
|
85
|
+
class QQWryRecord
|
86
|
+
include QQWryIpStr
|
87
|
+
|
88
|
+
attr_reader :city, :area
|
89
|
+
|
90
|
+
def initialize(file, pos)
|
91
|
+
file.seek(pos)
|
92
|
+
@ip = file.get_le32
|
93
|
+
case file.get_u8
|
94
|
+
when 0x1
|
95
|
+
file.seek(pos = file.get_le24)
|
96
|
+
case file.get_u8
|
97
|
+
when 0x2
|
98
|
+
file.seek(file.get_le24)
|
99
|
+
@city = file.get_string
|
100
|
+
file.seek(pos + 4)
|
101
|
+
else
|
102
|
+
file.seek(-1, IO::SEEK_CUR)
|
103
|
+
@city = file.get_string
|
104
|
+
end
|
105
|
+
parse_area(file)
|
106
|
+
when 0x2
|
107
|
+
pos = file.get_le24
|
108
|
+
parse_area(file)
|
109
|
+
file.seek(pos)
|
110
|
+
@city = file.get_string
|
111
|
+
else
|
112
|
+
file.seek(-1, IO::SEEK_CUR)
|
113
|
+
@city = file.get_string
|
114
|
+
parse_area(file)
|
115
|
+
end
|
116
|
+
|
117
|
+
iconv_city
|
118
|
+
end
|
119
|
+
|
120
|
+
attr_reader :ip
|
121
|
+
|
122
|
+
def _conv(str)
|
123
|
+
begin
|
124
|
+
if str.respond_to?(:encode)
|
125
|
+
str.force_encoding('GBK').encode('UTF-8')
|
126
|
+
else
|
127
|
+
Iconv::conv('UTF-8', 'GBK', str)
|
128
|
+
end
|
129
|
+
rescue
|
130
|
+
str = str[0, str.length - 1]
|
131
|
+
retry
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def iconv_city
|
136
|
+
@city = _conv @city.to_s
|
137
|
+
@city = '' if @city=~ /\s*CZ88\.NET\s*/
|
138
|
+
end
|
139
|
+
|
140
|
+
def parse_area(file)
|
141
|
+
case file.get_u8
|
142
|
+
when 0x2
|
143
|
+
if ((pos = file.get_le24) != 0)
|
144
|
+
file.seek(pos)
|
145
|
+
@area = file.get_string
|
146
|
+
else
|
147
|
+
@area = ""
|
148
|
+
end
|
149
|
+
else
|
150
|
+
file.seek(-1, IO::SEEK_CUR)
|
151
|
+
@area = file.get_string
|
152
|
+
end
|
153
|
+
|
154
|
+
@area = _conv(@area.to_s)
|
155
|
+
|
156
|
+
@area = '' if @area =~ /\s*CZ88\.NET\s*/
|
157
|
+
end
|
158
|
+
|
159
|
+
private :parse_area
|
160
|
+
end
|
161
|
+
|
162
|
+
class QQWryIndex
|
163
|
+
include QQWryIpStr
|
164
|
+
|
165
|
+
def initialize(file, pos)
|
166
|
+
file.seek(pos)
|
167
|
+
@ip = file.get_le32
|
168
|
+
@pos = file.get_le24
|
169
|
+
end
|
170
|
+
attr_reader :ip, :pos
|
171
|
+
end
|
172
|
+
|
173
|
+
class QQWryFile
|
174
|
+
def initialize(filename = "qqwry.dat")
|
175
|
+
@filename = filename
|
176
|
+
end
|
177
|
+
|
178
|
+
def each
|
179
|
+
File.open(@filename) do |file|
|
180
|
+
file.extend QQWryIO
|
181
|
+
header = QQWryHeader.new(file)
|
182
|
+
pos = header.first
|
183
|
+
while pos <= header.last
|
184
|
+
index = QQWryIndex.new(file, pos)
|
185
|
+
record = QQWryRecord.new(file, index.pos)
|
186
|
+
if block_given?
|
187
|
+
yield index, record
|
188
|
+
else
|
189
|
+
puts "#{index.ip_str}-#{record.ip_str} #{record.city}" +
|
190
|
+
" #{record.area}"
|
191
|
+
end
|
192
|
+
pos += 7
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def find(ip)
|
198
|
+
if ip.class == String
|
199
|
+
ip = ip.split(".").collect{|x| x.to_i}.pack("C4").unpack("N")[0]
|
200
|
+
end
|
201
|
+
|
202
|
+
File.open(@filename) do |file|
|
203
|
+
file.extend QQWryIO
|
204
|
+
header = QQWryHeader.new(file)
|
205
|
+
first = header.first
|
206
|
+
left = 0
|
207
|
+
right = (header.last - first) / 7
|
208
|
+
while left <= right
|
209
|
+
middle = (left + right) / 2
|
210
|
+
middle_index = QQWryIndex.new(file, first + middle * 7)
|
211
|
+
if (ip > middle_index.ip)
|
212
|
+
left = middle + 1
|
213
|
+
elsif (ip < middle_index.ip)
|
214
|
+
right = middle - 1
|
215
|
+
else
|
216
|
+
return QQWryRecord.new(file, middle_index.pos)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
index = QQWryIndex.new(file, first + right * 7)
|
220
|
+
return QQWryRecord.new(file, index.pos)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
data/lib/loyal_ipinfo.rb
ADDED
data/resources/qqwry.dat
ADDED
Binary file
|
metadata
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: loyal_ipinfo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- happy
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-08-08 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bindata
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ">="
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
description: Description of LoyalIpinfo.
|
31
|
+
email:
|
32
|
+
- andywang7259@gmail.com
|
33
|
+
executables: []
|
34
|
+
extensions: []
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- resources/qqwry.dat
|
38
|
+
- lib/loyal_ipinfo/config.rb
|
39
|
+
- lib/loyal_ipinfo/version.rb
|
40
|
+
- lib/loyal_ipinfo/array_util.rb
|
41
|
+
- lib/loyal_ipinfo/worker.rb
|
42
|
+
- lib/loyal_ipinfo.rb
|
43
|
+
- lib/tasks/loyal_ipinfo_tasks.rake
|
44
|
+
- MIT-LICENSE
|
45
|
+
- Rakefile
|
46
|
+
- README.md
|
47
|
+
homepage: http://develop.xiuxian123.com/
|
48
|
+
licenses: []
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options: []
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
59
|
+
segments:
|
60
|
+
- 0
|
61
|
+
hash: 1415171691332789189
|
62
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
segments:
|
69
|
+
- 0
|
70
|
+
hash: 1415171691332789189
|
71
|
+
requirements: []
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 1.8.25
|
74
|
+
signing_key:
|
75
|
+
specification_version: 3
|
76
|
+
summary: Summary of LoyalIpinfo.
|
77
|
+
test_files: []
|