From e978c853b64b95ecb52a98b89fac52e89be89905 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Pudil?= Date: Thu, 19 Aug 2021 15:52:36 +0200 Subject: [PATCH] FileUpload: support full_path --- src/Http/FileUpload.php | 17 +++++++++++++++++ tests/Http/FileUpload.basic.phpt | 3 +++ 2 files changed, 20 insertions(+) diff --git a/src/Http/FileUpload.php b/src/Http/FileUpload.php index 37f074bd..1967a235 100644 --- a/src/Http/FileUpload.php +++ b/src/Http/FileUpload.php @@ -17,6 +17,7 @@ * * @property-read string $name * @property-read string $sanitizedName + * @property-read string $untrustedFullPath * @property-read string|null $contentType * @property-read int $size * @property-read string $temporaryFile @@ -32,6 +33,8 @@ final class FileUpload private string $name; + private string|null $fullPath; + private string|false|null $type = null; private int $size; @@ -50,6 +53,7 @@ public function __construct(?array $value) } } $this->name = $value['name']; + $this->fullPath = $value['full_path'] ?? null; $this->size = $value['size']; $this->tmpName = $value['tmp_name']; $this->error = $value['error']; @@ -94,6 +98,19 @@ public function getSanitizedName(): string } + /** + * Returns the original full path as submitted by the browser during directory upload. Do not trust the value + * returned by this method. A client could send a malicious directory structure with the intention to corrupt + * or hack your application. + * + * The full path is only available in PHP 8.1 and above. In previous versions, this method returns the file name. + */ + public function getUntrustedFullPath(): string + { + return $this->fullPath ?? $this->name; + } + + /** * Detects the MIME content type of the uploaded file based on its signature. Requires PHP extension fileinfo. * If the upload was not successful or the detection failed, it returns null. diff --git a/tests/Http/FileUpload.basic.phpt b/tests/Http/FileUpload.basic.phpt index 7e2bd736..00bf6fb7 100644 --- a/tests/Http/FileUpload.basic.phpt +++ b/tests/Http/FileUpload.basic.phpt @@ -16,6 +16,7 @@ require __DIR__ . '/../bootstrap.php'; test('', function () { $upload = new FileUpload([ 'name' => 'readme.txt', + 'full_path' => 'path/to/readme.txt', 'type' => 'text/plain', 'tmp_name' => __DIR__ . '/files/file.txt', 'error' => 0, @@ -25,6 +26,7 @@ test('', function () { Assert::same('readme.txt', $upload->getName()); Assert::same('readme.txt', $upload->getUntrustedName()); Assert::same('readme.txt', $upload->getSanitizedName()); + Assert::same('path/to/readme.txt', $upload->getUntrustedFullPath()); Assert::same(209, $upload->getSize()); Assert::same(__DIR__ . '/files/file.txt', $upload->getTemporaryFile()); Assert::same(__DIR__ . '/files/file.txt', (string) $upload); @@ -48,6 +50,7 @@ test('', function () { Assert::same('../.image.png', $upload->getName()); Assert::same('image.png', $upload->getSanitizedName()); + Assert::same('../.image.png', $upload->getUntrustedFullPath()); Assert::same('image/png', $upload->getContentType()); Assert::same('png', $upload->getImageFileExtension()); Assert::same([108, 46], $upload->getImageSize());