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