passivedns-client 2.1.6 → 2.1.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -7,7 +7,7 @@ module PassiveDNS #:nodoc: don't document this
7
7
  # The Provider module contains all the Passive DNS provider client code
8
8
  module Provider
9
9
  # Queries VirusTotal's passive DNS database
10
- class VirusTotal < PassiveDB
10
+ class VirusTotal < PassiveDB
11
11
  # Sets the modules self-reported name to "VirusTotal"
12
12
  def self.name
13
13
  "VirusTotal"
@@ -39,7 +39,7 @@ module PassiveDNS #:nodoc: don't document this
39
39
  #
40
40
  # PassiveDNS::Provider::VirusTotal.new(options)
41
41
  #
42
- def initialize(options={})
42
+ def initialize(options={})
43
43
  @debug = options[:debug] || false
44
44
  @apikey = options["APIKEY"] || raise("#{self.class.name} requires an APIKEY. See README.md")
45
45
  @url = options["URL"] || "https://www.virustotal.com/vtapi/v2/"
@@ -47,59 +47,59 @@ module PassiveDNS #:nodoc: don't document this
47
47
 
48
48
  # Takes a label (either a domain or an IP address) and returns
49
49
  # an array of PassiveDNS::PDNSResult instances with the answers to the query
50
- def lookup(label, limit=nil)
51
- $stderr.puts "DEBUG: #{self.class.name}.lookup(#{label})" if @debug
52
- Timeout::timeout(240) {
53
- url = nil
54
- if label =~ /^[\d\.]+$/
55
- url = "#{@url}ip-address/report?ip=#{label}&apikey=#{@apikey}"
56
- else
57
- url = "#{@url}domain/report?domain=#{label}&apikey=#{@apikey}"
58
- end
59
- $stderr.puts "DEBUG: #{self.class.name} url = #{url}" if @debug
60
- url = URI.parse url
61
- http = Net::HTTP.new(url.host, url.port)
62
- http.use_ssl = (url.scheme == 'https')
63
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
64
- http.verify_depth = 5
65
- request = Net::HTTP::Get.new(url.path+"?"+url.query)
66
- request.add_field("User-Agent", "Ruby/#{RUBY_VERSION} passivedns-client rubygem v#{PassiveDNS::Client::VERSION}")
67
- t1 = Time.now
68
- response = http.request(request)
69
- t2 = Time.now
70
- recs = parse_json(response.body, label, t2-t1)
50
+ def lookup(label, limit=nil)
51
+ $stderr.puts "DEBUG: #{self.class.name}.lookup(#{label})" if @debug
52
+ Timeout::timeout(240) {
53
+ url = nil
54
+ if label =~ /^[\d\.]+$/
55
+ url = "#{@url}ip-address/report?ip=#{label}&apikey=#{@apikey}"
56
+ else
57
+ url = "#{@url}domain/report?domain=#{label}&apikey=#{@apikey}"
58
+ end
59
+ $stderr.puts "DEBUG: #{self.class.name} url = #{url}" if @debug
60
+ url = URI.parse url
61
+ http = Net::HTTP.new(url.host, url.port)
62
+ http.use_ssl = (url.scheme == 'https')
63
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
64
+ http.verify_depth = 5
65
+ request = Net::HTTP::Get.new(url.path+"?"+url.query)
66
+ request.add_field("User-Agent", "Ruby/#{RUBY_VERSION} passivedns-client rubygem v#{PassiveDNS::Client::VERSION}")
67
+ t1 = Time.now
68
+ response = http.request(request)
69
+ t2 = Time.now
70
+ recs = parse_json(response.body, label, t2-t1)
71
71
  if limit
72
72
  recs[0,limit]
73
73
  else
74
74
  recs
75
75
  end
76
- }
77
- rescue Timeout::Error => e
78
- $stderr.puts "#{self.class.name} lookup timed out: #{label}"
79
- end
76
+ }
77
+ rescue Timeout::Error => e
78
+ $stderr.puts "#{self.class.name} lookup timed out: #{label}"
79
+ end
80
80
 
81
81
  private
82
82
 
83
83
  # parses the response of virustotal's JSON reply to generate an array of PDNSResult
84
- def parse_json(page,query,response_time=0)
85
- res = []
86
- data = JSON.parse(page)
87
- if data['resolutions']
88
- data['resolutions'].each do |row|
84
+ def parse_json(page,query,response_time=0)
85
+ res = []
86
+ data = JSON.parse(page)
87
+ if data['resolutions']
88
+ data['resolutions'].each do |row|
89
89
  lastseen = Time.parse(row['last_resolved']+" +0000")
