sinatra 2.1.0 → 2.2.4

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.1.0
1
+ 2.2.4
data/lib/sinatra/base.rb CHANGED
@@ -78,6 +78,8 @@ module Sinatra
78
78
  super
79
79
  rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError => e
80
80
  raise BadRequest, "Invalid query parameters: #{Rack::Utils.escape_html(e.message)}"
81
+ rescue EOFError => e
82
+ raise BadRequest, "Invalid multipart/form-data: #{Rack::Utils.escape_html(e.message)}"
81
83
  end
82
84
 
83
85
  class AcceptEntry
@@ -188,7 +190,7 @@ module Sinatra
188
190
  headers["Content-Length"] = body.map(&:bytesize).reduce(0, :+).to_s
189
191
  end
190
192
 
191
- [status.to_i, headers, result]
193
+ [status, headers, result]
192
194
  end
193
195
 
194
196
  private
@@ -198,11 +200,11 @@ module Sinatra
198
200
  end
199
201
 
200
202
  def drop_content_info?
201
- status.to_i / 100 == 1 or drop_body?
203
+ informational? or drop_body?
202
204
  end
203
205
 
204
206
  def drop_body?
205
- DROP_BODY_RESPONSES.include?(status.to_i)
207
+ DROP_BODY_RESPONSES.include?(status)
206
208
  end
207
209
  end
208
210
 
@@ -379,16 +381,23 @@ module Sinatra
379
381
  response['Content-Type'] = mime_type
380
382
  end
381
383
 
384
+ # https://html.spec.whatwg.org/#multipart-form-data
385
+ MULTIPART_FORM_DATA_REPLACEMENT_TABLE = {
386
+ '"' => '%22',
387
+ "\r" => '%0D',
388
+ "\n" => '%0A'
389
+ }.freeze
390
+
382
391
  # Set the Content-Disposition to "attachment" with the specified filename,
383
392
  # instructing the user agents to prompt to save.
384
393
  def attachment(filename = nil, disposition = :attachment)
385
394
  response['Content-Disposition'] = disposition.to_s.dup
