annotate vendor/symfony/http-foundation/File/UploadedFile.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 129ea1e6d783
children
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 /*
Chris@0 4 * This file is part of the Symfony package.
Chris@0 5 *
Chris@0 6 * (c) Fabien Potencier <fabien@symfony.com>
Chris@0 7 *
Chris@0 8 * For the full copyright and license information, please view the LICENSE
Chris@0 9 * file that was distributed with this source code.
Chris@0 10 */
Chris@0 11
Chris@0 12 namespace Symfony\Component\HttpFoundation\File;
Chris@0 13
Chris@0 14 use Symfony\Component\HttpFoundation\File\Exception\FileException;
Chris@0 15 use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
Chris@0 16 use Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser;
Chris@0 17
Chris@0 18 /**
Chris@0 19 * A file uploaded through a form.
Chris@0 20 *
Chris@0 21 * @author Bernhard Schussek <bschussek@gmail.com>
Chris@0 22 * @author Florian Eckerstorfer <florian@eckerstorfer.org>
Chris@0 23 * @author Fabien Potencier <fabien@symfony.com>
Chris@0 24 */
Chris@0 25 class UploadedFile extends File
Chris@0 26 {
Chris@0 27 private $test = false;
Chris@0 28 private $originalName;
Chris@0 29 private $mimeType;
Chris@0 30 private $size;
Chris@0 31 private $error;
Chris@0 32
Chris@0 33 /**
Chris@0 34 * Accepts the information of the uploaded file as provided by the PHP global $_FILES.
Chris@0 35 *
Chris@0 36 * The file object is only created when the uploaded file is valid (i.e. when the
Chris@0 37 * isValid() method returns true). Otherwise the only methods that could be called
Chris@0 38 * on an UploadedFile instance are:
Chris@0 39 *
Chris@0 40 * * getClientOriginalName,
Chris@0 41 * * getClientMimeType,
Chris@0 42 * * isValid,
Chris@0 43 * * getError.
Chris@0 44 *
Chris@0 45 * Calling any other method on an non-valid instance will cause an unpredictable result.
Chris@0 46 *
Chris@0 47 * @param string $path The full temporary path to the file
Chris@14 48 * @param string $originalName The original file name of the uploaded file
Chris@0 49 * @param string|null $mimeType The type of the file as provided by PHP; null defaults to application/octet-stream
Chris@14 50 * @param int|null $size The file size provided by the uploader
Chris@0 51 * @param int|null $error The error constant of the upload (one of PHP's UPLOAD_ERR_XXX constants); null defaults to UPLOAD_ERR_OK
Chris@0 52 * @param bool $test Whether the test mode is active
Chris@14 53 * Local files are used in test mode hence the code should not enforce HTTP uploads
Chris@0 54 *
Chris@0 55 * @throws FileException If file_uploads is disabled
Chris@0 56 * @throws FileNotFoundException If the file does not exist
Chris@0 57 */
Chris@0 58 public function __construct($path, $originalName, $mimeType = null, $size = null, $error = null, $test = false)
Chris@0 59 {
Chris@0 60 $this->originalName = $this->getName($originalName);
Chris@0 61 $this->mimeType = $mimeType ?: 'application/octet-stream';
Chris@0 62 $this->size = $size;
Chris@0 63 $this->error = $error ?: UPLOAD_ERR_OK;
Chris@0 64 $this->test = (bool) $test;
Chris@0 65
Chris@0 66 parent::__construct($path, UPLOAD_ERR_OK === $this->error);
Chris@0 67 }
Chris@0 68
Chris@0 69 /**
Chris@0 70 * Returns the original file name.
Chris@0 71 *
Chris@0 72 * It is extracted from the request from which the file has been uploaded.
Chris@0 73 * Then it should not be considered as a safe value.
Chris@0 74 *
Chris@0 75 * @return string|null The original name
Chris@0 76 */
Chris@0 77 public function getClientOriginalName()
Chris@0 78 {
Chris@0 79 return $this->originalName;
Chris@0 80 }
Chris@0 81
Chris@0 82 /**
Chris@0 83 * Returns the original file extension.
Chris@0 84 *
Chris@0 85 * It is extracted from the original file name that was uploaded.
Chris@0 86 * Then it should not be considered as a safe value.
Chris@0 87 *
Chris@0 88 * @return string The extension
Chris@0 89 */
Chris@0 90 public function getClientOriginalExtension()
Chris@0 91 {
Chris@0 92 return pathinfo($this->originalName, PATHINFO_EXTENSION);
Chris@0 93 }
Chris@0 94
Chris@0 95 /**
Chris@0 96 * Returns the file mime type.
Chris@0 97 *
Chris@0 98 * The client mime type is extracted from the request from which the file
Chris@0 99 * was uploaded, so it should not be considered as a safe value.
Chris@0 100 *
Chris@0 101 * For a trusted mime type, use getMimeType() instead (which guesses the mime
Chris@0 102 * type based on the file content).
Chris@0 103 *
Chris@0 104 * @return string|null The mime type
Chris@0 105 *
Chris@0 106 * @see getMimeType()
Chris@0 107 */
Chris@0 108 public function getClientMimeType()
Chris@0 109 {
Chris@0 110 return $this->mimeType;
Chris@0 111 }
Chris@0 112
Chris@0 113 /**
Chris@0 114 * Returns the extension based on the client mime type.
Chris@0 115 *
Chris@0 116 * If the mime type is unknown, returns null.
Chris@0 117 *
Chris@0 118 * This method uses the mime type as guessed by getClientMimeType()
Chris@0 119 * to guess the file extension. As such, the extension returned
Chris@0 120 * by this method cannot be trusted.
Chris@0 121 *
Chris@0 122 * For a trusted extension, use guessExtension() instead (which guesses
Chris@0 123 * the extension based on the guessed mime type for the file).
Chris@0 124 *
Chris@0 125 * @return string|null The guessed extension or null if it cannot be guessed
Chris@0 126 *
Chris@0 127 * @see guessExtension()
Chris@0 128 * @see getClientMimeType()
Chris@0 129 */
Chris@0 130 public function guessClientExtension()
Chris@0 131 {
Chris@0 132 $type = $this->getClientMimeType();
Chris@0 133 $guesser = ExtensionGuesser::getInstance();
Chris@0 134
Chris@0 135 return $guesser->guess($type);
Chris@0 136 }
Chris@0 137
Chris@0 138 /**
Chris@0 139 * Returns the file size.
Chris@0 140 *
Chris@0 141 * It is extracted from the request from which the file has been uploaded.
Chris@0 142 * Then it should not be considered as a safe value.
Chris@0 143 *
Chris@0 144 * @return int|null The file size
Chris@0 145 */
Chris@0 146 public function getClientSize()
Chris@0 147 {
Chris@0 148 return $this->size;
Chris@0 149 }
Chris@0 150
Chris@0 151 /**
Chris@0 152 * Returns the upload error.
Chris@0 153 *
Chris@0 154 * If the upload was successful, the constant UPLOAD_ERR_OK is returned.
Chris@0 155 * Otherwise one of the other UPLOAD_ERR_XXX constants is returned.
Chris@0 156 *
Chris@0 157 * @return int The upload error
Chris@0 158 */
Chris@0 159 public function getError()
Chris@0 160 {
Chris@0 161 return $this->error;
Chris@0 162 }
Chris@0 163
Chris@0 164 /**
Chris@0 165 * Returns whether the file was uploaded successfully.
Chris@0 166 *
Chris@0 167 * @return bool True if the file has been uploaded with HTTP and no error occurred
Chris@0 168 */
Chris@0 169 public function isValid()
Chris@0 170 {
Chris@14 171 $isOk = UPLOAD_ERR_OK === $this->error;
Chris@0 172
Chris@0 173 return $this->test ? $isOk : $isOk && is_uploaded_file($this->getPathname());
Chris@0 174 }
Chris@0 175
Chris@0 176 /**
Chris@0 177 * Moves the file to a new location.
Chris@0 178 *
Chris@0 179 * @param string $directory The destination folder
Chris@0 180 * @param string $name The new file name
Chris@0 181 *
Chris@0 182 * @return File A File object representing the new file
Chris@0 183 *
Chris@0 184 * @throws FileException if, for any reason, the file could not have been moved
Chris@0 185 */
Chris@0 186 public function move($directory, $name = null)
Chris@0 187 {
Chris@0 188 if ($this->isValid()) {
Chris@0 189 if ($this->test) {
Chris@0 190 return parent::move($directory, $name);
Chris@0 191 }
Chris@0 192
Chris@0 193 $target = $this->getTargetFile($directory, $name);
Chris@0 194
Chris@16 195 set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
Chris@16 196 $moved = move_uploaded_file($this->getPathname(), $target);
Chris@16 197 restore_error_handler();
Chris@16 198 if (!$moved) {
Chris@16 199 throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error)));
Chris@0 200 }
Chris@0 201
Chris@0 202 @chmod($target, 0666 & ~umask());
Chris@0 203
Chris@0 204 return $target;
Chris@0 205 }
Chris@0 206
Chris@0 207 throw new FileException($this->getErrorMessage());
Chris@0 208 }
Chris@0 209
Chris@0 210 /**
Chris@0 211 * Returns the maximum size of an uploaded file as configured in php.ini.
Chris@0 212 *
Chris@0 213 * @return int The maximum size of an uploaded file in bytes
Chris@0 214 */
Chris@0 215 public static function getMaxFilesize()
Chris@0 216 {
Chris@0 217 $iniMax = strtolower(ini_get('upload_max_filesize'));
Chris@0 218
Chris@0 219 if ('' === $iniMax) {
Chris@0 220 return PHP_INT_MAX;
Chris@0 221 }
Chris@0 222
Chris@0 223 $max = ltrim($iniMax, '+');
Chris@0 224 if (0 === strpos($max, '0x')) {
Chris@17 225 $max = \intval($max, 16);
Chris@0 226 } elseif (0 === strpos($max, '0')) {
Chris@17 227 $max = \intval($max, 8);
Chris@0 228 } else {
Chris@0 229 $max = (int) $max;
Chris@0 230 }
Chris@0 231
Chris@0 232 switch (substr($iniMax, -1)) {
Chris@0 233 case 't': $max *= 1024;
Chris@14 234 // no break
Chris@0 235 case 'g': $max *= 1024;
Chris@14 236 // no break
Chris@0 237 case 'm': $max *= 1024;
Chris@14 238 // no break
Chris@0 239 case 'k': $max *= 1024;
Chris@0 240 }
Chris@0 241
Chris@0 242 return $max;
Chris@0 243 }
Chris@0 244
Chris@0 245 /**
Chris@0 246 * Returns an informative upload error message.
Chris@0 247 *
Chris@0 248 * @return string The error message regarding the specified error code
Chris@0 249 */
Chris@0 250 public function getErrorMessage()
Chris@0 251 {
Chris@17 252 static $errors = [
Chris@0 253 UPLOAD_ERR_INI_SIZE => 'The file "%s" exceeds your upload_max_filesize ini directive (limit is %d KiB).',
Chris@0 254 UPLOAD_ERR_FORM_SIZE => 'The file "%s" exceeds the upload limit defined in your form.',
Chris@0 255 UPLOAD_ERR_PARTIAL => 'The file "%s" was only partially uploaded.',
Chris@0 256 UPLOAD_ERR_NO_FILE => 'No file was uploaded.',
Chris@0 257 UPLOAD_ERR_CANT_WRITE => 'The file "%s" could not be written on disk.',
Chris@0 258 UPLOAD_ERR_NO_TMP_DIR => 'File could not be uploaded: missing temporary directory.',
Chris@0 259 UPLOAD_ERR_EXTENSION => 'File upload was stopped by a PHP extension.',
Chris@17 260 ];
Chris@0 261
Chris@0 262 $errorCode = $this->error;
Chris@14 263 $maxFilesize = UPLOAD_ERR_INI_SIZE === $errorCode ? self::getMaxFilesize() / 1024 : 0;
Chris@0 264 $message = isset($errors[$errorCode]) ? $errors[$errorCode] : 'The file "%s" was not uploaded due to an unknown error.';
Chris@0 265
Chris@0 266 return sprintf($message, $this->getClientOriginalName(), $maxFilesize);
Chris@0 267 }
Chris@0 268 }