whois-parser-next 0.4.4 → 0.4.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f4c96a0a74b64788109bc1bf2d100571089e9bbbd49668c8146e175567b0f08c
4
- data.tar.gz: e9e721292aaad948280edebea47d502ce309c1db903be8da692bfb50bf4e6e00
3
+ metadata.gz: 1006a5373a7bed9d074cee1bc20d02bd78d9bd7a682d740c78c5fa6cf44aaf1f
4
+ data.tar.gz: 99899f0e0a3db2b665119c876d4c561b11deaca2de4172a89bbdecebbb9f4b0d
5
5
  SHA512:
6
- metadata.gz: daf6ebf45111891d95f5c3bd6bc0bc57d5be7a0e641fd8054cdb359bf5bc64a2406db5cc4aeb9cf02e195e65a740abc15260b5f092f3c23b75a1c6927bc3a56a
7
- data.tar.gz: 87849973634827aa16cc8ecad6e78031cf348ee01351709217bcfc9580cf9603a7943824d87df9a0222d76bf7940db020b4dc5928f2141f225390dfffc07e639
6
+ metadata.gz: 0e32b486fb6c61548fe11307395704a4548ac68ac2187d7dd95f42dc5a9ecee9147466f83639ab9ea2637732f771f38ef2c1331a8cc3514cc386e8228ac80afc
7
+ data.tar.gz: 4939cb1e255090dc84e95a824df8db82cdd11eceda1625a1caf3a465f12c8dc835afdcb023dea059cc874bbf4ea938154d823128951601dedd1b7f3694a3b972
data/CHANGELOG.md CHANGED
@@ -2,6 +2,38 @@
2
2
 
