Class: Reader

Inherits:
Object
  • Object
show all
Defined in:
lib/ipdb/reader.rb

Instance Method Summary collapse

Constructor Details

#initialize(name) ⇒ Reader

Returns a new instance of Reader.



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/ipdb/reader.rb', line 5

def initialize(name)

  if name.nil? || !File.exists?(name)
    raise "You must specify 'database => ...' in your ipip filter (I looked for '#{name}')"
  end
  if !File.readable? name
    raise "ip database is not readable."
  end

  @data = File.binread name

  meta_len = @data[0 ... 4].unpack('N')[0]
  meta_buf = @data[4 ... 4+meta_len]

  @meta = JSON.parse(meta_buf)

  if @data.length != (4 + meta_len + @meta['total_size'])
    raise "ip database file size error."
  end

  @node_count = @meta['node_count']
  @cache = {}
  @body = @data[4+meta_len ... @data.length]
end

Instance Method Details

#find(ipx, lang) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/ipdb/reader.rb', line 66

def find(ipx,lang)
  begin
    ipv = IPAddr.new ipx
  rescue => e
    return e.message
  end
  node = self.find_node ipv
  resolved = node - @node_count + @node_count * 8
  size = @body[resolved..resolved+1].unpack('n')[0]

  temp = @body[resolved+2..resolved+1+size]
  loc = temp.encode("UTF-8", "UTF-8").split("\t", @meta['fields'].length * @meta['languages'].length)

  off = @meta['languages'][lang]

  loc[off ... @meta['fields'].length+off]
end

#find_node(ipv) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/ipdb/reader.rb', line 36

def find_node(ipv)
  addr = ipv.hton
  node = ipv.ipv4? ? 96 : 0

  idx = 0
  key = addr[0...16]
  val = @cache[key]
  if !val.nil?
    node = val
    idx = 16
  end

  if node < @node_count
    while idx < 128 do
      bin = addr[idx >> 3].unpack("C")[0]
      flag = (1 & (bin >> 7 - (idx % 8)))
      node = self.read_node(node, flag)
      idx += 1
      if idx == 16
        @cache[key] = node
      end
      if node > @node_count
        break
      end
    end
  end

  node
end

#read_node(node, idx) ⇒ Object



30
31
32
33
# File 'lib/ipdb/reader.rb', line 30

def read_node(node, idx)
  off = node * 8 + idx * 4
  @body[off..off+3].unpack('N')[0]
end