whois 2.6.2 → 2.6.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +1 -1
- data/CHANGELOG.md +13 -0
- data/README.md +11 -13
- data/lib/whois.rb +2 -2
- data/lib/whois/errors.rb +1 -1
- data/lib/whois/record.rb +49 -43
- data/lib/whois/record/parser.rb +102 -102
- data/lib/whois/record/parser/base.rb +4 -4
- data/lib/whois/record/parser/whois.aero.rb +4 -0
- data/lib/whois/record/parser/whois.ati.tn.rb +1 -1
- data/lib/whois/record/parser/whois.audns.net.au.rb +1 -1
- data/lib/whois/record/parser/whois.cira.ca.rb +1 -1
- data/lib/whois/record/parser/whois.dns.hr.rb +1 -1
- data/lib/whois/record/parser/whois.dreamhost.com.rb +1 -1
- data/lib/whois/record/parser/whois.enom.com.rb +1 -1
- data/lib/whois/record/parser/whois.fi.rb +1 -1
- data/lib/whois/record/parser/whois.nc.rb +1 -1
- data/lib/whois/record/parser/whois.networksolutions.com.rb +1 -1
- data/lib/whois/record/parser/whois.nic.lk.rb +1 -1
- data/lib/whois/record/parser/whois.registry.om.rb +1 -1
- data/lib/whois/record/parser/whois.registrypro.pro.rb +5 -50
- data/lib/whois/record/parser/whois.rnids.rs.rb +1 -1
- data/lib/whois/record/parser/whois.sx.rb +1 -1
- data/lib/whois/record/parser/whois.ua.rb +2 -2
- data/lib/whois/record/scanners/whois.ati.tn.rb +1 -1
- data/lib/whois/record/scanners/whois.audns.net.au.rb +1 -1
- data/lib/whois/record/scanners/whois.centralnic.com.rb +1 -1
- data/lib/whois/record/scanners/whois.cira.ca.rb +1 -1
- data/lib/whois/record/scanners/whois.dns.hr.rb +1 -1
- data/lib/whois/record/scanners/whois.nc.rb +1 -1
- data/lib/whois/record/scanners/whois.registry.om.rb +1 -1
- data/lib/whois/record/scanners/whois.rnids.rs.rb +1 -1
- data/lib/whois/record/scanners/whois.sx.rb +1 -1
- data/lib/whois/server.rb +9 -5
- data/lib/whois/server/adapters/base.rb +3 -3
- data/lib/whois/version.rb +1 -1
- data/spec/fixtures/responses/whois.aero/status_registered.expected +36 -36
- data/spec/fixtures/responses/whois.registrypro.pro/status_available.expected +34 -0
- data/spec/fixtures/responses/whois.registrypro.pro/status_available.txt +1 -20
- data/spec/fixtures/responses/whois.registrypro.pro/status_registered.expected +87 -9
- data/spec/fixtures/responses/whois.registrypro.pro/status_registered.txt +94 -55
- data/spec/fixtures/responses/whois.ua/property_created_at_outofrange.expected +2 -0
- data/spec/fixtures/responses/whois.ua/property_created_at_outofrange.txt +93 -0
- data/spec/tlds +1 -1
- data/spec/whois/record/parser/responses/whois.aero/status_registered_spec.rb +36 -36
- data/spec/whois/record/parser/responses/whois.registrypro.pro/status_available_spec.rb +48 -0
- data/spec/whois/record/parser/responses/whois.registrypro.pro/status_registered_spec.rb +101 -9
- data/spec/whois/record/parser/responses/whois.ua/property_created_at_outofrange_spec.rb +29 -0
- data/spec/whois/record/parser_spec.rb +4 -0
- data/spec/whois/server_spec.rb +11 -2
- data/whois.gemspec +3 -3
- metadata +5 -2
data/.yardopts
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
--readme README.
|
1
|
+
--readme README.md
|
2
2
|
--title 'Whois API Documentation'
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,19 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
3
|
|
4
|
+
## Release 2.6.3
|
5
|
+
|
6
|
+
* NEW: whois.registrypro.pro is now a full parser.
|
7
|
+
|
8
|
+
* FIXED: In some cases the parser class is not correctly detected from hostname (GH-173). [Thanks @JustinCampbell]
|
9
|
+
|
10
|
+
* FIXED: whois.ua parser raises ArgumentError when the created_on object invalid data.
|
11
|
+
|
12
|
+
* FIXED: Whois::Server may occasionally raise an error trying to resolve an IPv6 matching query object (GH-174). [Thanks @aeden].
|
13
|
+
|
14
|
+
* CHANGED: Updated whois.registrypro.pro parser to the new response format.
|
15
|
+
|
16
|
+
|
4
17
|
## Release 2.6.2
|
5
18
|
|
6
19
|
* SERVER: Added .SX TLD server (GH-170).
|
data/README.md
CHANGED
@@ -6,11 +6,20 @@
|
|
6
6
|
|
7
7
|
*Whois* is a OS-independent library and doesn't require any external binaries or C libraries: it is a 100% Ruby software.
|
8
8
|
|
9
|
-
This library was developed to power [RoboDomain](https://www.robodomain.com) and
|
9
|
+
This library was developed to power [RoboDomain](https://www.robodomain.com/) and [RoboWhois](http://www.robowhois.com/). It has been performing queries in production since July 2009.
|
10
10
|
|
11
11
|
An extensive test suite is available to verify the library correctness but you must be aware that registrant might change WHOIS interfaces without notice and at any time causing queries to specific hosts to stop working.
|
12
12
|
|
13
13
|
|
14
|
+
## Donations
|
15
|
+
|
16
|
+
[Support Whois at Pledgie](http://www.pledgie.com/campaigns/11383).
|
17
|
+
|
18
|
+
<a href='http://www.pledgie.com/campaigns/11383'><img alt='Click here to lend your support to: whois and make a donation at www.pledgie.com !' src='http://www.pledgie.com/campaigns/11383.png?skin_name=chrome' border='0' /></a>
|
19
|
+
|
20
|
+
*Whois* is free software, but it costs money to write, test, and distribute it. You can support the development by sending a donation. **Any amount, even $5, is greatly appreciated**.
|
21
|
+
|
22
|
+
|
14
23
|
## Features
|
15
24
|
|
16
25
|
* Ability to query registry data for [IPv4, IPv6, TLDs, and domain names](http://www.ruby-whois.org/manual/usage.html#usage-objects)
|
@@ -183,15 +192,6 @@ Pull requests are very welcome! Please include spec and/or feature coverage for
|
|
183
192
|
Report issues or feature requests to [GitHub Issues](https://github.com/weppos/whois/issues).
|
184
193
|
|
185
194
|
|
186
|
-
## Donations
|
187
|
-
|
188
|
-
[Support Whois at Pledgie](http://www.pledgie.com/campaigns/11383).
|
189
|
-
|
190
|
-
<a href='http://www.pledgie.com/campaigns/11383'><img alt='Click here to lend your support to: whois and make a donation at www.pledgie.com !' src='http://www.pledgie.com/campaigns/11383.png?skin_name=chrome' border='0' /></a>
|
191
|
-
|
192
|
-
Whois is free software, but it costs money to write, test, and distribute it. You can support the development by sending a donation. **Any amount, even $5, is greatly appreciated**.
|
193
|
-
|
194
|
-
|
195
195
|
## More
|
196
196
|
|
197
197
|
- [Homepage](http://www.ruby-whois.org/)
|
@@ -207,6 +207,4 @@ See the [CHANGELOG](CHANGELOG.md) file for details.
|
|
207
207
|
|
208
208
|
## License
|
209
209
|
|
210
|
-
Copyright (c) 2009-2012 Simone Carletti.
|
211
|
-
|
212
|
-
This is Free Software distributed under the MIT license.
|
210
|
+
Copyright (c) 2009-2012 Simone Carletti. This is Free Software distributed under the MIT license.
|
data/lib/whois.rb
CHANGED
@@ -112,7 +112,7 @@ module Whois
|
|
112
112
|
# @param [String] message The message to display.
|
113
113
|
# @return [void]
|
114
114
|
#
|
115
|
-
# @api
|
115
|
+
# @api private
|
116
116
|
# @private
|
117
117
|
def deprecate(message = nil, callstack = caller)
|
118
118
|
message ||= "You are using deprecated behavior which will be removed from the next major or minor release."
|
@@ -127,7 +127,7 @@ module Whois
|
|
127
127
|
# @param [String] message
|
128
128
|
# @return [void]
|
129
129
|
#
|
130
|
-
# @api
|
130
|
+
# @api private
|
131
131
|
# @private
|
132
132
|
def bug!(error, message)
|
133
133
|
raise error, message.dup <<
|
data/lib/whois/errors.rb
CHANGED
@@ -132,7 +132,7 @@ module Whois
|
|
132
132
|
|
133
133
|
# Raised when attempting to access a property when the response is unavailable.
|
134
134
|
#
|
135
|
-
# @since
|
135
|
+
# @since 2.0.3
|
136
136
|
# @see Whois::Record::Parser::Base#response_unavailable?
|
137
137
|
class ResponseIsUnavailable < ResponseError
|
138
138
|
end
|
data/lib/whois/record.rb
CHANGED
@@ -39,6 +39,7 @@ module Whois
|
|
39
39
|
# for {Parser::PROPERTIES} and {Parser::METHODS}.
|
40
40
|
#
|
41
41
|
# @return [Boolean]
|
42
|
+
#
|
42
43
|
def respond_to?(symbol, include_private = false)
|
43
44
|
super || Parser::PROPERTIES.include?(symbol) || Parser::METHODS.include?(symbol)
|
44
45
|
end
|
@@ -46,6 +47,7 @@ module Whois
|
|
46
47
|
# Returns a String representation of this record.
|
47
48
|
#
|
48
49
|
# @return [String] The record content.
|
50
|
+
#
|
49
51
|
def to_s
|
50
52
|
content.to_s
|
51
53
|
end
|
@@ -53,6 +55,7 @@ module Whois
|
|
53
55
|
# Returns a human-readable representation of this record.
|
54
56
|
#
|
55
57
|
# @return [String] The result of {#inspect} on content.
|
58
|
+
#
|
56
59
|
def inspect
|
57
60
|
content.inspect
|
58
61
|
end
|
@@ -62,6 +65,7 @@ module Whois
|
|
62
65
|
#
|
63
66
|
# @param [Whois::Record] other The record to compare.
|
64
67
|
# @return [Boolean]
|
68
|
+
#
|
65
69
|
def ==(other)
|
66
70
|
if equal?(other)
|
67
71
|
true
|
@@ -78,7 +82,7 @@ module Whois
|
|
78
82
|
# Invokes {#match} on record {#content}
|
79
83
|
# and returns the match as <tt>MatchData</tt> or <tt>nil</tt>.
|
80
84
|
#
|
81
|
-
# @param [Regexp, String] match
|
85
|
+
# @param [Regexp, String] pattern The regex pattern to match.
|
82
86
|
# @return [MatchData] If pattern matches #content
|
83
87
|
# @return [nil] If pattern doesn't match #content
|
84
88
|
#
|
@@ -91,7 +95,7 @@ module Whois
|
|
91
95
|
# Invokes {#match} and returns <tt>true</tt> if <tt>pattern</tt>
|
92
96
|
# matches {#content}, <tt>false</tt> otherwise.
|
93
97
|
#
|
94
|
-
# @param [Regexp, String] match
|
98
|
+
# @param [Regexp, String] pattern The regex pattern to match.
|
95
99
|
# @return [Boolean]
|
96
100
|
#
|
97
101
|
# @see #match
|
@@ -122,6 +126,7 @@ module Whois
|
|
122
126
|
# Lazy-loads and returns the parser proxy for current record.
|
123
127
|
#
|
124
128
|
# @return [Whois::Record::Parser]
|
129
|
+
#
|
125
130
|
def parser
|
126
131
|
@parser ||= Parser.new(self)
|
127
132
|
end
|
@@ -145,6 +150,7 @@ module Whois
|
|
145
150
|
# along with corresponding values.
|
146
151
|
#
|
147
152
|
# @return [{ Symbol => Object }]
|
153
|
+
#
|
148
154
|
def properties
|
149
155
|
hash = {}
|
150
156
|
Parser::PROPERTIES.each { |property| hash[property] = send(property) }
|
@@ -288,54 +294,54 @@ module Whois
|
|
288
294
|
# @endgroup
|
289
295
|
|
290
296
|
|
291
|
-
|
297
|
+
private
|
292
298
|
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
end
|
299
|
+
# @api private
|
300
|
+
def self.define_property_method(method)
|
301
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
302
|
+
def #{method}(*args, &block)
|
303
|
+
if property_supported?(:#{method})
|
304
|
+
parser.#{method}(*args, &block)
|
300
305
|
end
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
# @api internal
|
305
|
-
def self.define_method_method(method)
|
306
|
-
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
307
|
-
def #{method}(*args, &block)
|
308
|
-
if parser.respond_to?(:#{method})
|
309
|
-
parser.#{method}(*args, &block)
|
310
|
-
end
|
311
|
-
end
|
312
|
-
RUBY
|
313
|
-
end
|
306
|
+
end
|
307
|
+
RUBY
|
308
|
+
end
|
314
309
|
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
310
|
+
# @api private
|
311
|
+
def self.define_method_method(method)
|
312
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
313
|
+
def #{method}(*args, &block)
|
314
|
+
if parser.respond_to?(:#{method})
|
315
|
+
parser.#{method}(*args, &block)
|
320
316
|
end
|
321
|
-
|
322
|
-
|
317
|
+
end
|
318
|
+
RUBY
|
319
|
+
end
|
323
320
|
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
elsif Parser::METHODS.include?(method)
|
330
|
-
self.class.define_method_method(method)
|
331
|
-
send(method, *args, &block)
|
332
|
-
elsif method.to_s =~ /([a-z_]+)\?/ and (Parser::PROPERTIES + Parser::METHODS).include?($1.to_sym)
|
333
|
-
self.class.define_question_method($1)
|
334
|
-
send(method)
|
335
|
-
else
|
336
|
-
super
|
321
|
+
# @api private
|
322
|
+
def self.define_question_method(method)
|
323
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
324
|
+
def #{method}?
|
325
|
+
!#{method}.nil?
|
337
326
|
end
|
327
|
+
RUBY
|
328
|
+
end
|
329
|
+
|
330
|
+
# Delegates all method calls to the internal parser.
|
331
|
+
def method_missing(method, *args, &block)
|
332
|
+
if Parser::PROPERTIES.include?(method)
|
333
|
+
self.class.define_property_method(method)
|
334
|
+
send(method, *args, &block)
|
335
|
+
elsif Parser::METHODS.include?(method)
|
336
|
+
self.class.define_method_method(method)
|
337
|
+
send(method, *args, &block)
|
338
|
+
elsif method.to_s =~ /([a-z_]+)\?/ and (Parser::PROPERTIES + Parser::METHODS).include?($1.to_sym)
|
339
|
+
self.class.define_question_method($1)
|
340
|
+
send(method)
|
341
|
+
else
|
342
|
+
super
|
338
343
|
end
|
344
|
+
end
|
339
345
|
|
340
346
|
end
|
341
347
|
|
data/lib/whois/record/parser.rb
CHANGED
@@ -114,7 +114,7 @@ module Whois
|
|
114
114
|
# # => "WhoisNicInfoIt"
|
115
115
|
#
|
116
116
|
def self.host_to_parser(host)
|
117
|
-
host.to_s.
|
117
|
+
host.to_s.downcase.
|
118
118
|
gsub(/[.-]/, '_').
|
119
119
|
gsub(/(?:^|_)(.)/) { $1.upcase }
|
120
120
|
end
|
@@ -136,7 +136,7 @@ module Whois
|
|
136
136
|
|
137
137
|
# Initializes and return a new parser from +record+.
|
138
138
|
#
|
139
|
-
# @param [Whois::Record]
|
139
|
+
# @param [Whois::Record] record
|
140
140
|
#
|
141
141
|
def initialize(record)
|
142
142
|
@record = record
|
@@ -262,119 +262,119 @@ module Whois
|
|
262
262
|
# @endgroup
|
263
263
|
|
264
264
|
|
265
|
-
|
265
|
+
private
|
266
266
|
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
end
|
273
|
-
RUBY
|
274
|
-
end
|
275
|
-
|
276
|
-
def method_missing(method, *args, &block)
|
277
|
-
if PROPERTIES.include?(method)
|
278
|
-
self.class.define_missing_method(method)
|
279
|
-
send(method, *args, &block)
|
280
|
-
elsif METHODS.include?(method)
|
281
|
-
self.class.define_missing_method(method)
|
282
|
-
send(method, *args, &block)
|
283
|
-
else
|
284
|
-
super
|
267
|
+
# @api private
|
268
|
+
def self.define_missing_method(method)
|
269
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
270
|
+
def #{method}(*args, &block)
|
271
|
+
delegate_to_parsers(:#{method}, *args, &block)
|
285
272
|
end
|
286
|
-
|
273
|
+
RUBY
|
274
|
+
end
|
287
275
|
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
# Select a parser where the property is defined but not supported
|
299
|
-
# and call the method.
|
300
|
-
# The call is expected to raise an exception.
|
301
|
-
elsif parser = select_parser(method, :not_supported)
|
302
|
-
parser.send(method, *args, &block)
|
303
|
-
|
304
|
-
# The property is not supported nor defined.
|
305
|
-
else
|
306
|
-
raise PropertyNotAvailable, "Unable to find a parser for `#{method}'"
|
307
|
-
end
|
276
|
+
def method_missing(method, *args, &block)
|
277
|
+
if PROPERTIES.include?(method)
|
278
|
+
self.class.define_missing_method(method)
|
279
|
+
send(method, *args, &block)
|
280
|
+
elsif METHODS.include?(method)
|
281
|
+
self.class.define_missing_method(method)
|
282
|
+
send(method, *args, &block)
|
283
|
+
else
|
284
|
+
super
|
308
285
|
end
|
286
|
+
end
|
309
287
|
|
310
|
-
|
311
|
-
#
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
#
|
316
|
-
#
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
#
|
321
|
-
#
|
322
|
-
#
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
#
|
327
|
-
|
328
|
-
|
329
|
-
#
|
330
|
-
def init_parsers
|
331
|
-
record.parts.reverse.map { |part| self.class.parser_for(part) }
|
288
|
+
def delegate_to_parsers(method, *args, &block)
|
289
|
+
# Raise an error without any parser
|
290
|
+
if parsers.empty?
|
291
|
+
raise ParserError, "Unable to select a parser because the record is empty"
|
292
|
+
|
293
|
+
# Select a parser where the property is supported
|
294
|
+
# and call the method.
|
295
|
+
elsif parser = select_parser(method, :supported)
|
296
|
+
parser.send(method, *args, &block)
|
297
|
+
|
298
|
+
# Select a parser where the property is defined but not supported
|
299
|
+
# and call the method.
|
300
|
+
# The call is expected to raise an exception.
|
301
|
+
elsif parser = select_parser(method, :not_supported)
|
302
|
+
parser.send(method, *args, &block)
|
303
|
+
|
304
|
+
# The property is not supported nor defined.
|
305
|
+
else
|
306
|
+
raise PropertyNotAvailable, "Unable to find a parser for `#{method}'"
|
332
307
|
end
|
308
|
+
end
|
333
309
|
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
310
|
+
# Loops through all record parts, for each part
|
311
|
+
# tries to guess the appropriate parser object whenever available,
|
312
|
+
# and returns the final array of server-specific parsers.
|
313
|
+
#
|
314
|
+
# Parsers are initialized in reverse order for performance reason.
|
315
|
+
#
|
316
|
+
# @return [Array<Class>] An array of Class,
|
317
|
+
# where each item is the parts reverse-N specific parser {Class}.
|
318
|
+
# Each {Class} is expected to be a child of {Whois::Record::Parser::Base}.
|
319
|
+
#
|
320
|
+
# @example
|
321
|
+
#
|
322
|
+
# parser.parts
|
323
|
+
# # => [whois.foo.com, whois.bar.com]
|
324
|
+
#
|
325
|
+
# parser.parsers
|
326
|
+
# # => [Whois::Record::Parser::WhoisBarCom, Whois::Record::Parser::WhoisFooCom]
|
327
|
+
#
|
328
|
+
# @see Whois::Record::Parser#select_parser
|
329
|
+
#
|
330
|
+
def init_parsers
|
331
|
+
record.parts.reverse.map { |part| self.class.parser_for(part) }
|
332
|
+
end
|
333
|
+
|
334
|
+
# Selects the first parser in {#parsers}
|
335
|
+
# where given property matches <tt>status</tt>.
|
336
|
+
#
|
337
|
+
# @param [Symbol] property The property to search for.
|
338
|
+
# @param [Symbol] status The status value.
|
339
|
+
#
|
340
|
+
# @return [Whois::Record::Parser::Base]
|
341
|
+
# The parser which satisfies given requirement.
|
342
|
+
# @return [nil]
|
343
|
+
# If the parser wasn't found.
|
344
|
+
#
|
345
|
+
# @example
|
346
|
+
#
|
347
|
+
# select_parser(:nameservers)
|
348
|
+
# # => #<Whois::Record::Parser::WhoisExampleCom>
|
349
|
+
#
|
350
|
+
# select_parser(:nameservers, :supported)
|
351
|
+
# # => nil
|
352
|
+
#
|
353
|
+
def select_parser(property, status = :any)
|
354
|
+
parsers.each do |parser|
|
355
|
+
return parser if parser.class.property_registered?(property, status)
|
358
356
|
end
|
357
|
+
nil
|
358
|
+
end
|
359
359
|
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
360
|
+
# @api private
|
361
|
+
def all_in_parallel?(*args)
|
362
|
+
count = args.first.size
|
363
|
+
index = 0
|
364
364
|
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
end
|
369
|
-
true
|
365
|
+
while index < count
|
366
|
+
return false unless yield(*args.map { |arg| arg[index] })
|
367
|
+
index += 1
|
370
368
|
end
|
369
|
+
true
|
370
|
+
end
|
371
371
|
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
372
|
+
# @api private
|
373
|
+
def any_is?(collection, symbol)
|
374
|
+
collection.any? { |item| item.is(symbol) }
|
375
|
+
end
|
376
376
|
|
377
377
|
end
|
378
378
|
|
379
379
|
end
|
380
|
-
end
|
380
|
+
end
|