sinatra 1.4.6 → 1.4.7

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sinatra might be problematic. Click here for more details.

data/Rakefile CHANGED
@@ -182,8 +182,8 @@ if defined?(Gem)
182
182
  end
183
183
 
184
184
  task 'release' => ['test', package('.gem')] do
185
- if File.binread("CHANGES") =~ /= \d\.\d\.\d . not yet released$/i
186
- fail 'please update changes first' unless %x{git symbolic-ref HEAD} == "refs/heads/prerelease\n"
185
+ if File.binread("CHANGELOG.md") =~ /= \d\.\d\.\d . not yet released$/i
186
+ fail 'please update the changelog first' unless %x{git symbolic-ref HEAD} == "refs/heads/prerelease\n"
187
187
  end
188
188
 
189
189
  sh <<-SH
@@ -10,6 +10,7 @@ require 'uri'
10
10
 
11
11
  # other files we need
12
12
  require 'sinatra/show_exceptions'
13
+ require 'sinatra/ext'
13
14
  require 'sinatra/version'
14
15
 
15
16
  module Sinatra
@@ -1034,7 +1035,7 @@ module Sinatra
1034
1035
  # a matching file is found, returns nil otherwise.
1035
1036
  def static!(options = {})
1036
1037
  return if (public_dir = settings.public_folder).nil?
1037
- path = File.expand_path("#{public_dir}#{unescape(request.path_info)}" )
1038
+ path = File.expand_path("#{public_dir}#{URI_INSTANCE.unescape(request.path_info)}" )
1038
1039
  return unless File.file?(path)
1039
1040
 
1040
1041
  env['sinatra.static_file'] = path
@@ -1617,25 +1618,21 @@ module Sinatra
1617
1618
  if path.respond_to? :to_str
1618
1619
  keys = []
1619
1620
 
1620
- # We append a / at the end if there was one.
1621
- # Reason: Splitting does not split off an empty
1622
- # string at the end if the split separator
1623
- # is at the end.
1624
- #
1625
- postfix = '/' if path =~ /\/\z/
1626
-
1627
1621
  # Split the path into pieces in between forward slashes.
1622
+ # A negative number is given as the second argument of path.split
1623
+ # because with this number, the method does not ignore / at the end
1624
+ # and appends an empty string at the end of the return value.
1628
1625
  #
1629
- segments = path.split('/').map! do |segment|
1626
+ segments = path.split('/', -1).map! do |segment|
1630
1627
  ignore = []
1631
1628
 
1632
1629
  # Special character handling.
1633
1630
  #
1634
- pattern = segment.to_str.gsub(/[^\?\%\\\/\:\*\w]/) do |c|
1631
+ pattern = segment.to_str.gsub(/[^\?\%\\\/\:\*\w]|:(?!\w)/) do |c|
1635
1632
  ignore << escaped(c).join if c.match(/[\.@]/)
1636
1633
  patt = encoded(c)
1637
1634
  patt.gsub(/%[\da-fA-F]{2}/) do |match|
