addressable 2.6.0 → 2.8.1

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
- 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