rack 1.6.13 → 2.0.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.

Files changed (144) hide show
  1. checksums.yaml +5 -5
  2. data/COPYING +1 -1
  3. data/HISTORY.md +138 -8
  4. data/README.rdoc +17 -25
  5. data/Rakefile +6 -14
  6. data/SPEC +8 -9
  7. data/contrib/rack_logo.svg +164 -111
  8. data/example/protectedlobster.rb +1 -1
  9. data/example/protectedlobster.ru +1 -1
  10. data/lib/rack/auth/abstract/request.rb +5 -1
  11. data/lib/rack/auth/digest/params.rb +2 -3
  12. data/lib/rack/auth/digest/request.rb +1 -1
  13. data/lib/rack/body_proxy.rb +14 -9
  14. data/lib/rack/builder.rb +3 -3
  15. data/lib/rack/chunked.rb +5 -5
  16. data/lib/rack/{commonlogger.rb → common_logger.rb} +3 -3
  17. data/lib/rack/{conditionalget.rb → conditional_get.rb} +0 -0
  18. data/lib/rack/content_length.rb +2 -2
  19. data/lib/rack/deflater.rb +4 -4
  20. data/lib/rack/directory.rb +66 -54
  21. data/lib/rack/etag.rb +4 -3
  22. data/lib/rack/events.rb +154 -0
  23. data/lib/rack/file.rb +63 -39
  24. data/lib/rack/handler/cgi.rb +15 -16
  25. data/lib/rack/handler/fastcgi.rb +13 -14
  26. data/lib/rack/handler/lsws.rb +11 -11
  27. data/lib/rack/handler/scgi.rb +15 -15
  28. data/lib/rack/handler/thin.rb +3 -0
  29. data/lib/rack/handler/webrick.rb +22 -24
  30. data/lib/rack/handler.rb +3 -25
  31. data/lib/rack/head.rb +15 -17
  32. data/lib/rack/lint.rb +38 -38
  33. data/lib/rack/lobster.rb +1 -1
  34. data/lib/rack/lock.rb +6 -10
  35. data/lib/rack/logger.rb +2 -2
  36. data/lib/rack/media_type.rb +38 -0
  37. data/lib/rack/{methodoverride.rb → method_override.rb} +4 -11
  38. data/lib/rack/mime.rb +18 -5
  39. data/lib/rack/mock.rb +35 -53
  40. data/lib/rack/multipart/generator.rb +5 -5
  41. data/lib/rack/multipart/parser.rb +272 -158
  42. data/lib/rack/multipart/uploaded_file.rb +1 -2
  43. data/lib/rack/multipart.rb +35 -6
  44. data/lib/rack/{nulllogger.rb → null_logger.rb} +1 -1
  45. data/lib/rack/query_parser.rb +192 -0
  46. data/lib/rack/recursive.rb +8 -8
  47. data/lib/rack/request.rb +383 -307
  48. data/lib/rack/response.rb +129 -56
  49. data/lib/rack/rewindable_input.rb +1 -12
  50. data/lib/rack/runtime.rb +10 -18
  51. data/lib/rack/sendfile.rb +5 -7
  52. data/lib/rack/server.rb +31 -25
  53. data/lib/rack/session/abstract/id.rb +95 -135
  54. data/lib/rack/session/cookie.rb +26 -28
  55. data/lib/rack/session/memcache.rb +8 -14
  56. data/lib/rack/session/pool.rb +14 -21
  57. data/lib/rack/show_exceptions.rb +386 -0
  58. data/lib/rack/{showstatus.rb → show_status.rb} +3 -3
  59. data/lib/rack/static.rb +30 -5
  60. data/lib/rack/tempfile_reaper.rb +2 -2
  61. data/lib/rack/urlmap.rb +15 -14
  62. data/lib/rack/utils.rb +135 -210
  63. data/lib/rack.rb +70 -21
  64. data/rack.gemspec +7 -5
  65. data/test/builder/an_underscore_app.rb +5 -0
  66. data/test/builder/options.ru +1 -1
  67. data/test/cgi/test.fcgi +1 -0
  68. data/test/cgi/test.gz +0 -0
  69. data/test/helper.rb +34 -0
  70. data/test/multipart/filename_with_encoded_words +7 -0
  71. data/test/multipart/{filename_with_null_byte → filename_with_single_quote} +1 -1
  72. data/test/multipart/quoted +15 -0
  73. data/test/multipart/rack-logo.png +0 -0
  74. data/test/multipart/unity3d_wwwform +11 -0
  75. data/test/registering_handler/rack/handler/registering_myself.rb +1 -1
  76. data/test/spec_auth_basic.rb +27 -19
  77. data/test/spec_auth_digest.rb +47 -46
  78. data/test/spec_body_proxy.rb +27 -27
  79. data/test/spec_builder.rb +51 -41
  80. data/test/spec_cascade.rb +24 -22
  81. data/test/spec_cgi.rb +49 -67
  82. data/test/spec_chunked.rb +36 -34
  83. data/test/{spec_commonlogger.rb → spec_common_logger.rb} +23 -21
  84. data/test/{spec_conditionalget.rb → spec_conditional_get.rb} +29 -28
  85. data/test/spec_config.rb +3 -2
  86. data/test/spec_content_length.rb +18 -17
  87. data/test/spec_content_type.rb +13 -12
  88. data/test/spec_deflater.rb +66 -40
  89. data/test/spec_directory.rb +87 -27
  90. data/test/spec_etag.rb +32 -31
  91. data/test/spec_events.rb +133 -0
  92. data/test/spec_fastcgi.rb +50 -72
  93. data/test/spec_file.rb +107 -77
  94. data/test/spec_handler.rb +19 -34
  95. data/test/spec_head.rb +15 -14
  96. data/test/spec_lint.rb +162 -197
  97. data/test/spec_lobster.rb +24 -23
  98. data/test/spec_lock.rb +69 -39
  99. data/test/spec_logger.rb +4 -3
  100. data/test/spec_media_type.rb +42 -0
  101. data/test/spec_method_override.rb +83 -0
  102. data/test/spec_mime.rb +19 -19
  103. data/test/spec_mock.rb +196 -151
  104. data/test/spec_multipart.rb +317 -201
  105. data/test/{spec_nulllogger.rb → spec_null_logger.rb} +5 -4
  106. data/test/spec_recursive.rb +17 -14
  107. data/test/spec_request.rb +768 -607
  108. data/test/spec_response.rb +214 -111
  109. data/test/spec_rewindable_input.rb +50 -40
  110. data/test/spec_runtime.rb +11 -10
  111. data/test/spec_sendfile.rb +30 -35
  112. data/test/spec_server.rb +78 -52
  113. data/test/spec_session_abstract_id.rb +11 -33
  114. data/test/spec_session_abstract_session_hash.rb +28 -0
  115. data/test/spec_session_cookie.rb +97 -65
  116. data/test/spec_session_memcache.rb +63 -101
  117. data/test/spec_session_pool.rb +48 -84
  118. data/test/spec_show_exceptions.rb +80 -0
  119. data/test/{spec_showstatus.rb → spec_show_status.rb} +36 -35
  120. data/test/spec_static.rb +71 -32
  121. data/test/spec_tempfile_reaper.rb +11 -10
  122. data/test/spec_thin.rb +55 -50
  123. data/test/spec_urlmap.rb +79 -78
  124. data/test/spec_utils.rb +441 -346
  125. data/test/spec_version.rb +2 -8
  126. data/test/spec_webrick.rb +91 -67
  127. data/test/static/foo.html +1 -0
  128. data/test/testrequest.rb +1 -1
  129. data/test/unregistered_handler/rack/handler/unregistered.rb +1 -1
  130. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +1 -1
  131. metadata +103 -69
  132. data/KNOWN-ISSUES +0 -44
  133. data/lib/rack/backports/uri/common_18.rb +0 -56
  134. data/lib/rack/backports/uri/common_192.rb +0 -52
  135. data/lib/rack/backports/uri/common_193.rb +0 -29
  136. data/lib/rack/handler/evented_mongrel.rb +0 -8
  137. data/lib/rack/handler/mongrel.rb +0 -106
  138. data/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
  139. data/lib/rack/showexceptions.rb +0 -387
  140. data/lib/rack/utils/okjson.rb +0 -600
  141. data/test/spec_methodoverride.rb +0 -111
  142. data/test/spec_mongrel.rb +0 -182
  143. data/test/spec_session_persisted_secure_secure_session_hash.rb +0 -73
  144. data/test/spec_showexceptions.rb +0 -98
