Verzeichnisstruktur phpBB-3.2.0


Veröffentlicht
06.01.2017

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

filespec.php

Zuletzt modifiziert: 09.10.2024, 12:52 - Dateigröße: 14.90 KiB


 001  <?php
 002  /**
 003   *
 004   * This file is part of the phpBB Forum Software package.
 005   *
 006   * @copyright (c) phpBB Limited <https://www.phpbb.com>
 007   * @license GNU General Public License, version 2 (GPL-2.0)
 008   *
 009   * For full copyright and license information, please see
 010   * the docs/CREDITS.txt file.
 011   *
 012   */
 013   
 014  namespace phpbb\files;
 015   
 016  use phpbb\language\language;
 017   
 018  /**
 019   * Responsible for holding all file relevant information, as well as doing file-specific operations.
 020   * The {@link fileupload fileupload class} can be used to upload several files, each of them being this object to operate further on.
 021   */
 022  class filespec
 023  {
 024      /** @var string File name */
 025      protected $filename = '';
 026   
 027      /** @var string Real name of file */
 028      protected $realname = '';
 029   
 030      /** @var string Upload name of file */
 031      protected $uploadname = '';
 032   
 033      /** @var string Mimetype of file */
 034      protected $mimetype = '';
 035   
 036      /** @var string File extension */
 037      protected $extension = '';
 038   
 039      /** @var int File size */
 040      protected $filesize = 0;
 041   
 042      /** @var int Width of file */
 043      protected $width = 0;
 044   
 045      /** @var int Height of file */
 046      protected $height = 0;
 047   
 048      /** @var array Image info including type and size */
 049      protected $image_info = array();
 050   
 051      /** @var string Destination file name */
 052      protected $destination_file = '';
 053   
 054      /** @var string Destination file path */
 055      protected $destination_path = '';
 056   
 057      /** @var bool Whether file was moved */
 058      protected $file_moved = false;
 059   
 060      /** @var bool Whether file is local */
 061      protected $local = false;
 062   
 063      /** @var bool Class initialization flag */
 064      protected $class_initialized = false;
 065   
 066      /** @var array Error array */
 067      public $error = array();
 068   
 069      /** @var upload Instance of upload class  */
 070      public $upload;
 071   
 072      /** @var \phpbb\filesystem\filesystem_interface */
 073      protected $filesystem;
 074   
 075      /** @var \bantu\IniGetWrapper\IniGetWrapper ini_get() wrapper class */
 076      protected $php_ini;
 077   
 078      /** @var \FastImageSize\FastImageSize */
 079      protected $imagesize;
 080   
 081      /** @var language Language class */
 082      protected $language;
 083   
 084      /** @var string phpBB root path */
 085      protected $phpbb_root_path;
 086   
 087      /** @var \phpbb\plupload\plupload The plupload object */
 088      protected $plupload;
 089   
 090      /** @var \phpbb\mimetype\guesser phpBB Mimetype guesser */
 091      protected $mimetype_guesser;
 092   
 093      /**
 094       * File upload class
 095       *
 096       * @param \phpbb\filesystem\filesystem_interface    $phpbb_filesystem Filesystem
 097       * @param language                    $language Language
 098       * @param \bantu\IniGetWrapper\IniGetWrapper            $php_ini ini_get() wrapper
 099       * @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) || !sizeof($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 = (STRIP) ? stripslashes($upload_ary['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 (sizeof($this->error))
 407          {
 408              return false;
 409          }
 410   
 411          $chmod = ($chmod === false) ? CHMOD_READ | 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') || $this->php_ini->getBool('safe_mode')) ? '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              @unlink($this->filename);
 480   
 481              if (sizeof($this->error))
 482              {
 483                  return false;
 484              }
 485   
 486              try
 487              {
 488                  $this->filesystem->phpbb_chmod($this->destination_file, $chmod);
 489              }
 490              catch (\phpbb\filesystem\exception\filesystem_exception $e)
 491              {
 492                  // Do nothing
 493              }
 494          }
 495   
 496          // Try to get real filesize from destination folder
 497          $this->filesize = ($this->get_filesize($this->destination_file)) ?: $this->filesize;
 498   
 499          // Get mimetype of supplied file
 500          $this->mimetype = $this->get_mimetype($this->destination_file);
 501   
 502          if ($this->is_image() && !$skip_image_check)
 503          {
 504              $this->width = $this->height = 0;
 505   
 506              $this->image_info = $this->imagesize->getImageSize($this->destination_file, $this->mimetype);
 507   
 508              if ($this->image_info !== false)
 509              {
 510                  $this->width = $this->image_info['width'];
 511                  $this->height = $this->image_info['height'];
 512   
 513                  // Check image type
 514                  $types = upload::image_types();
 515   
 516                  if (!isset($types[$this->image_info['type']]) || !in_array($this->extension, $types[$this->image_info['type']]))
 517                  {
 518                      if (!isset($types[$this->image_info['type']]))
 519                      {
 520                          $this->error[] = $this->language->lang('IMAGE_FILETYPE_INVALID', $this->image_info['type'], $this->mimetype);
 521                      }
 522                      else
 523                      {
 524                          $this->error[] = $this->language->lang('IMAGE_FILETYPE_MISMATCH', $types[$this->image_info['type']][0], $this->extension);
 525                      }
 526                  }
 527   
 528                  // Make sure the dimensions match a valid image
 529                  if (empty($this->width) || empty($this->height))
 530                  {
 531                      $this->error[] = $this->language->lang('ATTACHED_IMAGE_NOT_IMAGE');
 532                  }
 533              }
 534              else
 535              {
 536                  $this->error[] = $this->language->lang('UNABLE_GET_IMAGE_SIZE');
 537              }
 538          }
 539   
 540          $this->file_moved = true;
 541          $this->additional_checks();
 542          unset($this->upload);
 543   
 544          return true;
 545      }
 546   
 547      /**
 548       * Performing additional checks
 549       *
 550       * @return bool False if issue was found, true if not
 551       */
 552      public function additional_checks()
 553      {
 554          if (!$this->file_moved)
 555          {
 556              return false;
 557          }
 558   
 559          // Filesize is too big or it's 0 if it was larger than the maxsize in the upload form
 560          if ($this->upload->max_filesize && ($this->get('filesize') > $this->upload->max_filesize || $this->filesize == 0))
 561          {
 562              $max_filesize = get_formatted_filesize($this->upload->max_filesize, false);
 563   
 564              $this->error[] = $this->language->lang($this->upload->error_prefix . 'WRONG_FILESIZE', $max_filesize['value'], $max_filesize['unit']);
 565   
 566              return false;
 567          }
 568   
 569          if (!$this->upload->valid_dimensions($this))
 570          {
 571              $this->error[] = $this->language->lang($this->upload->error_prefix . 'WRONG_SIZE',
 572                  $this->language->lang('PIXELS', (int) $this->upload->min_width),
 573                  $this->language->lang('PIXELS', (int) $this->upload->min_height),
 574                  $this->language->lang('PIXELS', (int) $this->upload->max_width),
 575                  $this->language->lang('PIXELS', (int) $this->upload->max_height),
 576                  $this->language->lang('PIXELS', (int) $this->width),
 577                  $this->language->lang('PIXELS', (int) $this->height));
 578   
 579              return false;
 580          }
 581   
 582          return true;
 583      }
 584  }
 585