1638
- match.split(//).map! {|char| char =~ /[A-Z]/ ? "[#{char}#{char.tr('A-Z', 'a-z')}]" : char}.join
1635
+ match.split(//).map! { |char| char == char.downcase ? char : "[#{char}#{char.downcase}]" }.join
1639
1636
  end
1640
1637
  end
1641
1638
 
@@ -1658,16 +1655,12 @@ module Sinatra
1658
1655
 
1659
1656
  # Special case handling.
1660
1657
  #
1661
- if segment = segments.pop
1662
- if segment.match(/\[\^\\\./)
1663
- parts = segment.rpartition(/\[\^\\\./)
1664
- parts[1] = '[^'
1665
- segments << parts.join
1666
- else
1667
- segments << segment
1668
- end
1658
+ if last_segment = segments[-1] and last_segment.match(/\[\^\\\./)
1659
+ parts = last_segment.rpartition(/\[\^\\\./)
1660
+ parts[1] = '[^'
1661
+ segments[-1] = parts.join
1669
1662
  end
1670
- [/\A#{segments.join('/')}#{postfix}\z/, keys]
1663
+ [/\A#{segments.join('/')}\z/, keys]
1671
1664
  elsif path.respond_to?(:keys) && path.respond_to?(:match)
1672
1665
  [path, path.keys]
1673
1666
  elsif path.respond_to?(:names) && path.respond_to?(:match)
@@ -1698,10 +1691,7 @@ module Sinatra
1698
1691
  end
1699
1692
  unsafe_patterns = unsafe_ignore.map! do |unsafe|
1700
1693
  chars = unsafe.split(//).map! do |char|
1701
- if char =~ /[A-Z]/
1702
- char <<= char.tr('A-Z', 'a-z')
1703
- end
1704
- char
1694
+ char == char.downcase ? char : char + char.downcase
1705
1695
  end
1706
1696
 
1707
1697
  "|(?:%[^#{chars[0]}].|%[#{chars[0]}][^#{chars[1]}])"
@@ -1776,6 +1766,8 @@ module Sinatra
1776
1766
  begin
1777
1767
  return Rack::Handler.get(server_name.to_s)
1778
1768
  rescue LoadError, NameError
1769
+ rescue ArgumentError
1770
+ Sinatra::Ext.get_handler(server_name.to_s)
1779
1771
  end
1780
1772
  end
1781
1773
  fail "Server handler (#{servers.join(',')}) not found."
@@ -0,0 +1,17 @@
1
+ # This can be removed once rack/rack@2fd9df71 is released
2
+ module Sinatra
3
+ module Ext
4
+ def self.get_handler(str)
5
+ begin
6
+ ::Object.const_get("Object", false)
7
+ def self._const_get(str, inherit = true)
8
+ Rack::Handler.const_get(str, inherit)
9
+ end
10
+ rescue
11
+ def self._const_get(str, inherit = true)
12
+ Rack::Handler.const_get(str)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,4 +1,8 @@
1
- require 'rack/showexceptions'
1
+ begin
2
+ require 'rack/show_exceptions'
3
+ rescue LoadError
4
+ require 'rack/showexceptions'
5
+ end
2
6
 
3
7
  module Sinatra
4
8
  # Sinatra::ShowExceptions catches all exceptions raised from the app it
@@ -24,23 +28,25 @@ module Sinatra
24
28
 
25
29
  if prefers_plain_text?(env)
26
30
  content_type = "text/plain"
27
- exception_string = dump_exception(e)
31
+ exception = dump_exception(e)
28
32
  else
29
33
  content_type = "text/html"
30
- exception_string = pretty(env, e)
34
+ exception = pretty(env, e)
31
35
  end
32
36
 
33
37
  env["rack.errors"] = errors
34
38
 
35
39
  # Post 893a2c50 in rack/rack, the #pretty method above, implemented in
36
40
  # Rack::ShowExceptions, returns a String instead of an array.
37
- body = Array(exception_string)
41
+ body = Array(exception)
38
42
 
39
43
  [
40
44
  500,
41
- {"Content-Type" => content_type,
42
- "Content-Length" => Rack::Utils.bytesize(body.join).to_s},
43
- body
45
+ {
46
+ "Content-Type" => content_type,
47
+ "Content-Length" => Rack::Utils.bytesize(body.join).to_s
48
+ },
49
+ body
44
50
  ]
45
51
  end
46
52
 
@@ -1,3 +1,3 @@
1
1
  module Sinatra
2
- VERSION = '1.4.6'
2
+ VERSION = '1.4.7'
3
3
  end
@@ -13,7 +13,7 @@ Gem::Specification.new 'sinatra', Sinatra::VERSION do |s|
13
13
  s.extra_rdoc_files = s.files.select { |p| p =~ /^README/ } << 'LICENSE'
14
14
  s.rdoc_options = %w[--line-numbers --inline-source --title Sinatra --main README.rdoc --encoding=UTF-8]
15
15
 
16
- s.add_dependency 'rack', '~> 1.4'
16
+ s.add_dependency 'rack', '~> 1.5'
17
17
  s.add_dependency 'tilt', '>= 1.3', '< 3'
18
18
  s.add_dependency 'rack-protection', '~> 1.4'
19
19
  end
@@ -0,0 +1 @@
1
+ This is a test intended for the + sign in urls for static serving
@@ -99,6 +99,50 @@ class RoutingTest < Minitest::Test
99
99
  assert_body "foo/bar"
100
100
  end
101
101
 
102
+ it "it handles encoded colons correctly" do
103
+ mock_app {
104
+ get("/:") { 'a' }
105
+ get("/a/:") { 'b' }
106
+ get("/a/:/b") { 'c' }
107
+ get("/a/b:") { 'd' }
108
+ get("/a/b: ") { 'e' }
109
+ }
110
+ get '/:'
111
+ assert_equal 200, status
112
+ assert_body "a"
113
+ get '/%3a'
114
+ assert_equal 200, status
115
+ assert_body "a"
116
+
117
+ get '/a/:'
118
+ assert_equal 200, status
119
+ assert_body "b"
120
+ get '/a/%3a'
121
+ assert_equal 200, status
122
+ assert_body "b"
123
+
124
+ get '/a/:/b'
125
+ assert_equal 200, status
126
+ assert_body "c"
127
+ get '/a/%3A/b'
128
+ assert_equal 200, status
129
+ assert_body "c"
130
+
131
+ get '/a/b:'
132
+ assert_equal 200, status
133
+ assert_body "d"
134
+ get '/a/b%3a'
135
+ assert_equal 200, status
136
+ assert_body "d"
137
+
138
+ get '/a/b%3a%20'
139
+ assert_equal 200, status
140
+ assert_body "e"
141
+ get '/a/b%3a+'
142
+ assert_equal 200, status
143
+ assert_body "e"
144
+ end
145
+
102
146
  it "overrides the content-type in error handlers" do
103
147
  mock_app {
104
148
  before { content_type 'text/plain' }
@@ -233,4 +233,34 @@ class StaticTest < Minitest::Test
233
233
  assert response.headers.include?('Last-Modified')
234
234
  end
235
235
 
236
+ it 'serves files with a + sign in the path' do
237
+ mock_app do
238
+ set :static, true
239
+ set :public_folder, File.join(File.dirname(__FILE__), 'public')
240
+ end
241
+
242
+ get "/hello+world.txt"
243
+
244
+ real_path = File.join(File.dirname(__FILE__), 'public', 'hello+world.txt')
245
+ assert ok?
246
+ assert_equal File.read(real_path), body
247
+ assert_equal File.size(real_path).to_s, response['Content-Length']
248
+ assert response.headers.include?('Last-Modified')
249
+ end
250
+
251
+ it 'serves files with a URL encoded + sign (%2B) in the path' do
252
+ mock_app do
253
+ set :static, true
254
+ set :public_folder, File.join(File.dirname(__FILE__), 'public')
255
+ end
256
+
257
+ get "/hello%2bworld.txt"
258
+
259
+ real_path = File.join(File.dirname(__FILE__), 'public', 'hello+world.txt')
260
+ assert ok?
261
+ assert_equal File.read(real_path), body
262
+ assert_equal File.size(real_path).to_s, response['Content-Length']
263
+ assert response.headers.include?('Last-Modified')
264
+ end
265
+
236
266
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sinatra
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.6
4
+ version: 1.4.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Blake Mizerany
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2015-03-24 00:00:00.000000000 Z
14
+ date: 2016-01-24 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rack
@@ -19,14 +19,14 @@ dependencies:
19
19
  requirements:
20
20
  - - "~>"
21
21
  - !ruby/object:Gem::Version
22
- version: '1.4'
22
+ version: '1.5'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - "~>"
28
28
  - !ruby/object:Gem::Version
29
- version: '1.4'
29
+ version: '1.5'
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: tilt
32
32
  requirement: !ruby/object:Gem::Requirement
@@ -82,7 +82,8 @@ extra_rdoc_files:
82
82
  files:
83
83
  - ".yardopts"
84
84
  - AUTHORS.md
85
- - CHANGES
85
+ - CHANGELOG.md
86
+ - CONTRIBUTING.md
86
87
  - Gemfile
87
88
  - LICENSE
88
89
  - README.de.md
@@ -102,6 +103,7 @@ files:
102
103
  - examples/stream.ru
103
104
  - lib/sinatra.rb
104
105
  - lib/sinatra/base.rb
106
+ - lib/sinatra/ext.rb
105
107
  - lib/sinatra/images/404.png
106
108
  - lib/sinatra/images/500.png
107
109
  - lib/sinatra/main.rb
@@ -135,6 +137,7 @@ files:
135
137
  - test/middleware_test.rb
136
138
  - test/nokogiri_test.rb
137
139
  - test/public/favicon.ico
140
+ - test/public/hello+world.txt
138
141
  - test/rabl_test.rb
139
142
  - test/rack_test.rb
140
143
  - test/radius_test.rb
@@ -233,7 +236,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
233
236
  version: '0'
234
237
  requirements: []
235
238
  rubyforge_project:
236
- rubygems_version: 2.4.5
239
+ rubygems_version: 2.5.1
237
240
  signing_key:
238
241
  specification_version: 4
239
242
  summary: Classy web-development dressed in a DSL