@@ -1,3 +1,9 @@
1
+ # coding: utf-8
2
+
3
+ require 'minitest/autorun'
4
+ require 'rack'
5
+ require 'rack/multipart'
6
+ require 'rack/multipart/parser'
1
7
  require 'rack/utils'
2
8
  require 'rack/mock'
3
9
 
@@ -6,8 +12,8 @@ describe Rack::Multipart do
6
12
  file = multipart_file(name)
7
13
  data = File.open(file, 'rb') { |io| io.read }
8
14
 
9
- type = "multipart/form-data; boundary=#{boundary}"
10
- length = data.respond_to?(:bytesize) ? data.bytesize : data.size
15
+ type = %(multipart/form-data; boundary=#{boundary})
16
+ length = data.bytesize
11
17
 
12
18
  { "CONTENT_TYPE" => type,
13
19
  "CONTENT_LENGTH" => length.to_s,
@@ -18,75 +24,81 @@ describe Rack::Multipart do
18
24
  File.join(File.dirname(__FILE__), "multipart", name.to_s)
19
25
  end
20
26
 
21
- should "return nil if content type is not multipart" do
27
+ it "return nil if content type is not multipart" do
22
28
  env = Rack::MockRequest.env_for("/",
23
29
  "CONTENT_TYPE" => 'application/x-www-form-urlencoded')
24
- Rack::Multipart.parse_multipart(env).should.equal nil
30
+ Rack::Multipart.parse_multipart(env).must_equal nil
25
31
  end
26
32
 
27
- should "parse multipart content when content type present but filename is not" do
33
+ it "parse multipart content when content type present but filename is not" do
28
34
  env = Rack::MockRequest.env_for("/", multipart_fixture(:content_type_and_no_filename))
29
35
  params = Rack::Multipart.parse_multipart(env)
30
- params["text"].should.equal "contents"
36
+ params["text"].must_equal "contents"
31
37
  end
32
38
 
33
- if "<3".respond_to?(:force_encoding)
34
- should "set US_ASCII encoding based on charset" do
39
+ it "set US_ASCII encoding based on charset" do
35
40
  env = Rack::MockRequest.env_for("/", multipart_fixture(:content_type_and_no_filename))
36
41
  params = Rack::Multipart.parse_multipart(env)
37
- params["text"].encoding.should.equal Encoding::US_ASCII
42
+ params["text"].encoding.must_equal Encoding::US_ASCII
38
43
 
39
44
  # I'm not 100% sure if making the param name encoding match the
40
45
  # Content-Type charset is the right thing to do. We should revisit this.
41
46
  params.keys.each do |key|
42
- key.encoding.should.equal Encoding::US_ASCII
47
+ key.encoding.must_equal Encoding::US_ASCII
43
48
  end
44
49
  end
45
50
 
46
- should "set BINARY encoding on things without content type" do
51
+ it "set BINARY encoding on things without content type" do
47
52
  env = Rack::MockRequest.env_for("/", multipart_fixture(:none))
48
53
  params = Rack::Multipart.parse_multipart(env)
49
- params["submit-name"].encoding.should.equal Encoding::UTF_8
54
+ params["submit-name"].encoding.must_equal Encoding::UTF_8
50
55
  end
51
56
 
52
- should "set UTF8 encoding on names of things without content type" do
57
+ it "set UTF8 encoding on names of things without content type" do
53
58
  env = Rack::MockRequest.env_for("/", multipart_fixture(:none))
54
59
  params = Rack::Multipart.parse_multipart(env)
55
60
  params.keys.each do |key|
56
- key.encoding.should.equal Encoding::UTF_8
61
+ key.encoding.must_equal Encoding::UTF_8
57
62
  end
58
63
  end
59
64
 
60
- should "default text to UTF8" do
65
+ it "default text to UTF8" do
61
66
  env = Rack::MockRequest.env_for("/", multipart_fixture(:text))
62
67
  params = Rack::Multipart.parse_multipart(env)
63
- params['submit-name'].encoding.should.equal Encoding::UTF_8
64
- params['submit-name-with-content'].encoding.should.equal Encoding::UTF_8
68
+ params['submit-name'].encoding.must_equal Encoding::UTF_8
69
+ params['submit-name-with-content'].encoding.must_equal Encoding::UTF_8
65
70
  params.keys.each do |key|
66
- key.encoding.should.equal Encoding::UTF_8
71
+ key.encoding.must_equal Encoding::UTF_8
67
72
  end
68
73
  end
74
+
75
+ it "handles quoted encodings" do
76
+ # See #905
77
+ env = Rack::MockRequest.env_for("/", multipart_fixture(:unity3d_wwwform))
78
+ params = Rack::Multipart.parse_multipart(env)
79
+ params['user_sid'].encoding.must_equal Encoding::UTF_8
69
80
  end
70
81
 
71
- should "raise RangeError if the key space is exhausted" do
82
+ it "raise RangeError if the key space is exhausted" do
72
83
  env = Rack::MockRequest.env_for("/", multipart_fixture(:content_type_and_no_filename))
73
84
 
74
85
  old, Rack::Utils.key_space_limit = Rack::Utils.key_space_limit, 1
75
86
  begin
76
- lambda { Rack::Multipart.parse_multipart(env) }.should.raise(RangeError)
87
+ lambda { Rack::Multipart.parse_multipart(env) }.must_raise(RangeError)
77
88
  ensure
78
89
  Rack::Utils.key_space_limit = old
79
90
  end
80
91
  end
81
92
 
82
- should "parse multipart form webkit style" do
93
+ it "parse multipart form webkit style" do
83
94
  env = Rack::MockRequest.env_for '/', multipart_fixture(:webkit)
84
95
  env['CONTENT_TYPE'] = "multipart/form-data; boundary=----WebKitFormBoundaryWLHCs9qmcJJoyjKR"
85
96
  params = Rack::Multipart.parse_multipart(env)
86
- params['profile']['bio'].should.include 'hello'
97
+ params['profile']['bio'].must_include 'hello'
98
+ params['profile'].keys.must_include 'public_email'
87
99
  end
88
100
 
89
- should "reject insanely long boundaries" do
101
+ it "reject insanely long boundaries" do
90
102
  # using a pipe since a tempfile can use up too much space
91
103
  rd, wr = IO.pipe
92
104
 
@@ -131,279 +143,309 @@ describe Rack::Multipart do
131
143
  env = Rack::MockRequest.env_for '/', fixture
132
144
  lambda {
133
145
  Rack::Multipart.parse_multipart(env)
134
- }.should.raise(EOFError)
146
+ }.must_raise EOFError
135
147
  rd.close
136
148
 
137
149
  err = thr.value
138
- err.should.be.instance_of Errno::EPIPE
150
+ err.must_be_instance_of Errno::EPIPE
139
151
  wr.close
140
152
  end
141
153
 
142
- should "parse multipart upload with text file" do
154
+ it 'raises an EOF error on content-length mistmatch' do
155
+ env = Rack::MockRequest.env_for("/", multipart_fixture(:empty))
156
+ env['rack.input'] = StringIO.new
157
+ assert_raises(EOFError) do
158
+ Rack::Multipart.parse_multipart(env)
159
+ end
160
+ end
161
+
162
+ it "parse multipart upload with text file" do
143
163
  env = Rack::MockRequest.env_for("/", multipart_fixture(:text))
144
164
  params = Rack::Multipart.parse_multipart(env)
145
- params["submit-name"].should.equal "Larry"
146
- params["submit-name-with-content"].should.equal "Berry"
147
- params["files"][:type].should.equal "text/plain"
148
- params["files"][:filename].should.equal "file1.txt"
149
- params["files"][:head].should.equal "Content-Disposition: form-data; " +
165
+ params["submit-name"].must_equal "Larry"
166
+ params["submit-name-with-content"].must_equal "Berry"
167
+ params["files"][:type].must_equal "text/plain"
168
+ params["files"][:filename].must_equal "file1.txt"
169
+ params["files"][:head].must_equal "Content-Disposition: form-data; " +
150
170
  "name=\"files\"; filename=\"file1.txt\"\r\n" +
151
171
  "Content-Type: text/plain\r\n"
152
- params["files"][:name].should.equal "files"
153
- params["files"][:tempfile].read.should.equal "contents"
172
+ params["files"][:name].must_equal "files"
173
+ params["files"][:tempfile].read.must_equal "contents"
154
174
  end
155
175
 
156
- should "preserve extension in the created tempfile" do
176
+ it "accept the params hash class to use for multipart parsing" do
177
+ c = Class.new(Rack::QueryParser::Params) do
178
+ def initialize(*)
179
+ super
180
+ @params = Hash.new{|h,k| h[k.to_s] if k.is_a?(Symbol)}
181
+ end
182
+ end
183
+ query_parser = Rack::QueryParser.new c, 65536, 100
184
+ env = Rack::MockRequest.env_for("/", multipart_fixture(:text))
185
+ params = Rack::Multipart.parse_multipart(env, query_parser)
186
+ params[:files][:type].must_equal "text/plain"
187
+ end
188
+
189
+ it "preserve extension in the created tempfile" do
157
190
  env = Rack::MockRequest.env_for("/", multipart_fixture(:text))
158
191
  params = Rack::Multipart.parse_multipart(env)
159
- File.extname(params["files"][:tempfile].path).should.equal ".txt"
192
+ File.extname(params["files"][:tempfile].path).must_equal ".txt"
160
193
  end
161
194
 
162
- should "parse multipart upload with text file with no name field" do
195
+ it "parse multipart upload with text file with no name field" do
163
196
  env = Rack::MockRequest.env_for("/", multipart_fixture(:filename_and_no_name))
164
197
  params = Rack::Multipart.parse_multipart(env)
165
- params["file1.txt"][:type].should.equal "text/plain"
166
- params["file1.txt"][:filename].should.equal "file1.txt"
167
- params["file1.txt"][:head].should.equal "Content-Disposition: form-data; " +
198
+ params["file1.txt"][:type].must_equal "text/plain"
199
+ params["file1.txt"][:filename].must_equal "file1.txt"
200
+ params["file1.txt"][:head].must_equal "Content-Disposition: form-data; " +
168
201
  "filename=\"file1.txt\"\r\n" +
169
202
  "Content-Type: text/plain\r\n"
170
- params["file1.txt"][:name].should.equal "file1.txt"
171
- params["file1.txt"][:tempfile].read.should.equal "contents"
203
+ params["file1.txt"][:name].must_equal "file1.txt"
204
+ params["file1.txt"][:tempfile].read.must_equal "contents"
172
205
  end
173
206
 
174
- should "parse multipart upload file using custom tempfile class" do
207
+ it "parse multipart upload file using custom tempfile class" do
175
208
  env = Rack::MockRequest.env_for("/", multipart_fixture(:text))
176
209
  my_tempfile = ""
177
210
  env['rack.multipart.tempfile_factory'] = lambda { |filename, content_type| my_tempfile }
178
211
  params = Rack::Multipart.parse_multipart(env)
179
- params["files"][:tempfile].object_id.should.equal my_tempfile.object_id
180
- my_tempfile.should.equal "contents"
212
+ params["files"][:tempfile].object_id.must_equal my_tempfile.object_id
213
+ my_tempfile.must_equal "contents"
181
214
  end
182
215
 
183
- should "parse multipart upload with nested parameters" do
216
+ it "parse multipart upload with nested parameters" do
184
217
  env = Rack::MockRequest.env_for("/", multipart_fixture(:nested))
185
218
  params = Rack::Multipart.parse_multipart(env)
186
- params["foo"]["submit-name"].should.equal "Larry"
187
- params["foo"]["files"][:type].should.equal "text/plain"
188
- params["foo"]["files"][:filename].should.equal "file1.txt"
189
- params["foo"]["files"][:head].should.equal "Content-Disposition: form-data; " +
219
+ params["foo"]["submit-name"].must_equal "Larry"
220
+ params["foo"]["files"][:type].must_equal "text/plain"
221
+ params["foo"]["files"][:filename].must_equal "file1.txt"
222
+ params["foo"]["files"][:head].must_equal "Content-Disposition: form-data; " +
190
223
  "name=\"foo[files]\"; filename=\"file1.txt\"\r\n" +
191
224
  "Content-Type: text/plain\r\n"
192
- params["foo"]["files"][:name].should.equal "foo[files]"
193
- params["foo"]["files"][:tempfile].read.should.equal "contents"
225
+ params["foo"]["files"][:name].must_equal "foo[files]"
226
+ params["foo"]["files"][:tempfile].read.must_equal "contents"
194
227
  end
195
228
 
196
- should "parse multipart upload with binary file" do
229
+ it "parse multipart upload with binary file" do
197
230
  env = Rack::MockRequest.env_for("/", multipart_fixture(:binary))
198
231
  params = Rack::Multipart.parse_multipart(env)
199
- params["submit-name"].should.equal "Larry"
200
- params["files"][:type].should.equal "image/png"
201
- params["files"][:filename].should.equal "rack-logo.png"
202
- params["files"][:head].should.equal "Content-Disposition: form-data; " +
232
+ params["submit-name"].must_equal "Larry"
233
+
234
+ params["files"][:type].must_equal "image/png"
235
+ params["files"][:filename].must_equal "rack-logo.png"
236
+ params["files"][:head].must_equal "Content-Disposition: form-data; " +
203
237
  "name=\"files\"; filename=\"rack-logo.png\"\r\n" +
204
238
  "Content-Type: image/png\r\n"
205
- params["files"][:name].should.equal "files"
206
- params["files"][:tempfile].read.length.should.equal 26473
239
+ params["files"][:name].must_equal "files"
240
+ params["files"][:tempfile].read.length.must_equal 26473
207
241
  end
208
242
 
209
- should "parse multipart upload with empty file" do
243
+ it "parse multipart upload with empty file" do
210
244
  env = Rack::MockRequest.env_for("/", multipart_fixture(:empty))
211
245
  params = Rack::Multipart.parse_multipart(env)
212
- params["submit-name"].should.equal "Larry"
213
- params["files"][:type].should.equal "text/plain"
214
- params["files"][:filename].should.equal "file1.txt"
215
- params["files"][:head].should.equal "Content-Disposition: form-data; " +
246
+ params["submit-name"].must_equal "Larry"
247
+ params["files"][:type].must_equal "text/plain"
248
+ params["files"][:filename].must_equal "file1.txt"
249
+ params["files"][:head].must_equal "Content-Disposition: form-data; " +
216
250
  "name=\"files\"; filename=\"file1.txt\"\r\n" +
217
251
  "Content-Type: text/plain\r\n"
218
- params["files"][:name].should.equal "files"
219
- params["files"][:tempfile].read.should.equal ""
252
+ params["files"][:name].must_equal "files"
253
+ params["files"][:tempfile].read.must_equal ""
220
254
  end
221
255
 
222
- should "parse multipart upload with filename with semicolons" do
256
+ it "parse multipart upload with filename with semicolons" do
223
257
  env = Rack::MockRequest.env_for("/", multipart_fixture(:semicolon))
224
258
  params = Rack::Multipart.parse_multipart(env)
225
- params["files"][:type].should.equal "text/plain"
226
- params["files"][:filename].should.equal "fi;le1.txt"
227
- params["files"][:head].should.equal "Content-Disposition: form-data; " +
259
+ params["files"][:type].must_equal "text/plain"
260
+ params["files"][:filename].must_equal "fi;le1.txt"
261
+ params["files"][:head].must_equal "Content-Disposition: form-data; " +
228
262
  "name=\"files\"; filename=\"fi;le1.txt\"\r\n" +
229
263
  "Content-Type: text/plain\r\n"
230
- params["files"][:name].should.equal "files"
231
- params["files"][:tempfile].read.should.equal "contents"
264
+ params["files"][:name].must_equal "files"
265
+ params["files"][:tempfile].read.must_equal "contents"
266
+ end
267
+
268
+ it "parse multipart upload with quoted boundary" do
269
+ env = Rack::MockRequest.env_for("/", multipart_fixture(:quoted, %("AaB:03x")))
270
+ params = Rack::Multipart.parse_multipart(env)
271
+ params["submit-name"].must_equal "Larry"
272
+ params["submit-name-with-content"].must_equal "Berry"
273
+ params["files"][:type].must_equal "text/plain"
274
+ params["files"][:filename].must_equal "file1.txt"
275
+ params["files"][:head].must_equal "Content-Disposition: form-data; " +
276
+ "name=\"files\"; filename=\"file1.txt\"\r\n" +
277
+ "Content-Type: text/plain\r\n"
278
+ params["files"][:name].must_equal "files"
279
+ params["files"][:tempfile].read.must_equal "contents"
232
280
  end
233
281
 
234
- should "parse multipart upload with filename with invalid characters" do
282
+ it "parse multipart upload with filename with invalid characters" do
235
283
  env = Rack::MockRequest.env_for("/", multipart_fixture(:invalid_character))
236
284
  params = Rack::Multipart.parse_multipart(env)
237
- params["files"][:type].should.equal "text/plain"
238
- params["files"][:filename].should.match(/invalid/)
285
+ params["files"][:type].must_equal "text/plain"
286
+ params["files"][:filename].must_match(/invalid/)
239
287
  head = "Content-Disposition: form-data; " +
240
288
  "name=\"files\"; filename=\"invalid\xC3.txt\"\r\n" +
241
289
  "Content-Type: text/plain\r\n"
242
- head = head.force_encoding("ASCII-8BIT") if head.respond_to?(:force_encoding)
243
- params["files"][:head].should.equal head
244
- params["files"][:name].should.equal "files"
245
- params["files"][:tempfile].read.should.equal "contents"
290
+ head = head.force_encoding(Encoding::ASCII_8BIT)
291
+ params["files"][:head].must_equal head
292
+ params["files"][:name].must_equal "files"
293
+ params["files"][:tempfile].read.must_equal "contents"
246
294
  end
247
295
 
248
- should "not include file params if no file was selected" do
249
- env = Rack::MockRequest.env_for("/", multipart_fixture(:none))
296
+ it "parse multipart form with an encoded word filename" do
297
+ env = Rack::MockRequest.env_for '/', multipart_fixture(:filename_with_encoded_words)
250
298
  params = Rack::Multipart.parse_multipart(env)
251
- params["submit-name"].should.equal "Larry"
252
- params["files"].should.equal nil
253
- params.keys.should.not.include "files"
299
+ params["files"][:filename].must_equal "файл"
254
300
  end
255
301
 
256
- should "parse multipart/mixed" do
257
- env = Rack::MockRequest.env_for("/", multipart_fixture(:mixed_files))
258
- params = Rack::Utils::Multipart.parse_multipart(env)
259
- params["foo"].should.equal "bar"
260
- params["files"].should.be.instance_of String
261
- params["files"].size.should.equal 252
302
+ it "parse multipart form with a single quote in the filename" do
303
+ env = Rack::MockRequest.env_for '/', multipart_fixture(:filename_with_single_quote)
304
+ params = Rack::Multipart.parse_multipart(env)
305
+ params["files"][:filename].must_equal "bob's flowers.jpg"
262
306
  end
263
307
 
264
- should "parse multipart form with a null byte in the filename" do
265
- env = Rack::MockRequest.env_for '/', multipart_fixture(:filename_with_null_byte)
308
+ it "not include file params if no file was selected" do
309
+ env = Rack::MockRequest.env_for("/", multipart_fixture(:none))
266
310
  params = Rack::Multipart.parse_multipart(env)
267
- if "<3".respond_to?(:encoding)
268
- params["files"][:filename].should.equal "flowers.exe\u0000.jpg"
269
- else
270
- params["files"][:filename].should.equal "flowers.exe\000.jpg"
271
- end
311
+ params["submit-name"].must_equal "Larry"
312
+ params["files"].must_equal nil
313
+ params.keys.wont_include "files"
272
314
  end
273
315
 
274
- should "parse multipart/mixed" do
316
+ it "parse multipart/mixed" do
275
317
  env = Rack::MockRequest.env_for("/", multipart_fixture(:mixed_files))
276
- params = Rack::Utils::Multipart.parse_multipart(env)
277
- params["foo"].should.equal "bar"
278
- params["files"].should.be.instance_of String
279
- params["files"].size.should.equal 252
318
+ params = Rack::Multipart.parse_multipart(env)
319
+ params["foo"].must_equal "bar"
320
+ params["files"].must_be_instance_of String
321
+ params["files"].size.must_equal 252
280
322
  end
281
323
 
282
- should "parse IE multipart upload and clean up filename" do
324
+ it "parse IE multipart upload and clean up filename" do
283
325
  env = Rack::MockRequest.env_for("/", multipart_fixture(:ie))
284
326
  params = Rack::Multipart.parse_multipart(env)
285
- params["files"][:type].should.equal "text/plain"
286
- params["files"][:filename].should.equal "file1.txt"
287
- params["files"][:head].should.equal "Content-Disposition: form-data; " +
327
+ params["files"][:type].must_equal "text/plain"
328
+ params["files"][:filename].must_equal "file1.txt"
329
+ params["files"][:head].must_equal "Content-Disposition: form-data; " +
288
330
  "name=\"files\"; " +
289
331
  'filename="C:\Documents and Settings\Administrator\Desktop\file1.txt"' +
290
332
  "\r\nContent-Type: text/plain\r\n"
291
- params["files"][:name].should.equal "files"
292
- params["files"][:tempfile].read.should.equal "contents"
333
+ params["files"][:name].must_equal "files"
334
+ params["files"][:tempfile].read.must_equal "contents"
293
335
  end
294
336
 
295
- should "parse filename and modification param" do
337
+ it "parse filename and modification param" do
296
338
  env = Rack::MockRequest.env_for("/", multipart_fixture(:filename_and_modification_param))
297
339
  params = Rack::Multipart.parse_multipart(env)
298
- params["files"][:type].should.equal "image/jpeg"
299
- params["files"][:filename].should.equal "genome.jpeg"
300
- params["files"][:head].should.equal "Content-Type: image/jpeg\r\n" +
340
+ params["files"][:type].must_equal "image/jpeg"
341
+ params["files"][:filename].must_equal "genome.jpeg"
342
+ params["files"][:head].must_equal "Content-Type: image/jpeg\r\n" +
301
343
  "Content-Disposition: attachment; " +
302
344
  "name=\"files\"; " +
303
345
  "filename=genome.jpeg; " +
304
346
  "modification-date=\"Wed, 12 Feb 1997 16:29:51 -0500\";\r\n" +
305
347
  "Content-Description: a complete map of the human genome\r\n"
306
- params["files"][:name].should.equal "files"
307
- params["files"][:tempfile].read.should.equal "contents"
348
+ params["files"][:name].must_equal "files"
349
+ params["files"][:tempfile].read.must_equal "contents"
308
350
  end
309
351
 
310
- should "parse filename with escaped quotes" do
352
+ it "parse filename with escaped quotes" do
311
353
  env = Rack::MockRequest.env_for("/", multipart_fixture(:filename_with_escaped_quotes))
312
354
  params = Rack::Multipart.parse_multipart(env)
313
- params["files"][:type].should.equal "application/octet-stream"
314
- params["files"][:filename].should.equal "escape \"quotes"
315
- params["files"][:head].should.equal "Content-Disposition: form-data; " +
355
+ params["files"][:type].must_equal "application/octet-stream"
356
+ params["files"][:filename].must_equal "escape \"quotes"
357
+ params["files"][:head].must_equal "Content-Disposition: form-data; " +
316
358
  "name=\"files\"; " +
317
359
  "filename=\"escape \\\"quotes\"\r\n" +
318
360
  "Content-Type: application/octet-stream\r\n"
319
- params["files"][:name].should.equal "files"
320
- params["files"][:tempfile].read.should.equal "contents"
361
+ params["files"][:name].must_equal "files"
362
+ params["files"][:tempfile].read.must_equal "contents"
321
363
  end
322
364
 
323
- should "parse filename with percent escaped quotes" do
365
+ it "parse filename with percent escaped quotes" do
324
366
  env = Rack::MockRequest.env_for("/", multipart_fixture(:filename_with_percent_escaped_quotes))
325
367
  params = Rack::Multipart.parse_multipart(env)
326
- params["files"][:type].should.equal "application/octet-stream"
327
- params["files"][:filename].should.equal "escape \"quotes"
328
- params["files"][:head].should.equal "Content-Disposition: form-data; " +
368
+ params["files"][:type].must_equal "application/octet-stream"
369
+ params["files"][:filename].must_equal "escape \"quotes"
370
+ params["files"][:head].must_equal "Content-Disposition: form-data; " +
329
371
  "name=\"files\"; " +
330
372
  "filename=\"escape %22quotes\"\r\n" +
331
373
  "Content-Type: application/octet-stream\r\n"
332
- params["files"][:name].should.equal "files"
333
- params["files"][:tempfile].read.should.equal "contents"
374
+ params["files"][:name].must_equal "files"
375
+ params["files"][:tempfile].read.must_equal "contents"
334
376
  end
335
377
 
336
- should "parse filename with unescaped quotes" do
378
+ it "parse filename with unescaped quotes" do
337
379
  env = Rack::MockRequest.env_for("/", multipart_fixture(:filename_with_unescaped_quotes))
338
380
  params = Rack::Multipart.parse_multipart(env)
339
- params["files"][:type].should.equal "application/octet-stream"
340
- params["files"][:filename].should.equal "escape \"quotes"
341
- params["files"][:head].should.equal "Content-Disposition: form-data; " +
381
+ params["files"][:type].must_equal "application/octet-stream"
382
+ params["files"][:filename].must_equal "escape \"quotes"
383
+ params["files"][:head].must_equal "Content-Disposition: form-data; " +
342
384
  "name=\"files\"; " +
343
385
  "filename=\"escape \"quotes\"\r\n" +
344
386
  "Content-Type: application/octet-stream\r\n"
345
- params["files"][:name].should.equal "files"
346
- params["files"][:tempfile].read.should.equal "contents"
387
+ params["files"][:name].must_equal "files"
388
+ params["files"][:tempfile].read.must_equal "contents"
347
389
  end
348
390
 
349
- should "parse filename with escaped quotes and modification param" do
391
+ it "parse filename with escaped quotes and modification param" do
350
392
  env = Rack::MockRequest.env_for("/", multipart_fixture(:filename_with_escaped_quotes_and_modification_param))
351
393
  params = Rack::Multipart.parse_multipart(env)
352
- params["files"][:type].should.equal "image/jpeg"
353
- params["files"][:filename].should.equal "\"human\" genome.jpeg"
354
- params["files"][:head].should.equal "Content-Type: image/jpeg\r\n" +
394
+ params["files"][:type].must_equal "image/jpeg"
395
+ params["files"][:filename].must_equal "\"human\" genome.jpeg"
396
+ params["files"][:head].must_equal "Content-Type: image/jpeg\r\n" +
355
397
  "Content-Disposition: attachment; " +
356
398
  "name=\"files\"; " +
357
399
  "filename=\"\"human\" genome.jpeg\"; " +
358
400
  "modification-date=\"Wed, 12 Feb 1997 16:29:51 -0500\";\r\n" +
359
401
  "Content-Description: a complete map of the human genome\r\n"
360
- params["files"][:name].should.equal "files"
361
- params["files"][:tempfile].read.should.equal "contents"
402
+ params["files"][:name].must_equal "files"
403
+ params["files"][:tempfile].read.must_equal "contents"
362
404
  end
363
405
 
364
- should "parse filename with unescaped percentage characters" do
406
+ it "parse filename with unescaped percentage characters" do
365
407
  env = Rack::MockRequest.env_for("/", multipart_fixture(:filename_with_unescaped_percentages, "----WebKitFormBoundary2NHc7OhsgU68l3Al"))
366
408
  params = Rack::Multipart.parse_multipart(env)
367
409
  files = params["document"]["attachment"]
368
- files[:type].should.equal "image/jpeg"
369
- files[:filename].should.equal "100% of a photo.jpeg"
370
- files[:head].should.equal <<-MULTIPART
410
+ files[:type].must_equal "image/jpeg"
411
+ files[:filename].must_equal "100% of a photo.jpeg"
412
+ files[:head].must_equal <<-MULTIPART
371
413
  Content-Disposition: form-data; name="document[attachment]"; filename="100% of a photo.jpeg"\r
372
414
  Content-Type: image/jpeg\r
373
415
  MULTIPART
374
416
 
375
- files[:name].should.equal "document[attachment]"
376
- files[:tempfile].read.should.equal "contents"
417
+ files[:name].must_equal "document[attachment]"
418
+ files[:tempfile].read.must_equal "contents"
377
419
  end
378
420
 
379
- should "parse filename with unescaped percentage characters that look like partial hex escapes" do
421
+ it "parse filename with unescaped percentage characters that look like partial hex escapes" do
380
422
  env = Rack::MockRequest.env_for("/", multipart_fixture(:filename_with_unescaped_percentages2, "----WebKitFormBoundary2NHc7OhsgU68l3Al"))
381
423
  params = Rack::Multipart.parse_multipart(env)
382
424
  files = params["document"]["attachment"]
383
- files[:type].should.equal "image/jpeg"
384
- files[:filename].should.equal "100%a"
385
- files[:head].should.equal <<-MULTIPART
425
+ files[:type].must_equal "image/jpeg"
426
+ files[:filename].must_equal "100%a"
427
+ files[:head].must_equal <<-MULTIPART
386
428
  Content-Disposition: form-data; name="document[attachment]"; filename="100%a"\r
387
429
  Content-Type: image/jpeg\r
388
430
  MULTIPART
389
431
 
390
- files[:name].should.equal "document[attachment]"
391
- files[:tempfile].read.should.equal "contents"
432
+ files[:name].must_equal "document[attachment]"
433
+ files[:tempfile].read.must_equal "contents"
392
434
  end
393
435
 
394
- should "parse filename with unescaped percentage characters that look like partial hex escapes" do
436
+ it "parse filename with unescaped percentage characters that look like partial hex escapes" do
395
437
  env = Rack::MockRequest.env_for("/", multipart_fixture(:filename_with_unescaped_percentages3, "----WebKitFormBoundary2NHc7OhsgU68l3Al"))
396
438
  params = Rack::Multipart.parse_multipart(env)
397
439
  files = params["document"]["attachment"]
398
- files[:type].should.equal "image/jpeg"
399
- files[:filename].should.equal "100%"
400
- files[:head].should.equal <<-MULTIPART
440
+ files[:type].must_equal "image/jpeg"
441
+ files[:filename].must_equal "100%"
442
+ files[:head].must_equal <<-MULTIPART
401
443
  Content-Disposition: form-data; name="document[attachment]"; filename="100%"\r
402
444
  Content-Type: image/jpeg\r
403
445
  MULTIPART
404
446
 
405
- files[:name].should.equal "document[attachment]"
406
- files[:tempfile].read.should.equal "contents"
447
+ files[:name].must_equal "document[attachment]"
448
+ files[:tempfile].read.must_equal "contents"
407
449
  end
408
450
 
409
451
  it "rewinds input after parsing upload" do
@@ -411,9 +453,9 @@ Content-Type: image/jpeg\r
411
453
  input = options[:input]
412
454
  env = Rack::MockRequest.env_for("/", options)
413
455
  params = Rack::Multipart.parse_multipart(env)
414
- params["submit-name"].should.equal "Larry"
415
- params["files"][:filename].should.equal "file1.txt"
416
- input.read.length.should.equal 307
456
+ params["submit-name"].must_equal "Larry"
457
+ params["files"][:filename].must_equal "file1.txt"
458
+ input.read.length.must_equal 307
417
459
  end
418
460
 
419
461
  it "builds multipart body" do
@@ -427,9 +469,9 @@ Content-Type: image/jpeg\r
427
469
  }
