rack 2.2.10 → 3.0.0
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 +152 -100
- 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 +2 -1
- data/lib/rack/auth/digest/md5.rb +1 -131
- data/lib/rack/auth/digest/nonce.rb +1 -53
- 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 +60 -42
- 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 +63 -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 +754 -648
- data/lib/rack/lock.rb +2 -5
- data/lib/rack/logger.rb +2 -0
- data/lib/rack/media_type.rb +4 -9
- 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 -85
- 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 +189 -91
- data/lib/rack/response.rb +131 -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 +4 -2
- data/lib/rack/utils.rb +212 -202
- 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 -203
- 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{[^ \t\v\n\r)(><@,;:\\"/\[\]?='*%]}
|
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.
|
77
|
-
|
78
|
-
loop do
|
79
|
-
break if parser.state == :DONE
|
80
|
-
parser.on_read io.read(bufsize, outbuf)
|
81
|
-
end
|
105
|
+
parser.parse(io)
|
82
106
|
|
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,33 +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
|
-
@
|
195
|
-
@rx_max_size = EOL.size + @boundary.bytesize + [EOL.size, '--'.size].max
|
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)
|
196
205
|
@head_regex = /(.*?#{EOL})#{EOL}/m
|
197
206
|
end
|
198
207
|
|
199
|
-
def
|
200
|
-
|
201
|
-
|
202
|
-
|
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
|
203
229
|
end
|
204
230
|
|
205
231
|
def result
|
206
232
|
@collector.each do |part|
|
207
233
|
part.get_data do |data|
|
208
234
|
tag_multipart_encoding(part.filename, part.content_type, part.name, data)
|
209
|
-
@query_parser.normalize_params(@params, part.name, data
|
235
|
+
@query_parser.normalize_params(@params, part.name, data)
|
210
236
|
end
|
211
237
|
end
|
212
238
|
MultipartInfo.new @params.to_params_hash, @collector.find_all(&:file?).map(&:body)
|
@@ -214,34 +240,38 @@ module Rack
|
|
214
240
|
|
215
241
|
private
|
216
242
|
|
217
|
-
def
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
break if handle_fast_forward == :want_read
|
222
|
-
when :CONSUME_TOKEN
|
223
|
-
break if handle_consume_token == :want_read
|
224
|
-
when :MIME_HEAD
|
225
|
-
break if handle_mime_head == :want_read
|
226
|
-
when :MIME_BODY
|
227
|
-
break if handle_mime_body == :want_read
|
228
|
-
when :DONE
|
229
|
-
break
|
230
|
-
end
|
231
|
-
end
|
243
|
+
def dequote(str) # From WEBrick::HTTPUtils
|
244
|
+
ret = (/\A"(.*)"\Z/ =~ str) ? $1 : str.dup
|
245
|
+
ret.gsub!(/\\(.)/, "\\1")
|
246
|
+
ret
|
232
247
|
end
|
233
248
|
|
234
|
-
def
|
235
|
-
|
249
|
+
def read_data(io, outbuf)
|
250
|
+
content = io.read(@bufsize, outbuf)
|
251
|
+
handle_empty_content!(content)
|
252
|
+
@sbuf.concat(content)
|
253
|
+
end
|
236
254
|
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
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.
|
262
|
+
def handle_fast_forward
|
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
|
245
275
|
end
|
246
276
|
end
|
247
277
|
|
@@ -260,7 +290,7 @@ module Rack
|
|
260
290
|
head = @sbuf[1]
|
261
291
|
content_type = head[MULTIPART_CONTENT_TYPE, 1]
|
262
292
|
if name = head[MULTIPART_CONTENT_DISPOSITION, 1]
|
263
|
-
name =
|
293
|
+
name = dequote(name)
|
264
294
|
else
|
265
295
|
name = head[MULTIPART_CONTENT_ID, 1]
|
266
296
|
end
|
@@ -297,15 +327,16 @@ module Rack
|
|
297
327
|
end
|
298
328
|
end
|
299
329
|
|
300
|
-
|
301
|
-
|
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.
|
302
334
|
def consume_boundary
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
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
|
309
340
|
end
|
310
341
|
end
|
311
342
|
|
@@ -315,10 +346,10 @@ module Rack
|
|
315
346
|
when RFC2183
|
316
347
|
params = Hash[*head.scan(DISPPARM).flat_map(&:compact)]
|
317
348
|
|
318
|
-
if filename = params['filename']
|
319
|
-
filename = $1 if filename =~ /^"(.*)"$/
|
320
|
-
elsif filename = params['filename*']
|
349
|
+
if filename = params['filename*']
|
321
350
|
encoding, _, filename = filename.split("'", 3)
|
351
|
+
elsif filename = params['filename']
|
352
|
+
filename = $1 if filename =~ /^"(.*)"$/
|
322
353
|
end
|
323
354
|
when BROKEN
|
324
355
|
filename = $1
|
@@ -345,6 +376,7 @@ module Rack
|
|
345
376
|
end
|
346
377
|
|
347
378
|
CHARSET = "charset"
|
379
|
+
deprecate_constant :CHARSET
|
348
380
|
|
349
381
|
def tag_multipart_encoding(filename, content_type, name, body)
|
350
382
|
name = name.to_s
|
@@ -365,7 +397,13 @@ module Rack
|
|
365
397
|
k.strip!
|
366
398
|
v.strip!
|
367
399
|
v = v[1..-2] if v.start_with?('"') && v.end_with?('"')
|
368
|
-
|
400
|
+
if k == "charset"
|
401
|
+
encoding = begin
|
402
|
+
Encoding.find v
|
403
|
+
rescue ArgumentError
|
404
|
+
Encoding::BINARY
|
405
|
+
end
|
406
|
+
end
|
369
407
|
end
|
370
408
|
end
|
371
409
|
end
|
@@ -376,7 +414,7 @@ module Rack
|
|
376
414
|
|
377
415
|
def handle_empty_content!(content)
|
378
416
|
if content.nil? || content.empty?
|
379
|
-
raise
|
417
|
+
raise EmptyContentError
|
380
418
|
end
|
381
419
|
end
|
382
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
|