addressable 2.6.0 → 2.8.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: afa411655b3715e655e0cdca551d20df31b83491
4
- data.tar.gz: 0cd2871c45abb19f6b6238ad202856e7afb8619d
2
+ SHA256:
3
+ metadata.gz: 3ddda72232f6aef9f6f4311c2855f1b3fea9acc80f51c4e5e90bd23820b0d74e
4
+ data.tar.gz: 88f208cb2d73dec64663e6e3c1710dc08b188402937038fefce6a2d47debc97d
5
5
  SHA512:
6
- metadata.gz: 16274bd51d38c58b3712dbbdad1368417051937dbe33d74fa73951a39b71d824092c0ecd50005d467db9c914cc074fd0344282df2e23e1182c764b1a1da9750a
7
- data.tar.gz: c53ff1d0e09a5e3d997a13a464d50c45fd7d548326f94d3ad40dc97753ce3a47aad4804a62faea48b89775394538982e70ac22d7488fab8ee6594b6816d8ff28
6
+ metadata.gz: 4e1b0c83fc2f2e54cba6804f3840c8bb29f0d73259979d5bf678ebd5d32257b91585d9b71a780321427835d10f98b9c07969267878f0b032c53d031c30202a4c
7
+ data.tar.gz: 35abc3652c8ff92032411e4daad7133b7c4649aff4a1a25fe622cf1c9b661d56f096a1084392e053788baea79f551a9d4a448d16c9e61e23bf4d9692a6728bf3
data/CHANGELOG.md CHANGED
@@ -1,3 +1,38 @@
1
+ # Addressable 2.8.1
2
+ - refactor `Addressable::URI.normalize_path` to address linter offenses ([#430](https://github.com/sporkmonger/addressable/pull/430))
3
+ - remove redundant colon in `Addressable::URI::CharacterClasses::AUTHORITY` regex ([#438](https://github.com/sporkmonger/addressable/pull/438))
4
+ - update gemspec to reflect supported Ruby versions ([#466], [#464], [#463])
5
+ - compatibility w/ public_suffix 5.x ([#466], [#465], [#460])
6
+ - fixes "invalid byte sequence in UTF-8" exception when unencoding URLs containing non UTF-8 characters ([#459](https://github.com/sporkmonger/addressable/pull/459))
7
+ - `Ractor` compatibility ([#449](https://github.com/sporkmonger/addressable/pull/449))
8
+ - use the whole string instead of a single line for template match ([#431](https://github.com/sporkmonger/addressable/pull/431))
9
+ - force UTF-8 encoding only if needed ([#341](https://github.com/sporkmonger/addressable/pull/341))
10
+
11
+ [#460]: https://github.com/sporkmonger/addressable/pull/460
12
+ [#463]: https://github.com/sporkmonger/addressable/pull/463
13
+ [#464]: https://github.com/sporkmonger/addressable/pull/464
14
+ [#465]: https://github.com/sporkmonger/addressable/pull/465
15
+ [#466]: https://github.com/sporkmonger/addressable/pull/466
16
+
17
+ # Addressable 2.8.0
18
+ - fixes ReDoS vulnerability in Addressable::Template#match
19
+ - no longer replaces `+` with spaces in queries for non-http(s) schemes
20
+ - fixed encoding ipv6 literals
21
+ - the `:compacted` flag for `normalized_query` now dedupes parameters
22
+ - fix broken `escape_component` alias
23
+ - dropping support for Ruby 2.0 and 2.1
24
+ - adding Ruby 3.0 compatibility for development tasks
25
+ - drop support for `rack-mount` and remove Addressable::Template#generate
26
+ - performance improvements
27
+ - switch CI/CD to GitHub Actions
28
+
29
+ # Addressable 2.7.0
30
+ - added `:compacted` flag to `normalized_query`
31
+ - `heuristic_parse` handles `mailto:` more intuitively
32
+ - dropped explicit support for JRuby 9.0.5.0
33
+ - compatibility w/ public_suffix 4.x
34
+ - performance improvements
35
+
1
36
  # Addressable 2.6.0
2
37
  - added `tld=` method to allow assignment to the public suffix
3
38
  - most `heuristic_parse` patterns are now case-insensitive
data/Gemfile CHANGED
@@ -1,10 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  gemspec
4
6
 
5
7
  group :test do
6
- gem 'rspec', '~> 3.5'
7
- gem 'rspec-its', '~> 1.1'
8
+ gem 'rspec', '~> 3.8'
9
+ gem 'rspec-its', '~> 1.3'
10
+ end
11
+
12
+ group :coverage do
13
+ gem "coveralls", "> 0.7", require: false, platforms: :mri
14
+ gem "simplecov", require: false
8
15
  end
9
16
 
10
17
  group :development do
@@ -14,19 +21,10 @@ group :development do
14
21
  end
15
22
 
16
23
  group :test, :development do
17
- gem 'rake', '> 10.0', '< 12'
18
- gem 'simplecov', :require => false
19
- gem 'coveralls', :require => false, :platforms => [
20
- :ruby_20, :ruby_21, :ruby_22, :ruby_23
21
- ]
22
- # Used to test compatibility.
23
- gem 'rack-mount', git: 'https://github.com/sporkmonger/rack-mount.git', require: 'rack/mount'
24
-
25
- if RUBY_VERSION.start_with?('2.0', '2.1')
26
- gem 'rack', '< 2', :require => false
27
- else
28
- gem 'rack', :require => false
29
- end
24
+ gem 'memory_profiler'
25
+ gem "rake", ">= 12.3.3"
30
26
  end
31
27
 
32
- gem 'idn-ruby', :platform => [:mri_20, :mri_21, :mri_22, :mri_23, :mri_24]
28
+ unless ENV["IDNA_MODE"] == "pure"
29
+ gem "idn-ruby", platform: :mri
30
+ end
data/README.md CHANGED
@@ -7,21 +7,23 @@
7
7
  <dt>License</dt><dd>Apache 2.0</dd>
8
8
  </dl>
9
9
 
10
- [![Gem Version](http://img.shields.io/gem/dt/addressable.svg)][gem]
11
- [![Build Status](https://secure.travis-ci.org/sporkmonger/addressable.svg?branch=master)][travis]
10
+ [![Gem Version](https://img.shields.io/gem/dt/addressable.svg)][gem]
11
+ [![Build Status](https://github.com/sporkmonger/addressable/workflows/CI/badge.svg)][actions]
12
12
  [![Test Coverage Status](https://img.shields.io/coveralls/sporkmonger/addressable.svg)][coveralls]
13
- [![Documentation Coverage Status](http://inch-ci.org/github/sporkmonger/addressable.svg?branch=master)][inch]
13
+ [![Documentation Coverage Status](https://inch-ci.org/github/sporkmonger/addressable.svg?branch=master)][inch]
14
14
 
15
15
  [gem]: https://rubygems.org/gems/addressable
16
- [travis]: http://travis-ci.org/sporkmonger/addressable
16
+ [actions]: https://github.com/sporkmonger/addressable/actions
17
17
  [coveralls]: https://coveralls.io/r/sporkmonger/addressable
18
- [inch]: http://inch-ci.org/github/sporkmonger/addressable
18
+ [inch]: https://inch-ci.org/github/sporkmonger/addressable
19
19
 
20
20
  # Description
21
21
 
22
- Addressable is a replacement for the URI implementation that is part of
23
- Ruby's standard library. It more closely conforms to RFC 3986, RFC 3987, and
24
- RFC 6570 (level 4), providing support for IRIs and URI templates.
22
+ Addressable is an alternative implementation to the URI implementation
23
+ that is part of Ruby's standard library. It is flexible, offers heuristic
24
+ parsing, and additionally provides extensive support for IRIs and URI templates.
25
+
26
+ Addressable closely conforms to RFC 3986, RFC 3987, and RFC 6570 (level 4).
25
27
 
26
28
  # Reference
27
29
 
@@ -96,7 +98,7 @@ You may optionally turn on native IDN support by installing libidn and the
96
98
  idn gem:
97
99
 
98
100
  ```console
99
- $ sudo apt-get install idn # Debian/Ubuntu
101
+ $ sudo apt-get install libidn11-dev # Debian/Ubuntu
100
102
  $ brew install libidn # OS X
101
103
  $ gem install idn-ruby
102
104
  ```
@@ -108,7 +110,7 @@ dependency using a pessimistic version constraint covering the major and minor
108
110
  values:
109
111
 
110
112
  ```ruby
111
- spec.add_dependency 'addressable', '~> 2.5'
113
+ spec.add_dependency 'addressable', '~> 2.7'
112
114
  ```
113
115
 
114
116
  If you need a specific bug fix, you can also specify minimum tiny versions
data/Rakefile CHANGED
@@ -14,9 +14,9 @@ RELEASE_NAME = "REL #{PKG_VERSION}"
14
14
 
15
15
  PKG_SUMMARY = "URI Implementation"
16
16
  PKG_DESCRIPTION = <<-TEXT
17
- Addressable is a replacement for the URI implementation that is part of
18
- Ruby's standard library. It more closely conforms to the relevant RFCs and
19
- adds support for IRIs and URI templates.
17
+ Addressable is an alternative implementation to the URI implementation that is
18
+ part of Ruby's standard library. It is flexible, offers heuristic parsing, and
19
+ additionally provides extensive support for IRIs and URI templates.
20
20
  TEXT
21
21
 
22
22
  PKG_FILES = FileList[
@@ -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
  #
@@ -135,7 +134,7 @@ module Addressable
135
134
  unpacked.map! { |codepoint| lookup_unicode_lowercase(codepoint) }
136
135
  return unpacked.pack("U*")
137
136
  end
138
- (class <<self; private :unicode_downcase; end)
137
+ private_class_method :unicode_downcase
139
138
 
140
139
  def self.unicode_compose(unpacked)
141
140
  unpacked_result = []
@@ -160,7 +159,7 @@ module Addressable
160
159
  unpacked_result << starter
161
160
  return unpacked_result
162
161
  end
163
- (class <<self; private :unicode_compose; end)
162
+ private_class_method :unicode_compose
164
163
 
165
164
  def self.unicode_compose_pair(ch_one, ch_two)
166
165
  if ch_one >= HANGUL_LBASE && ch_one < HANGUL_LBASE + HANGUL_LCOUNT &&
@@ -178,43 +177,45 @@ module Addressable
178
177
  end
179
178
 
180
179
  p = []
181
- ucs4_to_utf8 = lambda do |ch|
182
- if ch < 128
183
- p << ch
184
- elsif ch < 2048
185
- p << (ch >> 6 | 192)
186
- p << (ch & 63 | 128)
187
- elsif ch < 0x10000
188
- p << (ch >> 12 | 224)
189
- p << (ch >> 6 & 63 | 128)
190
- p << (ch & 63 | 128)
191
- elsif ch < 0x200000
192
- p << (ch >> 18 | 240)
193
- p << (ch >> 12 & 63 | 128)
194
- p << (ch >> 6 & 63 | 128)
195
- p << (ch & 63 | 128)
196
- elsif ch < 0x4000000
197
- p << (ch >> 24 | 248)
198
- p << (ch >> 18 & 63 | 128)
199
- p << (ch >> 12 & 63 | 128)
200
- p << (ch >> 6 & 63 | 128)
201
- p << (ch & 63 | 128)
202
- elsif ch < 0x80000000
203
- p << (ch >> 30 | 252)
204
- p << (ch >> 24 & 63 | 128)
205
- p << (ch >> 18 & 63 | 128)
206
- p << (ch >> 12 & 63 | 128)
207
- p << (ch >> 6 & 63 | 128)
208
- p << (ch & 63 | 128)
209
- end
210
- end
211
180
 
212
- ucs4_to_utf8.call(ch_one)
213
- ucs4_to_utf8.call(ch_two)
181
+ ucs4_to_utf8(ch_one, p)
182
+ ucs4_to_utf8(ch_two, p)
214
183
 
215
184
  return lookup_unicode_composition(p)
216
185
  end
217
- (class <<self; private :unicode_compose_pair; end)
186
+ private_class_method :unicode_compose_pair
187
+
188
+ def self.ucs4_to_utf8(char, buffer)
189
+ if char < 128
190
+ buffer << char
191
+ elsif char < 2048
192
+ buffer << (char >> 6 | 192)
193
+ buffer << (char & 63 | 128)
194
+ elsif char < 0x10000
195
+ buffer << (char >> 12 | 224)
196
+ buffer << (char >> 6 & 63 | 128)
197
+ buffer << (char & 63 | 128)
198
+ elsif char < 0x200000
199
+ buffer << (char >> 18 | 240)
200
+ buffer << (char >> 12 & 63 | 128)
201
+ buffer << (char >> 6 & 63 | 128)
202
+ buffer << (char & 63 | 128)
203
+ elsif char < 0x4000000
204
+ buffer << (char >> 24 | 248)
205
+ buffer << (char >> 18 & 63 | 128)
206
+ buffer << (char >> 12 & 63 | 128)
207
+ buffer << (char >> 6 & 63 | 128)
208
+ buffer << (char & 63 | 128)
209
+ elsif char < 0x80000000
210
+ buffer << (char >> 30 | 252)
211
+ buffer << (char >> 24 & 63 | 128)
212
+ buffer << (char >> 18 & 63 | 128)
213
+ buffer << (char >> 12 & 63 | 128)
214
+ buffer << (char >> 6 & 63 | 128)
215
+ buffer << (char & 63 | 128)
216
+ end
217
+ end
218
+ private_class_method :ucs4_to_utf8
218
219
 
219
220
  def self.unicode_sort_canonical(unpacked)
220
221
  unpacked = unpacked.dup
@@ -238,7 +239,7 @@ module Addressable
238
239
  end
239
240
  return unpacked
240
241
  end
241
- (class <<self; private :unicode_sort_canonical; end)
242
+ private_class_method :unicode_sort_canonical
242
243
 
243
244
  def self.unicode_decompose(unpacked)
244
245
  unpacked_result = []
@@ -259,7 +260,7 @@ module Addressable
259
260
  end
260
261
  return unpacked_result
261
262
  end
262
- (class <<self; private :unicode_decompose; end)
263
+ private_class_method :unicode_decompose
263
264
 
264
265
  def self.unicode_decompose_hangul(codepoint)
265
266
  sindex = codepoint - HANGUL_SBASE;
@@ -276,7 +277,7 @@ module Addressable
276
277
  end
277
278
  return l, v, t
278
279
  end
279
- (class <<self; private :unicode_decompose_hangul; end)
280
+ private_class_method :unicode_decompose_hangul
280
281
 
281
282
  def self.lookup_unicode_combining_class(codepoint)
282
283
  codepoint_data = UNICODE_DATA[codepoint]
@@ -284,14 +285,14 @@ module Addressable
284
285
  (codepoint_data[UNICODE_DATA_COMBINING_CLASS] || 0) :
285
286
  0)
286
287
  end
287
- (class <<self; private :lookup_unicode_combining_class; end)
288
+ private_class_method :lookup_unicode_combining_class
288
289
 
289
290
  def self.lookup_unicode_compatibility(codepoint)
290
291
  codepoint_data = UNICODE_DATA[codepoint]
291
292
  (codepoint_data ?
292
293
  codepoint_data[UNICODE_DATA_COMPATIBILITY] : nil)
293
294
  end
294
- (class <<self; private :lookup_unicode_compatibility; end)
295
+ private_class_method :lookup_unicode_compatibility
295
296
 
296
297
  def self.lookup_unicode_lowercase(codepoint)
297
298
  codepoint_data = UNICODE_DATA[codepoint]
@@ -299,12 +300,12 @@ module Addressable
299
300
  (codepoint_data[UNICODE_DATA_LOWERCASE] || codepoint) :
300
301
  codepoint)
301
302
  end
302
- (class <<self; private :lookup_unicode_lowercase; end)
303
+ private_class_method :lookup_unicode_lowercase
303
304
 
304
305
  def self.lookup_unicode_composition(unpacked)
305
306
  return COMPOSITION_TABLE[unpacked]
306
307
  end
307
- (class <<self; private :lookup_unicode_composition; end)
308
+ private_class_method :lookup_unicode_composition
308
309
 
309
310
  HANGUL_SBASE = 0xac00
310
311
  HANGUL_LBASE = 0x1100
@@ -341,7 +342,7 @@ module Addressable
341
342
  end
342
343
 
343
344
  COMPOSITION_TABLE = {}
344
- for codepoint, data in UNICODE_DATA
345
+ UNICODE_DATA.each do |codepoint, data|
345
346
  canonical = data[UNICODE_DATA_CANONICAL]
346
347
  exclusion = data[UNICODE_DATA_EXCLUSION]
347
348
 
@@ -500,7 +501,7 @@ module Addressable
500
501
 
501
502
  output[0..outlen].map { |x| x.chr }.join("").sub(/\0+\z/, "")
502
503
  end
503
- (class <<self; private :punycode_encode; end)
504
+ private_class_method :punycode_encode
504
505
 
505
506
  def self.punycode_decode(punycode)
506
507
  input = []
@@ -622,22 +623,22 @@ module Addressable
622
623
 
623
624
  output.pack("U*")
624
625
  end
625
- (class <<self; private :punycode_decode; end)
626
+ private_class_method :punycode_decode
626
627
 
627
628
  def self.punycode_basic?(codepoint)
628
629
  codepoint < 0x80
629
630
  end
630
- (class <<self; private :punycode_basic?; end)
631
+ private_class_method :punycode_basic?
631
632
 
632
633
  def self.punycode_delimiter?(codepoint)
633
634
  codepoint == PUNYCODE_DELIMITER
634
635
  end
635
- (class <<self; private :punycode_delimiter?; end)
636
+ private_class_method :punycode_delimiter?
636
637
 
637
638
  def self.punycode_encode_digit(d)
638
639
  d + 22 + 75 * ((d < 26) ? 1 : 0)
639
640
  end
640
- (class <<self; private :punycode_encode_digit; end)
641
+ private_class_method :punycode_encode_digit
641
642
 
642
643
  # Returns the numeric value of a basic codepoint
643
644
  # (for use in representing integers) in the range 0 to
@@ -653,7 +654,7 @@ module Addressable
653
654
  PUNYCODE_BASE
654
655
  end
655
656
  end
656
- (class <<self; private :punycode_decode_digit; end)
657
+ private_class_method :punycode_decode_digit
657
658
 
658
659
  # Bias adaptation method
659
660
  def self.punycode_adapt(delta, numpoints, firsttime)
@@ -670,7 +671,7 @@ module Addressable
670
671
 
671
672
  k + (difference + 1) * delta / (delta + PUNYCODE_SKEW)
672
673
  end
673
- (class <<self; private :punycode_adapt; end)
674
+ private_class_method :punycode_adapt
674
675
  end
675
676
  # :startdoc:
676
677
  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
  #
@@ -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
  #
@@ -37,7 +36,7 @@ module Addressable
37
36
  Addressable::URI::CharacterClasses::DIGIT + '_'
38
37
 
39
38
  var_char =
40
- "(?:(?:[#{variable_char_class}]|%[a-fA-F0-9][a-fA-F0-9])+)"
39
+ "(?>(?:[#{variable_char_class}]|%[a-fA-F0-9][a-fA-F0-9])+)"
41
40
  RESERVED =
42
41
  "(?:[#{anything}]|%[a-fA-F0-9][a-fA-F0-9])"
43
42
  UNRESERVED =
@@ -412,7 +411,7 @@ module Addressable
412
411
  # match.captures
413
412
  # #=> ["a", ["b", "c"]]
414
413
  def match(uri, processor=nil)
415
- uri = Addressable::URI.parse(uri)
414
+ uri = Addressable::URI.parse(uri) unless uri.is_a?(Addressable::URI)
416
415
  mapping = {}
417
416
 
418
417
  # First, we need to process the pattern, and extract the values.
@@ -653,50 +652,16 @@ module Addressable
653
652
  self.to_regexp.named_captures
654
653
  end
655
654
 
656
- ##
657
- # Generates a route result for a given set of parameters.
658
- # Should only be used by rack-mount.
659
- #
660
- # @param params [Hash] The set of parameters used to expand the template.
661
- # @param recall [Hash] Default parameters used to expand the template.
662
- # @param options [Hash] Either a `:processor` or a `:parameterize` block.
663
- #
664
- # @api private
665
- def generate(params={}, recall={}, options={})
666
- merged = recall.merge(params)
667
- if options[:processor]
668
- processor = options[:processor]
669
- elsif options[:parameterize]
670
- # TODO: This is sending me into fits trying to shoe-horn this into
671
- # the existing API. I think I've got this backwards and processors
672
- # should be a set of 4 optional blocks named :validate, :transform,
673
- # :match, and :restore. Having to use a singleton here is a huge
674
- # code smell.
675
- processor = Object.new
676
- class <<processor
677
- attr_accessor :block
678
- def transform(name, value)
679
- block.call(name, value)
680
- end
681
- end
682
- processor.block = options[:parameterize]
683
- else
684
- processor = nil
685
- end
686
- result = self.expand(merged, processor)
687
- result.to_s if result
688
- end
689
-
690
655
  private
691
656
  def ordered_variable_defaults
692
657
  @ordered_variable_defaults ||= begin
693
658
  expansions, _ = parse_template_pattern(pattern)
694
- expansions.map do |capture|
659
+ expansions.flat_map do |capture|
695
660
  _, _, varlist = *capture.match(EXPRESSION)
696
661
  varlist.split(',').map do |varspec|
697
662
  varspec[VARSPEC, 1]
698
663
  end
699
- end.flatten
664
+ end
700
665
  end
701
666
  end
702
667
 
@@ -973,15 +938,35 @@ module Addressable
973
938
  end
974
939
  end
975
940
 
941
+ ##
942
+ # Generates the <tt>Regexp</tt> that parses a template pattern. Memoizes the
943
+ # value if template processor not set (processors may not be deterministic)
944
+ #
945
+ # @param [String] pattern The URI template pattern.
946
+ # @param [#match] processor The template processor to use.
947
+ #
948
+ # @return [Array, Regexp]
949
+ # An array of expansion variables nad a regular expression which may be
950
+ # used to parse a template pattern
951
+ def parse_template_pattern(pattern, processor = nil)
952
+ if processor.nil? && pattern == @pattern
953
+ @cached_template_parse ||=
954
+ parse_new_template_pattern(pattern, processor)
955
+ else
956
+ parse_new_template_pattern(pattern, processor)
957
+ end
958
+ end
959
+
976
960
  ##
977
961
  # Generates the <tt>Regexp</tt> that parses a template pattern.
978
962
  #
979
963
  # @param [String] pattern The URI template pattern.
980
964
  # @param [#match] processor The template processor to use.
981
965
  #
982
- # @return [Regexp]
983
- # A regular expression which may be used to parse a template pattern.
984
- def parse_template_pattern(pattern, processor=nil)
966
+ # @return [Array, Regexp]
967
+ # An array of expansion variables nad a regular expression which may be
968
+ # used to parse a template pattern
969
+ def parse_new_template_pattern(pattern, processor = nil)
985
970
  # Escape the pattern. The two gsubs restore the escaped curly braces
986
971
  # back to their original form. Basically, escape everything that isn't
987
972
  # within an expansion.
@@ -1037,7 +1022,7 @@ module Addressable
1037
1022
  end
1038
1023
 
1039
1024
  # Ensure that the regular expression matches the whole URI.
1040
- regexp_string = "^#{regexp_string}$"
1025
+ regexp_string = "\\A#{regexp_string}\\z"
1041
1026
  return expansions, Regexp.new(regexp_string)
1042
1027
  end
1043
1028