428
470
  env = Rack::MockRequest.env_for("/", options)
429
471
  params = Rack::Multipart.parse_multipart(env)
430
- params["submit-name"].should.equal "Larry"
431
- params["files"][:filename].should.equal "file1.txt"
432
- params["files"][:tempfile].read.should.equal "contents"
472
+ params["submit-name"].must_equal "Larry"
473
+ params["files"][:filename].must_equal "file1.txt"
474
+ params["files"][:tempfile].read.must_equal "contents"
433
475
  end
434
476
 
435
477
  it "builds nested multipart body" do
@@ -443,9 +485,9 @@ Content-Type: image/jpeg\r
443
485
  }
444
486
  env = Rack::MockRequest.env_for("/", options)
445
487
  params = Rack::Multipart.parse_multipart(env)
446
- params["people"][0]["submit-name"].should.equal "Larry"
447
- params["people"][0]["files"][:filename].should.equal "file1.txt"
448
- params["people"][0]["files"][:tempfile].read.should.equal "contents"
488
+ params["people"][0]["submit-name"].must_equal "Larry"
489
+ params["people"][0]["files"][:filename].must_equal "file1.txt"
490
+ params["people"][0]["files"][:tempfile].read.must_equal "contents"
449
491
  end
450
492
 
451
493
  it "can parse fields that end at the end of the buffer" do
