Verzeichnisstruktur phpBB-3.3.15


Veröffentlicht
28.08.2024

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: 02.04.2025, 15:02 - Dateigröße: 14.94 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) || !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  }
588