public_suffix 3.0.3 → 4.0.6
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/.github/FUNDING.yml +12 -0
- data/.github/workflows/tests.yml +36 -0
- data/.gitignore +5 -8
- data/.rubocop.yml +2 -2
- data/{.rubocop_defaults.yml → .rubocop_opinionated.yml} +12 -39
- data/.travis.yml +5 -7
- data/CHANGELOG.md +116 -50
- data/Gemfile +9 -4
- data/LICENSE.txt +1 -1
- data/README.md +20 -15
- data/Rakefile +3 -1
- data/SECURITY.md +104 -0
- data/bin/console +1 -0
- data/codecov.yml +12 -0
- data/data/list.txt +1097 -376
- data/lib/public_suffix.rb +8 -4
- data/lib/public_suffix/domain.rb +4 -2
- data/lib/public_suffix/errors.rb +3 -1
- data/lib/public_suffix/list.rb +12 -8
- data/lib/public_suffix/rule.rb +4 -2
- data/lib/public_suffix/version.rb +5 -2
- data/public_suffix.gemspec +9 -5
- data/test/acceptance_test.rb +33 -29
- data/test/psl_test.rb +4 -1
- data/test/test_helper.rb +9 -4
- data/test/unit/domain_test.rb +2 -0
- data/test/unit/errors_test.rb +2 -0
- data/test/unit/list_test.rb +2 -0
- data/test/unit/public_suffix_test.rb +13 -11
- data/test/unit/rule_test.rb +32 -30
- metadata +16 -51
- data/.ruby-gemset +0 -1
data/lib/public_suffix.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# = Public Suffix
|
2
4
|
#
|
3
5
|
# Domain name parser based on the Public Suffix List.
|
4
6
|
#
|
5
|
-
# Copyright (c) 2009-
|
7
|
+
# Copyright (c) 2009-2020 Simone Carletti <weppos@weppos.net>
|
6
8
|
|
7
9
|
require_relative "public_suffix/domain"
|
8
10
|
require_relative "public_suffix/version"
|
@@ -20,9 +22,9 @@ require_relative "public_suffix/list"
|
|
20
22
|
# but was originally created to meet the needs of browser manufacturers.
|
21
23
|
module PublicSuffix
|
22
24
|
|
23
|
-
DOT = "."
|
24
|
-
BANG = "!"
|
25
|
-
STAR = "*"
|
25
|
+
DOT = "."
|
26
|
+
BANG = "!"
|
27
|
+
STAR = "*"
|
26
28
|
|
27
29
|
# Parses +name+ and returns the {PublicSuffix::Domain} instance.
|
28
30
|
#
|
@@ -77,6 +79,7 @@ module PublicSuffix
|
|
77
79
|
if rule.decompose(what).last.nil?
|
78
80
|
raise DomainNotAllowed, "`#{what}` is not allowed according to Registry policy"
|
79
81
|
end
|
82
|
+
|
80
83
|
# rubocop:enable Style/IfUnlessModifier
|
81
84
|
|
82
85
|
decompose(what, rule)
|
@@ -169,6 +172,7 @@ module PublicSuffix
|
|
169
172
|
return DomainInvalid.new("Name is blank") if name.empty?
|
170
173
|
return DomainInvalid.new("Name starts with a dot") if name.start_with?(DOT)
|
171
174
|
return DomainInvalid.new("%s is not expected to contain a scheme" % name) if name.include?("://")
|
175
|
+
|
172
176
|
name
|
173
177
|
end
|
174
178
|
|
data/lib/public_suffix/domain.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# = Public Suffix
|
2
4
|
#
|
3
5
|
# Domain name parser based on the Public Suffix List.
|
4
6
|
#
|
5
|
-
# Copyright (c) 2009-
|
7
|
+
# Copyright (c) 2009-2020 Simone Carletti <weppos@weppos.net>
|
6
8
|
|
7
9
|
module PublicSuffix
|
8
10
|
|
@@ -43,7 +45,7 @@ module PublicSuffix
|
|
43
45
|
# Initializes with a +tld+, +sld+ and +trd+.
|
44
46
|
# @param [String] tld The TLD (extension)
|
45
47
|
# @param [String] sld The SLD (domain)
|
46
|
-
# @param [String]
|
48
|
+
# @param [String] trd The TRD (subdomain)
|
47
49
|
#
|
48
50
|
# @yield [self] Yields on self.
|
49
51
|
# @yieldparam [PublicSuffix::Domain] self The newly creates instance
|
data/lib/public_suffix/errors.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# = Public Suffix
|
2
4
|
#
|
3
5
|
# Domain name parser based on the Public Suffix List.
|
4
6
|
#
|
5
|
-
# Copyright (c) 2009-
|
7
|
+
# Copyright (c) 2009-2020 Simone Carletti <weppos@weppos.net>
|
6
8
|
|
7
9
|
module PublicSuffix
|
8
10
|
|
data/lib/public_suffix/list.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# = Public Suffix
|
2
4
|
#
|
3
5
|
# Domain name parser based on the Public Suffix List.
|
4
6
|
#
|
5
|
-
# Copyright (c) 2009-
|
7
|
+
# Copyright (c) 2009-2020 Simone Carletti <weppos@weppos.net>
|
6
8
|
|
7
9
|
module PublicSuffix
|
8
10
|
|
@@ -46,7 +48,7 @@ module PublicSuffix
|
|
46
48
|
#
|
47
49
|
# @return [PublicSuffix::List]
|
48
50
|
def self.default(**options)
|
49
|
-
@default ||= parse(File.read(DEFAULT_LIST_PATH), options)
|
51
|
+
@default ||= parse(File.read(DEFAULT_LIST_PATH), **options)
|
50
52
|
end
|
51
53
|
|
52
54
|
# Sets the default rule list to +value+.
|
@@ -65,8 +67,8 @@ module PublicSuffix
|
|
65
67
|
# @param private_domains [Boolean] whether to ignore the private domains section
|
66
68
|
# @return [PublicSuffix::List]
|
67
69
|
def self.parse(input, private_domains: true)
|
68
|
-
comment_token = "//"
|
69
|
-
private_token = "===BEGIN PRIVATE DOMAINS==="
|
70
|
+
comment_token = "//"
|
71
|
+
private_token = "===BEGIN PRIVATE DOMAINS==="
|
70
72
|
section = nil # 1 == ICANN, 2 == PRIVATE
|
71
73
|
|
72
74
|
new do |list|
|
@@ -81,6 +83,7 @@ module PublicSuffix
|
|
81
83
|
# include private domains or stop scanner
|
82
84
|
when line.include?(private_token)
|
83
85
|
break if !private_domains
|
86
|
+
|
84
87
|
section = 2
|
85
88
|
|
86
89
|
# skip comments
|
@@ -116,6 +119,7 @@ module PublicSuffix
|
|
116
119
|
# @return [Boolean]
|
117
120
|
def ==(other)
|
118
121
|
return false unless other.is_a?(List)
|
122
|
+
|
119
123
|
equal?(other) || @rules == other.rules
|
120
124
|
end
|
121
125
|
alias eql? ==
|
@@ -170,6 +174,7 @@ module PublicSuffix
|
|
170
174
|
def find(name, default: default_rule, **options)
|
171
175
|
rule = select(name, **options).inject do |l, r|
|
172
176
|
return r if r.class == Rule::Exception
|
177
|
+
|
173
178
|
l.length > r.length ? l : r
|
174
179
|
end
|
175
180
|
rule || default
|
@@ -201,18 +206,17 @@ module PublicSuffix
|
|
201
206
|
|
202
207
|
loop do
|
203
208
|
match = @rules[query]
|
204
|
-
if !match.nil? && (ignore_private == false || match.private == false)
|
205
|
-
rules << entry_to_rule(match, query)
|
206
|
-
end
|
209
|
+
rules << entry_to_rule(match, query) if !match.nil? && (ignore_private == false || match.private == false)
|
207
210
|
|
208
211
|
index += 1
|
209
212
|
break if index >= parts.size
|
213
|
+
|
210
214
|
query = parts[index] + DOT + query
|
211
215
|
end
|
212
216
|
|
213
217
|
rules
|
214
218
|
end
|
215
|
-
private :select
|
219
|
+
private :select
|
216
220
|
|
217
221
|
# Gets the default rule.
|
218
222
|
#
|
data/lib/public_suffix/rule.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# = Public Suffix
|
2
4
|
#
|
3
5
|
# Domain name parser based on the Public Suffix List.
|
4
6
|
#
|
5
|
-
# Copyright (c) 2009-
|
7
|
+
# Copyright (c) 2009-2020 Simone Carletti <weppos@weppos.net>
|
6
8
|
|
7
9
|
module PublicSuffix
|
8
10
|
|
@@ -20,7 +22,7 @@ module PublicSuffix
|
|
20
22
|
module Rule
|
21
23
|
|
22
24
|
# @api internal
|
23
|
-
Entry = Struct.new(:type, :length, :private)
|
25
|
+
Entry = Struct.new(:type, :length, :private) # rubocop:disable Lint/StructNewOverride
|
24
26
|
|
25
27
|
# = Abstract rule class
|
26
28
|
#
|
@@ -1,10 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
1
4
|
# = Public Suffix
|
2
5
|
#
|
3
6
|
# Domain name parser based on the Public Suffix List.
|
4
7
|
#
|
5
|
-
# Copyright (c) 2009-
|
8
|
+
# Copyright (c) 2009-2020 Simone Carletti <weppos@weppos.net>
|
6
9
|
|
7
10
|
module PublicSuffix
|
8
11
|
# The current library version.
|
9
|
-
VERSION = "
|
12
|
+
VERSION = "4.0.6"
|
10
13
|
end
|
data/public_suffix.gemspec
CHANGED
@@ -12,14 +12,18 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.description = "PublicSuffix can parse and decompose a domain name into top level domain, domain and subdomains."
|
13
13
|
s.licenses = ["MIT"]
|
14
14
|
|
15
|
-
s.
|
15
|
+
s.metadata = {
|
16
|
+
"bug_tracker_uri" => "https://github.com/weppos/publicsuffix-ruby/issues",
|
17
|
+
"changelog_uri" => "https://github.com/weppos/publicsuffix-ruby/blob/master/CHANGELOG.md",
|
18
|
+
"documentation_uri" => "https://rubydoc.info/gems/#{s.name}/#{s.version}",
|
19
|
+
"homepage_uri" => s.homepage,
|
20
|
+
"source_code_uri" => "https://github.com/weppos/publicsuffix-ruby/tree/v#{s.version}",
|
21
|
+
}
|
22
|
+
|
23
|
+
s.required_ruby_version = ">= 2.3"
|
16
24
|
|
17
25
|
s.require_paths = ["lib"]
|
18
26
|
s.files = `git ls-files`.split("\n")
|
19
27
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
20
28
|
s.extra_rdoc_files = %w( LICENSE.txt )
|
21
|
-
|
22
|
-
s.add_development_dependency "rake"
|
23
|
-
s.add_development_dependency "mocha"
|
24
|
-
s.add_development_dependency "yard"
|
25
29
|
end
|
data/test/acceptance_test.rb
CHANGED
@@ -1,16 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "test_helper"
|
2
4
|
|
3
5
|
class AcceptanceTest < Minitest::Test
|
4
6
|
|
5
7
|
VALID_CASES = [
|
6
|
-
|
7
|
-
|
8
|
+
["example.com", "example.com", [nil, "example", "com"]],
|
9
|
+
["foo.example.com", "example.com", ["foo", "example", "com"]],
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
+
["verybritish.co.uk", "verybritish.co.uk", [nil, "verybritish", "co.uk"]],
|
12
|
+
["foo.verybritish.co.uk", "verybritish.co.uk", ["foo", "verybritish", "co.uk"]],
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
+
["parliament.uk", "parliament.uk", [nil, "parliament", "uk"]],
|
15
|
+
["foo.parliament.uk", "parliament.uk", ["foo", "parliament", "uk"]],
|
14
16
|
].freeze
|
15
17
|
|
16
18
|
def test_valid
|
@@ -32,10 +34,10 @@ class AcceptanceTest < Minitest::Test
|
|
32
34
|
|
33
35
|
|
34
36
|
INVALID_CASES = [
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
37
|
+
["nic.bd", PublicSuffix::DomainNotAllowed],
|
38
|
+
[nil, PublicSuffix::DomainInvalid],
|
39
|
+
["", PublicSuffix::DomainInvalid],
|
40
|
+
[" ", PublicSuffix::DomainInvalid],
|
39
41
|
].freeze
|
40
42
|
|
41
43
|
def test_invalid
|
@@ -47,16 +49,16 @@ class AcceptanceTest < Minitest::Test
|
|
47
49
|
|
48
50
|
|
49
51
|
REJECTED_CASES = [
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
52
|
+
["www. .com", true],
|
53
|
+
["foo.co..uk", true],
|
54
|
+
["goo,gle.com", true],
|
55
|
+
["-google.com", true],
|
56
|
+
["google-.com", true],
|
57
|
+
|
58
|
+
# This case was covered in GH-15.
|
59
|
+
# I decided to cover this case because it's not easily reproducible with URI.parse
|
60
|
+
# and can lead to several false positives.
|
61
|
+
["http://google.com", false],
|
60
62
|
].freeze
|
61
63
|
|
62
64
|
def test_rejected
|
@@ -70,9 +72,9 @@ class AcceptanceTest < Minitest::Test
|
|
70
72
|
|
71
73
|
|
72
74
|
CASE_CASES = [
|
73
|
-
|
74
|
-
|
75
|
-
|
75
|
+
["Www.google.com", %w( www google com )],
|
76
|
+
["www.Google.com", %w( www google com )],
|
77
|
+
["www.google.Com", %w( www google com )],
|
76
78
|
].freeze
|
77
79
|
|
78
80
|
def test_ignore_case
|
@@ -88,12 +90,13 @@ class AcceptanceTest < Minitest::Test
|
|
88
90
|
|
89
91
|
|
90
92
|
INCLUDE_PRIVATE_CASES = [
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
93
|
+
["blogspot.com", true, "blogspot.com"],
|
94
|
+
["blogspot.com", false, nil],
|
95
|
+
["subdomain.blogspot.com", true, "blogspot.com"],
|
96
|
+
["subdomain.blogspot.com", false, "subdomain.blogspot.com"],
|
95
97
|
].freeze
|
96
98
|
|
99
|
+
# rubocop:disable Style/CombinableLoops
|
97
100
|
def test_ignore_private
|
98
101
|
# test domain and parse
|
99
102
|
INCLUDE_PRIVATE_CASES.each do |given, ignore_private, expected|
|
@@ -108,19 +111,20 @@ class AcceptanceTest < Minitest::Test
|
|
108
111
|
assert_equal !expected.nil?, PublicSuffix.valid?(given, ignore_private: ignore_private)
|
109
112
|
end
|
110
113
|
end
|
114
|
+
# rubocop:enable Style/CombinableLoops
|
111
115
|
|
112
116
|
|
113
117
|
def valid_uri?(name)
|
114
118
|
uri = URI.parse(name)
|
115
119
|
!uri.host.nil?
|
116
|
-
rescue
|
120
|
+
rescue StandardError
|
117
121
|
false
|
118
122
|
end
|
119
123
|
|
120
124
|
def valid_domain?(name)
|
121
125
|
uri = URI.parse(name)
|
122
126
|
!uri.host.nil? && uri.scheme.nil?
|
123
|
-
rescue
|
127
|
+
rescue StandardError
|
124
128
|
false
|
125
129
|
end
|
126
130
|
|
data/test/psl_test.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "test_helper"
|
2
4
|
require "public_suffix"
|
3
5
|
|
@@ -13,6 +15,7 @@ class PslTest < Minitest::Test
|
|
13
15
|
line = line.strip
|
14
16
|
next if line.empty?
|
15
17
|
next if line.start_with?("//")
|
18
|
+
|
16
19
|
input, output = line.split(", ")
|
17
20
|
|
18
21
|
# handle the case of eval("null"), it must be eval("nil")
|
@@ -35,7 +38,7 @@ class PslTest < Minitest::Test
|
|
35
38
|
failures = []
|
36
39
|
self.class.tests.each do |input, output|
|
37
40
|
# Punycode domains are not supported ATM
|
38
|
-
next if input =~ /xn
|
41
|
+
next if input =~ /xn--/
|
39
42
|
|
40
43
|
domain = PublicSuffix.domain(input) rescue nil
|
41
44
|
failures << [input, output, domain] if output != domain
|
data/test/test_helper.rb
CHANGED
@@ -1,11 +1,16 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
if ENV["COVERAGE"]
|
4
|
+
require "simplecov"
|
5
|
+
SimpleCov.start
|
6
|
+
|
7
|
+
require "codecov"
|
8
|
+
SimpleCov.formatter = SimpleCov::Formatter::Codecov
|
4
9
|
end
|
5
10
|
|
6
11
|
require "minitest/autorun"
|
7
12
|
require "minitest/reporters"
|
8
|
-
require "mocha/
|
13
|
+
require "mocha/minitest"
|
9
14
|
|
10
15
|
Minitest::Reporters.use! Minitest::Reporters::DefaultReporter.new(color: true)
|
11
16
|
|
data/test/unit/domain_test.rb
CHANGED
data/test/unit/errors_test.rb
CHANGED
data/test/unit/list_test.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "test_helper"
|
2
4
|
|
3
5
|
class PublicSuffixTest < Minitest::Test
|
@@ -139,13 +141,13 @@ class PublicSuffixTest < Minitest::Test
|
|
139
141
|
|
140
142
|
def test_self_normalize
|
141
143
|
[
|
142
|
-
|
143
|
-
|
144
|
-
|
144
|
+
["com", "com"],
|
145
|
+
["example.com", "example.com"],
|
146
|
+
["www.example.com", "www.example.com"],
|
145
147
|
|
146
|
-
|
147
|
-
|
148
|
-
|
148
|
+
["example.com.", "example.com"], # strip FQDN
|
149
|
+
[" example.com ", "example.com"], # strip spaces
|
150
|
+
["Example.COM", "example.com"], # downcase
|
149
151
|
].each do |input, output|
|
150
152
|
assert_equal output, PublicSuffix.normalize(input)
|
151
153
|
end
|
@@ -153,9 +155,9 @@ class PublicSuffixTest < Minitest::Test
|
|
153
155
|
|
154
156
|
def test_normalize_blank
|
155
157
|
[
|
156
|
-
|
157
|
-
|
158
|
-
|
158
|
+
nil,
|
159
|
+
"",
|
160
|
+
" ",
|
159
161
|
].each do |input|
|
160
162
|
error = PublicSuffix.normalize(input)
|
161
163
|
assert_instance_of PublicSuffix::DomainInvalid, error
|
@@ -165,7 +167,7 @@ class PublicSuffixTest < Minitest::Test
|
|
165
167
|
|
166
168
|
def test_normalize_scheme
|
167
169
|
[
|
168
|
-
|
170
|
+
"https://google.com",
|
169
171
|
].each do |input|
|
170
172
|
error = PublicSuffix.normalize(input)
|
171
173
|
assert_instance_of PublicSuffix::DomainInvalid, error
|
@@ -175,7 +177,7 @@ class PublicSuffixTest < Minitest::Test
|
|
175
177
|
|
176
178
|
def test_normalize_leading_dot
|
177
179
|
[
|
178
|
-
|
180
|
+
".google.com",
|
179
181
|
].each do |input|
|
180
182
|
error = PublicSuffix.normalize(input)
|
181
183
|
assert_instance_of PublicSuffix::DomainInvalid, error
|