addressable 2.3.2 → 2.8.7

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.
@@ -1,6 +1,7 @@
1
- # encoding:utf-8
1
+ # frozen_string_literal: true
2
+
2
3
  #--
3
- # Copyright (C) 2006-2011 Bob Aman
4
+ # Copyright (C) Bob Aman
4
5
  #
5
6
  # Licensed under the Apache License, Version 2.0 (the "License");
6
7
  # you may not use this file except in compliance with the License.
@@ -21,23 +22,45 @@ require "idn"
21
22
  module Addressable
22
23
  module IDNA
23
24
  def self.punycode_encode(value)
24
- IDN::Punycode.encode(value)
25
+ IDN::Punycode.encode(value.to_s)
25
26
  end
26
27
 
27
28
  def self.punycode_decode(value)
28
- IDN::Punycode.decode(value)
29
+ IDN::Punycode.decode(value.to_s)
29
30
  end
30
31
 
31
- def self.unicode_normalize_kc(value)
32
- IDN::Stringprep.nfkc_normalize(value)
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
33
40
  end
34
41
 
35
42
  def self.to_ascii(value)
36
- IDN::Idna.toASCII(value)
43
+ value.to_s.split('.', -1).map do |segment|
44
+ if segment.size > 0 && segment.size < 64
45
+ IDN::Idna.toASCII(segment, IDN::Idna::ALLOW_UNASSIGNED)
46
+ elsif segment.size >= 64
47
+ segment
48
+ else
49
+ ''
50
+ end
51
+ end.join('.')
37
52
  end
38
53
 
39
54
  def self.to_unicode(value)
40
- IDN::Idna.toUnicode(value)
55
+ value.to_s.split('.', -1).map do |segment|
56
+ if segment.size > 0 && segment.size < 64
57
+ IDN::Idna.toUnicode(segment, IDN::Idna::ALLOW_UNASSIGNED)
58
+ elsif segment.size >= 64
59
+ segment
60
+ else
61
+ ''
62
+ end
63
+ end.join('.')
41
64
  end
42
65
  end
43
66
  end
@@ -1,6 +1,7 @@
1
- # encoding:utf-8
1
+ # frozen_string_literal: true
2
+
2
3
  #--
3
- # Copyright (C) 2006-2011 Bob Aman
4
+ # Copyright (C) Bob Aman
4
5
  #
5
6
  # Licensed under the Apache License, Version 2.0 (the "License");
6
7
  # you may not use this file except in compliance with the License.
@@ -64,7 +65,8 @@ module Addressable
64
65
  # Converts from a Unicode internationalized domain name to an ASCII
65
66
  # domain name as described in RFC 3490.
66
67
  def self.to_ascii(input)
67
- input = input.dup
68
+ input = input.to_s unless input.is_a?(String)
69
+ input = input.dup.force_encoding(Encoding::UTF_8).unicode_normalize(:nfkc)
68
70
  if input.respond_to?(:force_encoding)
69
71
  input.force_encoding(Encoding::ASCII_8BIT)
70
72
  end
@@ -75,7 +77,7 @@ module Addressable
75
77
  part.force_encoding(Encoding::ASCII_8BIT)
76
78
  end
77
79
  if part =~ UTF8_REGEX && part =~ UTF8_REGEX_MULTIBYTE
78
- ACE_PREFIX + punycode_encode(unicode_normalize_kc(part))
80
+ ACE_PREFIX + punycode_encode(part)
79
81
  else
80
82
  part
81
83
  end
@@ -89,10 +91,16 @@ module Addressable
89
91
  # Converts from an ASCII domain name to a Unicode internationalized
90
92
  # domain name as described in RFC 3490.
91
93
  def self.to_unicode(input)
94
+ input = input.to_s unless input.is_a?(String)
92
95
  parts = input.split('.')
93
96
  parts.map! do |part|
