domain_name 0.0.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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