Skip to content

Commit 7c790ef

Browse files
committed
Handle file uploads with missing or duplicate Content-Type header
1 parent d660095 commit 7c790ef

2 files changed

Lines changed: 70 additions & 3 deletions

File tree

src/Io/MultipartParser.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ private function parseUploadedFile($headers, $body)
140140
{
141141
$filename = $this->getParameterFromHeader($headers['content-disposition'], 'filename');
142142
$bodyLength = strlen($body);
143+
$contentType = isset($headers['content-type'][0]) ? $headers['content-type'][0] : null;
143144

144145
// no file selected (zero size and empty filename)
145146
if ($bodyLength === 0 && $filename === '') {
@@ -148,7 +149,7 @@ private function parseUploadedFile($headers, $body)
148149
$bodyLength,
149150
UPLOAD_ERR_NO_FILE,
150151
$filename,
151-
$headers['content-type'][0]
152+
$contentType
152153
);
153154
}
154155

@@ -159,7 +160,7 @@ private function parseUploadedFile($headers, $body)
159160
$bodyLength,
160161
UPLOAD_ERR_FORM_SIZE,
161162
$filename,
162-
$headers['content-type'][0]
163+
$contentType
163164
);
164165
}
165166

@@ -168,7 +169,7 @@ private function parseUploadedFile($headers, $body)
168169
$bodyLength,
169170
UPLOAD_ERR_OK,
170171
$filename,
171-
$headers['content-type'][0]
172+
$contentType
172173
);
173174
}
174175

tests/Io/MultipartParserTest.php

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,72 @@ public function testInvalidContentDispositionWithoutNameWillBeIgnored()
419419
$this->assertEmpty($parsedRequest->getParsedBody());
420420
}
421421

422+
public function testInvalidUploadFileWithoutContentTypeUsesNullValue()
423+
{
424+
$boundary = "---------------------------12758086162038677464950549563";
425+
426+
$data = "--$boundary\r\n";
427+
$data .= "Content-Disposition: form-data; name=\"file\"; filename=\"hello.txt\"\r\n";
428+
$data .= "\r\n";
429+
$data .= "world\r\n";
430+
$data .= "--$boundary--\r\n";
431+
432+
$request = new ServerRequest('POST', 'http://example.com/', array(
433+
'Content-Type' => 'multipart/mixed; boundary=' . $boundary,
434+
), $data, 1.1);
435+
436+
$parsedRequest = MultipartParser::parseRequest($request);
437+
438+
$files = $parsedRequest->getUploadedFiles();
439+
440+
$this->assertCount(1, $files);
441+
$this->assertTrue(isset($files['file']));
442+
$this->assertInstanceOf('Psr\Http\Message\UploadedFileInterface', $files['file']);
443+
444+
/* @var $file \Psr\Http\Message\UploadedFileInterface */
445+
$file = $files['file'];
446+
447+
$this->assertSame('hello.txt', $file->getClientFilename());
448+
$this->assertSame(null, $file->getClientMediaType());
449+
$this->assertSame(5, $file->getSize());
450+
$this->assertSame(UPLOAD_ERR_OK, $file->getError());
451+
$this->assertSame('world', (string)$file->getStream());
452+
}
453+
454+
public function testInvalidUploadFileWithoutMultipleContentTypeUsesLastValue()
455+
{
456+
$boundary = "---------------------------12758086162038677464950549563";
457+
458+
$data = "--$boundary\r\n";
459+
$data .= "Content-Disposition: form-data; name=\"file\"; filename=\"hello.txt\"\r\n";
460+
$data .= "Content-Type: text/ignored\r\n";
461+
$data .= "Content-Type: text/plain\r\n";
462+
$data .= "\r\n";
463+
$data .= "world\r\n";
464+
$data .= "--$boundary--\r\n";
465+
466+
$request = new ServerRequest('POST', 'http://example.com/', array(
467+
'Content-Type' => 'multipart/mixed; boundary=' . $boundary,
468+
), $data, 1.1);
469+
470+
$parsedRequest = MultipartParser::parseRequest($request);
471+
472+
$files = $parsedRequest->getUploadedFiles();
473+
474+
$this->assertCount(1, $files);
475+
$this->assertTrue(isset($files['file']));
476+
$this->assertInstanceOf('Psr\Http\Message\UploadedFileInterface', $files['file']);
477+
478+
/* @var $file \Psr\Http\Message\UploadedFileInterface */
479+
$file = $files['file'];
480+
481+
$this->assertSame('hello.txt', $file->getClientFilename());
482+
$this->assertSame('text/plain', $file->getClientMediaType());
483+
$this->assertSame(5, $file->getSize());
484+
$this->assertSame(UPLOAD_ERR_OK, $file->getError());
485+
$this->assertSame('world', (string)$file->getStream());
486+
}
487+
422488
public function testUploadEmptyFile()
423489
{
424490
$boundary = "---------------------------12758086162038677464950549563";

0 commit comments

Comments
 (0)