This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace XoopsModules\Smallworld; |
||
4 | |||
5 | /* |
||
6 | * jQuery File Upload Plugin PHP Class 6.1.2 |
||
7 | * https://github.com/blueimp/jQuery-File-Upload |
||
8 | * |
||
9 | * Copyright 2010, Sebastian Tschan |
||
10 | * https://blueimp.net |
||
11 | * |
||
12 | * Licensed under the MIT license: |
||
13 | * http://www.opensource.org/licenses/MIT |
||
14 | */ |
||
15 | |||
16 | /** |
||
17 | * Class UploadHandler |
||
18 | */ |
||
19 | class UploadHandler |
||
20 | { |
||
21 | protected $options; |
||
22 | |||
23 | // PHP File Upload error message codes: |
||
24 | // http://php.net/manual/en/features.file-upload.errors.php |
||
25 | protected $error_messages = [ |
||
26 | 1 => 'The uploaded file exceeds the upload_max_filesize directive in php.ini', |
||
27 | 2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form', |
||
28 | 3 => 'The uploaded file was only partially uploaded', |
||
29 | 4 => 'No file was uploaded', |
||
30 | 6 => 'Missing a temporary folder', |
||
31 | 7 => 'Failed to write file to disk', |
||
32 | 8 => 'A PHP extension stopped the file upload', |
||
33 | 'post_max_size' => 'The uploaded file exceeds the post_max_size directive in php.ini', |
||
34 | 'max_file_size' => 'File is too big', |
||
35 | 'min_file_size' => 'File is too small', |
||
36 | 'accept_file_types' => 'Filetype not allowed', |
||
37 | 'max_number_of_files' => 'Maximum number of files exceeded', |
||
38 | 'max_width' => 'Image exceeds maximum width', |
||
39 | 'min_width' => 'Image requires a minimum width', |
||
40 | 'max_height' => 'Image exceeds maximum height', |
||
41 | 'min_height' => 'Image requires a minimum height', |
||
42 | ]; |
||
43 | |||
44 | /** |
||
45 | * UploadHandler constructor. |
||
46 | * @param null $options |
||
47 | * @param bool $initialize |
||
48 | */ |
||
49 | public function __construct($options = null, $initialize = true) |
||
50 | { |
||
51 | $userID = $GLOBALS['xoopsUser']->getVar('uid'); |
||
52 | $this->options = [ |
||
53 | 'script_url' => $this->get_full_url() . '/imgupload.php', |
||
54 | 'upload_dir' => XOOPS_ROOT_PATH . '/uploads/albums_smallworld/' . $userID . '/', |
||
55 | 'upload_url' => XOOPS_URL . '/uploads/albums_smallworld/' . $userID . '/', |
||
56 | 'user_dirs' => false, |
||
57 | 'mkdir_mode' => 0755, |
||
58 | 'param_name' => 'files', |
||
59 | // Set the following option to 'POST', if your server does not support |
||
60 | // DELETE requests. This is a parameter sent to the client: |
||
61 | 'delete_type' => 'DELETE', |
||
62 | 'access_control_allow_origin' => '*', |
||
63 | 'access_control_allow_credentials' => false, |
||
64 | 'access_control_allow_methods' => [ |
||
65 | 'OPTIONS', |
||
66 | 'HEAD', |
||
67 | 'GET', |
||
68 | 'POST', |
||
69 | 'PUT', |
||
70 | 'PATCH', |
||
71 | 'DELETE', |
||
72 | ], |
||
73 | 'access_control_allow_headers' => [ |
||
74 | 'Content-Type', |
||
75 | 'Content-Range', |
||
76 | 'Content-Disposition', |
||
77 | ], |
||
78 | // Enable to provide file downloads via GET requests to the PHP script: |
||
79 | 'download_via_php' => false, |
||
80 | // Defines which files can be displayed inline when downloaded: |
||
81 | 'inline_file_types' => '/\.(gif|jpe?g|png|JPE?G)$/i', |
||
82 | // Defines which files (based on their names) are accepted for upload: |
||
83 | 'accept_file_types' => '/.+$/i', |
||
84 | // The php.ini settings upload_max_filesize and post_max_size |
||
85 | // take precedence over the following max_file_size setting: |
||
86 | 'max_file_size' => null, |
||
87 | 'min_file_size' => 1, |
||
88 | // The maximum number of files for the upload directory: |
||
89 | 'max_number_of_files' => null, |
||
90 | // Image resolution restrictions: |
||
91 | 'max_width' => null, |
||
92 | 'max_height' => null, |
||
93 | 'min_width' => 1, |
||
94 | 'min_height' => 1, |
||
95 | // Set the following option to false to enable resumable uploads: |
||
96 | 'discard_aborted_uploads' => true, |
||
97 | // Set to true to rotate images based on EXIF meta data, if available: |
||
98 | 'orient_image' => false, |
||
99 | 'image_versions' => [ |
||
100 | // Uncomment the following version to restrict the size of |
||
101 | // uploaded images: |
||
102 | /* |
||
103 | '' => array( |
||
104 | 'max_width' => 1920, |
||
105 | 'max_height' => 1200, |
||
106 | 'jpeg_quality' => 95 |
||
107 | ), |
||
108 | */ |
||
109 | // Uncomment the following to create medium sized images: |
||
110 | /* |
||
111 | 'medium' => array( |
||
112 | 'max_width' => 800, |
||
113 | 'max_height' => 600, |
||
114 | 'jpeg_quality' => 80 |
||
115 | ), |
||
116 | */ |
||
117 | 'thumbnails' => [ |
||
118 | 'upload_dir' => XOOPS_ROOT_PATH . '/uploads/albums_smallworld' . '/' . $userID . '/thumbnails/', |
||
119 | 'upload_url' => XOOPS_URL . '/uploads/albums_smallworld' . '/' . $userID . '/thumbnails/', |
||
120 | 'max_width' => 80, |
||
121 | 'max_height' => 80, |
||
122 | ], |
||
123 | ], |
||
124 | ]; |
||
125 | if ($options) { |
||
126 | $this->options = array_merge($this->options, $options); |
||
127 | } |
||
128 | if ($initialize) { |
||
129 | $this->initialize(); |
||
130 | } |
||
131 | } |
||
132 | |||
133 | protected function initialize() |
||
134 | { |
||
135 | switch ($_SERVER['REQUEST_METHOD']) { |
||
136 | case 'OPTIONS': |
||
137 | case 'HEAD': |
||
138 | $this->head(); |
||
139 | break; |
||
140 | case 'GET': |
||
141 | $this->get(); |
||
142 | break; |
||
143 | case 'PATCH': |
||
144 | case 'PUT': |
||
145 | case 'POST': |
||
146 | $this->post(); |
||
147 | break; |
||
148 | case 'DELETE': |
||
149 | $this->delete(); |
||
150 | break; |
||
151 | default: |
||
152 | $this->header('HTTP/1.1 405 Method Not Allowed'); |
||
153 | } |
||
154 | } |
||
155 | |||
156 | /** |
||
157 | * @return string |
||
158 | */ |
||
159 | protected function get_full_url() |
||
160 | { |
||
161 | $https = !empty($_SERVER['HTTPS']) && 'off' !== $_SERVER['HTTPS']; |
||
162 | |||
163 | return ($https ? 'https://' : 'http://') |
||
164 | . (!empty($_SERVER['REMOTE_USER']) ? $_SERVER['REMOTE_USER'] . '@' : '') |
||
165 | . (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : ($_SERVER['SERVER_NAME'] . ($https && 443 === $_SERVER['SERVER_PORT'] || 80 === $_SERVER['SERVER_PORT'] ? '' : ':' |
||
166 | . $_SERVER['SERVER_PORT']))) |
||
167 | . mb_substr($_SERVER['SCRIPT_NAME'], 0, mb_strrpos($_SERVER['SCRIPT_NAME'], '/')); |
||
168 | } |
||
169 | |||
170 | /** |
||
171 | * @return string |
||
172 | */ |
||
173 | protected function get_user_id() |
||
174 | { |
||
175 | @session_start(); |
||
0 ignored issues
–
show
|
|||
176 | |||
177 | return session_id(); |
||
178 | } |
||
179 | |||
180 | /** |
||
181 | * @return string |
||
182 | */ |
||
183 | protected function get_user_path() |
||
184 | { |
||
185 | if ($this->options['user_dirs']) { |
||
186 | return $this->get_user_id() . '/'; |
||
187 | } |
||
188 | |||
189 | return ''; |
||
190 | } |
||
191 | |||
192 | /** |
||
193 | * @param null|string $file_name |
||
194 | * @param null $version |
||
195 | * @return string |
||
196 | */ |
||
197 | protected function get_upload_path($file_name = null, $version = null) |
||
198 | { |
||
199 | $file_name = $file_name ?: ''; |
||
200 | $version_path = empty($version) ? '' : $version . '/'; |
||
201 | |||
202 | return $this->options['upload_dir'] . $this->get_user_path() . $version_path . $file_name; |
||
203 | } |
||
204 | |||
205 | /** |
||
206 | * @param $url |
||
207 | * @return string |
||
208 | */ |
||
209 | protected function get_query_separator($url) |
||
210 | { |
||
211 | return false === mb_strpos($url, '?') ? '?' : '&'; |
||
212 | } |
||
213 | |||
214 | /** |
||
215 | * @param $file_name |
||
216 | * @param null $version |
||
217 | * @return string |
||
218 | */ |
||
219 | protected function get_download_url($file_name, $version = null) |
||
220 | { |
||
221 | if ($this->options['download_via_php']) { |
||
222 | $url = $this->options['script_url'] . $this->get_query_separator($this->options['script_url']) . 'file=' . rawurlencode($file_name); |
||
223 | if ($version) { |
||
224 | $url .= '&version=' . rawurlencode($version); |
||
225 | } |
||
226 | |||
227 | return $url . '&download=1'; |
||
228 | } |
||
229 | $version_path = empty($version) ? '' : rawurlencode($version) . '/'; |
||
230 | |||
231 | return $this->options['upload_url'] . $this->get_user_path() . $version_path . rawurlencode($file_name); |
||
232 | } |
||
233 | |||
234 | /** |
||
235 | * @param $file |
||
236 | */ |
||
237 | protected function set_file_delete_properties($file) |
||
238 | { |
||
239 | $file->delete_url = $this->options['script_url'] . $this->get_query_separator($this->options['script_url']) . 'file=' . rawurlencode($file->name); |
||
240 | $file->delete_type = $this->options['delete_type']; |
||
241 | if ('DELETE' !== $file->delete_type) { |
||
242 | $file->delete_url .= '&_method=DELETE'; |
||
243 | } |
||
244 | if ($this->options['access_control_allow_credentials']) { |
||
245 | $file->delete_with_credentials = true; |
||
246 | } |
||
247 | } |
||
248 | |||
249 | // Fix for overflowing signed 32 bit integers, |
||
250 | // works for sizes up to 2^32-1 bytes (4 GiB - 1): |
||
251 | |||
252 | /** |
||
253 | * @param $size |
||
254 | * @return float|int |
||
255 | */ |
||
256 | protected function fix_integer_overflow($size) |
||
257 | { |
||
258 | if ($size < 0) { |
||
259 | $size += 2.0 * (PHP_INT_MAX + 1); |
||
260 | } |
||
261 | |||
262 | return $size; |
||
263 | } |
||
264 | |||
265 | /** |
||
266 | * @param $file_path |
||
267 | * @param bool $clear_stat_cache |
||
268 | * @return float|int |
||
269 | */ |
||
270 | protected function get_file_size($file_path, $clear_stat_cache = false) |
||
271 | { |
||
272 | if ($clear_stat_cache) { |
||
273 | clearstatcache(true, $file_path); |
||
274 | } |
||
275 | |||
276 | return $this->fix_integer_overflow(filesize($file_path)); |
||
277 | } |
||
278 | |||
279 | /** |
||
280 | * @param $file_name |
||
281 | * @return bool |
||
282 | */ |
||
283 | protected function is_valid_file_object($file_name) |
||
284 | { |
||
285 | $file_path = $this->get_upload_path($file_name); |
||
286 | |||
287 | return is_file($file_path) && '.' !== $file_name[0]; |
||
288 | } |
||
289 | |||
290 | /** |
||
291 | * @param $file_name |
||
292 | * @return null|\stdClass |
||
293 | */ |
||
294 | protected function get_file_object($file_name) |
||
295 | { |
||
296 | if ($this->is_valid_file_object($file_name)) { |
||
297 | $file = new \stdClass(); |
||
298 | $file->name = $file_name; |
||
299 | $file->size = $this->get_file_size($this->get_upload_path($file_name)); |
||
300 | $file->url = $this->get_download_url($file->name); |
||
301 | foreach ($this->options['image_versions'] as $version => $options) { |
||
0 ignored issues
–
show
The expression
$this->options['image_versions'] of type string|integer|array<int...ight\":\"integer\"}>"}> is not guaranteed to be traversable. How about adding an additional type check?
There are different options of fixing this problem.
![]() |
|||
302 | if (!empty($version)) { |
||
303 | if (is_file($this->get_upload_path($file_name, $version))) { |
||
304 | $file->{$version . '_url'} = $this->get_download_url($file->name, $version); |
||
305 | } |
||
306 | } |
||
307 | } |
||
308 | $this->set_file_delete_properties($file); |
||
309 | |||
310 | return $file; |
||
311 | } |
||
312 | |||
313 | return null; |
||
314 | } |
||
315 | |||
316 | /** |
||
317 | * @param string $iteration_method |
||
318 | * @return array |
||
319 | */ |
||
320 | protected function get_file_objects($iteration_method = 'get_file_object') |
||
321 | { |
||
322 | $upload_dir = $this->get_upload_path(); |
||
323 | if (!is_dir($upload_dir)) { |
||
324 | return []; |
||
325 | } |
||
326 | |||
327 | return array_values(array_filter(array_map([$this, $iteration_method], scandir($upload_dir, SCANDIR_SORT_NONE)))); |
||
328 | } |
||
329 | |||
330 | /** |
||
331 | * @return int |
||
332 | */ |
||
333 | protected function count_file_objects() |
||
334 | { |
||
335 | return count($this->get_file_objects('is_valid_file_object')); |
||
336 | } |
||
337 | |||
338 | /** |
||
339 | * @param $file_name |
||
340 | * @param $version |
||
341 | * @param $options |
||
342 | * @return bool |
||
343 | */ |
||
344 | protected function create_scaled_image($file_name, $version, $options) |
||
345 | { |
||
346 | $file_path = $this->get_upload_path($file_name); |
||
347 | if (!empty($version)) { |
||
348 | $version_dir = $this->get_upload_path(null, $version); |
||
349 | View Code Duplication | if (!is_dir($version_dir)) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
350 | if (!mkdir($version_dir, $this->options['mkdir_mode'], true) && !is_dir($version_dir)) { |
||
351 | throw new \RuntimeException(sprintf('Directory "%s" was not created', $version_dir)); |
||
352 | } |
||
353 | } |
||
354 | $new_file_path = $version_dir . '/' . $file_name; |
||
355 | } else { |
||
356 | $new_file_path = $file_path; |
||
357 | } |
||
358 | list($img_width, $img_height) = @getimagesize($file_path); |
||
359 | if (!$img_width || !$img_height) { |
||
360 | return false; |
||
361 | } |
||
362 | $scale = min($options['max_width'] / $img_width, $options['max_height'] / $img_height); |
||
363 | if ($scale >= 1) { |
||
364 | if ($file_path !== $new_file_path) { |
||
365 | return copy($file_path, $new_file_path); |
||
366 | } |
||
367 | |||
368 | return true; |
||
369 | } |
||
370 | $new_width = $img_width * $scale; |
||
371 | $new_height = $img_height * $scale; |
||
372 | $new_img = @imagecreatetruecolor($new_width, $new_height); |
||
373 | switch (mb_strtolower(mb_substr(mb_strrchr($file_name, '.'), 1))) { |
||
374 | case 'jpg': |
||
375 | case 'jpeg': |
||
376 | $src_img = @imagecreatefromjpeg($file_path); |
||
377 | $write_image = 'imagejpeg'; |
||
378 | $image_quality = isset($options['jpeg_quality']) ? $options['jpeg_quality'] : 75; |
||
379 | break; |
||
380 | case 'gif': |
||
381 | @imagecolortransparent($new_img, @imagecolorallocate($new_img, 0, 0, 0)); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
382 | $src_img = @imagecreatefromgif($file_path); |
||
383 | $write_image = 'imagegif'; |
||
384 | $image_quality = null; |
||
385 | break; |
||
386 | case 'png': |
||
387 | @imagecolortransparent($new_img, @imagecolorallocate($new_img, 0, 0, 0)); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
388 | @imagealphablending($new_img, false); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
389 | @imagesavealpha($new_img, true); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
390 | $src_img = @imagecreatefrompng($file_path); |
||
391 | $write_image = 'imagepng'; |
||
392 | $image_quality = isset($options['png_quality']) ? $options['png_quality'] : 9; |
||
393 | break; |
||
394 | default: |
||
395 | $src_img = null; |
||
396 | } |
||
397 | $success = $src_img && @imagecopyresampled($new_img, $src_img, 0, 0, 0, 0, $new_width, $new_height, $img_width, $img_height) && $write_image($new_img, $new_file_path, $image_quality); |
||
0 ignored issues
–
show
The variable
$write_image does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
![]() The variable
$image_quality does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
![]() |
|||
398 | // Free up memory (imagedestroy does not delete files): |
||
399 | @imagedestroy($src_img); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
400 | @imagedestroy($new_img); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
401 | |||
402 | return $success; |
||
403 | } |
||
404 | |||
405 | /** |
||
406 | * @param $error |
||
407 | * @return mixed |
||
408 | */ |
||
409 | protected function get_error_message($error) |
||
410 | { |
||
411 | return array_key_exists($error, $this->error_messages) ? $this->error_messages[$error] : $error; |
||
412 | } |
||
413 | |||
414 | /** |
||
415 | * @param $val |
||
416 | * @return float|int |
||
417 | */ |
||
418 | public function get_config_bytes($val) |
||
419 | { |
||
420 | $val = trim($val); |
||
421 | $last = mb_strtolower($val[mb_strlen($val) - 1]); |
||
422 | switch ($last) { |
||
423 | case 'g': |
||
424 | $val *= 1024; |
||
425 | // no break |
||
426 | case 'm': |
||
427 | $val *= 1024; |
||
428 | // no break |
||
429 | case 'k': |
||
430 | $val *= 1024; |
||
431 | } |
||
432 | |||
433 | return $this->fix_integer_overflow($val); |
||
434 | } |
||
435 | |||
436 | /** |
||
437 | * @param $uploaded_file |
||
438 | * @param $file |
||
439 | * @param $error |
||
440 | * @param $index |
||
441 | * @return bool |
||
442 | */ |
||
443 | protected function validate($uploaded_file, $file, $error, $index) |
||
0 ignored issues
–
show
|
|||
444 | { |
||
445 | if ($error) { |
||
446 | $file->error = $this->get_error_message($error); |
||
447 | |||
448 | return false; |
||
449 | } |
||
450 | $content_length = $this->fix_integer_overflow((int)$_SERVER['CONTENT_LENGTH']); |
||
451 | $post_max_size = $this->get_config_bytes(ini_get('post_max_size')); |
||
452 | if ($post_max_size && ($content_length > $post_max_size)) { |
||
453 | $file->error = $this->get_error_message('post_max_size'); |
||
454 | |||
455 | return false; |
||
456 | } |
||
457 | if (!preg_match($this->options['accept_file_types'], $file->name)) { |
||
458 | $file->error = $this->get_error_message('accept_file_types'); |
||
459 | |||
460 | return false; |
||
461 | } |
||
462 | if ($uploaded_file && is_uploaded_file($uploaded_file)) { |
||
463 | $file_size = $this->get_file_size($uploaded_file); |
||
464 | } else { |
||
465 | $file_size = $content_length; |
||
466 | } |
||
467 | if ($this->options['max_file_size'] && ($file_size > $this->options['max_file_size'] || $file->size > $this->options['max_file_size'])) { |
||
468 | $file->error = $this->get_error_message('max_file_size'); |
||
469 | |||
470 | return false; |
||
471 | } |
||
472 | if ($this->options['min_file_size'] && $file_size < $this->options['min_file_size']) { |
||
473 | $file->error = $this->get_error_message('min_file_size'); |
||
474 | |||
475 | return false; |
||
476 | } |
||
477 | if (is_int($this->options['max_number_of_files']) && ($this->count_file_objects() >= $this->options['max_number_of_files'])) { |
||
478 | $file->error = $this->get_error_message('max_number_of_files'); |
||
479 | |||
480 | return false; |
||
481 | } |
||
482 | list($img_width, $img_height) = @getimagesize($uploaded_file); |
||
483 | if (is_int($img_width)) { |
||
484 | View Code Duplication | if ($this->options['max_width'] && $img_width > $this->options['max_width']) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
485 | $file->error = $this->get_error_message('max_width'); |
||
486 | |||
487 | return false; |
||
488 | } |
||
489 | View Code Duplication | if ($this->options['max_height'] && $img_height > $this->options['max_height']) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
490 | $file->error = $this->get_error_message('max_height'); |
||
491 | |||
492 | return false; |
||
493 | } |
||
494 | View Code Duplication | if ($this->options['min_width'] && $img_width < $this->options['min_width']) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
495 | $file->error = $this->get_error_message('min_width'); |
||
496 | |||
497 | return false; |
||
498 | } |
||
499 | View Code Duplication | if ($this->options['min_height'] && $img_height < $this->options['min_height']) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
500 | $file->error = $this->get_error_message('min_height'); |
||
501 | |||
502 | return false; |
||
503 | } |
||
504 | } |
||
505 | |||
506 | return true; |
||
507 | } |
||
508 | |||
509 | /** |
||
510 | * @param $matches |
||
511 | * @return string |
||
512 | */ |
||
513 | protected function upcount_name_callback($matches) |
||
514 | { |
||
515 | $index = isset($matches[1]) ? (int)$matches[1] + 1 : 1; |
||
516 | $ext = isset($matches[2]) ? $matches[2] : ''; |
||
517 | |||
518 | return ' (' . $index . ')' . $ext; |
||
519 | } |
||
520 | |||
521 | /** |
||
522 | * @param $name |
||
523 | * @return null|string|string[] |
||
524 | */ |
||
525 | protected function upcount_name($name) |
||
526 | { |
||
527 | return preg_replace_callback('/(?:(?: \(([\d]+)\))?(\.[^.]+))?$/', [$this, 'upcount_name_callback'], $name, 1); |
||
528 | } |
||
529 | |||
530 | /** |
||
531 | * @param $name |
||
532 | * @param $type |
||
533 | * @param $index |
||
534 | * @param $content_range |
||
535 | * @return null|string|string[] |
||
536 | */ |
||
537 | protected function get_unique_filename($name, $type, $index, $content_range) |
||
0 ignored issues
–
show
|
|||
538 | { |
||
539 | while (is_dir($this->get_upload_path($name))) { |
||
540 | $name = $this->upcount_name($name); |
||
541 | } |
||
542 | // Keep an existing filename if this is part of a chunked upload: |
||
543 | $uploaded_bytes = $this->fix_integer_overflow((int)$content_range[1]); |
||
544 | while (is_file($this->get_upload_path($name))) { |
||
545 | if ($uploaded_bytes === $this->get_file_size($this->get_upload_path($name))) { |
||
546 | break; |
||
547 | } |
||
548 | $name = $this->upcount_name($name); |
||
549 | } |
||
550 | |||
551 | return $name; |
||
552 | } |
||
553 | |||
554 | /** |
||
555 | * @param $name |
||
556 | * @param $type |
||
557 | * @param $index |
||
558 | * @param $content_range |
||
559 | * @return mixed|string |
||
560 | */ |
||
561 | protected function trim_file_name($name, $type, $index, $content_range) |
||
0 ignored issues
–
show
|
|||
562 | { |
||
563 | // Remove path information and dots around the filename, to prevent uploading |
||
564 | // into different directories or replacing hidden system files. |
||
565 | // Also remove control characters and spaces (\x00..\x20) around the filename: |
||
566 | $name = trim(basename(stripslashes($name)), ".\x00..\x20"); |
||
567 | // Use a timestamp for empty filenames: |
||
568 | if (!$name) { |
||
569 | $name = str_replace('.', '-', microtime(true)); |
||
570 | } |
||
571 | // Add missing file extension for known image types: |
||
572 | if (false === mb_strpos($name, '.') && preg_match('/^image\/(gif|jpe?g|png)/', $type, $matches)) { |
||
573 | $name .= '.' . $matches[1]; |
||
574 | } |
||
575 | |||
576 | return $name; |
||
577 | } |
||
578 | |||
579 | /** |
||
580 | * @param $name |
||
581 | * @param $type |
||
582 | * @param $index |
||
583 | * @param $content_range |
||
584 | * @return null|string|string[] |
||
585 | */ |
||
586 | protected function get_file_name($name, $type, $index, $content_range) |
||
587 | { |
||
588 | return $this->get_unique_filename($this->trim_file_name($name, $type, $index, $content_range), $type, $index, $content_range); |
||
589 | } |
||
590 | |||
591 | /** |
||
592 | * @param $file |
||
593 | * @param $index |
||
594 | */ |
||
595 | protected function handle_form_data($file, $index) |
||
0 ignored issues
–
show
|
|||
596 | { |
||
597 | // Handle form data, e.g. $_REQUEST['description'][$index] |
||
598 | } |
||
599 | |||
600 | /** |
||
601 | * @param $file_path |
||
602 | * @return bool |
||
603 | */ |
||
604 | protected function orient_image($file_path) |
||
605 | { |
||
606 | if (!function_exists('exif_read_data')) { |
||
607 | return false; |
||
608 | } |
||
609 | $exif = @exif_read_data($file_path); |
||
610 | if (false === $exif) { |
||
611 | return false; |
||
612 | } |
||
613 | $orientation = (int)(@$exif['Orientation']); |
||
614 | if (!in_array($orientation, [3, 6, 8])) { |
||
615 | return false; |
||
616 | } |
||
617 | $image = @imagecreatefromjpeg($file_path); |
||
618 | switch ($orientation) { |
||
619 | case 3: |
||
620 | $image = @imagerotate($image, 180, 0); |
||
621 | break; |
||
622 | case 6: |
||
623 | $image = @imagerotate($image, 270, 0); |
||
624 | break; |
||
625 | case 8: |
||
626 | $image = @imagerotate($image, 90, 0); |
||
627 | break; |
||
628 | default: |
||
629 | return false; |
||
630 | } |
||
631 | $success = imagejpeg($image, $file_path); |
||
632 | // Free up memory (imagedestroy does not delete files): |
||
633 | @imagedestroy($image); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
634 | |||
635 | return $success; |
||
636 | } |
||
637 | |||
638 | /** |
||
639 | * @param $uploaded_file |
||
640 | * @param $name |
||
641 | * @param $size |
||
642 | * @param $type |
||
643 | * @param $error |
||
644 | * @param null $index |
||
645 | * @param null $content_range |
||
646 | * @return \stdClass |
||
647 | */ |
||
648 | protected function handle_file_upload( |
||
649 | $uploaded_file, |
||
650 | $name, |
||
651 | $size, |
||
652 | $type, |
||
653 | $error, |
||
654 | $index = null, |
||
655 | $content_range = null |
||
656 | ) |
||
657 | { |
||
658 | $file = new \stdClass(); |
||
659 | |||
660 | $file->name = $this->get_file_name($name, $type, $index, $content_range); |
||
661 | $file->size = $this->fix_integer_overflow((int)$size); |
||
662 | $file->type = $type; |
||
663 | |||
664 | // Save to database for later use |
||
665 | $swDB = new SwDatabase(); |
||
666 | $userid = $GLOBALS['xoopsUser']->getVar('uid'); |
||
667 | |||
668 | // Generate new name for file |
||
669 | $file->name = basename(stripslashes($name)); |
||
670 | $file->name = time() . mt_rand(0, 99999) . '.' . $this->getFileExtension($name); |
||
671 | $img = XOOPS_URL . '/uploads/albums_smallworld/' . $userid . '/' . $file->name; |
||
672 | $swDB->saveImage("null, '" . $userid . "', '" . $file->name . "', '" . addslashes($img) . "', '" . time() . "', ''"); |
||
673 | //$swDB->saveImage("'1', '" . $userid . "', '" . $file->name . "', '" . addslashes($img) . "', '" . time() . "', '1'"); |
||
674 | |||
675 | if ($this->validate($uploaded_file, $file, $error, $index)) { |
||
676 | $this->handle_form_data($file, $index); |
||
677 | $upload_dir = $this->get_upload_path(); |
||
678 | View Code Duplication | if (!is_dir($upload_dir)) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
679 | if (!mkdir($upload_dir, $this->options['mkdir_mode'], true) && !is_dir($upload_dir)) { |
||
680 | throw new \RuntimeException(sprintf('Directory "%s" was not created', $upload_dir)); |
||
681 | } |
||
682 | } |
||
683 | $file_path = $this->get_upload_path($file->name); |
||
684 | $append_file = $content_range && is_file($file_path) && $file->size > $this->get_file_size($file_path); |
||
685 | if ($uploaded_file && is_uploaded_file($uploaded_file)) { |
||
686 | // multipart/formdata uploads (POST method uploads) |
||
687 | if ($append_file) { |
||
688 | file_put_contents($file_path, fopen($uploaded_file, 'rb'), FILE_APPEND); |
||
689 | } else { |
||
690 | move_uploaded_file($uploaded_file, $file_path); |
||
691 | } |
||
692 | } else { |
||
693 | // Non-multipart uploads (PUT method support) |
||
694 | file_put_contents($file_path, fopen('php://input', 'rb'), $append_file ? FILE_APPEND : 0); |
||
695 | } |
||
696 | $file_size = $this->get_file_size($file_path, $append_file); |
||
697 | if ($file_size === $file->size) { |
||
698 | if ($this->options['orient_image']) { |
||
699 | $this->orient_image($file_path); |
||
700 | } |
||
701 | $file->url = $this->get_download_url($file->name); |
||
702 | foreach ($this->options['image_versions'] as $version => $options) { |
||
0 ignored issues
–
show
The expression
$this->options['image_versions'] of type string|integer|array<int...ight\":\"integer\"}>"}> is not guaranteed to be traversable. How about adding an additional type check?
There are different options of fixing this problem.
![]() |
|||
703 | if ($this->create_scaled_image($file->name, $version, $options)) { |
||
704 | if (!empty($version)) { |
||
705 | $file->{$version . '_url'} = $this->get_download_url($file->name, $version); |
||
706 | } else { |
||
707 | $file_size = $this->get_file_size($file_path, true); |
||
708 | } |
||
709 | } |
||
710 | } |
||
711 | } elseif (!$content_range && $this->options['discard_aborted_uploads']) { |
||
712 | unlink($file_path); |
||
713 | $file->error = 'abort'; |
||
714 | } |
||
715 | $file->size = $file_size; |
||
716 | $this->set_file_delete_properties($file); |
||
717 | } |
||
718 | |||
719 | return $file; |
||
720 | } |
||
721 | |||
722 | //function to return file extension from a path or file name |
||
723 | |||
724 | /** |
||
725 | * @param $path |
||
726 | * @return mixed |
||
727 | */ |
||
728 | public function getFileExtension($path) |
||
729 | { |
||
730 | $parts = pathinfo($path); |
||
731 | |||
732 | return $parts['extension']; |
||
733 | } |
||
734 | |||
735 | /** |
||
736 | * @param $file_path |
||
737 | * @return false|int |
||
738 | */ |
||
739 | protected function readfile($file_path) |
||
740 | { |
||
741 | return readfile($file_path); |
||
742 | } |
||
743 | |||
744 | /** |
||
745 | * @param $str |
||
746 | */ |
||
747 | protected function body($str) |
||
748 | { |
||
749 | echo $str; |
||
750 | } |
||
751 | |||
752 | /** |
||
753 | * @param $str |
||
754 | */ |
||
755 | protected function header($str) |
||
756 | { |
||
757 | header($str); |
||
758 | } |
||
759 | |||
760 | /** |
||
761 | * @param $content |
||
762 | * @param bool $print_response |
||
763 | */ |
||
764 | protected function generate_response($content, $print_response = true) |
||
0 ignored issues
–
show
The return type could not be reliably inferred; please add a
@return annotation.
Our type inference engine in quite powerful, but sometimes the code does not
provide enough clues to go by. In these cases we request you to add a ![]() |
|||
765 | { |
||
766 | if ($print_response) { |
||
767 | $json = json_encode($content); |
||
768 | $redirect = isset($_REQUEST['redirect']) ? stripslashes($_REQUEST['redirect']) : null; |
||
769 | if ($redirect) { |
||
0 ignored issues
–
show
The expression
$redirect of type string|null is loosely compared to true ; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
|||
770 | $this->header('Location: ' . sprintf($redirect, rawurlencode($json))); |
||
771 | |||
772 | return; |
||
773 | } |
||
774 | $this->head(); |
||
775 | if (isset($_SERVER['HTTP_CONTENT_RANGE'])) { |
||
776 | $files = isset($content[$this->options['param_name']]) ? $content[$this->options['param_name']] : null; |
||
777 | if ($files && is_array($files) && is_object($files[0]) && $files[0]->size) { |
||
778 | $this->header('Range: 0-' . ($this->fix_integer_overflow((int)$files[0]->size) - 1)); |
||
779 | } |
||
780 | } |
||
781 | $this->body($json); |
||
782 | } |
||
783 | |||
784 | return $content; |
||
785 | } |
||
786 | |||
787 | /** |
||
788 | * @return null|string |
||
789 | */ |
||
790 | protected function get_version_param() |
||
791 | { |
||
792 | return isset($_GET['version']) ? basename(stripslashes($_GET['version'])) : null; |
||
793 | } |
||
794 | |||
795 | /** |
||
796 | * @return null|string |
||
797 | */ |
||
798 | protected function get_file_name_param() |
||
799 | { |
||
800 | return isset($_GET['file']) ? basename(stripslashes($_GET['file'])) : null; |
||
801 | } |
||
802 | |||
803 | /** |
||
804 | * @param $file_path |
||
805 | * @return string |
||
806 | */ |
||
807 | protected function get_file_type($file_path) |
||
808 | { |
||
809 | switch (mb_strtolower(pathinfo($file_path, PATHINFO_EXTENSION))) { |
||
810 | case 'jpeg': |
||
811 | case 'jpg': |
||
812 | return 'image/jpeg'; |
||
813 | case 'png': |
||
814 | return 'image/png'; |
||
815 | case 'gif': |
||
816 | return 'image/gif'; |
||
817 | default: |
||
818 | return ''; |
||
819 | } |
||
820 | } |
||
821 | |||
822 | protected function download() |
||
823 | { |
||
824 | if (!$this->options['download_via_php']) { |
||
825 | $this->header('HTTP/1.1 403 Forbidden'); |
||
826 | |||
827 | return; |
||
828 | } |
||
829 | $file_name = $this->get_file_name_param(); |
||
830 | if ($this->is_valid_file_object($file_name)) { |
||
831 | $file_path = $this->get_upload_path($file_name, $this->get_version_param()); |
||
0 ignored issues
–
show
It seems like
$this->get_version_param() targeting XoopsModules\Smallworld\...er::get_version_param() can also be of type string ; however, XoopsModules\Smallworld\...dler::get_upload_path() does only seem to accept null , maybe add an additional type check?
This check looks at variables that are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. ![]() |
|||
832 | if (is_file($file_path)) { |
||
833 | if (!preg_match($this->options['inline_file_types'], $file_name)) { |
||
834 | $this->header('Content-Description: File Transfer'); |
||
835 | $this->header('Content-Type: application/octet-stream'); |
||
836 | $this->header('Content-Disposition: attachment; filename="' . $file_name . '"'); |
||
837 | $this->header('Content-Transfer-Encoding: binary'); |
||
838 | } else { |
||
839 | // Prevent Internet Explorer from MIME-sniffing the content-type: |
||
840 | $this->header('X-Content-Type-Options: nosniff'); |
||
841 | $this->header('Content-Type: ' . $this->get_file_type($file_path)); |
||
842 | $this->header('Content-Disposition: inline; filename="' . $file_name . '"'); |
||
843 | } |
||
844 | $this->header('Content-Length: ' . $this->get_file_size($file_path)); |
||
845 | $this->header('Last-Modified: ' . gmdate('D, d M Y H:i:s T', filemtime($file_path))); |
||
846 | $this->readfile($file_path); |
||
847 | } |
||
848 | } |
||
849 | } |
||
850 | |||
851 | protected function send_content_type_header() |
||
852 | { |
||
853 | $this->header('Vary: Accept'); |
||
854 | if (isset($_SERVER['HTTP_ACCEPT']) && (false !== mb_strpos($_SERVER['HTTP_ACCEPT'], 'application/json'))) { |
||
855 | $this->header('Content-type: application/json'); |
||
856 | } else { |
||
857 | $this->header('Content-type: text/plain'); |
||
858 | } |
||
859 | } |
||
860 | |||
861 | protected function send_access_control_headers() |
||
862 | { |
||
863 | $this->header('Access-Control-Allow-Origin: ' . $this->options['access_control_allow_origin']); |
||
864 | $this->header('Access-Control-Allow-Credentials: ' . ($this->options['access_control_allow_credentials'] ? 'true' : 'false')); |
||
865 | $this->header('Access-Control-Allow-Methods: ' . implode(', ', $this->options['access_control_allow_methods'])); |
||
866 | $this->header('Access-Control-Allow-Headers: ' . implode(', ', $this->options['access_control_allow_headers'])); |
||
867 | } |
||
868 | |||
869 | public function head() |
||
870 | { |
||
871 | $this->header('Pragma: no-cache'); |
||
872 | $this->header('Cache-Control: no-store, no-cache, must-revalidate'); |
||
873 | $this->header('Content-Disposition: inline; filename="files.json"'); |
||
874 | // Prevent Internet Explorer from MIME-sniffing the content-type: |
||
875 | $this->header('X-Content-Type-Options: nosniff'); |
||
876 | if ($this->options['access_control_allow_origin']) { |
||
877 | $this->send_access_control_headers(); |
||
878 | } |
||
879 | $this->send_content_type_header(); |
||
880 | } |
||
881 | |||
882 | /** |
||
883 | * @param bool $print_response |
||
884 | */ |
||
885 | public function get($print_response = true) |
||
0 ignored issues
–
show
The return type could not be reliably inferred; please add a
@return annotation.
Our type inference engine in quite powerful, but sometimes the code does not
provide enough clues to go by. In these cases we request you to add a ![]() |
|||
886 | { |
||
887 | if ($print_response && isset($_GET['download'])) { |
||
888 | return $this->download(); |
||
889 | } |
||
890 | $file_name = $this->get_file_name_param(); |
||
891 | if (null !== $file_name) { |
||
892 | $response = [ |
||
893 | mb_substr($this->options['param_name'], 0, -1) => $this->get_file_object($file_name), |
||
894 | ]; |
||
895 | } else { |
||
896 | $response = [ |
||
897 | $this->options['param_name'] => $this->get_file_objects(), |
||
898 | ]; |
||
899 | } |
||
900 | |||
901 | return $this->generate_response($response, $print_response); |
||
902 | } |
||
903 | |||
904 | /** |
||
905 | * @param bool $print_response |
||
906 | */ |
||
907 | public function post($print_response = true) |
||
0 ignored issues
–
show
The return type could not be reliably inferred; please add a
@return annotation.
Our type inference engine in quite powerful, but sometimes the code does not
provide enough clues to go by. In these cases we request you to add a ![]() |
|||
908 | { |
||
909 | if (isset($_REQUEST['_method']) && 'DELETE' === $_REQUEST['_method']) { |
||
910 | return $this->delete($print_response); |
||
911 | } |
||
912 | $upload = isset($_FILES[$this->options['param_name']]) ? $_FILES[$this->options['param_name']] : null; |
||
913 | // Parse the Content-Disposition header, if available: |
||
914 | $file_name = isset($_SERVER['HTTP_CONTENT_DISPOSITION']) ? rawurldecode(preg_replace('/(^[^"]+")|("$)/', '', $_SERVER['HTTP_CONTENT_DISPOSITION'])) : null; |
||
915 | // Parse the Content-Range header, which has the following form: |
||
916 | // Content-Range: bytes 0-524287/2000000 |
||
917 | $content_range = isset($_SERVER['HTTP_CONTENT_RANGE']) ? preg_split('/[^0-9]+/', $_SERVER['HTTP_CONTENT_RANGE']) : null; |
||
918 | $size = $content_range ? $content_range[3] : null; |
||
919 | $files = []; |
||
920 | if ($upload && is_array($upload['tmp_name'])) { |
||
921 | // param_name is an array identifier like "files[]", |
||
922 | // $_FILES is a multi-dimensional array: |
||
923 | foreach ($upload['tmp_name'] as $index => $value) { |
||
924 | $files[] = $this->handle_file_upload($upload['tmp_name'][$index], $file_name ?: $upload['name'][$index], $size ?: $upload['size'][$index], $upload['type'][$index], $upload['error'][$index], $index, $content_range); |
||
0 ignored issues
–
show
It seems like
$content_range defined by isset($_SERVER['HTTP_CON...CONTENT_RANGE']) : null on line 917 can also be of type array ; however, XoopsModules\Smallworld\...r::handle_file_upload() does only seem to accept null , maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue. ![]() |
|||
925 | } |
||
926 | } else { |
||
927 | // param_name is a single object identifier like "file", |
||
928 | // $_FILES is a one-dimensional array: |
||
929 | $files[] = $this->handle_file_upload( |
||
930 | isset($upload['tmp_name']) ? $upload['tmp_name'] : null, |
||
931 | $file_name ?: (isset($upload['name']) ? $upload['name'] : null), |
||
932 | $size ?: (isset($upload['size']) ? $upload['size'] : $_SERVER['CONTENT_LENGTH']), |
||
933 | isset($upload['type']) ? $upload['type'] : $_SERVER['CONTENT_TYPE'], |
||
934 | isset($upload['error']) ? $upload['error'] : null, |
||
935 | null, |
||
936 | $content_range |
||
0 ignored issues
–
show
It seems like
$content_range defined by isset($_SERVER['HTTP_CON...CONTENT_RANGE']) : null on line 917 can also be of type array ; however, XoopsModules\Smallworld\...r::handle_file_upload() does only seem to accept null , maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue. ![]() |
|||
937 | ); |
||
938 | } |
||
939 | |||
940 | return $this->generate_response([$this->options['param_name'] => $files], $print_response); |
||
941 | } |
||
942 | |||
943 | /** |
||
944 | * @param bool $print_response |
||
945 | */ |
||
946 | public function delete($print_response = true) |
||
0 ignored issues
–
show
The return type could not be reliably inferred; please add a
@return annotation.
Our type inference engine in quite powerful, but sometimes the code does not
provide enough clues to go by. In these cases we request you to add a ![]() |
|||
947 | { |
||
948 | $userid = $GLOBALS['xoopsUser']->getVar('uid'); |
||
949 | $swDB = new SwDatabase(); |
||
950 | $file_name = $this->get_file_name_param(); |
||
951 | $file_path = $this->get_upload_path($file_name); |
||
952 | $success = is_file($file_path) && '.' !== $file_name[0] && unlink($file_path); |
||
953 | |||
954 | // Delete file based on user and filename |
||
955 | $swDB->deleteImage($userid, $file_name); |
||
956 | $swDB->deleteImage($userid, 'Thumbs.db'); |
||
957 | |||
958 | if ($success) { |
||
959 | foreach ($this->options['image_versions'] as $version => $options) { |
||
0 ignored issues
–
show
The expression
$this->options['image_versions'] of type string|integer|array<int...ight\":\"integer\"}>"}> is not guaranteed to be traversable. How about adding an additional type check?
There are different options of fixing this problem.
![]() |
|||
960 | if (!empty($version)) { |
||
961 | $file = $this->get_upload_path($file_name, $version); |
||
962 | if (is_file($file)) { |
||
963 | unlink($file); |
||
964 | } |
||
965 | } |
||
966 | } |
||
967 | } |
||
968 | |||
969 | return $this->generate_response(['success' => $success], $print_response); |
||
970 | } |
||
971 | } |
||
972 |
If you suppress an error, we recommend checking for the error condition explicitly: