Skip to content

Commit d3f0e03

Browse files
jiripudildg
authored andcommitted
FileUpload: support directory upload (#207)
1 parent 97a8c7c commit d3f0e03

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;
@@ -50,6 +53,7 @@ public function __construct(?array $value)
5053
}
5154
}
5255
$this->name = $value['name'];
56+
$this->fullPath = $value['full_path'] ?? null;
5357
$this->size = $value['size'];
5458
$this->tmpName = $value['tmp_name'];
5559
$this->error = $value['error'];
@@ -94,6 +98,19 @@ public function getSanitizedName(): string
9498
}
9599

96100

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