Skip to content

Commit 870a936

Browse files
jiripudildg
authored andcommitted
FileUpload: support directory upload (#207)
1 parent 25daac5 commit 870a936

2 files changed

Lines changed: 20 additions & 0 deletions

File tree

src/Http/FileUpload.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
*
1818
* @property-read string $name
1919
* @property-read string $sanitizedName
20+
* @property-read string $untrustedFullPath
2021
* @property-read string|null $contentType
2122
* @property-read int $size
2223
* @property-read string $temporaryFile
@@ -32,6 +33,8 @@ final class FileUpload
3233

3334
private string $name;
3435

36+
private string|null $fullPath;
37+
3538
private string|false|null $type = null;
3639

3740
private int $size;
@@ -51,6 +54,7 @@ public function __construct(?array $value)
5154
}
5255

5356
$this->name = $value['name'];
57+
$this->fullPath = $value['full_path'] ?? null;
5458
$this->size = $value['size'];
5559
$this->tmpName = $value['tmp_name'];
5660
$this->error = $value['error'];
@@ -96,6 +100,19 @@ public function getSanitizedName(): string
96100
}
97101

98102

103+
/**
104+
* Returns the original full path as submitted by the browser during directory upload. Do not trust the value
105+
* returned by this method. A client could send a malicious directory structure with the intention to corrupt
106+
* or hack your application.
107+
*
108+
* The full path is only available in PHP 8.1 and above. In previous versions, this method returns the file name.
109+
*/
110+
public function getUntrustedFullPath(): string
111+
{
112+
return $this->fullPath ?? $this->name;
113+
}
114+
115+
99116
/**
100117
* Detects the MIME content type of the uploaded file based on its signature. Requires PHP extension fileinfo.
101118
* If the upload was not successful or the detection failed, it returns null.

tests/Http/FileUpload.basic.phpt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ require __DIR__ . '/../bootstrap.php';
1616
test('', function () {
1717
$upload = new FileUpload([
1818
'name' => 'readme.txt',
19+
'full_path' => 'path/to/readme.txt',
1920
'type' => 'text/plain',
2021
'tmp_name' => __DIR__ . '/files/file.txt',
2122
'error' => 0,
@@ -25,6 +26,7 @@ test('', function () {
2526
Assert::same('readme.txt', $upload->getName());
2627
Assert::same('readme.txt', $upload->getUntrustedName());
2728
Assert::same('readme.txt', $upload->getSanitizedName());
29+
Assert::same('path/to/readme.txt', $upload->getUntrustedFullPath());
2830
Assert::same(209, $upload->getSize());
2931
Assert::same(__DIR__ . '/files/file.txt', $upload->getTemporaryFile());
3032
Assert::same(__DIR__ . '/files/file.txt', (string) $upload);
@@ -48,6 +50,7 @@ test('', function () {
4850

4951
Assert::same('../.image.png', $upload->getName());
5052
Assert::same('image.png', $upload->getSanitizedName());
53+
Assert::same('../.image.png', $upload->getUntrustedFullPath());
5154
Assert::same('image/png', $upload->getContentType());
5255
Assert::same('png', $upload->getImageFileExtension());
5356
Assert::same([108, 46], $upload->getImageSize());

0 commit comments

Comments
 (0)