rack 2.2.8 → 3.0.4.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rack might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +187 -87
- data/CONTRIBUTING.md +53 -47
- data/MIT-LICENSE +1 -1
- data/README.md +293 -0
- data/SPEC.rdoc +174 -126
- data/lib/rack/auth/abstract/handler.rb +3 -1
- data/lib/rack/auth/abstract/request.rb +3 -1
- data/lib/rack/auth/basic.rb +0 -2
- data/lib/rack/auth/digest/md5.rb +1 -131
- data/lib/rack/auth/digest/nonce.rb +1 -54
- data/lib/rack/auth/digest/params.rb +1 -54
- data/lib/rack/auth/digest/request.rb +1 -43
- data/lib/rack/auth/digest.rb +256 -0
- data/lib/rack/body_proxy.rb +3 -1
- data/lib/rack/builder.rb +83 -63
- data/lib/rack/cascade.rb +2 -0
- data/lib/rack/chunked.rb +16 -13
- data/lib/rack/common_logger.rb +23 -18
- data/lib/rack/conditional_get.rb +18 -15
- data/lib/rack/constants.rb +64 -0
- data/lib/rack/content_length.rb +12 -16
- data/lib/rack/content_type.rb +8 -5
- data/lib/rack/deflater.rb +40 -26
- data/lib/rack/directory.rb +9 -3
- data/lib/rack/etag.rb +14 -23
- data/lib/rack/events.rb +4 -0
- data/lib/rack/file.rb +2 -0
- data/lib/rack/files.rb +15 -17
- data/lib/rack/head.rb +9 -8
- data/lib/rack/headers.rb +154 -0
- data/lib/rack/lint.rb +758 -646
- data/lib/rack/lock.rb +2 -5
- data/lib/rack/logger.rb +2 -0
- data/lib/rack/media_type.rb +1 -1
- data/lib/rack/method_override.rb +5 -1
- data/lib/rack/mime.rb +8 -0
- data/lib/rack/mock.rb +1 -271
- data/lib/rack/mock_request.rb +166 -0
- data/lib/rack/mock_response.rb +126 -0
- data/lib/rack/multipart/generator.rb +7 -5
- data/lib/rack/multipart/parser.rb +123 -79
- data/lib/rack/multipart/uploaded_file.rb +4 -0
- data/lib/rack/multipart.rb +20 -40
- data/lib/rack/null_logger.rb +9 -0
- data/lib/rack/query_parser.rb +76 -44
- data/lib/rack/recursive.rb +2 -0
- data/lib/rack/reloader.rb +0 -2
- data/lib/rack/request.rb +215 -108
- data/lib/rack/response.rb +136 -61
- data/lib/rack/rewindable_input.rb +24 -5
- data/lib/rack/runtime.rb +7 -6
- data/lib/rack/sendfile.rb +30 -25
- data/lib/rack/show_exceptions.rb +15 -2
- data/lib/rack/show_status.rb +17 -7
- data/lib/rack/static.rb +8 -8
- data/lib/rack/tempfile_reaper.rb +15 -4
- data/lib/rack/urlmap.rb +3 -1
- data/lib/rack/utils.rb +206 -191
- data/lib/rack/version.rb +9 -4
- data/lib/rack.rb +5 -76
- metadata +15 -35
- data/README.rdoc +0 -320
- data/Rakefile +0 -130
- data/bin/rackup +0 -5
- data/contrib/rack.png +0 -0
- data/contrib/rack.svg +0 -150
- data/contrib/rack_logo.svg +0 -164
- data/contrib/rdoc.css +0 -412
- data/example/lobster.ru +0 -6
- data/example/protectedlobster.rb +0 -16
- data/example/protectedlobster.ru +0 -10
- data/lib/rack/core_ext/regexp.rb +0 -14
- data/lib/rack/handler/cgi.rb +0 -59
- data/lib/rack/handler/fastcgi.rb +0 -100
- data/lib/rack/handler/lsws.rb +0 -61
- data/lib/rack/handler/scgi.rb +0 -71
- data/lib/rack/handler/thin.rb +0 -36
- data/lib/rack/handler/webrick.rb +0 -129
- data/lib/rack/handler.rb +0 -104
- data/lib/rack/lobster.rb +0 -70
- data/lib/rack/server.rb +0 -466
- data/lib/rack/session/abstract/id.rb +0 -523
- data/lib/rack/session/cookie.rb +0 -204
- data/lib/rack/session/memcache.rb +0 -10
- data/lib/rack/session/pool.rb +0 -85
- data/rack.gemspec +0 -46
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'uploaded_file'
|
4
|
+
|
3
5
|
module Rack
|
4
6
|
module Multipart
|
5
7
|
class Generator
|
@@ -74,12 +76,12 @@ module Rack
|
|
74
76
|
|
75
77
|
def content_for_tempfile(io, file, name)
|
76
78
|
length = ::File.stat(file.path).size if file.path
|
77
|
-
filename = "; filename=\"#{Utils.
|
79
|
+
filename = "; filename=\"#{Utils.escape_path(file.original_filename)}\""
|
78
80
|
<<-EOF
|
79
81
|
--#{MULTIPART_BOUNDARY}\r
|
80
|
-
|
81
|
-
|
82
|
-
#{"
|
82
|
+
content-disposition: form-data; name="#{name}"#{filename}\r
|
83
|
+
content-type: #{file.content_type}\r
|
84
|
+
#{"content-length: #{length}\r\n" if length}\r
|
83
85
|
#{io.read}\r
|
84
86
|
EOF
|
85
87
|
end
|
@@ -87,7 +89,7 @@ EOF
|
|
87
89
|
def content_for_other(file, name)
|
88
90
|
<<-EOF
|
89
91
|
--#{MULTIPART_BOUNDARY}\r
|
90
|
-
|
92
|
+
content-disposition: form-data; name="#{name}"\r
|
91
93
|
\r
|
92
94
|
#{file}\r
|
93
95
|
EOF
|
@@ -2,24 +2,52 @@
|
|
2
2
|
|
3
3
|
require 'strscan'
|
4
4
|
|
5
|
+
require_relative '../utils'
|
6
|
+
|
5
7
|
module Rack
|
6
8
|
module Multipart
|
7
9
|
class MultipartPartLimitError < Errno::EMFILE; end
|
8
|
-
class MultipartTotalPartLimitError < StandardError; end
|
9
10
|
|
10
|
-
class
|
11
|
-
|
11
|
+
# Use specific error class when parsing multipart request
|
12
|
+
# that ends early.
|
13
|
+
class EmptyContentError < ::EOFError; end
|
14
|
+
|
15
|
+
# Base class for multipart exceptions that do not subclass from
|
16
|
+
# other exception classes for backwards compatibility.
|
17
|
+
class Error < StandardError; end
|
18
|
+
|
19
|
+
EOL = "\r\n"
|
20
|
+
MULTIPART = %r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|ni
|
21
|
+
TOKEN = /[^\s()<>,;:\\"\/\[\]?=]+/
|
22
|
+
CONDISP = /Content-Disposition:\s*#{TOKEN}\s*/i
|
23
|
+
VALUE = /"(?:\\"|[^"])*"|#{TOKEN}/
|
24
|
+
BROKEN = /^#{CONDISP}.*;\s*filename=(#{VALUE})/i
|
25
|
+
MULTIPART_CONTENT_TYPE = /Content-Type: (.*)#{EOL}/ni
|
26
|
+
MULTIPART_CONTENT_DISPOSITION = /Content-Disposition:[^:]*;\s*name=(#{VALUE})/ni
|
27
|
+
MULTIPART_CONTENT_ID = /Content-ID:\s*([^#{EOL}]*)/ni
|
28
|
+
# Updated definitions from RFC 2231
|
29
|
+
ATTRIBUTE_CHAR = %r{[^ \x00-\x1f\x7f)(><@,;:\\"/\[\]?='*%]}
|
30
|
+
ATTRIBUTE = /#{ATTRIBUTE_CHAR}+/
|
31
|
+
SECTION = /\*[0-9]+/
|
32
|
+
REGULAR_PARAMETER_NAME = /#{ATTRIBUTE}#{SECTION}?/
|
33
|
+
REGULAR_PARAMETER = /(#{REGULAR_PARAMETER_NAME})=(#{VALUE})/
|
34
|
+
EXTENDED_OTHER_NAME = /#{ATTRIBUTE}\*[1-9][0-9]*\*/
|
35
|
+
EXTENDED_OTHER_VALUE = /%[0-9a-fA-F]{2}|#{ATTRIBUTE_CHAR}/
|
36
|
+
EXTENDED_OTHER_PARAMETER = /(#{EXTENDED_OTHER_NAME})=(#{EXTENDED_OTHER_VALUE}*)/
|
37
|
+
EXTENDED_INITIAL_NAME = /#{ATTRIBUTE}(?:\*0)?\*/
|
38
|
+
EXTENDED_INITIAL_VALUE = /[a-zA-Z0-9\-]*'[a-zA-Z0-9\-]*'#{EXTENDED_OTHER_VALUE}*/
|
39
|
+
EXTENDED_INITIAL_PARAMETER = /(#{EXTENDED_INITIAL_NAME})=(#{EXTENDED_INITIAL_VALUE})/
|
40
|
+
EXTENDED_PARAMETER = /#{EXTENDED_INITIAL_PARAMETER}|#{EXTENDED_OTHER_PARAMETER}/
|
41
|
+
DISPPARM = /;\s*(?:#{REGULAR_PARAMETER}|#{EXTENDED_PARAMETER})\s*/
|
42
|
+
RFC2183 = /^#{CONDISP}(#{DISPPARM})+$/i
|
12
43
|
|
44
|
+
class Parser
|
13
45
|
BUFSIZE = 1_048_576
|
14
46
|
TEXT_PLAIN = "text/plain"
|
15
47
|
TEMPFILE_FACTORY = lambda { |filename, content_type|
|
16
|
-
|
17
|
-
|
18
|
-
Tempfile.new(["RackMultipart", extension])
|
48
|
+
Tempfile.new(["RackMultipart", ::File.extname(filename.gsub("\0", '%00'))])
|
19
49
|
}
|
20
50
|
|
21
|
-
BOUNDARY_REGEX = /\A([^\n]*(?:\n|\Z))/
|
22
|
-
|
23
51
|
class BoundedIO # :nodoc:
|
24
52
|
def initialize(io, content_length)
|
25
53
|
@io = io
|
@@ -41,16 +69,12 @@ module Rack
|
|
41
69
|
if str
|
42
70
|
@cursor += str.bytesize
|
43
71
|
else
|
44
|
-
# Raise an error for mismatching
|
72
|
+
# Raise an error for mismatching content-length and actual contents
|
45
73
|
raise EOFError, "bad content body"
|
46
74
|
end
|
47
75
|
|
48
76
|
str
|
49
77
|
end
|
50
|
-
|
51
|
-
def rewind
|
52
|
-
@io.rewind
|
53
|
-
end
|
54
78
|
end
|
55
79
|
|
56
80
|
MultipartInfo = Struct.new :params, :tmp_files
|
@@ -69,18 +93,17 @@ module Rack
|
|
69
93
|
boundary = parse_boundary content_type
|
70
94
|
return EMPTY unless boundary
|
71
95
|
|
96
|
+
if boundary.length > 70
|
97
|
+
# RFC 1521 Section 7.2.1 imposes a 70 character maximum for the boundary.
|
98
|
+
# Most clients use no more than 55 characters.
|
99
|
+
raise Error, "multipart boundary size too large (#{boundary.length} characters)"
|
100
|
+
end
|
101
|
+
|
72
102
|
io = BoundedIO.new(io, content_length) if content_length
|
73
|
-
outbuf = String.new
|
74
103
|
|
75
104
|
parser = new(boundary, tmpfile, bufsize, qp)
|
76
|
-
parser.
|
105
|
+
parser.parse(io)
|
77
106
|
|
78
|
-
loop do
|
79
|
-
break if parser.state == :DONE
|
80
|
-
parser.on_read io.read(bufsize, outbuf)
|
81
|
-
end
|
82
|
-
|
83
|
-
io.rewind
|
84
107
|
parser.result
|
85
108
|
end
|
86
109
|
|
@@ -143,7 +166,7 @@ module Rack
|
|
143
166
|
|
144
167
|
@mime_parts[mime_index] = klass.new(body, head, filename, content_type, name)
|
145
168
|
|
146
|
-
|
169
|
+
check_open_files
|
147
170
|
end
|
148
171
|
|
149
172
|
def on_mime_body(mime_index, content)
|
@@ -155,23 +178,13 @@ module Rack
|
|
155
178
|
|
156
179
|
private
|
157
180
|
|
158
|
-
def
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
if file_limit && file_limit > 0
|
163
|
-
if @open_files >= file_limit
|
181
|
+
def check_open_files
|
182
|
+
if Utils.multipart_part_limit > 0
|
183
|
+
if @open_files >= Utils.multipart_part_limit
|
164
184
|
@mime_parts.each(&:close)
|
165
185
|
raise MultipartPartLimitError, 'Maximum file multiparts in content reached'
|
166
186
|
end
|
167
187
|
end
|
168
|
-
|
169
|
-
if part_limit && part_limit > 0
|
170
|
-
if @mime_parts.size >= part_limit
|
171
|
-
@mime_parts.each(&:close)
|
172
|
-
raise MultipartTotalPartLimitError, 'Maximum total multiparts in content reached'
|
173
|
-
end
|
174
|
-
end
|
175
188
|
end
|
176
189
|
end
|
177
190
|
|
@@ -180,32 +193,46 @@ module Rack
|
|
180
193
|
def initialize(boundary, tempfile, bufsize, query_parser)
|
181
194
|
@query_parser = query_parser
|
182
195
|
@params = query_parser.make_params
|
183
|
-
@boundary = "--#{boundary}"
|
184
196
|
@bufsize = bufsize
|
185
197
|
|
186
|
-
@full_boundary = @boundary
|
187
|
-
@end_boundary = @boundary + '--'
|
188
198
|
@state = :FAST_FORWARD
|
189
199
|
@mime_index = 0
|
190
200
|
@collector = Collector.new tempfile
|
191
201
|
|
192
202
|
@sbuf = StringScanner.new("".dup)
|
193
|
-
@body_regex = /(?:#{EOL})
|
194
|
-
@rx_max_size =
|
203
|
+
@body_regex = /(?:#{EOL}|\A)--#{Regexp.quote(boundary)}(?:#{EOL}|--)/m
|
204
|
+
@rx_max_size = boundary.bytesize + 6 # (\r\n-- at start, either \r\n or -- at finish)
|
195
205
|
@head_regex = /(.*?#{EOL})#{EOL}/m
|
196
206
|
end
|
197
207
|
|
198
|
-
def
|
199
|
-
|
200
|
-
|
201
|
-
|
208
|
+
def parse(io)
|
209
|
+
outbuf = String.new
|
210
|
+
read_data(io, outbuf)
|
211
|
+
|
212
|
+
loop do
|
213
|
+
status =
|
214
|
+
case @state
|
215
|
+
when :FAST_FORWARD
|
216
|
+
handle_fast_forward
|
217
|
+
when :CONSUME_TOKEN
|
218
|
+
handle_consume_token
|
219
|
+
when :MIME_HEAD
|
220
|
+
handle_mime_head
|
221
|
+
when :MIME_BODY
|
222
|
+
handle_mime_body
|
223
|
+
else # when :DONE
|
224
|
+
return
|
225
|
+
end
|
226
|
+
|
227
|
+
read_data(io, outbuf) if status == :want_read
|
228
|
+
end
|
202
229
|
end
|
203
230
|
|
204
231
|
def result
|
205
232
|
@collector.each do |part|
|
206
233
|
part.get_data do |data|
|
207
234
|
tag_multipart_encoding(part.filename, part.content_type, part.name, data)
|
208
|
-
@query_parser.normalize_params(@params, part.name, data
|
235
|
+
@query_parser.normalize_params(@params, part.name, data)
|
209
236
|
end
|
210
237
|
end
|
211
238
|
MultipartInfo.new @params.to_params_hash, @collector.find_all(&:file?).map(&:body)
|
@@ -213,29 +240,38 @@ module Rack
|
|
213
240
|
|
214
241
|
private
|
215
242
|
|
216
|
-
def
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
break if handle_mime_body == :want_read
|
227
|
-
when :DONE
|
228
|
-
break
|
229
|
-
end
|
230
|
-
end
|
243
|
+
def dequote(str) # From WEBrick::HTTPUtils
|
244
|
+
ret = (/\A"(.*)"\Z/ =~ str) ? $1 : str.dup
|
245
|
+
ret.gsub!(/\\(.)/, "\\1")
|
246
|
+
ret
|
247
|
+
end
|
248
|
+
|
249
|
+
def read_data(io, outbuf)
|
250
|
+
content = io.read(@bufsize, outbuf)
|
251
|
+
handle_empty_content!(content)
|
252
|
+
@sbuf.concat(content)
|
231
253
|
end
|
232
254
|
|
255
|
+
# This handles the initial parser state. We read until we find the starting
|
256
|
+
# boundary, then we can transition to the next state. If we find the ending
|
257
|
+
# boundary, this is an invalid multipart upload, but keep scanning for opening
|
258
|
+
# boundary in that case. If no boundary found, we need to keep reading data
|
259
|
+
# and retry. It's highly unlikely the initial read will not consume the
|
260
|
+
# boundary. The client would have to deliberately craft a response
|
261
|
+
# with the opening boundary beyond the buffer size for that to happen.
|
233
262
|
def handle_fast_forward
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
263
|
+
while true
|
264
|
+
case consume_boundary
|
265
|
+
when :BOUNDARY
|
266
|
+
# found opening boundary, transition to next state
|
267
|
+
@state = :MIME_HEAD
|
268
|
+
return
|
269
|
+
when :END_BOUNDARY
|
270
|
+
# invalid multipart upload, but retry for opening boundary
|
271
|
+
else
|
272
|
+
# no boundary found, keep reading data
|
273
|
+
return :want_read
|
274
|
+
end
|
239
275
|
end
|
240
276
|
end
|
241
277
|
|
@@ -254,7 +290,7 @@ module Rack
|
|
254
290
|
head = @sbuf[1]
|
255
291
|
content_type = head[MULTIPART_CONTENT_TYPE, 1]
|
256
292
|
if name = head[MULTIPART_CONTENT_DISPOSITION, 1]
|
257
|
-
name =
|
293
|
+
name = dequote(name)
|
258
294
|
else
|
259
295
|
name = head[MULTIPART_CONTENT_ID, 1]
|
260
296
|
end
|
@@ -291,15 +327,16 @@ module Rack
|
|
291
327
|
end
|
292
328
|
end
|
293
329
|
|
294
|
-
|
295
|
-
|
330
|
+
# Scan until the we find the start or end of the boundary.
|
331
|
+
# If we find it, return the appropriate symbol for the start or
|
332
|
+
# end of the boundary. If we don't find the start or end of the
|
333
|
+
# boundary, clear the buffer and return nil.
|
296
334
|
def consume_boundary
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
return if @sbuf.eos?
|
335
|
+
if read_buffer = @sbuf.scan_until(@body_regex)
|
336
|
+
read_buffer.end_with?(EOL) ? :BOUNDARY : :END_BOUNDARY
|
337
|
+
else
|
338
|
+
@sbuf.terminate
|
339
|
+
nil
|
303
340
|
end
|
304
341
|
end
|
305
342
|
|
@@ -309,10 +346,10 @@ module Rack
|
|
309
346
|
when RFC2183
|
310
347
|
params = Hash[*head.scan(DISPPARM).flat_map(&:compact)]
|
311
348
|
|
312
|
-
if filename = params['filename']
|
313
|
-
filename = $1 if filename =~ /^"(.*)"$/
|
314
|
-
elsif filename = params['filename*']
|
349
|
+
if filename = params['filename*']
|
315
350
|
encoding, _, filename = filename.split("'", 3)
|
351
|
+
elsif filename = params['filename']
|
352
|
+
filename = $1 if filename =~ /^"(.*)"$/
|
316
353
|
end
|
317
354
|
when BROKEN
|
318
355
|
filename = $1
|
@@ -339,6 +376,7 @@ module Rack
|
|
339
376
|
end
|
340
377
|
|
341
378
|
CHARSET = "charset"
|
379
|
+
deprecate_constant :CHARSET
|
342
380
|
|
343
381
|
def tag_multipart_encoding(filename, content_type, name, body)
|
344
382
|
name = name.to_s
|
@@ -359,7 +397,13 @@ module Rack
|
|
359
397
|
k.strip!
|
360
398
|
v.strip!
|
361
399
|
v = v[1..-2] if v.start_with?('"') && v.end_with?('"')
|
362
|
-
|
400
|
+
if k == "charset"
|
401
|
+
encoding = begin
|
402
|
+
Encoding.find v
|
403
|
+
rescue ArgumentError
|
404
|
+
Encoding::BINARY
|
405
|
+
end
|
406
|
+
end
|
363
407
|
end
|
364
408
|
end
|
365
409
|
end
|
@@ -370,7 +414,7 @@ module Rack
|
|
370
414
|
|
371
415
|
def handle_empty_content!(content)
|
372
416
|
if content.nil? || content.empty?
|
373
|
-
raise
|
417
|
+
raise EmptyContentError
|
374
418
|
end
|
375
419
|
end
|
376
420
|
end
|
data/lib/rack/multipart.rb
CHANGED
@@ -1,64 +1,44 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'constants'
|
4
|
+
require_relative 'utils'
|
5
|
+
|
3
6
|
require_relative 'multipart/parser'
|
7
|
+
require_relative 'multipart/generator'
|
4
8
|
|
5
9
|
module Rack
|
6
10
|
# A multipart form data parser, adapted from IOWA.
|
7
11
|
#
|
8
12
|
# Usually, Rack::Request#POST takes care of calling this.
|
9
13
|
module Multipart
|
10
|
-
autoload :UploadedFile, 'rack/multipart/uploaded_file'
|
11
|
-
autoload :Generator, 'rack/multipart/generator'
|
12
|
-
|
13
|
-
EOL = "\r\n"
|
14
14
|
MULTIPART_BOUNDARY = "AaB03x"
|
15
|
-
MULTIPART = %r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|ni
|
16
|
-
TOKEN = /[^\s()<>,;:\\"\/\[\]?=]+/
|
17
|
-
CONDISP = /Content-Disposition:\s*#{TOKEN}\s*/i
|
18
|
-
VALUE = /"(?:\\"|[^"])*"|#{TOKEN}/
|
19
|
-
BROKEN = /^#{CONDISP}.*;\s*filename=(#{VALUE})/i
|
20
|
-
MULTIPART_CONTENT_TYPE = /Content-Type: (.*)#{EOL}/ni
|
21
|
-
MULTIPART_CONTENT_DISPOSITION = /Content-Disposition:[^:]*;\s*name=(#{VALUE})/ni
|
22
|
-
MULTIPART_CONTENT_ID = /Content-ID:\s*([^#{EOL}]*)/ni
|
23
|
-
# Updated definitions from RFC 2231
|
24
|
-
ATTRIBUTE_CHAR = %r{[^ \x00-\x1f\x7f)(><@,;:\\"/\[\]?='*%]}
|
25
|
-
ATTRIBUTE = /#{ATTRIBUTE_CHAR}+/
|
26
|
-
SECTION = /\*[0-9]+/
|
27
|
-
REGULAR_PARAMETER_NAME = /#{ATTRIBUTE}#{SECTION}?/
|
28
|
-
REGULAR_PARAMETER = /(#{REGULAR_PARAMETER_NAME})=(#{VALUE})/
|
29
|
-
EXTENDED_OTHER_NAME = /#{ATTRIBUTE}\*[1-9][0-9]*\*/
|
30
|
-
EXTENDED_OTHER_VALUE = /%[0-9a-fA-F]{2}|#{ATTRIBUTE_CHAR}/
|
31
|
-
EXTENDED_OTHER_PARAMETER = /(#{EXTENDED_OTHER_NAME})=(#{EXTENDED_OTHER_VALUE}*)/
|
32
|
-
EXTENDED_INITIAL_NAME = /#{ATTRIBUTE}(?:\*0)?\*/
|
33
|
-
EXTENDED_INITIAL_VALUE = /[a-zA-Z0-9\-]*'[a-zA-Z0-9\-]*'#{EXTENDED_OTHER_VALUE}*/
|
34
|
-
EXTENDED_INITIAL_PARAMETER = /(#{EXTENDED_INITIAL_NAME})=(#{EXTENDED_INITIAL_VALUE})/
|
35
|
-
EXTENDED_PARAMETER = /#{EXTENDED_INITIAL_PARAMETER}|#{EXTENDED_OTHER_PARAMETER}/
|
36
|
-
DISPPARM = /;\s*(?:#{REGULAR_PARAMETER}|#{EXTENDED_PARAMETER})\s*/
|
37
|
-
RFC2183 = /^#{CONDISP}(#{DISPPARM})+$/i
|
38
15
|
|
39
16
|
class << self
|
40
17
|
def parse_multipart(env, params = Rack::Utils.default_query_parser)
|
41
|
-
|
42
|
-
|
18
|
+
io = env[RACK_INPUT]
|
19
|
+
|
20
|
+
if content_length = env['CONTENT_LENGTH']
|
21
|
+
content_length = content_length.to_i
|
22
|
+
end
|
43
23
|
|
44
|
-
|
45
|
-
io = req.get_header(RACK_INPUT)
|
46
|
-
io.rewind
|
47
|
-
content_length = req.content_length
|
48
|
-
content_length = content_length.to_i if content_length
|
24
|
+
content_type = env['CONTENT_TYPE']
|
49
25
|
|
50
|
-
tempfile =
|
51
|
-
bufsize =
|
26
|
+
tempfile = env[RACK_MULTIPART_TEMPFILE_FACTORY] || Parser::TEMPFILE_FACTORY
|
27
|
+
bufsize = env[RACK_MULTIPART_BUFFER_SIZE] || Parser::BUFSIZE
|
52
28
|
|
53
|
-
info = Parser.parse
|
54
|
-
|
55
|
-
|
29
|
+
info = Parser.parse(io, content_length, content_type, tempfile, bufsize, params)
|
30
|
+
env[RACK_TEMPFILES] = info.tmp_files
|
31
|
+
|
32
|
+
return info.params
|
33
|
+
end
|
34
|
+
|
35
|
+
def extract_multipart(request, params = Rack::Utils.default_query_parser)
|
36
|
+
parse_multipart(request.env)
|
56
37
|
end
|
57
38
|
|
58
39
|
def build_multipart(params, first = true)
|
59
40
|
Generator.new(params, first).dump
|
60
41
|
end
|
61
42
|
end
|
62
|
-
|
63
43
|
end
|
64
44
|
end
|
data/lib/rack/null_logger.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'constants'
|
4
|
+
|
3
5
|
module Rack
|
4
6
|
class NullLogger
|
5
7
|
def initialize(app)
|
@@ -22,6 +24,11 @@ module Rack
|
|
22
24
|
def warn? ; end
|
23
25
|
def error? ; end
|
24
26
|
def fatal? ; end
|
27
|
+
def debug! ; end
|
28
|
+
def error! ; end
|
29
|
+
def fatal! ; end
|
30
|
+
def info! ; end
|
31
|
+
def warn! ; end
|
25
32
|
def level ; end
|
26
33
|
def progname ; end
|
27
34
|
def datetime_format ; end
|
@@ -34,6 +41,8 @@ module Rack
|
|
34
41
|
def sev_threshold=(sev_threshold); end
|
35
42
|
def close ; end
|
36
43
|
def add(severity, message = nil, progname = nil, &block); end
|
44
|
+
def log(severity, message = nil, progname = nil, &block); end
|
37
45
|
def <<(msg); end
|
46
|
+
def reopen(logdev = nil); end
|
38
47
|
end
|
39
48
|
end
|