90
- if row['ip_address']
91
- res << PDNSResult.new(self.class.name,response_time,query,row['ip_address'],'A',nil,nil,lastseen)
92
- elsif row['hostname']
93
- res << PDNSResult.new(self.class.name,response_time,row['hostname'],query,'A',nil,nil,lastseen)
94
- end
95
- end
96
- end
97
- res
98
- rescue Exception => e
99
- $stderr.puts "VirusTotal Exception: #{e}"
100
- raise e
101
- end
90
+ if row['ip_address']
91
+ res << PDNSResult.new(self.class.name,response_time,query,row['ip_address'],'A',nil,nil,lastseen, 'yellow')
92
+ elsif row['hostname']
93
+ res << PDNSResult.new(self.class.name,response_time,row['hostname'],query,'A',nil,nil,lastseen, 'yellow')
94
+ end
95
+ end
96
+ end
97
+ res
98
+ rescue Exception => e
99
+ $stderr.puts "VirusTotal Exception: #{e}"
100
+ raise e
101
+ end
102
102
 
103
- end
103
+ end
104
104
  end
105
- end
105
+ end
@@ -4,297 +4,297 @@ require 'structformatter'
4
4
 
5
5
  module PassiveDNS # :nodoc:
6
6
  # struct to hold pending entries for query
7
- class PDNSQueueEntry < Struct.new(:query, :state, :level); end
7
+ class PDNSQueueEntry < Struct.new(:query, :state, :level); end
8
8
 
9
9
  # holds state in memory of the queue to be queried, records returned, and the level of recursion
10
- class PDNSToolState
10
+ class PDNSToolState
11
11
  # :debug enables verbose logging to standard output
12
- attr_accessor :debug
12
+ attr_accessor :debug
13
13
  # :level is the recursion depth
14
- attr_reader :level
14
+ attr_reader :level
15
15
 
16
16
  # creates a new, blank PDNSToolState instance
17
- def initialize
18
- @queue = []
19
- @recs = []
20
- @level = 0
21
- end
17
+ def initialize
18
+ @queue = []
19
+ @recs = []
20
+ @level = 0
21
+ end
22
22
 
23
23
  # returns the next record
24
- def next_result
25
- @recs.each do |rec|
26
- yield rec
27
- end
28
- end
24
+ def next_result
25
+ @recs.each do |rec|
26
+ yield rec
27
+ end
28
+ end
29
29
 
30
30
  # adds the record to the list of records received and tries to add the answer and query back to the queue for future query
31
- def add_result(res)
32
- @recs << res
33
- add_query(res.answer,'pending')
34
- add_query(res.query,'pending')
35
- end
31
+ def add_result(res)
32
+ @recs << res
33
+ add_query(res.answer,'pending')
34
+ add_query(res.query,'pending')
35
+ end
36
36
 
37
37
  # sets the state of a given query
38
- def update_query(query,state)
39
- @queue.each do |q|
40
- if q.query == query
41
- puts "update_query: #{query} (#{q.state}) -> (#{state})" if @debug
42
- q.state = state
43
- break
44
- end
45
- end
46
- end
38
+ def update_query(query,state)
39
+ @queue.each do |q|
40
+ if q.query == query
41
+ puts "update_query: #{query} (#{q.state}) -> (#{state})" if @debug
42
+ q.state = state
43
+ break
44
+ end
45
+ end
46
+ end
47
47
 
48
48
  # returns the state of a provided query
49
- def get_state(query)
50
- @queue.each do |q|
51
- if q.query == query
52
- return q.state
53
- end
54
- end
55
- false
56
- end
49
+ def get_state(query)
50
+ @queue.each do |q|
51
+ if q.query == query
52
+ return q.state
53
+ end
54
+ end
55
+ false
56
+ end
57
57
 
58
58
  # adding a query to the queue of things to be queried, but only if the query isn't already queued or answered
