domain_name 0.0.0 → 0.5.0

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.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.0
1
+ 0.5.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "domain_name"
8
- s.version = "0.0.0"
8
+ s.version = "0.5.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Akinori MUSHA"]
12
- s.date = "2011-10-29"
12
+ s.date = "2011-11-04"
13
13
  s.description = "This is a Domain Name manipulation library for Ruby.\n\nIt can also be used for cookie domain validation based on the Public\nSuffix List.\n"
14
14
  s.email = "knu@idaemons.org"
15
15
  s.extra_rdoc_files = [
@@ -37,7 +37,7 @@ Gem::Specification.new do |s|
37
37
  s.homepage = "http://github.com/knu/ruby-domain_name"
38
38
  s.licenses = ["BSD + MPL 1.1/GPL 2.0/LGPL 2.1"]
39
39
  s.require_paths = ["lib"]
40
- s.rubygems_version = "1.8.10"
40
+ s.rubygems_version = "1.8.11"
41
41
  s.summary = "Domain Name manipulation library for Ruby"
42
42
 
43
43
  if s.respond_to? :specification_version then
@@ -19,20 +19,20 @@ class DomainName
19
19
  # suitable for opening a connection to.
20
20
  attr_reader :hostname
21
21
 
22
- # The least "universally original" domain part of this hostname.
22
+ # The least "universally original" domain part of this domain name.
23
23
  # For example, "example.co.uk" for "www.sub.example.co.uk".
24
24
  attr_reader :domain
25
25
 
26
- # The TLD part of this hostname. For example, if the hostname is
26
+ # The TLD part of this domain name. For example, if the hostname is
27
27
  # "www.sub.example.co.uk", the TLD part is "uk". This property is
28
- # nil only if +ipaddr?+ is ptrue.
28
+ # nil only if +ipaddr?+ is true.
29
29
  attr_reader :tld
30
30
 
31
- # Returns an IPAddr object if this
31
+ # Returns an IPAddr object if this is an IP address.
32
32
  attr_reader :ipaddr
33
33
 
34
- # Returns true if this hostname is an IP address, such as
35
- # "192.168.0.1" and "[::1]".
34
+ # Returns true if this is an IP address, such as "192.168.0.1" and
35
+ # "[::1]".
36
36
  def ipaddr?
37
37
  @ipaddr ? true : false
38
38
  end
@@ -42,12 +42,13 @@ class DomainName
42
42
  # address enclosed in square brackets.
43
43
  attr_reader :uri_host
44
44
 
45
- # Returns true if this hostname has a canonical TLD.
45
+ # Returns true if this domain name has a canonical TLD.
46
46
  def canonical_tld?
47
47
  @canonical_tld_p
48
48
  end
49
49
 
50
- # Returns true if this hostname has a canonical registered domain.
50
+ # Returns true if this domain name has a canonical registered
51
+ # domain.
51
52
  def canonical?
52
53
  @canonical_tld_p && (@domain ? true : false)
53
54
  end
@@ -61,17 +62,20 @@ class DomainName
61
62
  raise ArgumentError, "domain name must not start with a dot: #{hostname}"
62
63
  end
63
64
  case hostname
64
- when /\A([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\z/,
65
- /\A\[([0-9A-Fa-f:]*:[0-9A-Fa-f:]*:[0-9A-Fa-f:]*)\]\z/
65
+ when /\A([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\z/
66
66
  @ipaddr = IPAddr.new($1)
67
67
  @uri_host = @hostname = @ipaddr.to_s
68
+ @domain = @tld = nil
68
69
  return
69
- when /\A\[([0-9A-Fa-f:]*:[0-9A-Fa-f:]*:[0-9A-Fa-f:]*)\]\z/
70
+ when /\A([0-9A-Fa-f:]*:[0-9A-Fa-f:]*:[0-9A-Fa-f:]*)\z/,
71
+ /\A\[([0-9A-Fa-f:]*:[0-9A-Fa-f:]*:[0-9A-Fa-f:]*)\]\z/
70
72
  @ipaddr = IPAddr.new($1)
71
73
  @hostname = @ipaddr.to_s
72
74
  @uri_host = "[#{@hostname}]"
75
+ @domain = @tld = nil
73
76
  return
74
77
  end
78
+ @ipaddr = nil
75
79
  @hostname = DomainName.normalize(hostname)
76
80
  @uri_host = @hostname
77
81
  if last_dot = @hostname.rindex(DOT)
@@ -120,29 +124,83 @@ class DomainName
120
124
  # Checks if the server represented by _domain_ is qualified to send
121
125
  # and receive cookies for _domain_.
122
126
  def cookie_domain?(domain)
123
- unless DomainName === domain
124
- domain = DomainName.new(domain)
125
- end
126
- if @hostname == domain.hostname
127
- true
128
- elsif ipaddr?
127
+ domain = DomainName.new(domain) unless DomainName === domain
128
+ if ipaddr?
129
129
  # RFC 6265 #5.1.3
130
130
  # Do not perform subdomain matching against IP addresses.
131
- false
131
+ @hostname == domain.hostname
132
132
  else
133
133
  # RFC 6265 #4.1.1
134
134
  # Domain-value must be a subdomain.
135
- @hostname.end_with?('.' << domain)
135
+ @domain && self <= domain && domain <= @domain ? true : false
136
136
  end
137
137
  end
138
138
 
139
139
  def ==(other)
140
- unless DomainName === other
141
- other = DomainName.new(other)
142
- end
140
+ other = DomainName.new(other) unless DomainName === other
143
141
  other.hostname == @hostname
144
142
  end
145
143
 
144
+ def <=>(other)
145
+ other = DomainName.new(other) unless DomainName === other
146
+ othername = other.hostname
147
+ if othername == @hostname
148
+ 0
149
+ elsif @hostname.end_with?(othername) && @hostname[-othername.size - 1] == '.'
150
+ # The other is higher
151
+ -1
152
+ elsif othername.end_with?(@hostname) && othername[-@hostname.size - 1] == '.'
153
+ # The other is lower
154
+ 1
155
+ else
156
+ nil
157
+ end
158
+ end
159
+
160
+ def <(other)
161
+ case self <=> other
162
+ when -1
163
+ true
164
+ when nil
165
+ nil
166
+ else
167
+ false
168
+ end
169
+ end
170
+
171
+ def >(other)
172
+ case self <=> other
173
+ when 1
174
+ true
175
+ when nil
176
+ nil
177
+ else
178
+ false
179
+ end
180
+ end
181
+
182
+ def <=(other)
183
+ case self <=> other
184
+ when -1, 0
185
+ true
186
+ when nil
187
+ nil
188
+ else
189
+ false
190
+ end
191
+ end
192
+
193
+ def >=(other)
194
+ case self <=> other
195
+ when 1, 0
196
+ true
197
+ when nil
198
+ nil
199
+ else
200
+ false
201
+ end
202
+ end
203
+
146
204
  def to_s
147
205
  @hostname
148
206
  end
@@ -1,4 +1,5 @@
1
1
  require 'helper'
2
+ require 'ipaddr'
2
3
 
3
4
  class TestDomainName < Test::Unit::TestCase
4
5
  should "raise ArgumentError if hostname starts with a dot" do
@@ -16,74 +17,192 @@ class TestDomainName < Test::Unit::TestCase
16
17
  should "parse canonical domain names correctly" do
17
18
  [
18
19
  # Mixed case.
19
- ['COM', nil],
20
- ['example.COM', 'example.com'],
21
- ['WwW.example.COM', 'example.com'],
20
+ ['COM', nil, false, 'com', true],
21
+ ['example.COM', 'example.com', true, 'com', true],
22
+ ['WwW.example.COM', 'example.com', true, 'com', true],
22
23
  # Unlisted TLD.
23
- ['example', 'example'],
24
- ['example.example', 'example.example'],
25
- ['b.example.example', 'example.example'],
26
- ['a.b.example.example', 'example.example'],
24
+ ['example', 'example', false, 'example', false],
25
+ ['example.example', 'example.example', false, 'example', false],
26
+ ['b.example.example', 'example.example', false, 'example', false],
27
+ ['a.b.example.example', 'example.example', false, 'example', false],
27
28
  # Listed, but non-Internet, TLD.
28
- ['local', 'local'],
29
- ['example.local', 'example.local'],
30
- ['b.example.local', 'example.local'],
31
- ['a.b.example.local', 'example.local'],
29
+ ['local', 'local', false, 'local', false],
30
+ ['example.local', 'example.local', false, 'local', false],
31
+ ['b.example.local', 'example.local', false, 'local', false],
32
+ ['a.b.example.local', 'example.local', false, 'local', false],
32
33
  # TLD with only 1 rule.
33
- ['biz', nil],
34
- ['domain.biz', 'domain.biz'],
35
- ['b.domain.biz', 'domain.biz'],
36
- ['a.b.domain.biz', 'domain.biz'],
34
+ ['biz', nil, false, 'biz', true],
35
+ ['domain.biz', 'domain.biz', true, 'biz', true],
36
+ ['b.domain.biz', 'domain.biz', true, 'biz', true],
37
+ ['a.b.domain.biz', 'domain.biz', true, 'biz', true],
37
38
  # TLD with some 2-level rules.
38
- ['com', nil],
39
- ['example.com', 'example.com'],
40
- ['b.example.com', 'example.com'],
41
- ['a.b.example.com', 'example.com'],
42
- ['uk.com', nil],
43
- ['example.uk.com', 'example.uk.com'],
44
- ['b.example.uk.com', 'example.uk.com'],
45
- ['a.b.example.uk.com', 'example.uk.com'],
46
- ['test.ac', 'test.ac'],
39
+ ['com', nil, false, 'com', true],
40
+ ['example.com', 'example.com', true, 'com', true],
41
+ ['b.example.com', 'example.com', true, 'com', true],
42
+ ['a.b.example.com', 'example.com', true, 'com', true],
43
+ ['uk.com', nil, false, 'com', true],
44
+ ['example.uk.com', 'example.uk.com', true, 'com', true],
45
+ ['b.example.uk.com', 'example.uk.com', true, 'com', true],
46
+ ['a.b.example.uk.com', 'example.uk.com', true, 'com', true],
47
+ ['test.ac', 'test.ac', true, 'ac', true],
47
48
  # TLD with only 1 (wildcard) rule.
48
- ['cy', nil],
49
- ['c.cy', nil],
50
- ['b.c.cy', 'b.c.cy'],
51
- ['a.b.c.cy', 'b.c.cy'],
49
+ ['cy', nil, false, 'cy', true],
50
+ ['c.cy', nil, false, 'cy', true],
51
+ ['b.c.cy', 'b.c.cy', true, 'cy', true],
52
+ ['a.b.c.cy', 'b.c.cy', true, 'cy', true],
52
53
  # More complex TLD.
53
- ['jp', nil],
54
- ['test.jp', 'test.jp'],
55
- ['www.test.jp', 'test.jp'],
56
- ['ac.jp', nil],
57
- ['test.ac.jp', 'test.ac.jp'],
58
- ['www.test.ac.jp', 'test.ac.jp'],
59
- ['kyoto.jp', nil],
60
- ['c.kyoto.jp', nil],
61
- ['b.c.kyoto.jp', 'b.c.kyoto.jp'],
62
- ['a.b.c.kyoto.jp', 'b.c.kyoto.jp'],
63
- ['pref.kyoto.jp', 'pref.kyoto.jp'], # Exception rule
64
- ['www.pref.kyoto.jp', 'pref.kyoto.jp'], # Exception rule.
65
- ['city.kyoto.jp', 'city.kyoto.jp'], # Exception rule.
66
- ['www.city.kyoto.jp', 'city.kyoto.jp'], # Exception rule.
54
+ ['jp', nil, false, 'jp', true],
55
+ ['test.jp', 'test.jp', true, 'jp', true],
56
+ ['www.test.jp', 'test.jp', true, 'jp', true],
57
+ ['ac.jp', nil, false, 'jp', true],
58
+ ['test.ac.jp', 'test.ac.jp', true, 'jp', true],
59
+ ['www.test.ac.jp', 'test.ac.jp', true, 'jp', true],
60
+ ['kyoto.jp', nil, false, 'jp', true],
61
+ ['c.kyoto.jp', nil, false, 'jp', true],
62
+ ['b.c.kyoto.jp', 'b.c.kyoto.jp', true, 'jp', true],
63
+ ['a.b.c.kyoto.jp', 'b.c.kyoto.jp', true, 'jp', true],
64
+ ['pref.kyoto.jp', 'pref.kyoto.jp', true, 'jp', true], # Exception rule
65
+ ['www.pref.kyoto.jp', 'pref.kyoto.jp', true, 'jp', true], # Exception rule.
66
+ ['city.kyoto.jp', 'city.kyoto.jp', true, 'jp', true], # Exception rule.
67
+ ['www.city.kyoto.jp', 'city.kyoto.jp', true, 'jp', true], # Exception rule.
67
68
  # TLD with a wildcard rule and exceptions.
68
- ['om', nil],
69
- ['test.om', nil],
70
- ['b.test.om', 'b.test.om'],
71
- ['a.b.test.om', 'b.test.om'],
72
- ['songfest.om', 'songfest.om'],
73
- ['www.songfest.om', 'songfest.om'],
69
+ ['om', nil, false, 'om', true],
70
+ ['test.om', nil, false, 'om', true],
71
+ ['b.test.om', 'b.test.om', true, 'om', true],
72
+ ['a.b.test.om', 'b.test.om', true, 'om', true],
73
+ ['songfest.om', 'songfest.om', true, 'om', true],
74
+ ['www.songfest.om', 'songfest.om', true, 'om', true],
74
75
  # US K12.
75
- ['us', nil],
76
- ['test.us', 'test.us'],
77
- ['www.test.us', 'test.us'],
78
- ['ak.us', nil],
79
- ['test.ak.us', 'test.ak.us'],
80
- ['www.test.ak.us', 'test.ak.us'],
81
- ['k12.ak.us', nil],
82
- ['test.k12.ak.us', 'test.k12.ak.us'],
83
- ['www.test.k12.ak.us', 'test.k12.ak.us'],
84
- ].each { |hostname, domain|
76
+ ['us', nil, false, 'us', true],
77
+ ['test.us', 'test.us', true, 'us', true],
78
+ ['www.test.us', 'test.us', true, 'us', true],
79
+ ['ak.us', nil, false, 'us', true],
80
+ ['test.ak.us', 'test.ak.us', true, 'us', true],
81
+ ['www.test.ak.us', 'test.ak.us', true, 'us', true],
82
+ ['k12.ak.us', nil, false, 'us', true],
83
+ ['test.k12.ak.us', 'test.k12.ak.us', true, 'us', true],
84
+ ['www.test.k12.ak.us', 'test.k12.ak.us', true, 'us', true],
85
+ ].each { |hostname, domain, canonical, tld, canonical_tld|
85
86
  dn = DomainName.new(hostname)
86
87
  assert_equal(domain, dn.domain)
88
+ assert_equal(canonical, dn.canonical?)
89
+ assert_equal(tld, dn.tld)
90
+ assert_equal(canonical_tld, dn.canonical_tld?)
91
+ }
92
+ end
93
+
94
+ should "compare hostnames correctly" do
95
+ [
96
+ ["foo.com", "abc.foo.com", 1],
97
+ ["COM", "abc.foo.com", 1],
98
+ ["abc.def.foo.com", "foo.com", -1],
99
+ ["abc.def.foo.com", "ABC.def.FOO.com", 0],
100
+ ["abc.def.foo.com", "bar.com", nil],
101
+ ].each { |x, y, v|
102
+ dx, dy = DomainName(x), DomainName(y)
103
+ [
104
+ [dx, y, v],
105
+ [dx, dy, v],
106
+ [dy, x, v ? -v : v],
107
+ [dy, dx, v ? -v : v],
108
+ ].each { |a, b, expected|
109
+ assert_equal expected, a <=> b
110
+ case expected
111
+ when 1
112
+ assert_equal(true, a > b)
113
+ assert_equal(true, a >= b)
114
+ assert_equal(false, a == b)
115
+ assert_equal(false, a <= b)
116
+ assert_equal(false, a < b)
117
+ when -1
118
+ assert_equal(true, a < b)
119
+ assert_equal(true, a <= b)
120
+ assert_equal(false, a == b)
121
+ assert_equal(false, a >= b)
122
+ assert_equal(false, a > b)
123
+ when 0
124
+ assert_equal(false, a < b)
125
+ assert_equal(true, a <= b)
126
+ assert_equal(true, a == b)
127
+ assert_equal(true, a >= b)
128
+ assert_equal(false, a > b)
129
+ when nil
130
+ assert_equal(nil, a < b)
131
+ assert_equal(nil, a <= b)
132
+ assert_equal(false, a == b)
133
+ assert_equal(nil, a >= b)
134
+ assert_equal(nil, a > b)
135
+ end
136
+ }
137
+ }
138
+ end
139
+
140
+ should "check cookie domain correctly" do
141
+ [
142
+ ['b.kyoto.jp', 'jp', false],
143
+ ['b.kyoto.jp', 'kyoto.jp', false],
144
+ ['b.kyoto.jp', 'b.kyoto.jp', false],
145
+ ['b.kyoto.jp', 'a.b.kyoto.jp', false],
146
+
147
+ ['b.c.kyoto.jp', 'jp', false],
148
+ ['b.c.kyoto.jp', 'kyoto.jp', false],
149
+ ['b.c.kyoto.jp', 'c.kyoto.jp', false],
150
+ ['b.c.kyoto.jp', 'b.c.kyoto.jp', true],
151
+ ['b.c.kyoto.jp', 'a.b.c.kyoto.jp', false],
152
+
153
+ ['b.c.d.kyoto.jp', 'jp', false],
154
+ ['b.c.d.kyoto.jp', 'kyoto.jp', false],
155
+ ['b.c.d.kyoto.jp', 'd.kyoto.jp', false],
156
+ ['b.c.d.kyoto.jp', 'c.d.kyoto.jp', true],
157
+ ['b.c.d.kyoto.jp', 'b.c.d.kyoto.jp', true],
158
+ ['b.c.d.kyoto.jp', 'a.b.c.d.kyoto.jp', false],
159
+
160
+ ['pref.kyoto.jp', 'jp', false],
161
+ ['pref.kyoto.jp', 'kyoto.jp', false],
162
+ ['pref.kyoto.jp', 'pref.kyoto.jp', true],
163
+ ['pref.kyoto.jp', 'a.pref.kyoto.jp', false],
164
+
165
+ ['b.pref.kyoto.jp', 'jp', false],
166
+ ['b.pref.kyoto.jp', 'kyoto.jp', false],
167
+ ['b.pref.kyoto.jp', 'pref.kyoto.jp', true],
168
+ ['b.pref.kyoto.jp', 'b.pref.kyoto.jp', true],
169
+ ['b.pref.kyoto.jp', 'a.b.pref.kyoto.jp', false],
170
+ ].each { |host, domain, expected|
171
+ dn = DomainName(host)
172
+ assert_equal(expected, dn.cookie_domain?(domain))
173
+ assert_equal(expected, dn.cookie_domain?(DomainName(domain)))
174
+ assert_equal(false, dn.ipaddr?)
175
+ }
176
+ end
177
+
178
+ should "parse IPv4 addresseses" do
179
+ a = '192.168.10.20'
180
+ b = '192.168.010.020'
181
+ dn = DomainName(b)
182
+ assert_equal(a, dn.hostname)
183
+ assert_equal(true, dn.ipaddr?)
184
+ assert_equal(IPAddr.new(a), dn.ipaddr)
185
+ assert_equal(true, dn.cookie_domain?(a))
186
+ assert_equal(true, dn.cookie_domain?(b))
187
+ assert_equal(true, dn.cookie_domain?(dn))
188
+ assert_equal(false, dn.cookie_domain?('168.10.20'))
189
+ assert_equal(false, dn.cookie_domain?('168.010.020'))
190
+ assert_equal(false, dn.cookie_domain?('20'))
191
+ assert_equal(false, dn.cookie_domain?('020'))
192
+ end
193
+
194
+ should "parse IPv6 addresseses" do
195
+ a = '2001:200:dff:fff1:216:3eff:feb1:44d7'
196
+ b = '2001:0200:0dff:fff1:0216:3eff:feb1:44d7'
197
+ [b, b.upcase, "[#{b}]", "[#{b.upcase}]"].each { |host|
198
+ dn = DomainName(host)
199
+ assert_equal("[#{a}]", dn.uri_host)
200
+ assert_equal(a, dn.hostname)
201
+ assert_equal(true, dn.ipaddr?)
202
+ assert_equal(IPAddr.new(a), dn.ipaddr)
203
+ assert_equal(true, dn.cookie_domain?(host))
204
+ assert_equal(true, dn.cookie_domain?(dn))
205
+ assert_equal(true, dn.cookie_domain?(a))
87
206
  }
88
207
  end
89
208
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: domain_name
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31
4
+ hash: 11
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
+ - 5
8
9
  - 0
9
- - 0
10
- version: 0.0.0
10
+ version: 0.5.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Akinori MUSHA
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-10-29 00:00:00 Z
18
+ date: 2011-11-04 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  requirement: &id001 !ruby/object:Gem::Requirement
@@ -153,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
153
153
  requirements: []
154
154
 
155
155
  rubyforge_project:
156
- rubygems_version: 1.8.10
156
+ rubygems_version: 1.8.11
157
157
  signing_key:
158
158
  specification_version: 3
159
159
  summary: Domain Name manipulation library for Ruby