@@ -456,8 +498,8 @@ Content-Type: image/jpeg\r
456
498
  "CONTENT_LENGTH" => input.size,
457
499
  :input => input)
458
500
 
459
- req.POST['file.path'].should.equal "/var/tmp/uploads/4/0001728414"
460
- req.POST['addresses'].should.not.equal nil
501
+ req.POST['file.path'].must_equal "/var/tmp/uploads/4/0001728414"
502
+ req.POST['addresses'].wont_equal nil
461
503
  end
462
504
 
463
505
  it "builds complete params with the chunk size of 16384 slicing exactly on boundary" do
@@ -474,54 +516,54 @@ Content-Type: image/jpeg\r
474
516
  env = Rack::MockRequest.env_for("/", options)
475
517
  params = Rack::Multipart.parse_multipart(env)
476
518
 
477
- params.should.not.equal nil
478
- params.keys.should.include "AAAAAAAAAAAAAAAAAAA"
479
- params["AAAAAAAAAAAAAAAAAAA"].keys.should.include "PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"
480
- params["AAAAAAAAAAAAAAAAAAA"]["PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"].keys.should.include "new"
481
- params["AAAAAAAAAAAAAAAAAAA"]["PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"]["new"].keys.should.include "-2"
482
- params["AAAAAAAAAAAAAAAAAAA"]["PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"]["new"]["-2"].keys.should.include "ba_unit_id"
483
- params["AAAAAAAAAAAAAAAAAAA"]["PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"]["new"]["-2"]["ba_unit_id"].should.equal "1017"
519
+ params.wont_equal nil
520
+ params.keys.must_include "AAAAAAAAAAAAAAAAAAA"
521
+ params["AAAAAAAAAAAAAAAAAAA"].keys.must_include "PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"
522
+ params["AAAAAAAAAAAAAAAAAAA"]["PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"].keys.must_include "new"
523
+ params["AAAAAAAAAAAAAAAAAAA"]["PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"]["new"].keys.must_include "-2"
524
+ params["AAAAAAAAAAAAAAAAAAA"]["PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"]["new"]["-2"].keys.must_include "ba_unit_id"
525
+ params["AAAAAAAAAAAAAAAAAAA"]["PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"]["new"]["-2"]["ba_unit_id"].must_equal "1017"
484
526
  ensure
