addressable 2.8.0 → 2.8.4
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/CHANGELOG.md +36 -0
- data/Gemfile +4 -2
- data/Rakefile +2 -1
- data/addressable.gemspec +9 -18
- data/lib/addressable/idna/native.rb +8 -3
- data/lib/addressable/idna/pure.rb +10 -183
- data/lib/addressable/idna.rb +0 -1
- data/lib/addressable/template.rb +12 -14
- data/lib/addressable/uri.rb +168 -148
- data/lib/addressable/version.rb +1 -2
- data/spec/addressable/idna_spec.rb +6 -6
- data/spec/addressable/net_http_compat_spec.rb +0 -1
- data/spec/addressable/security_spec.rb +0 -1
- data/spec/addressable/template_spec.rb +69 -265
- data/spec/addressable/uri_spec.rb +137 -1
- data/tasks/gem.rake +5 -2
- metadata +11 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9be949fe19003ebc13db9a486fe0bb50b488896fa1671a3dc5ac2cd62e30c875
|
4
|
+
data.tar.gz: '01824780e0172f78d7bf95857b4546e47b32a50426c2d953a07f9d1c63f37af3'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
-
|
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.
|
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.
|
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 = "
|
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.
|
20
|
-
s.rubygems_version = "3.
|
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
|
-
|
24
|
-
s.specification_version = 4
|
24
|
+
s.specification_version = 4
|
25
25
|
|
26
|
-
|
27
|
-
|
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
|
-
|
34
|
-
|
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(
|
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
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
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
|
data/lib/addressable/idna.rb
CHANGED
data/lib/addressable/template.rb
CHANGED
@@ -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.
|
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
|
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
|
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.
|
906
|
-
value.map! { |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[
|
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 =
|
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 = "
|
1024
|
+
regexp_string = "\\A#{regexp_string}\\z"
|
1027
1025
|
return expansions, Regexp.new(regexp_string)
|
1028
1026
|
end
|
1029
1027
|
|