roda 3.43.1 → 3.44.0

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: 95c0306a50aefb2cfa3bd700403ff2d8441acb78438dcca36bdb0341708208fe
4
- data.tar.gz: df524e11cab19b33d6f4e2a139f2813b89dc0832863aa2e0ac70c69cc4f98e68
3
+ metadata.gz: b60182ef0483279ac1d1983495ba020c1803d6c1fe0fa84af882142f816f72bc
4
+ data.tar.gz: 20f6053b7c73fed454dc3f39e55a516d7a5461a4005356b5788480b8aab36f14
5
5
  SHA512:
6
- metadata.gz: dc0c531cdc7d9ae5d122cae6394b49ebd9014811c6dfba64ef70bc2b4ffe03d66efe2a10dd11f180a1c68db15a7bf3e048f8fdd8550fa72584d2190d8b3d59ea
7
- data.tar.gz: 3f42b2dd764cae91a0b81f43933c230b5795f29f33aebf18a7cbfd800071dfdb9ce29f80b471747105e6caa524571877f207cffde621fdaf3d04b89d5c295f8e
6
+ metadata.gz: 89359f0c972c236bee671606fc7254f4999c6fc03f1b0ef8ff7c9691b581b6e796197b9fbee6fd109ae4d1026624f041d2e64c6182dbf8c80818756543923c9d
7
+ data.tar.gz: 2d786d8641f5195a65874f3326abe07057748e4de2df7d0a8e8cd9439b6afceb08e65b6a3733e15b0289e273cc070033c1dc466e1909880410b4d05541fa04ae
data/CHANGELOG CHANGED
@@ -1,3 +1,9 @@
1
+ = 3.44.0 (2021-05-12)
2
+
3
+ * Add optimized_segment_matchers plugin for optimized matchers for a single String class argument (jeremyevans)
4
+
5
+ * Use RFC 5987 UTF-8 and ISO-8859-1 encoded filenames when using send_file and attachment in the sinatra_helpers plugin (jeremyevans)
6
+
1
7
  = 3.43.1 (2021-04-13)
2
8
 
3
9
  * [SECURITY] Fix issue where loading content_security_policy plugin after default_headers plugin had no effect (jeremyevans)
@@ -0,0 +1,23 @@
1
+ = New Features
2
+
3
+ * An optimized_segment_matchers plugin has been added that offers
4
+ very fast matchers for arbitrary segments (the same segments
5
+ that would be matched by the String class matcher). The
6
+ on_segment method it offers accepts no arguments and yields
7
+ the next segment if there is a segment. The is_segment method
8
+ is similar, but only yields if the next segment is the final
9
+ segment.
10
+
11
+ = Other Improvements
12
+
13
+ * The send_file and attachment methods in the sinatra_helpers plugin
14
+ now support RFC 5987 UTF-8 and ISO-8859-1 encoded filenames,
15
+ allowing modern browsers to save files with encoded chracters. For
16
+ older browsers that do not support RFC 5987, unsupported characters
17
+ in filenames are replaced with dashes. This is considered to be an
18
+ improvement over the previous behavior of using Ruby's inspect
19
+ output for the filename, which could contain backslashes (backslash
20
+ is not an allowed chracter in Windows filenames).
21
+
22
+ * The performance of the String class matcher has been slightly
23
+ improved.
@@ -0,0 +1,53 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The optimized_segment_matchers plugin adds two optimized matcher methods,
7
+ # +r.on_segment+ and +r.is_segment+. +r.on_segment+ is an optimized version of
8
+ # +r.on String+ that accepts no arguments and yields the next segment if there
9
+ # is a segment. +r.is_segment+ is an optimized version of +r.is String+ that accepts
10
+ # no arguments and yields the next segment only if it is the last segment.
11
+ #
12
+ # plugin :optimized_segment_matchers
13
+ #
14
+ # route do |r|
15
+ # r.on_segment do |x|
16
+ # # matches any segment (e.g. /a, /b, but not /)
17
+ # r.is_segment do |y|
18
+ # # matches only if final segment (e.g. /a/b, /b/c, but not /c, /c/d/, /c/d/e)
19
+ # end
20
+ # end
21
+ # end
22
+ module OptimizedSegmentMatchers
23
+ module RequestMethods
24
+ # Optimized version of +r.on String+ that yields the next segment if there
25
+ # is a segment.
26
+ def on_segment
27
+ rp = @remaining_path
28
+ if rp.getbyte(0) == 47
29
+ if last = rp.index('/', 1)
30
+ @remaining_path = rp[last, rp.length]
31
+ always{yield rp[1, last-1]}
32
+ elsif (len = rp.length) > 1
33
+ @remaining_path = ""
34
+ always{yield rp[1, len]}
35
+ end
36
+ end
37
+ end
38
+
39
+ # Optimized version of +r.is String+ that yields the next segment only if it
40
+ # is the final segment.
41
+ def is_segment
42
+ rp = @remaining_path
43
+ if rp.getbyte(0) == 47 && !rp.index('/', 1) && (len = rp.length) > 1
44
+ @remaining_path = ""
45
+ always{yield rp[1, len]}
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ register_plugin(:optimized_segment_matchers, OptimizedSegmentMatchers)
52
+ end
53
+ end
@@ -19,7 +19,8 @@ class Roda
19
19
  # end
20
20
  # end
21
21
  #