485
527
  Rack::Utils.multipart_part_limit = previous_limit
486
528
  end
487
529
  end
488
530
 
489
- should "not reach a multi-part limit" do
531
+ it "not reach a multi-part limit" do
490
532
  begin
491
533
  previous_limit = Rack::Utils.multipart_part_limit
492
534
  Rack::Utils.multipart_part_limit = 4
493
535
 
494
536
  env = Rack::MockRequest.env_for '/', multipart_fixture(:three_files_three_fields)
495
537
  params = Rack::Multipart.parse_multipart(env)
496
- params['reply'].should.equal 'yes'
497
- params['to'].should.equal 'people'
498
- params['from'].should.equal 'others'
538
+ params['reply'].must_equal 'yes'
539
+ params['to'].must_equal 'people'
540
+ params['from'].must_equal 'others'
499
541
  ensure
500
542
  Rack::Utils.multipart_part_limit = previous_limit
501
543
  end
502
544
  end
503
545
 
504
- should "reach a multipart limit" do
546
+ it "reach a multipart limit" do
505
547
  begin
506
548
  previous_limit = Rack::Utils.multipart_part_limit
507
549
  Rack::Utils.multipart_part_limit = 3
508
550
 
509
551
  env = Rack::MockRequest.env_for '/', multipart_fixture(:three_files_three_fields)