3
3
  This project uses [Semantic Versioning 2.0.0](http://semver.org/).
4
4
 
5
+ #### Release 0.4.5 (2026-10-18)
6
+
7
+ - ADDED: Added current CoCCA response parsing for `.bf`, `.td`, and `.mr`,
8
+ requiring one valid domain identity and an exact `active` or `ok` EPP
9
+ registration state. `.bf` accepts `Domain Status: No Object Found`; `.td`,
10
+ `.mr`, and `.kn` require the exact absence line
11
+ `The queried object does not exist: No Object Found`. `.kn` also recognizes
12
+ its current CoCCA response while retaining the legacy format. Mixed or
13
+ incomplete replies remain unknown.
14
+ - ADDED: Added strict `.mc` parsing: registration requires one valid domain,
15
+ `Status: ACTIVE`, and a parseable `Created` value; absence requires the exact
16
+ `>> No data found for domain : <name>` line. Malformed or mixed replies
17
+ remain unknown.
18
+ - SAFETY: `.ws` recognizes the current `Domain Name` and `Creation Date` format
19
+ while preserving the legacy `Domain Created` format and exact absence
20
+ response. Invalid, inconsistent, or duplicate fields remain unknown.
21
+ - EVIDENCE: IANA lists the official hosts `whois.registre.bf`, `whois.nic.td`,
22
+ `whois.nic.mr`, `whois.nic.kn`, `whois.nic.mc`, and `whois.website.ws` for
23
+ [`.bf`](https://www.iana.org/domains/root/db/bf.html),
24
+ [`.td`](https://www.iana.org/domains/root/db/td.html),
25
+ [`.mr`](https://www.iana.org/domains/root/db/mr.html),
26
+ [`.kn`](https://www.iana.org/domains/root/db/kn.html),
27
+ [`.mc`](https://www.iana.org/domains/root/db/mc.html), and
28
+ [`.ws`](https://www.iana.org/domains/root/db/ws.html). Production-host queries
29
+ on 2026-10-18 observed registered and absent pairs for `.bf`, `.td`, `.mr`,
30
+ `.kn`, and `.mc`. Local-network queries observed both `.ws` states; the
31
+ production-proxy query confirmed a registered response only, so a production
32
+ registered/absent pair remains unverified. Committed examples are minimal
33
+ synthetic technical-shape controls without contact details.
34
+ - TESTED: The full suite passes 7,074 examples with 0 failures on Ruby 3.2.2
35
+ and 3.4.5. Final package smoke and supported-Ruby CI remain release gates.
36
+
5
37
  #### Release 0.4.4 (2026-10-18)
6
38
 
7
39
  - ADDED: Added parsers for the current `.gh` and `.do` CoCCA WHOIS response
@@ -1,6 +1,6 @@
1
1
  module Whois
2
2
  class Parser
3
3
  # The current library version.
4
- VERSION = "0.4.4".freeze
4
+ VERSION = "0.4.5".freeze
5
5
  end
6
6
  end
@@ -1,8 +1,17 @@
1
1
  require_relative 'base_icann_compliant'
2
+ require_relative 'cocca_epp_status'
2
3
 
3
4
  module Whois
4
5
  class Parsers
5
6
  class WhoisNicKn < BaseIcannCompliant
7
+ include CoccaEppStatus
8
+ CURRENT_COCCA_SUFFIX = "kn".freeze
9
+
10
+ property_supported(:status) { current_cocca_status || super() }
11
+ property_supported :available? do
12
+ current = current_cocca_status
13
+ current.nil? ? super() : current == :available
14
+ end
6
15
  end
7
16
  end
8
17
  end
@@ -0,0 +1,46 @@
1
+ require_relative 'base'
2
+ require_relative 'registry_response_safety'
3
+
4
+ module Whois
5
+ class Parsers
6
+ class WhoisNicMc < Base
7
+ include RegistryResponseSafety
8
+
9
+ property_supported(:domain) { content_for_scanner[/^Domain[ \t]*:[ \t]*(\S+)[ \t]*\r?$/i, 1]&.downcase }
10
+
11
+ property_supported :status do
12
+ text = content_for_scanner
13
+ names = text.scan(/^Domain[ \t]*:[ \t]*(\S+)[ \t]*\r?$/i).flatten
14
+ absent = text.scan(/^>> No data found for domain : (\S+)[ \t]*\r?$/i).flatten
15
+ dates = text.scan(/^Created[ \t]*:[ \t]*([^\r\n]+)$/i).flatten
16
+ statuses = text.scan(/^Status[ \t]*:[ \t]*([^\r\n]+)$/i).flatten.map(&:strip)
17
+ if absent.any?
18
+ absent.one? && valid_mc_domain?(absent.first) && names.empty? && dates.empty? && statuses.empty? ? :available : :unknown
19
+ else
20
+ valid_date = dates.one? && begin
21
+ !!parse_time(dates.first.strip)
22
+ rescue ArgumentError
23
+ false
24
+ end
25
+ names.one? && valid_mc_domain?(names.first) && statuses == ['ACTIVE'] && valid_date ? :registered : :unknown
26
+ end
27
+ end
28
+ property_supported(:registered?) { status == :registered }
29
+ property_supported(:available?) { status == :available }
30
+ property_supported :created_on do
31
+ value = content_for_scanner[/^Created[ \t]*:[ \t]*([^\r\n]+)$/i, 1]
32
+ parse_time(value.strip) if value
33
+ end
34
+ property_supported :expires_on do
35
+ value = content_for_scanner[/^Expires on[ \t]*:[ \t]*([^\r\n]+)$/i, 1]
36
+ parse_time(value.strip) if value
37
+ end
38
+
39
+ private
40
+
41
+ def valid_mc_domain?(name)
42
+ name.match?(/\A(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+mc\z/i)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,15 @@
1
+ require_relative 'base_cocca2'
2
+ require_relative 'cocca_epp_status'
3
+
4
+ module Whois
5
+ class Parsers
6
+ class WhoisNicMr < BaseCocca2
7
+ include CoccaEppStatus
8
+ CURRENT_COCCA_SUFFIX = "mr".freeze
9
+
10
+ property_supported(:status) { current_cocca_status || :unknown }
11
+ property_supported(:available?) { status == :available }
12
+ property_supported(:registered?) { status == :registered }
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ require_relative 'base_cocca2'
2
+ require_relative 'cocca_epp_status'
3
+
4
+ module Whois
5
+ class Parsers
6
+ class WhoisNicTd < BaseCocca2
7
+ include CoccaEppStatus
8
+ CURRENT_COCCA_SUFFIX = "td".freeze
9
+
10
+ property_supported(:status) { current_cocca_status || :unknown }
11
+ property_supported(:available?) { status == :available }
12
+ property_supported(:registered?) { status == :registered }
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ require_relative 'base_cocca2'
2
+ require_relative 'cocca_epp_status'
3
+
4
+ module Whois
5
+ class Parsers
6
+ class WhoisRegistreBf < BaseCocca2
7
+ include CoccaEppStatus
8
+ CURRENT_COCCA_SUFFIX = "bf".freeze
9
+
10
+ property_supported(:status) { current_cocca_status || :unknown }
11
+ property_supported(:available?) { status == :available }
12
+ property_supported(:registered?) { status == :registered }
13
+ end
14
+ end
15
+ end
@@ -26,19 +26,25 @@ module Whois
26
26
  class WhoisWebsiteWs < Base
27
27
  include RegistryResponseSafety
28
28
 
29
+ property_supported :domain do
30
+ content_for_scanner[/^[ \t]*Domain Name:[ \t]*(\S+)[ \t]*\r?$/i, 1]&.downcase
31
+ end
32
+
29
33
  property_supported :status do
30
- if available?
31
- :available
32
- elsif content_for_scanner.match?(/^\s+Domain Created:\s+/i)
33
- :registered
34
+ body = content_for_scanner
35
+ names = body.scan(/^[ \t]*Domain Name:[ \t]*(\S+)[ \t]*\r?$/i).flatten
36
+ missing = body.scan(/^(?:No match for "([^"\r\n]+)"\.|The queried object does not exist: ([^\r\n]+)\.)[ \t]*\r?$/i).map { |parts| parts.compact.first }
37
+ dates = body.scan(/^[ \t]*(?:Creation Date|Domain Created):[ \t]*([^\r\n]+)$/i).flatten
38
+ if missing.any?
39
+ missing.one? && names.empty? && dates.empty? && valid_ws_domain?(missing.first) ? :available : :unknown
34
40
  else
35
- :unknown
41
+ times = dates.map { |date| begin parse_time(date.strip); rescue ArgumentError; nil; end }
42
+ names.one? && valid_ws_domain?(names.first) && times.any? && times.none?(&:nil?) && times.uniq.one? ? :registered : :unknown
36
43
  end
37
44
  end
38
45
 
39
46
  property_supported :available? do
40
- !!(content_for_scanner =~ /^No match for "\S+"\.$/ ||
41
- content_for_scanner =~ /^The queried object does not exist: \S+\.$/)
47
+ status == :available
42
48
  end
43
49
 
44
50
  property_supported :registered? do
@@ -47,9 +53,8 @@ module Whois
47
53
 
48
54
 
49
55
  property_supported :created_on do
50
- if content_for_scanner =~ /\s+Domain Created:\s+(.*)\n/
51
- parse_time(::Regexp.last_match(1))
52
- end
56
+ value = content_for_scanner[/^[ \t]*(?:Creation Date|Domain Created):[ \t]*([^\r\n]+)$/i, 1]
57
+ parse_time(value.strip) if value
53
58
  end
54
59
 
55
60
  property_supported :updated_on do
@@ -73,6 +78,12 @@ module Whois
73
78
  end
74
79
  end
75
80
 
81
+ private
82
+
83
+ def valid_ws_domain?(name)
84
+ name.match?(/\A(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+ws\z/i)
85
+ end
86
+
76
87
  end
77
88
 
78
89
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: whois-parser-next
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.4
4
+ version: 0.4.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simone Carletti
@@ -513,6 +513,7 @@ files:
513
513
  - lib/whois/parsers/whois.nic.management.rb
514
514
  - lib/whois/parsers/whois.nic.market.rb
515
515
  - lib/whois/parsers/whois.nic.mba.rb
516
+ - lib/whois/parsers/whois.nic.mc.rb
516
517
  - lib/whois/parsers/whois.nic.md.rb
517
518
  - lib/whois/parsers/whois.nic.me.rb
518
519
  - lib/whois/parsers/whois.nic.media.rb
@@ -528,6 +529,7 @@ files:
528
529
  - lib/whois/parsers/whois.nic.monster.rb
529
530
  - lib/whois/parsers/whois.nic.mortgage.rb
530
531
  - lib/whois/parsers/whois.nic.moscow.rb
532
+ - lib/whois/parsers/whois.nic.mr.rb
531
533
  - lib/whois/parsers/whois.nic.ms.rb
532
534
  - lib/whois/parsers/whois.nic.mu.rb
533
535
  - lib/whois/parsers/whois.nic.museum.rb
@@ -624,6 +626,7 @@ files:
624
626
  - lib/whois/parsers/whois.nic.taipei.rb
625
627
  - lib/whois/parsers/whois.nic.tatar.rb
626
628
  - lib/whois/parsers/whois.nic.tc.rb
629
+ - lib/whois/parsers/whois.nic.td.rb
627
630
  - lib/whois/parsers/whois.nic.team.rb
628
631
  - lib/whois/parsers/whois.nic.tech.rb
629
632
  - lib/whois/parsers/whois.nic.technology.rb
@@ -698,6 +701,7 @@ files:
698
701
  - lib/whois/parsers/whois.register.bg.rb
699
702
  - lib/whois/parsers/whois.register.com.rb
700
703
  - lib/whois/parsers/whois.register.si.rb
704
+ - lib/whois/parsers/whois.registre.bf.rb
701
705
  - lib/whois/parsers/whois.registre.ma.rb
702
706
  - lib/whois/parsers/whois.registro.br.rb
703
707
  - lib/whois/parsers/whois.registry.click.rb