59
- def add_query(query,state,level=@level+1)
60
- if query =~ /^\d+ \w+\./
61
- query = query.split(/ /,2)[1]
62
- end
63
- return if get_state(query)
64
- puts "Adding query: #{query}, #{state}, #{level}" if @debug
65
- @queue << PDNSQueueEntry.new(query,state,level)
66
- end
59
+ def add_query(query,state,level=@level+1)
60
+ if query =~ /^\d+ \w+\./
61
+ query = query.split(/ /,2)[1]
62
+ end
63
+ return if get_state(query)
64
+ puts "Adding query: #{query}, #{state}, #{level}" if @debug
65
+ @queue << PDNSQueueEntry.new(query,state,level)
66
+ end
67
67
 
68
68
  # returns each query waiting on the queue
69
- def each_query(max_level=20)
70
- @queue.each do |q|
71
- if q.state == 'pending' or q.state == 'failed'
72
- @level = q.level
73
- q.state = 'queried'
74
- if q.level < max_level
75
- yield q.query
76
- end
77
- end
78
- end
79
- end
69
+ def each_query(max_level=20)
70
+ @queue.each do |q|
71
+ if q.state == 'pending' or q.state == 'failed'
72
+ @level = q.level
73
+ q.state = 'queried'
74
+ if q.level < max_level
75
+ yield q.query
76
+ end
77
+ end
78
+ end
79
+ end
80
80
 
81
81
  # transforms a set of results into GDF syntax