94
- if part =~ /^#{ACE_PREFIX}/
95
- punycode_decode(part[/^#{ACE_PREFIX}(.+)/, 1])
97
+ if part =~ /^#{ACE_PREFIX}(.+)/
98
+ begin
99
+ punycode_decode(part[/^#{ACE_PREFIX}(.+)/, 1])
100
+ rescue Addressable::IDNA::PunycodeBadInput
101
+ # toUnicode is explicitly defined as never-fails by the spec
102
+ part
103
+ end
96
104
  else
97
105
  part
98
106
  end
@@ -104,12 +112,14 @@ module Addressable
104
112
  output
105
113
  end
106
114
 
107
- # Unicode normalization form KC.
108
- def self.unicode_normalize_kc(input)
109
- unpacked = input.unpack("U*")
110
- unpacked =
111
- unicode_compose(unicode_sort_canonical(unicode_decompose(unpacked)))
112
- 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
113
123
  end
114
124
 
115
125
  ##
@@ -120,171 +130,12 @@ module Addressable
120
130
  # The input string.
121
131
  # @return [String] The downcased result.
122
132
  def self.unicode_downcase(input)
133
+ input = input.to_s unless input.is_a?(String)
123
134
  unpacked = input.unpack("U*")
124
135
  unpacked.map! { |codepoint| lookup_unicode_lowercase(codepoint) }
125
136
  return unpacked.pack("U*")
126
137
  end
127
- (class <<self; private :unicode_downcase; end)
128
-
129
- def self.unicode_compose(unpacked)
130
- unpacked_result = []
131
- length = unpacked.length
132
-
133
- return unpacked if length == 0
134
-
135
- starter = unpacked[0]
136
- starter_cc = lookup_unicode_combining_class(starter)
137
- starter_cc = 256 if starter_cc != 0
138
- for i in 1...length
139
- ch = unpacked[i]
140
- cc = lookup_unicode_combining_class(ch)
141
-
142
- if (starter_cc == 0 &&
143
- (composite = unicode_compose_pair(starter, ch)) != nil)
144
- starter = composite
145
- startercc = lookup_unicode_combining_class(composite)
146
- else
147
- unpacked_result << starter
148
- starter = ch
149
- startercc = cc
150
- end
151
- end
152
- unpacked_result << starter
153
- return unpacked_result
154
- end
155
- (class <<self; private :unicode_compose; end)
156
-
157
- def self.unicode_compose_pair(ch_one, ch_two)
158
- if ch_one >= HANGUL_LBASE && ch_one < HANGUL_LBASE + HANGUL_LCOUNT &&
159
- ch_two >= HANGUL_VBASE && ch_two < HANGUL_VBASE + HANGUL_VCOUNT
160
- # Hangul L + V
161
- return HANGUL_SBASE + (
162
- (ch_one - HANGUL_LBASE) * HANGUL_VCOUNT + (ch_two - HANGUL_VBASE)
163
- ) * HANGUL_TCOUNT
164
- elsif ch_one >= HANGUL_SBASE &&
165
- ch_one < HANGUL_SBASE + HANGUL_SCOUNT &&
166
- (ch_one - HANGUL_SBASE) % HANGUL_TCOUNT == 0 &&
167
- ch_two >= HANGUL_TBASE && ch_two < HANGUL_TBASE + HANGUL_TCOUNT
168
- # Hangul LV + T
169
- return ch_one + (ch_two - HANGUL_TBASE)
170
- end
171
-
172
- p = []
173
- ucs4_to_utf8 = lambda do |ch|
174
- # For some reason, rcov likes to drop BUS errors here.
175
- if ch < 128
176
- p << ch
177
- elsif ch < 2048
178
- p << (ch >> 6 | 192)
179
- p << (ch & 63 | 128)
180
- elsif ch < 0x10000
181
- p << (ch >> 12 | 224)
182
- p << (ch >> 6 & 63 | 128)
183
- p << (ch & 63 | 128)
184
- elsif ch < 0x200000
185
- p << (ch >> 18 | 240)
186
- p << (ch >> 12 & 63 | 128)
187
- p << (ch >> 6 & 63 | 128)
188
- p << (ch & 63 | 128)
189
- elsif ch < 0x4000000
190
- p << (ch >> 24 | 248)
191
- p << (ch >> 18 & 63 | 128)
192
- p << (ch >> 12 & 63 | 128)
193
- p << (ch >> 6 & 63 | 128)
194
- p << (ch & 63 | 128)
195
- elsif ch < 0x80000000
196
- p << (ch >> 30 | 252)
197
- p << (ch >> 24 & 63 | 128)
198
- p << (ch >> 18 & 63 | 128)
199
- p << (ch >> 12 & 63 | 128)
200
- p << (ch >> 6 & 63 | 128)
201
- p << (ch & 63 | 128)
202
- end
203
- end
204
-
205
- ucs4_to_utf8.call(ch_one)
206
- ucs4_to_utf8.call(ch_two)
207
-
208
- return lookup_unicode_composition(p)
209
- end
210
- (class <<self; private :unicode_compose_pair; end)
211
-
212
- def self.unicode_sort_canonical(unpacked)
213
- unpacked = unpacked.dup
214
- i = 1
215
- length = unpacked.length
216
-
217
- return unpacked if length < 2
218
-
219
- while i < length
220
- last = unpacked[i-1]
221
- ch = unpacked[i]
222
- last_cc = lookup_unicode_combining_class(last)
223
- cc = lookup_unicode_combining_class(ch)
224
- if cc != 0 && last_cc != 0 && last_cc > cc
225
- unpacked[i] = last
226
- unpacked[i-1] = ch
227
- i -= 1 if i > 1
228
- else
229
- i += 1
230
- end
231
- end
232
- return unpacked
233
- end
234
- (class <<self; private :unicode_sort_canonical; end)
235
-
236
- def self.unicode_decompose(unpacked)
237
- unpacked_result = []
238
- for cp in unpacked
239
- if cp >= HANGUL_SBASE && cp < HANGUL_SBASE + HANGUL_SCOUNT
240
- l, v, t = unicode_decompose_hangul(cp)
241
- unpacked_result << l
242
- unpacked_result << v if v
243
- unpacked_result << t if t
244
- else
245
- dc = lookup_unicode_compatibility(cp)
246
- unless dc
247
- unpacked_result << cp
248
- else
249
- unpacked_result.concat(unicode_decompose(dc.unpack("U*")))
250
- end
251
- end
252
- end
253
- return unpacked_result
254
- end
255
- (class <<self; private :unicode_decompose; end)
256
-
257
- def self.unicode_decompose_hangul(codepoint)
258
- sindex = codepoint - HANGUL_SBASE;
259
- if sindex < 0 || sindex >= HANGUL_SCOUNT
260
- l = codepoint
261
- v = t = nil
262
- return l, v, t
263
- end
264
- l = HANGUL_LBASE + sindex / HANGUL_NCOUNT
265
- v = HANGUL_VBASE + (sindex % HANGUL_NCOUNT) / HANGUL_TCOUNT
266
- t = HANGUL_TBASE + sindex % HANGUL_TCOUNT
267
- if t == HANGUL_TBASE
268
- t = nil
269
- end
270
- return l, v, t
271
- end
272
- (class <<self; private :unicode_decompose_hangul; end)
273
-
274
- def self.lookup_unicode_combining_class(codepoint)
275
- codepoint_data = UNICODE_DATA[codepoint]
276
- (codepoint_data ?
277
- (codepoint_data[UNICODE_DATA_COMBINING_CLASS] || 0) :
278
- 0)
279
- end
280
- (class <<self; private :lookup_unicode_combining_class; end)
281
-
282
- def self.lookup_unicode_compatibility(codepoint)
283
- codepoint_data = UNICODE_DATA[codepoint]
284
- (codepoint_data ?
285
- codepoint_data[UNICODE_DATA_COMPATIBILITY] : nil)
286
- end
287
- (class <<self; private :lookup_unicode_compatibility; end)
138
+ private_class_method :unicode_downcase
288
139
 
289
140
  def self.lookup_unicode_lowercase(codepoint)
290
141
  codepoint_data = UNICODE_DATA[codepoint]
@@ -292,22 +143,7 @@ module Addressable
292
143
  (codepoint_data[UNICODE_DATA_LOWERCASE] || codepoint) :
293
144
  codepoint)
294
145
  end
295
- (class <<self; private :lookup_unicode_lowercase; end)
296
-
297
- def self.lookup_unicode_composition(unpacked)
298
- return COMPOSITION_TABLE[unpacked]
299
- end
300
- (class <<self; private :lookup_unicode_composition; end)
301
-
302
- HANGUL_SBASE = 0xac00
303
- HANGUL_LBASE = 0x1100
304
- HANGUL_LCOUNT = 19
305
- HANGUL_VBASE = 0x1161
306
- HANGUL_VCOUNT = 21
307
- HANGUL_TBASE = 0x11a7
308
- HANGUL_TCOUNT = 28
309
- HANGUL_NCOUNT = HANGUL_VCOUNT * HANGUL_TCOUNT # 588
310
- HANGUL_SCOUNT = HANGUL_LCOUNT * HANGUL_NCOUNT # 11172
146
+ private_class_method :lookup_unicode_lowercase
311
147
 
312
148
  UNICODE_DATA_COMBINING_CLASS = 0
313
149
  UNICODE_DATA_EXCLUSION = 1
@@ -317,14 +153,24 @@ module Addressable
317
153
  UNICODE_DATA_LOWERCASE = 5
318
154
  UNICODE_DATA_TITLECASE = 6
319
155
 
320
- # This is a sparse Unicode table. Codepoints without entries are
321
- # assumed to have the value: [0, 0, nil, nil, nil, nil, nil]
322
- UNICODE_DATA = File.open(UNICODE_TABLE, "rb") do |file|
323
- Marshal.load(file.read)
156
+ begin
157
+ if defined?(FakeFS)
158
+ fakefs_state = FakeFS.activated?
159
+ FakeFS.deactivate!
160
+ end
161
+ # This is a sparse Unicode table. Codepoints without entries are
162
+ # assumed to have the value: [0, 0, nil, nil, nil, nil, nil]
163
+ UNICODE_DATA = File.open(UNICODE_TABLE, "rb") do |file|
164
+ Marshal.load(file.read)
165
+ end
166
+ ensure
167
+ if defined?(FakeFS)
168
+ FakeFS.activate! if fakefs_state
169
+ end
324
170
  end
325
171
 
326
172
  COMPOSITION_TABLE = {}
327
- for codepoint, data in UNICODE_DATA
173
+ UNICODE_DATA.each do |codepoint, data|
328
174
  canonical = data[UNICODE_DATA_CANONICAL]
329
175
  exclusion = data[UNICODE_DATA_EXCLUSION]
330
176
 
@@ -365,6 +211,7 @@ module Addressable
365
211
  class PunycodeOverflow < StandardError; end
366
212
 
367
213
  def self.punycode_encode(unicode)
214
+ unicode = unicode.to_s unless unicode.is_a?(String)
368
215
  input = unicode.unpack("U*")
369
216
  output = [0] * (ACE_MAX_LENGTH + 1)
370
217
  input_length = input.size
@@ -473,7 +320,7 @@ module Addressable
473
320
  outlen.times do |j|
474
321
  c = output[j]
475
322
  unless c >= 0 && c <= 127
476
- raise Exception, "Invalid output char."
323
+ raise StandardError, "Invalid output char."
477
324
  end
478
325
  unless PUNYCODE_PRINT_ASCII[c]
479
326
  raise PunycodeBadInput, "Input is invalid."
@@ -482,7 +329,7 @@ module Addressable
482
329
 
483
330
  output[0..outlen].map { |x| x.chr }.join("").sub(/\0+\z/, "")
484
331
  end
485
- (class <<self; private :punycode_encode; end)
332
+ private_class_method :punycode_encode
486
333
 
487
334
  def self.punycode_decode(punycode)
488
335
  input = []
@@ -604,22 +451,22 @@ module Addressable
604
451
 
605
452
  output.pack("U*")
606
453
  end
607
- (class <<self; private :punycode_decode; end)
454
+ private_class_method :punycode_decode
608
455
 
609
456
  def self.punycode_basic?(codepoint)
610
457
  codepoint < 0x80
611
458
  end
612
- (class <<self; private :punycode_basic?; end)
459
+ private_class_method :punycode_basic?
613
460
 
614
461
  def self.punycode_delimiter?(codepoint)
615
462
  codepoint == PUNYCODE_DELIMITER
616
463
  end
617
- (class <<self; private :punycode_delimiter?; end)
464
+ private_class_method :punycode_delimiter?
618
465
 
619
466
  def self.punycode_encode_digit(d)
620
467
  d + 22 + 75 * ((d < 26) ? 1 : 0)
621
468
  end
622
- (class <<self; private :punycode_encode_digit; end)
469
+ private_class_method :punycode_encode_digit
623
470
 
624
471
  # Returns the numeric value of a basic codepoint
625
472
  # (for use in representing integers) in the range 0 to
@@ -635,7 +482,7 @@ module Addressable
635
482
  PUNYCODE_BASE
636
483
  end
637
484
  end
638
- (class <<self; private :punycode_decode_digit; end)
485
+ private_class_method :punycode_decode_digit
639
486
 
640
487
  # Bias adaptation method
641
488
  def self.punycode_adapt(delta, numpoints, firsttime)
@@ -652,7 +499,7 @@ module Addressable
652
499
 
653
500
  k + (difference + 1) * delta / (delta + PUNYCODE_SKEW)
654
501
  end
655
- (class <<self; private :punycode_adapt; end)
502
+ private_class_method :punycode_adapt
656
503
  end
657
504
  # :startdoc:
658
505
  end
@@ -1,6 +1,7 @@
1
- # encoding:utf-8
1
+ # frozen_string_literal: true
2
+
2
3
  #--
3
- # Copyright (C) 2006-2011 Bob Aman
4
+ # Copyright (C) Bob Aman
4
5
  #
5
6
  # Licensed under the Apache License, Version 2.0 (the "License");
6
7
  # you may not use this file except in compliance with the License.