whois-parser-next 0.4.9 → 0.4.10
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/lib/whois/parser/version.rb +1 -1
- data/lib/whois/parsers/base_nic_fr.rb +1 -1
- data/lib/whois/parsers/whois.registro.br.rb +1 -1
- data/lib/whois/parsers/whois.ua.rb +2 -2
- data/lib/whois/scanners/base.rb +18 -1
- data/lib/whois/scanners/iana.rb +3 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9e023caaec0b71465576d51e1aab35e0fa956f22fe435c9ebe91e7eae29e0d18
|
|
4
|
+
data.tar.gz: e90fe07318d7c90413f88ba7201eade76e7fc8ada882da016f1bcfb9574bc68e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2a55f20c2508a3a06d2a704e255532940ddf67b7ae3c9249b1a893b60c1f664c56ddd497aeac46cb1e14b4f6a9a8576db3411d318f768504027f0131916232c2
|
|
7
|
+
data.tar.gz: 3bd083076d0699b8520cd1cd232f09a8c755dcd33192198d7512974f44d73c50044201e34a919eb617c6132079710628c4fa3069e4306b4754292fbc8446f406
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
This project uses [Semantic Versioning 2.0.0](http://semver.org/).
|
|
4
4
|
|
|
5
|
+
#### Release 0.4.10 (2026-11-02)
|
|
6
|
+
|
|
7
|
+
- SAFETY: A response no longer keeps a scanner looping forever. A reply cut
|
|
8
|
+
off right after a disclaimer or notice header, with no final newline (for
|
|
9
|
+
example a Verisign body of just `TERMS OF USE:`, or the CIRA, `.ie`, ATI,
|
|
10
|
+
SX, PIR and configured Afilias disclaimers), made the tokenizer report
|
|
11
|
+
success without consuming input, so parsing never finished. The scanner now
|
|
12
|
+
raises `Whois::ParserError` when tokens stop consuming input, while still
|
|
13
|
+
allowing the short in-place state changes some scanners use to close a
|
|
14
|
+
section.
|
|
15
|
+
- SAFETY: The `whois.iana.org` scanner matches repeated field keys literally.
|
|
16
|
+
A key taken from the response was used as a regular expression, so a key
|
|
17
|
+
such as `()|^` matched without consuming input and looped forever. Contact
|
|
18
|
+
handles in the `.fr`-family, `.br` and `.ua` parsers are also matched
|
|
19
|
+
literally instead of as patterns.
|
|
20
|
+
- TESTED: `spec/whois/scanners/progress_spec.rb` covers each truncated
|
|
21
|
+
prefix and the regex-shaped IANA keys under a deadline.
|
|
22
|
+
|
|
5
23
|
#### Release 0.4.9 (2026-10-25)
|
|
6
24
|
|
|
7
25
|
- ADDED: Added `registrar`, `registrant_contacts` and `technical_contacts` to
|
data/lib/whois/parser/version.rb
CHANGED
|
@@ -117,7 +117,7 @@ module Whois
|
|
|
117
117
|
return unless content_for_scanner =~ /#{element}:\s+(.+)\n/
|
|
118
118
|
|
|
119
119
|
id = ::Regexp.last_match(1)
|
|
120
|
-
content_for_scanner.scan(/nic-hdl:\s+#{id}\n((.+\n)+)\n/).any? ||
|
|
120
|
+
content_for_scanner.scan(/nic-hdl:\s+#{Regexp.escape(id)}\n((.+\n)+)\n/).any? ||
|
|
121
121
|
Whois::Parser.bug!(ParserError, "Unable to parse contact block for nic-hdl: #{id}")
|
|
122
122
|
values = build_hash(::Regexp.last_match(1).scan(/(.+?):\s+(.+?)\n/))
|
|
123
123
|
|
|
@@ -96,7 +96,7 @@ module Whois
|
|
|
96
96
|
return unless content_for_scanner =~ /#{element}:\s+(.+)\n/
|
|
97
97
|
|
|
98
98
|
id = ::Regexp.last_match(1)
|
|
99
|
-
content_for_scanner.scan(/nic-hdl-br:\s+#{id}\n((.+\n)+)\n/).any? ||
|
|
99
|
+
content_for_scanner.scan(/nic-hdl-br:\s+#{Regexp.escape(id)}\n((.+\n)+)\n/).any? ||
|
|
100
100
|
Whois.bug!(ParserError, "Unable to parse contact block for nic-hdl-br: #{id}")
|
|
101
101
|
values = build_hash(::Regexp.last_match(1).scan(/(.+?):\s+(.+?)\n/))
|
|
102
102
|
|
|
@@ -65,7 +65,7 @@ module Whois
|
|
|
65
65
|
return if contact_ids.empty?
|
|
66
66
|
|
|
67
67
|
contact_ids.map do |contact_id|
|
|
68
|
-
textblock = content.slice(/contact-id:\s+#{contact_id}\n((?:.+\n)+)\n/, 1)
|
|
68
|
+
textblock = content.slice(/contact-id:\s+#{Regexp.escape(contact_id)}\n((?:.+\n)+)\n/, 1)
|
|
69
69
|
|
|
70
70
|
address = textblock.scan(/address:\s+(.+)\n/).flatten
|
|
71
71
|
address = address.reject { |a| a == "n/a" }
|
|
@@ -137,7 +137,7 @@ module Whois
|
|
|
137
137
|
return if contact_ids.empty?
|
|
138
138
|
|
|
139
139
|
contact_ids.map do |contact_id|
|
|
140
|
-
textblock = content.slice(/nic-handle:\s+#{contact_id}\n((?:.+\n)+)\n/, 1)
|
|
140
|
+
textblock = content.slice(/nic-handle:\s+#{Regexp.escape(contact_id)}\n((?:.+\n)+)\n/, 1)
|
|
141
141
|
|
|
142
142
|
address = textblock.scan(/address:\s+(.+)\n/).flatten
|
|
143
143
|
zip = nil
|
data/lib/whois/scanners/base.rb
CHANGED
|
@@ -6,6 +6,9 @@ module Whois
|
|
|
6
6
|
class_attribute :tokenizers
|
|
7
7
|
self.tokenizers = []
|
|
8
8
|
|
|
9
|
+
# Consecutive tokens allowed to succeed without consuming input.
|
|
10
|
+
MAX_IDLE_TOKENS = 100
|
|
11
|
+
|
|
9
12
|
def self.tokenizer(name, &block)
|
|
10
13
|
define_method(name, &block)
|
|
11
14
|
end
|
|
@@ -26,7 +29,21 @@ module Whois
|
|
|
26
29
|
@ast = {}
|
|
27
30
|
|
|
28
31
|
@input = StringScanner.new(content)
|
|
29
|
-
|
|
32
|
+
idle = 0
|
|
33
|
+
until @input.eos?
|
|
34
|
+
position = @input.pos
|
|
35
|
+
tokenize
|
|
36
|
+
if @input.pos == position
|
|
37
|
+
# Some tokenizers succeed once without consuming input to change
|
|
38
|
+
# state (e.g. close a section) for the next one. One that keeps
|
|
39
|
+
# succeeding in place loops forever, e.g. a disclaimer header matched
|
|
40
|
+
# by lookahead in a reply truncated before its final newline.
|
|
41
|
+
idle += 1
|
|
42
|
+
unexpected_token if idle > MAX_IDLE_TOKENS
|
|
43
|
+
else
|
|
44
|
+
idle = 0
|
|
45
|
+
end
|
|
46
|
+
end
|
|
30
47
|
|
|
31
48
|
@ast
|
|
32
49
|
end
|
data/lib/whois/scanners/iana.rb
CHANGED
|
@@ -79,7 +79,9 @@ module Whois
|
|
|
79
79
|
end
|
|
80
80
|
|
|
81
81
|
def parse_section_pair_newlinevalue(key)
|
|
82
|
-
|
|
82
|
+
# The key comes from the response: match it literally. As a pattern, a
|
|
83
|
+
# key such as "()|^" matches without consuming input and loops forever.
|
|
84
|
+
if @input.scan(/^#{Regexp.escape(key)}:\s*(.+)\n/)
|
|
83
85
|
@input[1].strip
|
|
84
86
|
end
|
|
85
87
|
end
|