[ Index ] |
PHP Cross Reference of phpBB-3.3.12-deutsch |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * 4 * This file is part of the phpBB Forum Software package. 5 * 6 * @copyright (c) phpBB Limited <https://www.phpbb.com> 7 * @license GNU General Public License, version 2 (GPL-2.0) 8 * 9 * For full copyright and license information, please see 10 * the docs/CREDITS.txt file. 11 * 12 */ 13 14 namespace phpbb\files; 15 16 use phpbb\language\language; 17 18 /** 19 * Responsible for holding all file relevant information, as well as doing file-specific operations. 20 * The {@link fileupload fileupload class} can be used to upload several files, each of them being this object to operate further on. 21 */ 22 class filespec 23 { 24 /** @var string File name */ 25 protected $filename = ''; 26 27 /** @var string Real name of file */ 28 protected $realname = ''; 29 30 /** @var string Upload name of file */ 31 protected $uploadname = ''; 32 33 /** @var string Mimetype of file */ 34 protected $mimetype = ''; 35 36 /** @var string File extension */ 37 protected $extension = ''; 38 39 /** @var int File size */ 40 protected $filesize = 0; 41 42 /** @var int Width of file */ 43 protected $width = 0; 44 45 /** @var int Height of file */ 46 protected $height = 0; 47 48 /** @var array Image info including type and size */ 49 protected $image_info = array(); 50 51 /** @var string Destination file name */ 52 protected $destination_file = ''; 53 54 /** @var string Destination file path */ 55 protected $destination_path = ''; 56 57 /** @var bool Whether file was moved */ 58 protected $file_moved = false; 59 60 /** @var bool Whether file is local */ 61 protected $local = false; 62 63 /** @var bool Class initialization flag */ 64 protected $class_initialized = false; 65 66 /** @var array Error array */ 67 public $error = array(); 68 69 /** @var upload Instance of upload class */ 70 public $upload; 71 72 /** @var \phpbb\filesystem\filesystem_interface */ 73 protected $filesystem; 74 75 /** @var \bantu\IniGetWrapper\IniGetWrapper ini_get() wrapper class */ 76 protected $php_ini; 77 78 /** @var \FastImageSize\FastImageSize */ 79 protected $imagesize; 80 81 /** @var language Language class */ 82 protected $language; 83 84 /** @var string phpBB root path */ 85 protected $phpbb_root_path; 86 87 /** @var \phpbb\plupload\plupload The plupload object */ 88 protected $plupload; 89 90 /** @var \phpbb\mimetype\guesser phpBB Mimetype guesser */ 91 protected $mimetype_guesser; 92 93 /** 94 * File upload class 95 * 96 * @param \phpbb\filesystem\filesystem_interface $phpbb_filesystem Filesystem 97 * @param language $language Language 98 * @param \bantu\IniGetWrapper\IniGetWrapper $php_ini ini_get() wrapper 99 * @param \FastImageSize\FastImageSize $imagesize Imagesize class 100 * @param string $phpbb_root_path phpBB root path 101 * @param \phpbb\mimetype\guesser $mimetype_guesser Mime type guesser 102 * @param \phpbb\plupload\plupload $plupload Plupload 103 */ 104 public function __construct(\phpbb\filesystem\filesystem_interface $phpbb_filesystem, language $language, \bantu\IniGetWrapper\IniGetWrapper $php_ini, \FastImageSize\FastImageSize $imagesize, $phpbb_root_path, \phpbb\mimetype\guesser $mimetype_guesser = null, \phpbb\plupload\plupload $plupload = null) 105 { 106 $this->filesystem = $phpbb_filesystem; 107 $this->language = $language; 108 $this->php_ini = $php_ini; 109 $this->imagesize = $imagesize; 110 $this->phpbb_root_path = $phpbb_root_path; 111 $this->plupload = $plupload; 112 $this->mimetype_guesser = $mimetype_guesser; 113 } 114 115 /** 116 * Set upload ary 117 * 118 * @param array $upload_ary Upload ary 119 * 120 * @return filespec This instance of the filespec class 121 */ 122 public function set_upload_ary($upload_ary) 123 { 124 if (!isset($upload_ary) || !count($upload_ary)) 125 { 126 return $this; 127 } 128 129 $this->class_initialized = true; 130 $this->filename = $upload_ary['tmp_name']; 131 $this->filesize = $upload_ary['size']; 132 $name = $upload_ary['name']; 133 $name = trim(utf8_basename($name)); 134 $this->realname = $this->uploadname = $name; 135 $this->mimetype = $upload_ary['type']; 136 137 // Opera adds the name to the mime type 138 $this->mimetype = (strpos($this->mimetype, '; name') !== false) ? str_replace(strstr($this->mimetype, '; name'), '', $this->mimetype) : $this->mimetype; 139 140 if (!$this->mimetype) 141 { 142 $this->mimetype = 'application/octet-stream'; 143 } 144 145 $this->extension = strtolower(self::get_extension($this->realname)); 146 147 // Try to get real filesize from temporary folder (not always working) ;) 148 $this->filesize = ($this->get_filesize($this->filename)) ?: $this->filesize; 149 150 $this->width = $this->height = 0; 151 $this->file_moved = false; 152 153 $this->local = (isset($upload_ary['local_mode'])) ? true : false; 154 155 return $this; 156 } 157 158 /** 159 * Set the upload namespace 160 * 161 * @param upload $namespace Instance of upload class 162 * 163 * @return filespec This instance of the filespec class 164 */ 165 public function set_upload_namespace($namespace) 166 { 167 $this->upload = $namespace; 168 169 return $this; 170 } 171 172 /** 173 * Check if class members were not properly initialised yet 174 * 175 * @return bool True if there was an init error, false if not 176 */ 177 public function init_error() 178 { 179 return !$this->class_initialized; 180 } 181 182 /** 183 * Set error in error array 184 * 185 * @param mixed $error Content for error array 186 * 187 * @return \phpbb\files\filespec This instance of the filespec class 188 */ 189 public function set_error($error) 190 { 191 $this->error[] = $error; 192 193 return $this; 194 } 195 196 /** 197 * Cleans destination filename 198 * 199 * @param string $mode Either real, unique, or unique_ext. Real creates a 200 * realname, filtering some characters, lowering every 201 * character. Unique creates a unique filename. 202 * @param string $prefix Prefix applied to filename 203 * @param string $user_id The user_id is only needed for when cleaning a user's avatar 204 */ 205 public function clean_filename($mode = 'unique', $prefix = '', $user_id = '') 206 { 207 if ($this->init_error()) 208 { 209 return; 210 } 211 212 switch ($mode) 213 { 214 case 'real': 215 // Remove every extension from filename (to not let the mime bug being exposed) 216 if (strpos($this->realname, '.') !== false) 217 { 218 $this->realname = substr($this->realname, 0, strpos($this->realname, '.')); 219 } 220 221 // Replace any chars which may cause us problems with _ 222 $bad_chars = array("'", "\\", ' ', '/', ':', '*', '?', '"', '<', '>', '|'); 223 224 $this->realname = rawurlencode(str_replace($bad_chars, '_', strtolower($this->realname))); 225 $this->realname = preg_replace("/%(\w{2})/", '_', $this->realname); 226 227 $this->realname = $prefix . $this->realname . '.' . $this->extension; 228 break; 229 230 case 'unique': 231 $this->realname = $prefix . md5(unique_id()); 232 break; 233 234 case 'avatar': 235 $this->extension = strtolower($this->extension); 236 $this->realname = $prefix . $user_id . '.' . $this->extension; 237 238 break; 239 240 case 'unique_ext': 241 default: 242 $this->realname = $prefix . md5(unique_id()) . '.' . $this->extension; 243 } 244 } 245 246 /** 247 * Get property from file object 248 * 249 * @param string $property Name of property 250 * 251 * @return mixed Content of property 252 */ 253 public function get($property) 254 { 255 if ($this->init_error() || !isset($this->$property)) 256 { 257 return false; 258 } 259 260 return $this->$property; 261 } 262 263 /** 264 * Check if file is an image (mime type) 265 * 266 * @return bool true if it is an image, false if not 267 */ 268 public function is_image() 269 { 270 return (strpos($this->mimetype, 'image/') === 0); 271 } 272 273 /** 274 * Check if the file got correctly uploaded 275 * 276 * @return bool true if it is a valid upload, false if not 277 */ 278 public function is_uploaded() 279 { 280 $is_plupload = $this->plupload && $this->plupload->is_active(); 281 282 if (!$this->local && !$is_plupload && !is_uploaded_file($this->filename)) 283 { 284 return false; 285 } 286 287 if (($this->local || $is_plupload) && !file_exists($this->filename)) 288 { 289 return false; 290 } 291 292 return true; 293 } 294 295 /** 296 * Remove file 297 */ 298 public function remove() 299 { 300 if ($this->file_moved) 301 { 302 @unlink($this->destination_file); 303 } 304 } 305 306 /** 307 * Get file extension 308 * 309 * @param string $filename Filename that needs to be checked 310 * 311 * @return string Extension of the supplied filename 312 */ 313 static public function get_extension($filename) 314 { 315 $filename = utf8_basename($filename); 316 317 if (strpos($filename, '.') === false) 318 { 319 return ''; 320 } 321 322 $filename = explode('.', $filename); 323 return array_pop($filename); 324 } 325 326 /** 327 * Get mime type 328 * 329 * @param string $filename Filename that needs to be checked 330 * @return string Mime type of supplied filename 331 */ 332 public function get_mimetype($filename) 333 { 334 if ($this->mimetype_guesser !== null) 335 { 336 $mimetype = $this->mimetype_guesser->guess($filename, $this->uploadname); 337 338 if ($mimetype !== 'application/octet-stream') 339 { 340 $this->mimetype = $mimetype; 341 } 342 } 343 344 return $this->mimetype; 345 } 346 347 /** 348 * Get file size 349 * 350 * @param string $filename File name of file to check 351 * 352 * @return int File size 353 */ 354 public function get_filesize($filename) 355 { 356 return @filesize($filename); 357 } 358 359 360 /** 361 * Check the first 256 bytes for forbidden content 362 * 363 * @param array $disallowed_content Array containg disallowed content 364 * 365 * @return bool False if disallowed content found, true if not 366 */ 367 public function check_content($disallowed_content) 368 { 369 if (empty($disallowed_content)) 370 { 371 return true; 372 } 373 374 $fp = @fopen($this->filename, 'rb'); 375 376 if ($fp !== false) 377 { 378 $ie_mime_relevant = fread($fp, 256); 379 fclose($fp); 380 foreach ($disallowed_content as $forbidden) 381 { 382 if (stripos($ie_mime_relevant, '<' . $forbidden) !== false) 383 { 384 return false; 385 } 386 } 387 } 388 return true; 389 } 390 391 /** 392 * Move file to destination folder 393 * The phpbb_root_path variable will be applied to the destination path 394 * 395 * @param string $destination Destination path, for example $config['avatar_path'] 396 * @param bool $overwrite If set to true, an already existing file will be overwritten 397 * @param bool $skip_image_check If set to true, the check for the file to be a valid image is skipped 398 * @param string|bool $chmod Permission mask for chmodding the file after a successful move. 399 * The mode entered here reflects the mode defined by {@link phpbb_chmod()} 400 * 401 * @return bool True if file was moved, false if not 402 * @access public 403 */ 404 public function move_file($destination, $overwrite = false, $skip_image_check = false, $chmod = false) 405 { 406 if (count($this->error)) 407 { 408 return false; 409 } 410 411 $chmod = ($chmod === false) ? \phpbb\filesystem\filesystem_interface::CHMOD_READ | \phpbb\filesystem\filesystem_interface::CHMOD_WRITE : $chmod; 412 413 // We need to trust the admin in specifying valid upload directories and an attacker not being able to overwrite it... 414 $this->destination_path = $this->phpbb_root_path . $destination; 415 416 // Check if the destination path exist... 417 if (!file_exists($this->destination_path)) 418 { 419 @unlink($this->filename); 420 return false; 421 } 422 423 $upload_mode = ($this->php_ini->getBool('open_basedir')) ? 'move' : 'copy'; 424 $upload_mode = ($this->local) ? 'local' : $upload_mode; 425 $this->destination_file = $this->destination_path . '/' . utf8_basename($this->realname); 426 427 // Check if the file already exist, else there is something wrong... 428 if (file_exists($this->destination_file) && !$overwrite) 429 { 430 @unlink($this->filename); 431 $this->error[] = $this->language->lang($this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR', $this->destination_file); 432 $this->file_moved = false; 433 return false; 434 } 435 else 436 { 437 if (file_exists($this->destination_file)) 438 { 439 @unlink($this->destination_file); 440 } 441 442 switch ($upload_mode) 443 { 444 case 'copy': 445 446 if (!@copy($this->filename, $this->destination_file)) 447 { 448 if (!@move_uploaded_file($this->filename, $this->destination_file)) 449 { 450 $this->error[] = $this->language->lang($this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR', $this->destination_file); 451 } 452 } 453 454 break; 455 456 case 'move': 457 458 if (!@move_uploaded_file($this->filename, $this->destination_file)) 459 { 460 if (!@copy($this->filename, $this->destination_file)) 461 { 462 $this->error[] = $this->language->lang($this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR', $this->destination_file); 463 } 464 } 465 466 break; 467 468 case 'local': 469 470 if (!@copy($this->filename, $this->destination_file)) 471 { 472 $this->error[] = $this->language->lang($this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR', $this->destination_file); 473 } 474 475 break; 476 } 477 478 // Remove temporary filename 479 if (file_exists($this->filename)) 480 { 481 @unlink($this->filename); 482 } 483 484 if (count($this->error)) 485 { 486 return false; 487 } 488 489 try 490 { 491 $this->filesystem->phpbb_chmod($this->destination_file, $chmod); 492 } 493 catch (\phpbb\filesystem\exception\filesystem_exception $e) 494 { 495 // Do nothing 496 } 497 } 498 499 // Try to get real filesize from destination folder 500 $this->filesize = ($this->get_filesize($this->destination_file)) ?: $this->filesize; 501 502 // Get mimetype of supplied file 503 $this->mimetype = $this->get_mimetype($this->destination_file); 504 505 if ($this->is_image() && !$skip_image_check) 506 { 507 $this->width = $this->height = 0; 508 509 $this->image_info = $this->imagesize->getImageSize($this->destination_file, $this->mimetype); 510 511 if ($this->image_info !== false) 512 { 513 $this->width = $this->image_info['width']; 514 $this->height = $this->image_info['height']; 515 516 // Check image type 517 $types = upload::image_types(); 518 519 if (!isset($types[$this->image_info['type']]) || !in_array($this->extension, $types[$this->image_info['type']])) 520 { 521 if (!isset($types[$this->image_info['type']])) 522 { 523 $this->error[] = $this->language->lang('IMAGE_FILETYPE_INVALID', $this->image_info['type'], $this->mimetype); 524 } 525 else 526 { 527 $this->error[] = $this->language->lang('IMAGE_FILETYPE_MISMATCH', $types[$this->image_info['type']][0], $this->extension); 528 } 529 } 530 531 // Make sure the dimensions match a valid image 532 if (empty($this->width) || empty($this->height)) 533 { 534 $this->error[] = $this->language->lang('ATTACHED_IMAGE_NOT_IMAGE'); 535 } 536 } 537 else 538 { 539 $this->error[] = $this->language->lang('UNABLE_GET_IMAGE_SIZE'); 540 } 541 } 542 543 $this->file_moved = true; 544 $this->additional_checks(); 545 unset($this->upload); 546 547 return true; 548 } 549 550 /** 551 * Performing additional checks 552 * 553 * @return bool False if issue was found, true if not 554 */ 555 public function additional_checks() 556 { 557 if (!$this->file_moved) 558 { 559 return false; 560 } 561 562 // Filesize is too big or it's 0 if it was larger than the maxsize in the upload form 563 if ($this->upload->max_filesize && ($this->get('filesize') > $this->upload->max_filesize || $this->filesize == 0)) 564 { 565 $max_filesize = get_formatted_filesize($this->upload->max_filesize, false); 566 567 $this->error[] = $this->language->lang($this->upload->error_prefix . 'WRONG_FILESIZE', $max_filesize['value'], $max_filesize['unit']); 568 569 return false; 570 } 571 572 if (!$this->upload->valid_dimensions($this)) 573 { 574 $this->error[] = $this->language->lang($this->upload->error_prefix . 'WRONG_SIZE', 575 $this->language->lang('PIXELS', (int) $this->upload->min_width), 576 $this->language->lang('PIXELS', (int) $this->upload->min_height), 577 $this->language->lang('PIXELS', (int) $this->upload->max_width), 578 $this->language->lang('PIXELS', (int) $this->upload->max_height), 579 $this->language->lang('PIXELS', (int) $this->width), 580 $this->language->lang('PIXELS', (int) $this->height)); 581 582 return false; 583 } 584 585 return true; 586 } 587 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Jun 23 12:25:44 2024 | Cross-referenced by PHPXref 0.7.1 |