PluginProbe ʕ •ᴥ•ʔ
FAPI Member / 2.2.31
FAPI Member v2.2.31
2.2.33 2.2.32 trunk 1.9.47 2.1.18 2.2.24 2.2.25 2.2.26 2.2.28 2.2.29 2.2.30 2.2.31
fapi-member / libs / nette / http / src / Http / FileUpload.php
fapi-member / libs / nette / http / src / Http Last commit date
Context.php 4 weeks ago FileUpload.php 4 weeks ago Helpers.php 4 weeks ago IRequest.php 4 weeks ago IResponse.php 4 weeks ago Request.php 4 weeks ago RequestFactory.php 4 weeks ago Response.php 4 weeks ago Session.php 4 weeks ago SessionSection.php 4 weeks ago Url.php 4 weeks ago UrlImmutable.php 4 weeks ago UrlScript.php 4 weeks ago UserStorage.php 4 weeks ago
FileUpload.php
234 lines
1 <?php
2
3 /**
4 * This file is part of the Nette Framework (https://nette.org)
5 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
6 */
7 declare (strict_types=1);
8 namespace FapiMember\Library\Nette\Http;
9
10 use FapiMember\Library\Nette;
11 /**
12 * Provides access to individual files that have been uploaded by a client.
13 *
14 * @property-read string $name
15 * @property-read string $sanitizedName
16 * @property-read string $untrustedFullPath
17 * @property-read string|null $contentType
18 * @property-read int $size
19 * @property-read string $temporaryFile
20 * @property-read int $error
21 * @property-read bool $ok
22 * @property-read string|null $contents
23 */
24 final class FileUpload
25 {
26 use Nette\SmartObject;
27 /** @deprecated */
28 public const IMAGE_MIME_TYPES = ['image/gif', 'image/png', 'image/jpeg', 'image/webp'];
29 /** @var string */
30 private $name;
31 /** @var string|null */
32 private $fullPath;
33 /** @var string|false|null */
34 private $type;
35 /** @var string|false|null */
36 private $extension;
37 /** @var int */
38 private $size;
39 /** @var string */
40 private $tmpName;
41 /** @var int */
42 private $error;
43 public function __construct(?array $value)
44 {
45 foreach (['name', 'size', 'tmp_name', 'error'] as $key) {
46 if (!isset($value[$key]) || !is_scalar($value[$key])) {
47 $this->error = \UPLOAD_ERR_NO_FILE;
48 return;
49 // or throw exception?
50 }
51 }
52 $this->name = $value['name'];
53 $this->fullPath = $value['full_path'] ?? null;
54 $this->size = $value['size'];
55 $this->tmpName = $value['tmp_name'];
56 $this->error = $value['error'];
57 }
58 /**
59 * @deprecated use getUntrustedName()
60 */
61 public function getName(): string
62 {
63 return $this->name;
64 }
65 /**
66 * Returns the original file name as submitted by the browser. Do not trust the value returned by this method.
67 * A client could send a malicious filename with the intention to corrupt or hack your application.
68 */
69 public function getUntrustedName(): string
70 {
71 return $this->name;
72 }
73 /**
74 * Returns the sanitized file name. The resulting name contains only ASCII characters [a-zA-Z0-9.-].
75 * If the name does not contain such characters, it returns 'unknown'. If the file is JPEG, PNG, GIF, or WebP image,
76 * it returns the correct file extension. Do not blindly trust the value returned by this method.
77 */
78 public function getSanitizedName(): string
79 {
80 $name = Nette\Utils\Strings::webalize($this->name, '.', \false);
81 $name = str_replace(['-.', '.-'], '.', $name);
82 $name = trim($name, '.-');
83 $name = ($name === '') ? 'unknown' : $name;
84 if ($ext = $this->getSuggestedExtension()) {
85 $name = preg_replace('#\.[^.]+$#D', '', $name);
86 $name .= '.' . $ext;
87 }
88 return $name;
89 }
90 /**
91 * Returns the original full path as submitted by the browser during directory upload. Do not trust the value
92 * returned by this method. A client could send a malicious directory structure with the intention to corrupt
93 * or hack your application.
94 *
95 * The full path is only available in PHP 8.1 and above. In previous versions, this method returns the file name.
96 */
97 public function getUntrustedFullPath(): string
98 {
99 return $this->fullPath ?? $this->name;
100 }
101 /**
102 * Detects the MIME content type of the uploaded file based on its signature. Requires PHP extension fileinfo.
103 * If the upload was not successful or the detection failed, it returns null.
104 */
105 public function getContentType(): ?string
106 {
107 if ($this->isOk() && $this->type === null) {
108 $this->type = finfo_file(finfo_open(\FILEINFO_MIME_TYPE), $this->tmpName);
109 }
110 return $this->type ?: null;
111 }
112 /**
113 * Returns the appropriate file extension (without the period) corresponding to the detected MIME type. Requires the PHP extension fileinfo.
114 */
115 public function getSuggestedExtension(): ?string
116 {
117 if ($this->isOk() && $this->extension === null) {
118 $exts = finfo_file(finfo_open(\FILEINFO_EXTENSION), $this->tmpName);
119 if ($exts && $exts !== '???') {
120 return $this->extension = preg_replace('~[/,].*~', '', $exts);
121 }
122 [, , $type] = @getimagesize($this->tmpName);
123 // @ - files smaller than 12 bytes causes read error
124 if ($type) {
125 return $this->extension = image_type_to_extension($type, \false);
126 }
127 $this->extension = \false;
128 }
129 return $this->extension ?: null;
130 }
131 /**
132 * Returns the size of the uploaded file in bytes.
133 */
134 public function getSize(): int
135 {
136 return $this->size;
137 }
138 /**
139 * Returns the path of the temporary location of the uploaded file.
140 */
141 public function getTemporaryFile(): string
142 {
143 return $this->tmpName;
144 }
145 /**
146 * Returns the path of the temporary location of the uploaded file.
147 */
148 public function __toString(): string
149 {
150 return $this->tmpName;
151 }
152 /**
153 * Returns the error code. It is be one of UPLOAD_ERR_XXX constants.
154 * @see http://php.net/manual/en/features.file-upload.errors.php
155 */
156 public function getError(): int
157 {
158 return $this->error;
159 }
160 /**
161 * Returns true if the file was uploaded successfully.
162 */
163 public function isOk(): bool
164 {
165 return $this->error === \UPLOAD_ERR_OK;
166 }
167 /**
168 * Returns true if the user has uploaded a file.
169 */
170 public function hasFile(): bool
171 {
172 return $this->error !== \UPLOAD_ERR_NO_FILE;
173 }
174 /**
175 * Moves an uploaded file to a new location. If the destination file already exists, it will be overwritten.
176 * @return static
177 */
178 public function move(string $dest)
179 {
180 $dir = dirname($dest);
181 Nette\Utils\FileSystem::createDir($dir);
182 @unlink($dest);
183 // @ - file may not exists
184 Nette\Utils\Callback::invokeSafe(is_uploaded_file($this->tmpName) ? 'move_uploaded_file' : 'rename', [$this->tmpName, $dest], function (string $message) use ($dest): void {
185 throw new Nette\InvalidStateException("Unable to move uploaded file '{$this->tmpName}' to '{$dest}'. {$message}");
186 });
187 @chmod($dest, 0666);
188 // @ - possible low permission to chmod
189 $this->tmpName = $dest;
190 return $this;
191 }
192 /**
193 * Returns true if the uploaded file is an image and the format is supported by PHP, so it can be loaded using the toImage() method.
194 * Detection is based on its signature, the integrity of the file is not checked. Requires PHP extensions fileinfo & gd.
195 */
196 public function isImage(): bool
197 {
198 $flag = imagetypes();
199 $types = array_filter([($flag & \IMG_GIF) ? 'image/gif' : null, ($flag & \IMG_JPG) ? 'image/jpeg' : null, ($flag & \IMG_PNG) ? 'image/png' : null, ($flag & \IMG_WEBP) ? 'image/webp' : null, ($flag & 256) ? 'image/avif' : null]);
200 return in_array($this->getContentType(), $types, \true);
201 }
202 /**
203 * Converts uploaded image to Nette\Utils\Image object.
204 * @throws Nette\Utils\ImageException If the upload was not successful or is not a valid image
205 */
206 public function toImage(): Nette\Utils\Image
207 {
208 return Nette\Utils\Image::fromFile($this->tmpName);
209 }
210 /**
211 * Returns a pair of [width, height] with dimensions of the uploaded image.
212 */
213 public function getImageSize(): ?array
214 {
215 return $this->isImage() ? array_intersect_key(getimagesize($this->tmpName), [0, 1]) : null;
216 }
217 /**
218 * Returns image file extension based on detected content type (without dot).
219 * @deprecated use getSuggestedExtension()
220 */
221 public function getImageFileExtension(): ?string
222 {
223 return $this->getSuggestedExtension();
224 }
225 /**
226 * Returns the contents of the uploaded file. If the upload was not successful, it returns null.
227 */
228 public function getContents(): ?string
229 {
230 // future implementation can try to work around safe_mode and open_basedir limitations
231 return $this->isOk() ? file_get_contents($this->tmpName) : null;
232 }
233 }
234