addressable 2.8.0 → 2.8.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 03a21b1eab156a16e90bd7963af85980edfbddc8f3dbe052766303dba76cc000
4
- data.tar.gz: 03eca5d86f4c70f9320000f36e3cff4fd8023342a4e0ac855d0ef1ec89ee6183
3
+ metadata.gz: 9be949fe19003ebc13db9a486fe0bb50b488896fa1671a3dc5ac2cd62e30c875
4
+ data.tar.gz: '01824780e0172f78d7bf95857b4546e47b32a50426c2d953a07f9d1c63f37af3'
5
5
  SHA512:
6
- metadata.gz: d504f9475ad823f5bb077b9c039a2c91c83e52c20896247a7289b61725c61b1ddefe8ae06155fb018fc67087cf04276081b42105a18394b45e2374ad0b2fadb0
7
- data.tar.gz: b81766fbcb9335d5ca94403b62d3b2a6fae31b66cd3c05f48e1885eaf07883bfa1321b6930271fe1415135aec687af51312a26ce27bd4b83b2ac6424dec597c9
6
+ metadata.gz: 051d1501ab89efff21d5bcc3aed23bec2f7ff2defdf21915455142d7c1382e6b734053162dc9a19a9ba5946e9978ff6baa305035ebea5f947ba48e6241973059
7
+ data.tar.gz: 7cca09d71ccbb21e116ddb36075ab1fab39078dc5b51b9c7c34df8a88db3d90f8158c8c066692997fd551c97e983e6a9ddec3054741ee1337a9c185cca1c8a88
data/CHANGELOG.md CHANGED
@@ -1,3 +1,39 @@
1
+ # Addressable 2.8.4
2
+ - Restore `Addressable::IDNA.unicode_normalize_kc` as a deprecated method ([#504])
3
+
4
+ [#504]: https://github.com/sporkmonger/addressable/pull/504
5
+
6
+ # Addressable 2.8.3
7
+ - Fix template expand level 2 hash support for non-string objects ([#499], [#498])
8
+
9
+ [#499]: https://github.com/sporkmonger/addressable/pull/499
10
+ [#498]: https://github.com/sporkmonger/addressable/pull/498
11
+
12
+ # Addressable 2.8.2
13
+ - Improve cache hits and JIT friendliness ([#486](https://github.com/sporkmonger/addressable/pull/486))
14
+ - Improve code style and test coverage ([#482](https://github.com/sporkmonger/addressable/pull/482))
15
+ - Ensure reset of deferred validation ([#481](https://github.com/sporkmonger/addressable/pull/481))
16
+ - Resolve normalization differences between `IDNA::Native` and `IDNA::Pure` ([#408](https://github.com/sporkmonger/addressable/issues/408), [#492])
17
+ - Remove redundant colon in `Addressable::URI::CharacterClasses::AUTHORITY` regex ([#438](https://github.com/sporkmonger/addressable/pull/438)) (accidentally reverted by [#449] merge but [added back](https://github.com/sporkmonger/addressable/pull/492#discussion_r1105125280) in [#492])
18
+
19
+ [#492]: https://github.com/sporkmonger/addressable/pull/492
20
+
21
+ # Addressable 2.8.1
22
+ - refactor `Addressable::URI.normalize_path` to address linter offenses ([#430](https://github.com/sporkmonger/addressable/pull/430))
23
+ - update gemspec to reflect supported Ruby versions ([#466], [#464], [#463])
24
+ - compatibility w/ public_suffix 5.x ([#466], [#465], [#460])
25
+ - fixes "invalid byte sequence in UTF-8" exception when unencoding URLs containing non UTF-8 characters ([#459](https://github.com/sporkmonger/addressable/pull/459))
26
+ - `Ractor` compatibility ([#449])
27
+ - use the whole string instead of a single line for template match ([#431](https://github.com/sporkmonger/addressable/pull/431))
28
+ - force UTF-8 encoding only if needed ([#341](https://github.com/sporkmonger/addressable/pull/341))
29
+
30
+ [#449]: https://github.com/sporkmonger/addressable/pull/449
31
+ [#460]: https://github.com/sporkmonger/addressable/pull/460
32
+ [#463]: https://github.com/sporkmonger/addressable/pull/463
33
+ [#464]: https://github.com/sporkmonger/addressable/pull/464
34
+ [#465]: https://github.com/sporkmonger/addressable/pull/465
35
+ [#466]: https://github.com/sporkmonger/addressable/pull/466
36
+
1
37
  # Addressable 2.8.0
2
38
  - fixes ReDoS vulnerability in Addressable::Template#match
3
39
  - no longer replaces `+` with spaces in queries for non-http(s) schemes
data/Gemfile CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  source 'https://rubygems.org'
4
4
 
5
- gemspec(path: __FILE__ == "(eval)" ? ".." : ".")
5
+ gemspec
6
6
 
7
7
  group :test do
8
8
  gem 'rspec', '~> 3.8'
@@ -25,4 +25,6 @@ group :test, :development do
25
25
  gem "rake", ">= 12.3.3"
26
26
  end
27
27
 
28
- gem "idn-ruby", platform: :mri
28
+ unless ENV["IDNA_MODE"] == "pure"
29
+ gem "idn-ruby", platform: :mri
30
+ end
data/Rakefile CHANGED
@@ -24,7 +24,8 @@ PKG_FILES = FileList[
24
24
  "tasks/**/*",
25
25
  "[A-Z]*", "Rakefile"
26
26
  ].exclude(/pkg/).exclude(/database\.yml/).
27
- exclude(/Gemfile\.lock/).exclude(/[_\.]git$/)
27
+ exclude(/Gemfile\.lock/).exclude(/[_\.]git$/).
28
+ exclude(/coverage/)
28
29
 
29
30
  task :default => "spec"
30
31
 
data/addressable.gemspec CHANGED
@@ -1,14 +1,15 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: addressable 2.8.0 ruby lib
2
+ # stub: addressable 2.8.4 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "addressable".freeze
6
- s.version = "2.8.0"
6
+ s.version = "2.8.4"
7
7
 
8
8
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
9
+ s.metadata = { "changelog_uri" => "https://github.com/sporkmonger/addressable/blob/main/CHANGELOG.md" } if s.respond_to? :metadata=
9
10
  s.require_paths = ["lib".freeze]
10
11
  s.authors = ["Bob Aman".freeze]
11
- s.date = "2021-07-03"
12
+ s.date = "2023-04-09"
12
13
  s.description = "Addressable is an alternative implementation to the URI implementation that is\npart of Ruby's standard library. It is flexible, offers heuristic parsing, and\nadditionally provides extensive support for IRIs and URI templates.\n".freeze
13
14
  s.email = "bob@sporkmonger.com".freeze
14
15
  s.extra_rdoc_files = ["README.md".freeze]
@@ -16,22 +17,12 @@ Gem::Specification.new do |s|
16
17
  s.homepage = "https://github.com/sporkmonger/addressable".freeze
17
18
  s.licenses = ["Apache-2.0".freeze]
18
19
  s.rdoc_options = ["--main".freeze, "README.md".freeze]
19
- s.required_ruby_version = Gem::Requirement.new(">= 2.0".freeze)
20
- s.rubygems_version = "3.0.3".freeze
20
+ s.required_ruby_version = Gem::Requirement.new(">= 2.2".freeze)
21
+ s.rubygems_version = "3.4.10".freeze
21
22
  s.summary = "URI Implementation".freeze
22
23
 
23
- if s.respond_to? :specification_version then
24
- s.specification_version = 4
24
+ s.specification_version = 4
25
25
 
26
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
27
- s.add_runtime_dependency(%q<public_suffix>.freeze, [">= 2.0.2", "< 5.0"])
28
- s.add_development_dependency(%q<bundler>.freeze, [">= 1.0", "< 3.0"])
29
- else
30
- s.add_dependency(%q<public_suffix>.freeze, [">= 2.0.2", "< 5.0"])
31
- s.add_dependency(%q<bundler>.freeze, [">= 1.0", "< 3.0"])
32
- end
33
- else
34
- s.add_dependency(%q<public_suffix>.freeze, [">= 2.0.2", "< 5.0"])
35
- s.add_dependency(%q<bundler>.freeze, [">= 1.0", "< 3.0"])
36
- end
26
+ s.add_runtime_dependency(%q<public_suffix>.freeze, [">= 2.0.2", "< 6.0"])
27
+ s.add_development_dependency(%q<bundler>.freeze, [">= 1.0", "< 3.0"])
37
28
  end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # encoding:utf-8
4
3
  #--
5
4
  # Copyright (C) Bob Aman
6
5
  #
@@ -30,8 +29,14 @@ module Addressable
30
29
  IDN::Punycode.decode(value.to_s)
31
30
  end
32
31
 
33
- def self.unicode_normalize_kc(value)
34
- IDN::Stringprep.nfkc_normalize(value.to_s)
32
+ class << self
33
+ # @deprecated Use {String#unicode_normalize(:nfkc)} instead
34
+ def unicode_normalize_kc(value)
35
+ value.to_s.unicode_normalize(:nfkc)
36
+ end
37
+
38
+ extend Gem::Deprecate
39
+ deprecate :unicode_normalize_kc, "String#unicode_normalize(:nfkc)", 2023, 4
35
40
  end
36
41
 
37
42
  def self.to_ascii(value)
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # encoding:utf-8
4
3
  #--
5
4
  # Copyright (C) Bob Aman
6
5
  #
@@ -67,7 +66,7 @@ module Addressable
67
66
  # domain name as described in RFC 3490.
68
67
  def self.to_ascii(input)
69
68
  input = input.to_s unless input.is_a?(String)
70
- input = input.dup
69
+ input = input.dup.force_encoding(Encoding::UTF_8).unicode_normalize(:nfkc)
71
70
  if input.respond_to?(:force_encoding)
72
71
  input.force_encoding(Encoding::ASCII_8BIT)
73
72
  end
@@ -78,7 +77,7 @@ module Addressable
78
77
  part.force_encoding(Encoding::ASCII_8BIT)
79
78
  end
80
79
  if part =~ UTF8_REGEX && part =~ UTF8_REGEX_MULTIBYTE
81
- ACE_PREFIX + punycode_encode(unicode_normalize_kc(part))
80
+ ACE_PREFIX + punycode_encode(part)
82
81
  else
83
82
  part
84
83
  end
@@ -113,13 +112,14 @@ module Addressable
113
112
  output
114
113
  end
115
114
 
116
- # Unicode normalization form KC.
117
- def self.unicode_normalize_kc(input)
118
- input = input.to_s unless input.is_a?(String)
119
- unpacked = input.unpack("U*")
120
- unpacked =
121
- unicode_compose(unicode_sort_canonical(unicode_decompose(unpacked)))
122
- return unpacked.pack("U*")
115
+ class << self
116
+ # @deprecated Use {String#unicode_normalize(:nfkc)} instead
117
+ def unicode_normalize_kc(value)
118
+ value.to_s.unicode_normalize(:nfkc)
119
+ end
120
+
121
+ extend Gem::Deprecate
122
+ deprecate :unicode_normalize_kc, "String#unicode_normalize(:nfkc)", 2023, 4
123
123
  end
124
124
 
125
125
  ##
@@ -137,164 +137,6 @@ module Addressable
137
137
  end
138
138
  private_class_method :unicode_downcase
139
139
 
140
- def self.unicode_compose(unpacked)
141
- unpacked_result = []
142
- length = unpacked.length
143
-
144
- return unpacked if length == 0
145
-
146
- starter = unpacked[0]
147
- starter_cc = lookup_unicode_combining_class(starter)
148
- starter_cc = 256 if starter_cc != 0
149
- for i in 1...length
150
- ch = unpacked[i]
151
-
152
- if (starter_cc == 0 &&
153
- (composite = unicode_compose_pair(starter, ch)) != nil)
154
- starter = composite
155
- else
156
- unpacked_result << starter
157
- starter = ch
158
- end
159
- end
160
- unpacked_result << starter
161
- return unpacked_result
162
- end
163
- private_class_method :unicode_compose
164
-
165
- def self.unicode_compose_pair(ch_one, ch_two)
166
- if ch_one >= HANGUL_LBASE && ch_one < HANGUL_LBASE + HANGUL_LCOUNT &&
167
- ch_two >= HANGUL_VBASE && ch_two < HANGUL_VBASE + HANGUL_VCOUNT
168
- # Hangul L + V
169
- return HANGUL_SBASE + (
170
- (ch_one - HANGUL_LBASE) * HANGUL_VCOUNT + (ch_two - HANGUL_VBASE)
171
- ) * HANGUL_TCOUNT
172
- elsif ch_one >= HANGUL_SBASE &&
173
- ch_one < HANGUL_SBASE + HANGUL_SCOUNT &&
174
- (ch_one - HANGUL_SBASE) % HANGUL_TCOUNT == 0 &&
175
- ch_two >= HANGUL_TBASE && ch_two < HANGUL_TBASE + HANGUL_TCOUNT
176
- # Hangul LV + T
177
- return ch_one + (ch_two - HANGUL_TBASE)
178
- end
179
-
180
- p = []
181
-
182
- ucs4_to_utf8(ch_one, p)
183
- ucs4_to_utf8(ch_two, p)
184
-
185
- return lookup_unicode_composition(p)
186
- end
187
- private_class_method :unicode_compose_pair
188
-
189
- def self.ucs4_to_utf8(char, buffer)
190
- if char < 128
191
- buffer << char
192
- elsif char < 2048
193
- buffer << (char >> 6 | 192)
194
- buffer << (char & 63 | 128)
195
- elsif char < 0x10000
196
- buffer << (char >> 12 | 224)
197
- buffer << (char >> 6 & 63 | 128)
198
- buffer << (char & 63 | 128)
199
- elsif char < 0x200000
200
- buffer << (char >> 18 | 240)
201
- buffer << (char >> 12 & 63 | 128)
202
- buffer << (char >> 6 & 63 | 128)
203
- buffer << (char & 63 | 128)
204
- elsif char < 0x4000000
205
- buffer << (char >> 24 | 248)
206
- buffer << (char >> 18 & 63 | 128)
207
- buffer << (char >> 12 & 63 | 128)
208
- buffer << (char >> 6 & 63 | 128)
209
- buffer << (char & 63 | 128)
210
- elsif char < 0x80000000
211
- buffer << (char >> 30 | 252)
212
- buffer << (char >> 24 & 63 | 128)
213
- buffer << (char >> 18 & 63 | 128)
214
- buffer << (char >> 12 & 63 | 128)
215
- buffer << (char >> 6 & 63 | 128)
216
- buffer << (char & 63 | 128)
217
- end
218
- end
219
- private_class_method :ucs4_to_utf8
220
-
221
- def self.unicode_sort_canonical(unpacked)
222
- unpacked = unpacked.dup
223
- i = 1
224
- length = unpacked.length
225
-
226
- return unpacked if length < 2
227
-
228
- while i < length
229
- last = unpacked[i-1]
230
- ch = unpacked[i]
231
- last_cc = lookup_unicode_combining_class(last)
232
- cc = lookup_unicode_combining_class(ch)
233
- if cc != 0 && last_cc != 0 && last_cc > cc
234
- unpacked[i] = last
235
- unpacked[i-1] = ch
236
- i -= 1 if i > 1
237
- else
238
- i += 1
239
- end
240
- end
241
- return unpacked
242
- end
243
- private_class_method :unicode_sort_canonical
244
-
245
- def self.unicode_decompose(unpacked)
246
- unpacked_result = []
247
- for cp in unpacked
248
- if cp >= HANGUL_SBASE && cp < HANGUL_SBASE + HANGUL_SCOUNT
249
- l, v, t = unicode_decompose_hangul(cp)
250
- unpacked_result << l
251
- unpacked_result << v if v
252
- unpacked_result << t if t
253
- else
254
- dc = lookup_unicode_compatibility(cp)
255
- unless dc
256
- unpacked_result << cp
257
- else
258
- unpacked_result.concat(unicode_decompose(dc.unpack("U*")))
259
- end
260
- end
261
- end
262
- return unpacked_result
263
- end
264
- private_class_method :unicode_decompose
265
-
266
- def self.unicode_decompose_hangul(codepoint)
267
- sindex = codepoint - HANGUL_SBASE;
268
- if sindex < 0 || sindex >= HANGUL_SCOUNT
269
- l = codepoint
270
- v = t = nil
271
- return l, v, t
272
- end
273
- l = HANGUL_LBASE + sindex / HANGUL_NCOUNT
274
- v = HANGUL_VBASE + (sindex % HANGUL_NCOUNT) / HANGUL_TCOUNT
275
- t = HANGUL_TBASE + sindex % HANGUL_TCOUNT
276
- if t == HANGUL_TBASE
277
- t = nil
278
- end
279
- return l, v, t
280
- end
281
- private_class_method :unicode_decompose_hangul
282
-
283
- def self.lookup_unicode_combining_class(codepoint)
284
- codepoint_data = UNICODE_DATA[codepoint]
285
- (codepoint_data ?
286
- (codepoint_data[UNICODE_DATA_COMBINING_CLASS] || 0) :
287
- 0)
288
- end
289
- private_class_method :lookup_unicode_combining_class
290
-
291
- def self.lookup_unicode_compatibility(codepoint)
292
- codepoint_data = UNICODE_DATA[codepoint]
293
- (codepoint_data ?
294
- codepoint_data[UNICODE_DATA_COMPATIBILITY] : nil)
295
- end
296
- private_class_method :lookup_unicode_compatibility
297
-
298
140
  def self.lookup_unicode_lowercase(codepoint)
299
141
  codepoint_data = UNICODE_DATA[codepoint]
300
142
  (codepoint_data ?
@@ -303,21 +145,6 @@ module Addressable
303
145
  end
304
146
  private_class_method :lookup_unicode_lowercase
305
147
 
306
- def self.lookup_unicode_composition(unpacked)
307
- return COMPOSITION_TABLE[unpacked]
308
- end
309
- private_class_method :lookup_unicode_composition
310
-
311
- HANGUL_SBASE = 0xac00
312
- HANGUL_LBASE = 0x1100
313
- HANGUL_LCOUNT = 19
314
- HANGUL_VBASE = 0x1161
315
- HANGUL_VCOUNT = 21
316
- HANGUL_TBASE = 0x11a7
317
- HANGUL_TCOUNT = 28
318
- HANGUL_NCOUNT = HANGUL_VCOUNT * HANGUL_TCOUNT # 588
319
- HANGUL_SCOUNT = HANGUL_LCOUNT * HANGUL_NCOUNT # 11172
320
-
321
148
  UNICODE_DATA_COMBINING_CLASS = 0
322
149
  UNICODE_DATA_EXCLUSION = 1
323
150
  UNICODE_DATA_CANONICAL = 2
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # encoding:utf-8
4
3
  #--
5
4
  # Copyright (C) Bob Aman
6
5
  #
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # encoding:utf-8
4
3
  #--
5
4
  # Copyright (C) Bob Aman
6
5
  #
@@ -657,12 +656,12 @@ module Addressable
657
656
  def ordered_variable_defaults
658
657
  @ordered_variable_defaults ||= begin
659
658
  expansions, _ = parse_template_pattern(pattern)
660
- expansions.map do |capture|
659
+ expansions.flat_map do |capture|
661
660
  _, _, varlist = *capture.match(EXPRESSION)
662
661
  varlist.split(',').map do |varspec|
663
662
  varspec[VARSPEC, 1]
664
663
  end
665
- end.flatten
664
+ end
666
665
  end
667
666
  end
668
667
 
@@ -893,25 +892,24 @@ module Addressable
893
892
  # operator.
894
893
  #
895
894
  # @param [Hash, Array, String] value
896
- # Normalizes keys and values with IDNA#unicode_normalize_kc
895
+ # Normalizes unicode keys and values with String#unicode_normalize (NFC)
897
896
  #
898
897
  # @return [Hash, Array, String] The normalized values
899
898
  def normalize_value(value)
900
- unless value.is_a?(Hash)
901
- value = value.respond_to?(:to_ary) ? value.to_ary : value.to_str
902
- end
903
-
904
899
  # Handle unicode normalization
905
- if value.kind_of?(Array)
906
- value.map! { |val| Addressable::IDNA.unicode_normalize_kc(val) }
900
+ if value.respond_to?(:to_ary)
901
+ value.to_ary.map! { |val| normalize_value(val) }
907
902
  elsif value.kind_of?(Hash)
908
903
  value = value.inject({}) { |acc, (k, v)|
909
- acc[Addressable::IDNA.unicode_normalize_kc(k)] =
910
- Addressable::IDNA.unicode_normalize_kc(v)
904
+ acc[normalize_value(k)] = normalize_value(v)
911
905
  acc
912
906
  }
913
907
  else
914
- value = Addressable::IDNA.unicode_normalize_kc(value)
908
+ value = value.to_s if !value.kind_of?(String)
909
+ if value.encoding != Encoding::UTF_8
910
+ value = value.dup.force_encoding(Encoding::UTF_8)
911
+ end
912
+ value = value.unicode_normalize(:nfc)
915
913
  end
916
914
  value
917
915
  end
@@ -1023,7 +1021,7 @@ module Addressable
1023
1021
  end
1024
1022
 
1025
1023
  # Ensure that the regular expression matches the whole URI.
1026
- regexp_string = "^#{regexp_string}$"
1024
+ regexp_string = "\\A#{regexp_string}\\z"
1027
1025
  return expansions, Regexp.new(regexp_string)
1028
1026
  end
1029
1027