22
- # Note that both of these methods only work with plain strings, not
22
+ # If you are using the placeholder_string_matchers plugin, note
23
+ # that both of these methods only work with plain strings, not
23
24
  # with strings with embedded colons for capturing. Matching will work
24
25
  # correctly in such cases, but the captures will not be yielded to the
25
26
  # match blocks.
@@ -211,6 +211,10 @@ class Roda
211
211
  # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
212
212
  # OTHER DEALINGS IN THE SOFTWARE.
213
213
  module SinatraHelpers
214
+ UTF8_ENCODING = Encoding.find('UTF-8')
215
+ ISO88591_ENCODING = Encoding.find('ISO-8859-1')
216
+ BINARY_ENCODING = Encoding.find('BINARY')
217
+
214
218
  # Depend on the status_303 plugin.
215
219
  def self.load_dependencies(app, _opts = nil)
216
220
  app.plugin :status_303
@@ -432,7 +436,25 @@ class Roda
432
436
  # instructing the user agents to prompt to save.
433
437
  def attachment(filename = nil, disposition='attachment')
434
438
  if filename
435
- params = "; filename=#{File.basename(filename).inspect}"
439
+ param_filename = File.basename(filename)
440
+ encoding = param_filename.encoding
441
+
442
+ needs_encoding = param_filename.gsub!(/[^ 0-9a-zA-Z!\#$&\+\.\^_`\|~]+/, '-')
443
+ params = "; filename=#{param_filename.inspect}"
444
+
445
+ if needs_encoding && (encoding == UTF8_ENCODING || encoding == ISO88591_ENCODING)
446
+ # File name contains non attr-char characters from RFC 5987 Section 3.2.1
447
+
448
+ encoded_filename = File.basename(filename).force_encoding(BINARY_ENCODING)
449
+ # Similar regexp as above, but treat each byte separately, and encode
450
+ # space characters, since those aren't allowed in attr-char
451
+ encoded_filename.gsub!(/[^0-9a-zA-Z!\#$&\+\.\^_`\|~]/) do |c|
452
+ "%%%X" % c.ord
453
+ end
454
+
455
+ encoded_params = "; filename*=#{encoding.to_s}''#{encoded_filename}"
456
+ end
457
+
436
458
  unless @headers["Content-Type"]
437
459
  ext = File.extname(filename)
438
460
  unless ext.empty?
@@ -440,7 +462,7 @@ class Roda
440
462
  end
441
463
  end
442
464
  end
443
- @headers["Content-Disposition"] = "#{disposition}#{params}"
465
+ @headers["Content-Disposition"] = "#{disposition}#{params}#{encoded_params}"
444
466
  end
445
467
 
446
468
  # Whether or not the status is set to 1xx. Returns nil if status not yet set.
data/lib/roda/request.rb CHANGED
@@ -468,8 +468,8 @@ class Roda
468
468
  if last = rp.index('/', 1)
469
469
  @captures << rp[1, last-1]
470
470
  @remaining_path = rp[last, rp.length]
471
- elsif rp.length > 1
472
- @captures << rp[1,rp.length]
471
+ elsif (len = rp.length) > 1
472
+ @captures << rp[1, len]
473
473
  @remaining_path = ""
474
474
  end
475
475
  end
data/lib/roda/version.rb CHANGED
@@ -4,11 +4,11 @@ class Roda
4
4
  RodaMajorVersion = 3
5
5
 
6
6
  # The minor version of Roda, updated for new feature releases of Roda.
7
- RodaMinorVersion = 43
7
+ RodaMinorVersion = 44
8
8
 
9
9
  # The patch version of Roda, updated only for bug fixes from the last
10
10
  # feature release.
11
- RodaPatchVersion = 1
11
+ RodaPatchVersion = 0
12
12
 
13
13
  # The full version of Roda as a string.
14
14
  RodaVersion = "#{RodaMajorVersion}.#{RodaMinorVersion}.#{RodaPatchVersion}".freeze
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: roda
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.43.1
4
+ version: 3.44.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Evans
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-13 00:00:00.000000000 Z
11
+ date: 2021-05-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -214,6 +214,7 @@ extra_rdoc_files:
214
214
  - doc/release_notes/3.41.0.txt
215
215
  - doc/release_notes/3.42.0.txt
216
216
  - doc/release_notes/3.43.0.txt
217
+ - doc/release_notes/3.44.0.txt
217
218
  - doc/release_notes/3.5.0.txt
218
219
  - doc/release_notes/3.6.0.txt
219
220
  - doc/release_notes/3.7.0.txt
@@ -264,6 +265,7 @@ files:
264
265
  - doc/release_notes/3.41.0.txt
265
266
  - doc/release_notes/3.42.0.txt
266
267
  - doc/release_notes/3.43.0.txt
268
+ - doc/release_notes/3.44.0.txt
267
269
  - doc/release_notes/3.5.0.txt
268
270
  - doc/release_notes/3.6.0.txt
269
271
  - doc/release_notes/3.7.0.txt
@@ -333,6 +335,7 @@ files:
333
335
  - lib/roda/plugins/named_templates.rb
334
336
  - lib/roda/plugins/not_allowed.rb
335
337
  - lib/roda/plugins/not_found.rb
338
+ - lib/roda/plugins/optimized_segment_matchers.rb
336
339
  - lib/roda/plugins/optimized_string_matchers.rb
337
340
  - lib/roda/plugins/padrino_render.rb
338
341
  - lib/roda/plugins/param_matchers.rb