82
- def to_gdf
83
- output = "nodedef> name,description VARCHAR(12),color,style\n"
84
- # IP "$node2,,white,1"
85
- # domain "$node2,,gray,2"
86
- # Struct.new(:query, :answer, :rrtype, :ttl, :firstseen, :lastseen)
87
- colors = {"MX" => "green", "A" => "blue", "CNAME" => "pink", "NS" => "red", "SOA" => "white", "PTR" => "purple", "TXT" => "brown"}
88
- nodes = {}
89
- edges = {}
90
- next_result do |i|
91
- if i
92
- nodes[i.query + ",,gray,2"] = true
93
- if i.answer =~ /[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/ then
94
- nodes[i.answer + ",,white,1"] = true
95
- else
96
- nodes[i.answer + ",,gray,2"] = true
97
- end
98
- color = colors[i.rrtype]
99
- color ||= "blue"
100
- edges[i.query + "," + i.answer + "," + color] = true
101
- end
102
- end
103
- nodes.each do |i,j|
104
- output += i+"\n"
105
- end
106
- output += "edgedef> node1,node2,color\n"
107
- edges.each do |i,j|
108
- output += i+"\n"
109
- end
110
- output
111
- end
82
+ def to_gdf
83
+ output = "nodedef> name,description VARCHAR(12),color,style\n"
84
+ # IP "$node2,,white,1"
85
+ # domain "$node2,,gray,2"
86
+ # Struct.new(:query, :answer, :rrtype, :ttl, :firstseen, :lastseen)
87
+ colors = {"MX" => "green", "A" => "blue", "CNAME" => "pink", "NS" => "red", "SOA" => "white", "PTR" => "purple", "TXT" => "brown"}
88
+ nodes = {}
89
+ edges = {}
90
+ next_result do |i|
91
+ if i
92
+ nodes[i.query + ",,gray,2"] = true
93
+ if i.answer =~ /[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/ then
94
+ nodes[i.answer + ",,white,1"] = true
95
+ else
96
+ nodes[i.answer + ",,gray,2"] = true
97
+ end
98
+ color = colors[i.rrtype]
99
+ color ||= "blue"
100
+ edges[i.query + "," + i.answer + "," + color] = true
101
+ end
102
+ end
103
+ nodes.each do |i,j|
104
+ output += i+"\n"
105
+ end
106
+ output += "edgedef> node1,node2,color\n"
107
+ edges.each do |i,j|
108
+ output += i+"\n"
109
+ end
110
+ output
111
+ end
112
112
 
113
113
  # transforms a set of results into graphviz syntax
114
- def to_graphviz
115
- colors = {"MX" => "green", "A" => "blue", "CNAME" => "pink", "NS" => "red", "SOA" => "white", "PTR" => "purple", "TXT" => "brown"}
116
- output = "graph pdns {\n"
117
- nodes = {}
118
- next_result do |l|
119
- if l
120
- unless nodes[l.query]
121
- output += " \"#{l.query}\" [shape=ellipse, style=filled, color=gray];\n"
122
- if l.answer =~ /^\d{3}\.\d{3}\.\d{3}\.\d{3}$/
123
- output += " \"#{l.answer}\" [shape=box, style=filled, color=white];\n"
124
- else
125
- output += " \"#{l.answer}\" [shape=ellipse, style=filled, color=gray];\n"
126
- end
127
- nodes[l.query] = true
128
- end
129
- output += " \"#{l.query}\" -- \"#{l.answer}\" [color=#{colors[l.rrtype]}];\n"
130
- end
131
- end
132
- output += "}\n"
133
- end
114
+ def to_graphviz
115
+ colors = {"MX" => "green", "A" => "blue", "CNAME" => "pink", "NS" => "red", "SOA" => "white", "PTR" => "purple", "TXT" => "brown"}
116
+ output = "graph pdns {\n"
117
+ nodes = {}
118
+ next_result do |l|
119
+ if l
120
+ unless nodes[l.query]
121
+ output += " \"#{l.query}\" [shape=ellipse, style=filled, color=gray];\n"
122
+ if l.answer =~ /^\d{3}\.\d{3}\.\d{3}\.\d{3}$/
123
+ output += " \"#{l.answer}\" [shape=box, style=filled, color=white];\n"
124
+ else
125
+ output += " \"#{l.answer}\" [shape=ellipse, style=filled, color=gray];\n"
126
+ end
127
+ nodes[l.query] = true
128
+ end
129
+ output += " \"#{l.query}\" -- \"#{l.answer}\" [color=#{colors[l.rrtype]}];\n"
130
+ end
131
+ end
132
+ output += "}\n"
133
+ end
134
134
 
135
135
  # transforms a set of results into graphml syntax
136
- def to_graphml
137
- output = '<?xml version="1.0" encoding="UTF-8"?>
136
+ def to_graphml
137
+ output = '<?xml version="1.0" encoding="UTF-8"?>
138
138
  <graphml xmlns="http://graphml.graphdrawing.org/xmlns"
139
139
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
140
140
  xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
141
141
  http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
142
142
  <graph id="G" edgedefault="directed">
143
143
  '
144
- nodes = {}
145
- edges = {}
146
- next_result do |r|
147
- if r
148
- output += " <node id='#{r.query}'/>\n" unless nodes["#{r.query}"]
149
- nodes[r.query] = true
150
- output += " <node id='#{r.answer}'/>\n" unless nodes["#{r.answer}"]
151
- nodes[r.answer] = true
152
- output += " <edge source='#{r.query}' target='#{r.answer}'/>\n" unless edges["#{r.query}|#{r.answer}"]
153
- end
154
- end
155
- output += '</graph></graphml>'+"\n"
156
- end
144
+ nodes = {}
145
+ edges = {}
146
+ next_result do |r|
147
+ if r
148
+ output += " <node id='#{r.query}'/>\n" unless nodes["#{r.query}"]
149
+ nodes[r.query] = true
150
+ output += " <node id='#{r.answer}'/>\n" unless nodes["#{r.answer}"]
151
+ nodes[r.answer] = true
152
+ output += " <edge source='#{r.query}' target='#{r.answer}'/>\n" unless edges["#{r.query}|#{r.answer}"]
153
+ end
154
+ end
155
+ output += '</graph></graphml>'+"\n"
156
+ end
157
157
 
158
158
  # transforms a set of results into XML
159
- def to_xml
160
- output = '<?xml version="1.0" encoding="UTF-8" ?>'+"\n"
161
- output += "<report>\n"
162
- output += " <results>\n"
163
- next_result do |rec|
164
- output += " "+rec.to_xml+"\n"
165
- end
166
- output += " </results>\n"
167
- output += "</report>\n"
168
- end
159
+ def to_xml
160
+ output = '<?xml version="1.0" encoding="UTF-8" ?>'+"\n"
161
+ output += "<report>\n"
162
+ output += " <results>\n"
163
+ next_result do |rec|
164
+ output += " "+rec.to_xml+"\n"
165
+ end
166
+ output += " </results>\n"
167
+ output += "</report>\n"
168
+ end
169
169
 
170
170
  # transforms a set of results into YAML
171
- def to_yaml
172
- output = ""
173
- next_result do |rec|
174
- output += rec.to_yaml+"\n"
175
- end
176
- output
177
- end
171
+ def to_yaml
172
+ output = ""
173
+ next_result do |rec|
174
+ output += rec.to_yaml+"\n"
175
+ end
176
+ output
177
+ end
178
178
 
179
179
  # transforms a set of results into JSON
180
- def to_json
181
- output = "[\n"
182
- sep = ""
183
- next_result do |rec|
184
- output += sep
185
- output += rec.to_json
186
- sep = ",\n"
187
- end
188
- output += "\n]\n"
189
- end
180
+ def to_json
181
+ output = "[\n"
182
+ sep = ""
183
+ next_result do |rec|
184
+ output += sep
185
+ output += rec.to_json
186
+ sep = ",\n"
187
+ end
188
+ output += "\n]\n"
189
+ end
190
190
 
191
191
  # transforms a set of results into a text string
192
- def to_s(sep="\t")
193
- output = ""
194
- next_result do |rec|
195
- output += rec.to_s(sep)+"\n"
196
- end
197
- output
198
- end
199
- end # class PDNSToolState
192
+ def to_s(sep="\t")
193
+ output = ""
194
+ next_result do |rec|
195
+ output += rec.to_s(sep)+"\n"
196
+ end
197
+ output
198
+ end
199
+ end # class PDNSToolState
200
200
 
201
201
 
202
202
  # creates persistence to the tool state by leveraging SQLite3
203
- class PDNSToolStateDB < PDNSToolState
204
- attr_reader :level
203
+ class PDNSToolStateDB < PDNSToolState
204
+ attr_reader :level
205
205
  # creates an SQLite3-based Passive DNS Client state
206
206
  # only argument is the filename of the sqlite3 database
207
- def initialize(sqlitedb=nil)
208
- puts "PDNSToolState initialize #{sqlitedb}" if @debug
209
- @level = 0
210
- @sqlitedb = sqlitedb
211
- raise "Cannot use this class without a database file" unless @sqlitedb
212
- unless File.exists?(@sqlitedb)
213
- newdb = true
214
- end
215
- @sqlitedbh = SQLite3::Database.new(@sqlitedb)
216
- if newdb
217
- create_tables
218
- end
219
- res = @sqlitedbh.execute("select min(level) from queue where state = 'pending'")
220
- if res
221
- res.each do |row|
222
- @level = row[0].to_i
223
- puts "changed @level = #{@level}" if @debug
224
- end
225
- end
226
- end
207
+ def initialize(sqlitedb=nil)
208
+ puts "PDNSToolState initialize #{sqlitedb}" if @debug
209
+ @level = 0
210
+ @sqlitedb = sqlitedb
211
+ raise "Cannot use this class without a database file" unless @sqlitedb
212
+ unless File.exists?(@sqlitedb)
213
+ newdb = true
214
+ end
215
+ @sqlitedbh = SQLite3::Database.new(@sqlitedb)
216
+ if newdb
217
+ create_tables
218
+ end
219
+ res = @sqlitedbh.execute("select min(level) from queue where state = 'pending'")
220
+ if res
221
+ res.each do |row|
222
+ @level = row[0].to_i
223
+ puts "changed @level = #{@level}" if @debug
224
+ end
225
+ end
226
+ end
227
227
 
228
228
  # creates the sqlite3 tables needed to track the state of this tool as itqueries and recurses
229
- def create_tables
230
- puts "creating tables" if @debug
231
- @sqlitedbh.execute("create table results (query, answer, rrtype, ttl, firstseen, lastseen, ts REAL)")
232
- @sqlitedbh.execute("create table queue (query, state, level INTEGER, ts REAL)")
233
- @sqlitedbh.execute("create index residx on results (ts)")
234
- @sqlitedbh.execute("create unique index queue_unique on queue (query)")
235
- @sqlitedbh.execute("create index queue_level_idx on queue (level)")
236
- @sqlitedbh.execute("create index queue_state_idx on queue (state)")
237
- end
229
+ def create_tables
230
+ puts "creating tables" if @debug
231
+ @sqlitedbh.execute("create table results (query, answer, rrtype, ttl, firstseen, lastseen, ts REAL)")
232
+ @sqlitedbh.execute("create table queue (query, state, level INTEGER, ts REAL)")
233
+ @sqlitedbh.execute("create index residx on results (ts)")
234
+ @sqlitedbh.execute("create unique index queue_unique on queue (query)")
235
+ @sqlitedbh.execute("create index queue_level_idx on queue (level)")
236
+ @sqlitedbh.execute("create index queue_state_idx on queue (state)")
237
+ end
238
238
 
239
239
  # returns the next record
240
- def next_result
241
- rows = @sqlitedbh.execute("select query, answer, rrtype, ttl, firstseen, lastseen from results order by ts")
242
- rows.each do |row|
243
- yield PDNSResult.new(*row)
244
- end
245
- end
240
+ def next_result
241
+ rows = @sqlitedbh.execute("select query, answer, rrtype, ttl, firstseen, lastseen from results order by ts")
242
+ rows.each do |row|
243
+ yield PDNSResult.new(*row)
244
+ end
245
+ end
246
246
 
247
247
  # adds the record to the list of records received and tries to add the answer and query back to the queue for future query
248
- def add_result(res)
249
- puts "adding result: #{res.to_s}" if @debug
250
- curtime = Time.now().to_f
251
- @sqlitedbh.execute("insert into results values ('#{res.query}','#{res.answer}','#{res.rrtype}','#{res.ttl}','#{res.firstseen}','#{res.lastseen}',#{curtime})")
248
+ def add_result(res)
249
+ puts "adding result: #{res.to_s}" if @debug
250
+ curtime = Time.now().to_f
251
+ @sqlitedbh.execute("insert into results values ('#{res.query}','#{res.answer}','#{res.rrtype}','#{res.ttl}','#{res.firstseen}','#{res.lastseen}',#{curtime})")
252
252
 
253
- add_query(res.answer,'pending')
254
- add_query(res.query,'pending')
255
- end
253
+ add_query(res.answer,'pending')
254
+ add_query(res.query,'pending')
255
+ end
256
256
 
257
257
  # adding a query to the queue of things to be queried, but only if the query isn't already queued or answered
258
- def add_query(query,state,level=@level+1)
259
- return if get_state(query)
260
- curtime = Time.now().to_f
261
- begin
262
- puts "add_query(#{query},#{state},level=#{level})" if @debug
263
- @sqlitedbh.execute("insert into queue values ('#{query}','#{state}',#{level},#{curtime})")
264
- rescue
265
- end
266
- end
258
+ def add_query(query,state,level=@level+1)
259
+ return if get_state(query)
260
+ curtime = Time.now().to_f
261
+ begin
262
+ puts "add_query(#{query},#{state},level=#{level})" if @debug
263
+ @sqlitedbh.execute("insert into queue values ('#{query}','#{state}',#{level},#{curtime})")
264
+ rescue
265
+ end
266
+ end
267
267
 
268
268
  # sets the state of a given query
269
- def update_query(query,state)
270
- @sqlitedbh.execute("update queue set state = '#{state}' where query = '#{query}'")
271
- end
269
+ def update_query(query,state)
270
+ @sqlitedbh.execute("update queue set state = '#{state}' where query = '#{query}'")
271
+ end
272
272
 
273
273
  # returns each query waiting on the queue
274
- def get_state(query)
275
- rows = @sqlitedbh.execute("select state from queue where query = '#{query}'")
276
- if rows
277
- rows.each do |row|
278
- return row[0]
279
- end
280
- end
281
- false
282
- end
274
+ def get_state(query)
275
+ rows = @sqlitedbh.execute("select state from queue where query = '#{query}'")
276
+ if rows
277
+ rows.each do |row|
278
+ return row[0]
279
+ end
280
+ end
281
+ false
282
+ end
283
283
 
284
284
  # returns each query waiting on the queue
285
- def each_query(max_level=20)
286
- puts "each_query max_level=#{max_level} curlevel=#{@level}" if @debug
287
- rows = @sqlitedbh.execute("select query, state, level from queue where state = 'failed' or state = 'pending' order by level limit 1")
288
- if rows
289
- rows.each do |row|
290
- query,state,level = row
291
- puts " #{query},#{state},#{level}" if @debug
292
- if level < max_level
293
- update_query(query,'queried')
294
- yield query
295
- end
296
- end
297
- end
298
- end
299
- end # class PDNSToolStateDB
300
- end
285
+ def each_query(max_level=20)
286
+ puts "each_query max_level=#{max_level} curlevel=#{@level}" if @debug
287
+ rows = @sqlitedbh.execute("select query, state, level from queue where state = 'failed' or state = 'pending' order by level limit 1")
288
+ if rows
289
+ rows.each do |row|
290
+ query,state,level = row
291
+ puts " #{query},#{state},#{level}" if @debug
292
+ if level < max_level
293
+ update_query(query,'queried')
294
+ yield query
295
+ end
296
+ end
297
+ end
298
+ end
299
+ end # class PDNSToolStateDB
300
+ end