510
- lambda { Rack::Multipart.parse_multipart(env) }.should.raise(Rack::Multipart::MultipartPartLimitError)
552
+ lambda { Rack::Multipart.parse_multipart(env) }.must_raise Rack::Multipart::MultipartPartLimitError
511
553
  ensure
512
554
  Rack::Utils.multipart_part_limit = previous_limit
513
555
  end
514
556
  end
515
557
 
516
- should "return nil if no UploadedFiles were used" do
558
+ it "return nil if no UploadedFiles were used" do
517
559
  data = Rack::Multipart.build_multipart("people" => [{"submit-name" => "Larry", "files" => "contents"}])
518
- data.should.equal nil
560
+ data.must_equal nil
519
561
  end
520
562
 
521
- should "raise ArgumentError if params is not a Hash" do
522
- lambda { Rack::Multipart.build_multipart("foo=bar") }.
523
- should.raise(ArgumentError).
524
- message.should.equal "value must be a Hash"
563
+ it "raise ArgumentError if params is not a Hash" do
564
+ lambda {
565
+ Rack::Multipart.build_multipart("foo=bar")
566
+ }.must_raise(ArgumentError).message.must_equal "value must be a Hash"
525
567
  end
526
568
 
527
569
  it "can parse fields with a content type" do
@@ -539,20 +581,20 @@ EOF
539
581
  :input => StringIO.new(data)