386
- if filename
387
- params = '; filename="%s"' % File.basename(filename)
388
- response['Content-Disposition'] << params
389
- ext = File.extname(filename)
390
- content_type(ext) unless response['Content-Type'] or ext.empty?
391
- end
395
+ return unless filename
396
+
397
+ params = format('; filename="%s"', File.basename(filename).gsub(/["\r\n]/, MULTIPART_FORM_DATA_REPLACEMENT_TABLE))
398
+ response['Content-Disposition'] << params
399
+ ext = File.extname(filename)
400
+ content_type(ext) unless response['Content-Type'] || ext.empty?
392
401
  end
393
402
 
394
403
  # Use the contents of the file at +path+ as the response body.
@@ -869,12 +878,12 @@ module Sinatra
869
878
 
870
879
  def compile_template(engine, data, options, views)
871
880
  eat_errors = options.delete :eat_errors
872
- template_cache.fetch engine, data, options, views do
873
- template = Tilt[engine]
874
- raise "Template engine not found: #{engine}" if template.nil?
881
+ template = Tilt[engine]
882
+ raise "Template engine not found: #{engine}" if template.nil?
875
883
 
876
- case data
877
- when Symbol
884
+ case data
885
+ when Symbol
886
+ template_cache.fetch engine, data, options, views do
878
887
  body, path, line = settings.templates[data]
879
888
  if body
880
889
  body = body.call if body.respond_to?(:call)
@@ -892,17 +901,24 @@ module Sinatra
892
901
  throw :layout_missing if eat_errors and not found
893
902
  template.new(path, 1, options)
894
903
  end
895
- when Proc, String
896
- body = data.is_a?(String) ? Proc.new { data } : data
897
- caller = settings.caller_locations.first
898
- path = options[:path] || caller[0]
899
- line = options[:line] || caller[1]
900
- template.new(path, line.to_i, options, &body)
901
- else
902
- raise ArgumentError, "Sorry, don't know how to render #{data.inspect}."
903
904
  end
905
+ when Proc
906
+ compile_block_template(template, options, &data)
907
+ when String
908
+ template_cache.fetch engine, data, options, views do
909
+ compile_block_template(template, options) { data }
910
+ end
911
+ else
912
+ raise ArgumentError, "Sorry, don't know how to render #{data.inspect}."
904
913
  end
905
914
  end
915
+
916
+ def compile_block_template(template, options, &body)
917
+ caller = settings.caller_locations.first
918
+ path = options[:path] || caller[0]
919
+ line = options[:line] || caller[1]
920
+ template.new(path, line.to_i, options, &body)
921
+ end
906
922
  end
907
923
 
908
924
  # Base class for all Sinatra applications and middleware.
@@ -916,7 +932,7 @@ module Sinatra
916
932
  attr_accessor :app, :env, :request, :response, :params
917
933
  attr_reader :template_cache
918
934
 
919
- def initialize(app = nil)
935
+ def initialize(app = nil, **kwargs)
920
936
  super()
921
937
  @app = app
922
938
  @template_cache = Tilt::Cache.new
@@ -934,6 +950,7 @@ module Sinatra
934
950
  @params = IndifferentHash.new
935
951
  @request = Request.new(env)
936
952
  @response = Response.new
953
+ @pinned_response = nil
937
954
  template_cache.clear if settings.reload_templates
938
955
 
939
956
  invoke { dispatch! }
@@ -994,11 +1011,11 @@ module Sinatra
994
1011
 
995
1012
  # Run filters defined on the class and all superclasses.
996
1013
  # Accepts an optional block to call after each filter is applied.
997
- def filter!(type, base = settings)
998
- filter! type, base.superclass if base.superclass.respond_to?(:filters)
1014
+ def filter!(type, base = settings, &block)
1015
+ filter!(type, base.superclass, &block) if base.superclass.respond_to?(:filters)
999
1016
  base.filters[type].each do |args|
1000
1017
  result = process_route(*args)
1001
- yield result if block_given?
1018
+ block.call(result) if block_given?
1002
1019
  end
1003
1020
  end
1004
1021
 
@@ -1006,7 +1023,7 @@ module Sinatra
1006
1023
  def route!(base = settings, pass_block = nil)
1007
1024
  if routes = base.routes[@request.request_method]
1008
1025
  routes.each do |pattern, conditions, block|
1009
- @response.delete_header('Content-Type') unless @pinned_response
1026
+ response.delete_header('Content-Type') unless @pinned_response
1010
1027
 
1011
1028
  returned_pass_block = process_route(pattern, conditions) do |*args|
1012
1029
  env['sinatra.route'] = "#{@request.request_method} #{pattern}"
@@ -1089,6 +1106,7 @@ module Sinatra
1089
1106
  return unless valid_path?(path)
1090
1107
 
1091
1108
  path = File.expand_path(path)
1109
+ return unless path.start_with?(File.expand_path(public_dir) + '/')
1092
1110
  return unless File.file?(path)
1093
1111
 
1094
1112
  env['sinatra.static_file'] = path
@@ -1124,7 +1142,7 @@ module Sinatra
1124
1142
  invoke do
1125
1143
  static! if settings.static? && (request.get? || request.head?)
1126
1144
  filter! :before do
1127
- @pinned_response = !@response['Content-Type'].nil?
1145
+ @pinned_response = !response['Content-Type'].nil?
1128
1146
  end
1129
1147
  route!
1130
1148
  end
@@ -1145,7 +1163,7 @@ module Sinatra
1145
1163
  end
1146
1164
  @env['sinatra.error'] = boom
1147
1165
 
1148
- if boom.respond_to? :http_status
1166
+ if boom.respond_to? :http_status and boom.http_status.between? 400, 599
1149
1167
  status(boom.http_status)
1150
1168
  elsif settings.use_code? and boom.respond_to? :code and boom.code.between? 400, 599
1151
1169
  status(boom.code)
@@ -1153,8 +1171,6 @@ module Sinatra
1153
1171
  status(500)
1154
1172
  end
1155
1173
 
1156
- status(500) unless status.between? 400, 599
1157
-
1158
1174
  if server_error?
1159
1175
  dump_errors! boom if settings.dump_errors?
1160
1176
  raise boom if settings.show_exceptions? and settings.show_exceptions != :after_handler
@@ -1168,7 +1184,7 @@ module Sinatra
1168
1184
 
1169
1185
  if not_found? || bad_request?
1170
1186
  if boom.message && boom.message != boom.class.name
1171
- body boom.message
1187
+ body Rack::Utils.escape_html(boom.message)
1172
1188
  else
1173
1189
  content_type 'text/html'
1174
1190
  body '<h1>' + (not_found? ? 'Not Found' : 'Bad Request') + '</h1>'
@@ -1221,6 +1237,10 @@ module Sinatra
1221
1237
 
1222
1238
  attr_reader :routes, :filters, :templates, :errors
1223
1239
 
1240
+ def callers_to_ignore
1241
+ CALLERS_TO_IGNORE
1242
+ end
1243
+
1224
1244
  # Removes all routes, filters, middleware and extension hooks from the
1225
1245
  # current class (not routes/filters/... defined by its superclass).
1226
1246
  def reset!
@@ -1442,7 +1462,7 @@ module Sinatra
1442
1462
  # in `extensions` available to the handlers and templates
1443
1463
  def helpers(*extensions, &block)
1444
1464
  class_eval(&block) if block_given?
1445
- prepend(*extensions) if extensions.any?
1465
+ include(*extensions) if extensions.any?
1446
1466
  end
1447
1467
 
1448
1468
  # Register an extension. Alternatively take a block from which an
@@ -1471,6 +1491,7 @@ module Sinatra
1471
1491
  @prototype = nil
1472
1492
  @middleware << [middleware, args, block]
1473
1493
  end
1494
+ ruby2_keywords(:use) if respond_to?(:ruby2_keywords, true)
1474
1495
 
1475
1496
  # Stop the self-hosted server if running.
1476
1497
  def quit!
@@ -1490,7 +1511,7 @@ module Sinatra
1490
1511
  def run!(options = {}, &block)
1491
1512
  return if running?
1492
1513
  set options
1493
- handler = detect_rack_handler
1514
+ handler = Rack::Handler.pick(server)
1494
1515
  handler_name = handler.name.gsub(/.*::/, '')
1495
1516
  server_settings = settings.respond_to?(:server_settings) ? settings.server_settings : {}
1496
1517
  server_settings.merge!(:Port => port, :Host => bind)
@@ -1527,6 +1548,7 @@ module Sinatra
1527
1548
  instance = new!(*args, &bk)
1528
1549
  Wrapper.new(build(instance).to_app, instance)
1529
1550
  end
1551
+ ruby2_keywords :new if respond_to?(:ruby2_keywords, true)
1530
1552
 
1531
1553
  # Creates a Rack::Builder instance with all the middleware set up and
1532
1554
  # the given +app+ as end point.
@@ -1744,17 +1766,6 @@ module Sinatra
1744
1766
  builder.use session_store, options
1745
1767
  end
1746
1768
 
1747
- def detect_rack_handler
1748
- servers = Array(server)
1749
- servers.each do |server_name|
1750
- begin
1751
- return Rack::Handler.get(server_name.to_s)
1752
- rescue LoadError, NameError
1753
- end
1754
- end
1755
- fail "Server handler (#{servers.join(',')}) not found."
1756
- end
1757
-
1758
1769
  def inherited(subclass)
1759
1770
  subclass.reset!
1760
1771
  subclass.set :app_file, caller_files.first unless subclass.app_file?
@@ -1779,7 +1790,7 @@ module Sinatra
1779
1790
  def cleaned_caller(keep = 3)
1780
1791
  caller(1).
1781
1792
  map! { |line| line.split(/:(?=\d|in )/, 3)[0,keep] }.
1782
- reject { |file, *_| CALLERS_TO_IGNORE.any? { |pattern| file =~ pattern } }
1793
+ reject { |file, *_| callers_to_ignore.any? { |pattern| file =~ pattern } }
1783
1794
  end
1784
1795
  end
1785
1796
 
@@ -1958,6 +1969,8 @@ module Sinatra
1958
1969
  return super(*args, &block) if respond_to? method_name
1959
1970
  Delegator.target.send(method_name, *args, &block)
1960
1971
  end
1972
+ # ensure keyword argument passing is compatible with ruby >= 2.7
1973
+ ruby2_keywords(method_name) if respond_to?(:ruby2_keywords, true)
1961
1974
  private method_name
1962
1975
  end
1963
1976
  end
@@ -180,6 +180,20 @@ module Sinatra
180
180
  end
181
181
  end
182
182
 
183
+ def select(*args, &block)
184
+ return to_enum(:select) unless block_given?
185
+ dup.tap { |hash| hash.select!(*args, &block) }
186
+ end
187
+
188
+ def reject(*args, &block)
189
+ return to_enum(:reject) unless block_given?
190
+ dup.tap { |hash| hash.reject!(*args, &block) }
191
+ end
192
+
193
+ def compact
194
+ dup.tap(&:compact!)
195
+ end if method_defined?(:compact) # Added in Ruby 2.4
196
+
183
197
  private
184
198
 
185
199
  def convert_key(key)
@@ -1,3 +1,3 @@
1
1
  module Sinatra
2
- VERSION = '2.1.0'
2
+ VERSION = '2.2.3'
3
3
  end
data/sinatra.gemspec CHANGED
@@ -19,9 +19,8 @@ Gem::Specification.new 'sinatra', version do |s|
19
19
  "SECURITY.md",
20
20
  "sinatra.gemspec",
21
21
  "VERSION"]
22
- s.test_files = s.files.select { |p| p =~ /^test\/.*_test.rb/ }
23
- s.extra_rdoc_files = s.files.select { |p| p =~ /^README/ } << 'LICENSE'
24
- s.rdoc_options = %w[--line-numbers --inline-source --title Sinatra --main README.rdoc --encoding=UTF-8]
22
+ s.extra_rdoc_files = %w[README.md LICENSE]
23
+ s.rdoc_options = %w[--line-numbers --title Sinatra --main README.rdoc --encoding=UTF-8]
25
24
 
26
25
  if s.respond_to?(:metadata)
27
26
  s.metadata = {
@@ -33,11 +32,6 @@ Gem::Specification.new 'sinatra', version do |s|
33
32
  'documentation_uri' => 'https://www.rubydoc.info/gems/sinatra'
34
33
  }
35
34
  else
36
- msg = "RubyGems 2.0 or newer is required to protect against public "\
37
- "gem pushes. You can update your rubygems version by running:\n\n"\
38
- "gem install rubygems-update\n"\
39
- "update_rubygems\n"\
40
- "gem update --system"
41
35
  raise <<-EOF
42
36
  RubyGems 2.0 or newer is required to protect against public gem pushes. You can update your rubygems version by running:
43
37
  gem install rubygems-update
@@ -51,5 +45,5 @@ EOF
51
45
  s.add_dependency 'rack', '~> 2.2'
52
46
  s.add_dependency 'tilt', '~> 2.0'
53
47
  s.add_dependency 'rack-protection', version
54
- s.add_dependency 'mustermann', '~> 1.0'
48
+ s.add_dependency 'mustermann', '~> 2.0'
55
49
  end
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sinatra
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Blake Mizerany
8
8
  - Ryan Tomayko
9
9
  - Simon Rozet
10
10
  - Konstantin Haase
11
- autorequire:
11
+ autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2020-09-04 00:00:00.000000000 Z
14
+ date: 2022-12-16 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rack
@@ -47,46 +47,35 @@ dependencies:
47
47
  requirements:
48
48
  - - '='
49
49
  - !ruby/object:Gem::Version
50
- version: 2.1.0
50
+ version: 2.2.4
51
51
  type: :runtime
52
52
  prerelease: false
53
53
  version_requirements: !ruby/object:Gem::Requirement
54
54
  requirements:
55
55
  - - '='
56
56
  - !ruby/object:Gem::Version
57
- version: 2.1.0
57
+ version: 2.2.4
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: mustermann
60
60
  requirement: !ruby/object:Gem::Requirement
61
61
  requirements:
62
62
  - - "~>"
63
63
  - !ruby/object:Gem::Version
64
- version: '1.0'
64
+ version: '2.0'
65
65
  type: :runtime
66
66
  prerelease: false
67
67
  version_requirements: !ruby/object:Gem::Requirement
68
68
  requirements:
69
69
  - - "~>"
70
70
  - !ruby/object:Gem::Version
71
- version: '1.0'
71
+ version: '2.0'
72
72
  description: Sinatra is a DSL for quickly creating web applications in Ruby with minimal
73
73
  effort.
74
74
  email: sinatrarb@googlegroups.com
75
75
  executables: []
76
76
  extensions: []
77
77
  extra_rdoc_files:
78
- - README.de.md
79
- - README.es.md
80
- - README.fr.md
81
- - README.hu.md
82
- - README.ja.md
83
- - README.ko.md
84
- - README.malayalam.md
85
78
  - README.md
86
- - README.pt-br.md
87
- - README.pt-pt.md
88
- - README.ru.md
89
- - README.zh.md
90
79
  - LICENSE
91
80
  files:
92
81
  - ".yardopts"
@@ -135,10 +124,9 @@ metadata:
135
124
  bug_tracker_uri: https://github.com/sinatra/sinatra/issues
136
125
  mailing_list_uri: http://groups.google.com/group/sinatrarb
137
126
  documentation_uri: https://www.rubydoc.info/gems/sinatra
138
- post_install_message:
127
+ post_install_message:
139
128
  rdoc_options:
140
129
  - "--line-numbers"
141
- - "--inline-source"
142
130
  - "--title"
143
131
  - Sinatra
144
132
  - "--main"
@@ -157,8 +145,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
157
145
  - !ruby/object:Gem::Version
158
146
  version: '0'
159
147
  requirements: []
160
- rubygems_version: 3.1.2
161
- signing_key:
148
+ rubyforge_project:
149
+ rubygems_version: 2.7.6.3
150
+ signing_key:
162
151
  specification_version: 4
163
152
  summary: Classy web-development dressed in a DSL
164
153
  test_files: []