540
582
  }
541
583
  env = Rack::MockRequest.env_for("/", options)
542
- params = Rack::Utils::Multipart.parse_multipart(env)
584
+ params = Rack::Multipart.parse_multipart(env)
543
585
 
544
- params.should.equal({"description"=>"Very very blue"})
586
+ params.must_equal "description"=>"Very very blue"
545
587
  end
546
588
 
547
- should "parse multipart upload with no content-length header" do
589
+ it "parse multipart upload with no content-length header" do
548
590
  env = Rack::MockRequest.env_for '/', multipart_fixture(:webkit)
549
591
  env['CONTENT_TYPE'] = "multipart/form-data; boundary=----WebKitFormBoundaryWLHCs9qmcJJoyjKR"
550
592
  env.delete 'CONTENT_LENGTH'
551
593
  params = Rack::Multipart.parse_multipart(env)
552
- params['profile']['bio'].should.include 'hello'
594
+ params['profile']['bio'].must_include 'hello'
553
595
  end
554
596
 
555
- should "parse very long unquoted multipart file names" do
597
+ it "parse very long unquoted multipart file names" do
556
598
  data = <<-EOF
557
599
  --AaB03x\r
558
600
  Content-Type: text/plain\r
@@ -568,17 +610,57 @@ contents\r
568
610
  :input => StringIO.new(data)
569
611
  }
570
612
  env = Rack::MockRequest.env_for("/", options)
571
- params = Rack::Utils::Multipart.parse_multipart(env)
613
+ params = Rack::Multipart.parse_multipart(env)
572
614
 
573
- params["file"][:filename].should.equal('long' * 100)
615
+ params["file"][:filename].must_equal 'long' * 100
574
616
  end
575
617
 
576
- should "support mixed case metadata" do
618
+ it "parse unquoted parameter values at end of line" do
619
+ data = <<-EOF
620
+ --AaB03x\r
621
+ Content-Type: text/plain\r
622
+ Content-Disposition: attachment; name=inline\r
623
+ \r
624
+ true\r
625
+ --AaB03x--\r
626
+ EOF
627
+
628
+ options = {
629
+ "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x",
630
+ "CONTENT_LENGTH" => data.length.to_s,
631
+ :input => StringIO.new(data)
632
+ }
633
+ env = Rack::MockRequest.env_for("/", options)
634
+ params = Rack::Multipart.parse_multipart(env)
635
+ params["inline"].must_equal 'true'
636
+ end
637
+
638
+ it "parse quoted chars in name parameter" do
639
+ data = <<-EOF
640
+ --AaB03x\r
641
+ Content-Type: text/plain\r
642
+ Content-Disposition: attachment; name="quoted\\\\chars\\"in\rname"\r
643
+ \r
644
+ true\r
645
+ --AaB03x--\r
646
+ EOF
647
+
648
+ options = {
649
+ "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x",
650
+ "CONTENT_LENGTH" => data.length.to_s,
651
+ :input => StringIO.new(data)
652
+ }
653
+ env = Rack::MockRequest.env_for("/", options)
654
+ params = Rack::Multipart.parse_multipart(env)
655
+ params["quoted\\chars\"in\rname"].must_equal 'true'
656
+ end
657
+
658
+ it "support mixed case metadata" do
577
659
  file = multipart_file(:text)
578
660
  data = File.open(file, 'rb') { |io| io.read }
579
661
 
580
662
  type = "Multipart/Form-Data; Boundary=AaB03x"
581
- length = data.respond_to?(:bytesize) ? data.bytesize : data.size
663
+ length = data.bytesize
582
664
 
583
665
  e = { "CONTENT_TYPE" => type,
584
666
  "CONTENT_LENGTH" => length.to_s,
@@ -586,15 +668,49 @@ contents\r
586
668
 
587
669
  env = Rack::MockRequest.env_for("/", e)
588
670
  params = Rack::Multipart.parse_multipart(env)
589
- params["submit-name"].should.equal "Larry"
590
- params["submit-name-with-content"].should.equal "Berry"
591
- params["files"][:type].should.equal "text/plain"
592
- params["files"][:filename].should.equal "file1.txt"
593
- params["files"][:head].should.equal "Content-Disposition: form-data; " +
671
+ params["submit-name"].must_equal "Larry"
672
+ params["submit-name-with-content"].must_equal "Berry"
673
+ params["files"][:type].must_equal "text/plain"
674
+ params["files"][:filename].must_equal "file1.txt"
675
+ params["files"][:head].must_equal "Content-Disposition: form-data; " +
594
676
  "name=\"files\"; filename=\"file1.txt\"\r\n" +
595
677
  "Content-Type: text/plain\r\n"
596
- params["files"][:name].should.equal "files"
597
- params["files"][:tempfile].read.should.equal "contents"
678
+ params["files"][:name].must_equal "files"
679
+ params["files"][:tempfile].read.must_equal "contents"
598
680
  end
599
681
 
682
+ it "fallback to content-type for name" do
683
+ rack_logo = File.read(multipart_file("rack-logo.png"))
684
+
685
+ data = <<-EOF
686
+ --AaB03x\r
687
+ Content-Type: text/plain\r
688
+ \r
689
+ some text\r
690
+ --AaB03x\r
691
+ \r
692
+ \r
693
+ some more text (I didn't specify Content-Type)\r
694
+ --AaB03x\r
695
+ Content-Type: image/png\r
696
+ \r
697
+ #{rack_logo}\r
698
+ --AaB03x--\r
699
+ EOF
700
+
701
+ options = {
702
+ "CONTENT_TYPE" => "multipart/related; boundary=AaB03x",
703
+ "CONTENT_LENGTH" => data.bytesize.to_s,
704
+ :input => StringIO.new(data)
705
+ }
706
+ env = Rack::MockRequest.env_for("/", options)
707
+ params = Rack::Multipart.parse_multipart(env)
708
+
709
+ params["text/plain"].must_equal ["some text", "some more text (I didn't specify Content-Type)"]
710
+ params["image/png"].length.must_equal 1
711
+
712
+ f = Tempfile.new("rack-logo")
713
+ f.write(params["image/png"][0])
714
+ f.length.must_equal 26473
715
+ end
600
716
  end