[ Index ]

PHP Cross Reference of phpBB-3.1.12-deutsch

title

Body

[close]

/includes/ -> functions_upload.php (source)

   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  /**
  15  * @ignore
  16  */
  17  if (!defined('IN_PHPBB'))
  18  {
  19      exit;
  20  }
  21  
  22  /**
  23  * Responsible for holding all file relevant information, as well as doing file-specific operations.
  24  * The {@link fileupload fileupload class} can be used to upload several files, each of them being this object to operate further on.
  25  */
  26  class filespec
  27  {
  28      var $filename = '';
  29      var $realname = '';
  30      var $uploadname = '';
  31      var $mimetype = '';
  32      var $extension = '';
  33      var $filesize = 0;
  34      var $width = 0;
  35      var $height = 0;
  36      var $image_info = array();
  37  
  38      var $destination_file = '';
  39      var $destination_path = '';
  40  
  41      var $file_moved = false;
  42      var $init_error = false;
  43      var $local = false;
  44  
  45      var $error = array();
  46  
  47      var $upload = '';
  48  
  49      /**
  50       * The plupload object
  51       * @var \phpbb\plupload\plupload
  52       */
  53      protected $plupload;
  54  
  55      /**
  56       * phpBB Mimetype guesser
  57       * @var \phpbb\mimetype\guesser
  58       */
  59      protected $mimetype_guesser;
  60  
  61      /**
  62      * File Class
  63      * @access private
  64      */
  65  	function filespec($upload_ary, $upload_namespace, \phpbb\mimetype\guesser $mimetype_guesser = null, \phpbb\plupload\plupload $plupload = null)
  66      {
  67          if (!isset($upload_ary))
  68          {
  69              $this->init_error = true;
  70              return;
  71          }
  72  
  73          $this->filename = $upload_ary['tmp_name'];
  74          $this->filesize = $upload_ary['size'];
  75          $name = (STRIP) ? stripslashes($upload_ary['name']) : $upload_ary['name'];
  76          $name = trim(utf8_basename($name));
  77          $this->realname = $this->uploadname = $name;
  78          $this->mimetype = $upload_ary['type'];
  79  
  80          // Opera adds the name to the mime type
  81          $this->mimetype    = (strpos($this->mimetype, '; name') !== false) ? str_replace(strstr($this->mimetype, '; name'), '', $this->mimetype) : $this->mimetype;
  82  
  83          if (!$this->mimetype)
  84          {
  85              $this->mimetype = 'application/octet-stream';
  86          }
  87  
  88          $this->extension = strtolower(self::get_extension($this->realname));
  89  
  90          // Try to get real filesize from temporary folder (not always working) ;)
  91          $this->filesize = (@filesize($this->filename)) ? @filesize($this->filename) : $this->filesize;
  92  
  93          $this->width = $this->height = 0;
  94          $this->file_moved = false;
  95  
  96          $this->local = (isset($upload_ary['local_mode'])) ? true : false;
  97          $this->upload = $upload_namespace;
  98          $this->plupload = $plupload;
  99          $this->mimetype_guesser = $mimetype_guesser;
 100      }
 101  
 102      /**
 103      * Cleans destination filename
 104      *
 105      * @param real|unique|unique_ext $mode real creates a realname, filtering some characters, lowering every character. Unique creates an unique filename
 106      * @param string $prefix Prefix applied to filename
 107      * @param string $user_id The user_id is only needed for when cleaning a user's avatar
 108      * @access public
 109      */
 110  	function clean_filename($mode = 'unique', $prefix = '', $user_id = '')
 111      {
 112          if ($this->init_error)
 113          {
 114              return;
 115          }
 116  
 117          switch ($mode)
 118          {
 119              case 'real':
 120                  // Remove every extension from filename (to not let the mime bug being exposed)
 121                  if (strpos($this->realname, '.') !== false)
 122                  {
 123                      $this->realname = substr($this->realname, 0, strpos($this->realname, '.'));
 124                  }
 125  
 126                  // Replace any chars which may cause us problems with _
 127                  $bad_chars = array("'", "\\", ' ', '/', ':', '*', '?', '"', '<', '>', '|');
 128  
 129                  $this->realname = rawurlencode(str_replace($bad_chars, '_', strtolower($this->realname)));
 130                  $this->realname = preg_replace("/%(\w{2})/", '_', $this->realname);
 131  
 132                  $this->realname = $prefix . $this->realname . '.' . $this->extension;
 133              break;
 134  
 135              case 'unique':
 136                  $this->realname = $prefix . md5(unique_id());
 137              break;
 138  
 139              case 'avatar':
 140                  $this->extension = strtolower($this->extension);
 141                  $this->realname = $prefix . $user_id . '.' . $this->extension;
 142  
 143              break;
 144  
 145              case 'unique_ext':
 146              default:
 147                  $this->realname = $prefix . md5(unique_id()) . '.' . $this->extension;
 148              break;
 149          }
 150      }
 151  
 152      /**
 153      * Get property from file object
 154      */
 155  	function get($property)
 156      {
 157          if ($this->init_error || !isset($this->$property))
 158          {
 159              return false;
 160          }
 161  
 162          return $this->$property;
 163      }
 164  
 165      /**
 166      * Check if file is an image (mimetype)
 167      *
 168      * @return true if it is an image, false if not
 169      */
 170  	function is_image()
 171      {
 172          return (strpos($this->mimetype, 'image/') === 0);
 173      }
 174  
 175      /**
 176      * Check if the file got correctly uploaded
 177      *
 178      * @return true if it is a valid upload, false if not
 179      */
 180  	function is_uploaded()
 181      {
 182          $is_plupload = $this->plupload && $this->plupload->is_active();
 183  
 184          if (!$this->local && !$is_plupload && !is_uploaded_file($this->filename))
 185          {
 186              return false;
 187          }
 188  
 189          if (($this->local || $is_plupload) && !file_exists($this->filename))
 190          {
 191              return false;
 192          }
 193  
 194          return true;
 195      }
 196  
 197      /**
 198      * Remove file
 199      */
 200  	function remove()
 201      {
 202          if ($this->file_moved)
 203          {
 204              @unlink($this->destination_file);
 205          }
 206      }
 207  
 208      /**
 209      * Get file extension
 210      *
 211      * @param string Filename that needs to be checked
 212      * @return string Extension of the supplied filename
 213      */
 214  	static public function get_extension($filename)
 215      {
 216          $filename = utf8_basename($filename);
 217  
 218          if (strpos($filename, '.') === false)
 219          {
 220              return '';
 221          }
 222  
 223          $filename = explode('.', $filename);
 224          return array_pop($filename);
 225      }
 226  
 227      /**
 228      * Get mimetype
 229      *
 230      * @param string $filename Filename that needs to be checked
 231      * @return string Mimetype of supplied filename
 232      */
 233  	function get_mimetype($filename)
 234      {
 235          if ($this->mimetype_guesser !== null)
 236          {
 237              $mimetype = $this->mimetype_guesser->guess($filename, $this->uploadname);
 238  
 239              if ($mimetype !== 'application/octet-stream')
 240              {
 241                  $this->mimetype = $mimetype;
 242              }
 243          }
 244  
 245          return $this->mimetype;
 246      }
 247  
 248      /**
 249      * Get filesize
 250      */
 251  	function get_filesize($filename)
 252      {
 253          return @filesize($filename);
 254      }
 255  
 256  
 257      /**
 258      * Check the first 256 bytes for forbidden content
 259      */
 260  	function check_content($disallowed_content)
 261      {
 262          if (empty($disallowed_content))
 263          {
 264              return true;
 265          }
 266  
 267          $fp = @fopen($this->filename, 'rb');
 268  
 269          if ($fp !== false)
 270          {
 271              $ie_mime_relevant = fread($fp, 256);
 272              fclose($fp);
 273              foreach ($disallowed_content as $forbidden)
 274              {
 275                  if (stripos($ie_mime_relevant, '<' . $forbidden) !== false)
 276                  {
 277                      return false;
 278                  }
 279              }
 280          }
 281          return true;
 282      }
 283  
 284      /**
 285      * Move file to destination folder
 286      * The phpbb_root_path variable will be applied to the destination path
 287      *
 288      * @param string $destination Destination path, for example $config['avatar_path']
 289      * @param bool $overwrite If set to true, an already existing file will be overwritten
 290      * @param bool $skip_image_check If set to true, the check for the file to be a valid image is skipped
 291      * @param string $chmod Permission mask for chmodding the file after a successful move. The mode entered here reflects the mode defined by {@link phpbb_chmod()}
 292      *
 293      * @access public
 294      */
 295  	function move_file($destination, $overwrite = false, $skip_image_check = false, $chmod = false)
 296      {
 297          global $user, $phpbb_root_path;
 298  
 299          if (sizeof($this->error))
 300          {
 301              return false;
 302          }
 303  
 304          $chmod = ($chmod === false) ? CHMOD_READ | CHMOD_WRITE : $chmod;
 305  
 306          // We need to trust the admin in specifying valid upload directories and an attacker not being able to overwrite it...
 307          $this->destination_path = $phpbb_root_path . $destination;
 308  
 309          // Check if the destination path exist...
 310          if (!file_exists($this->destination_path))
 311          {
 312              @unlink($this->filename);
 313              return false;
 314          }
 315  
 316          $upload_mode = (@ini_get('open_basedir') || @ini_get('safe_mode') || strtolower(@ini_get('safe_mode')) == 'on') ? 'move' : 'copy';
 317          $upload_mode = ($this->local) ? 'local' : $upload_mode;
 318          $this->destination_file = $this->destination_path . '/' . utf8_basename($this->realname);
 319  
 320          // Check if the file already exist, else there is something wrong...
 321          if (file_exists($this->destination_file) && !$overwrite)
 322          {
 323              @unlink($this->filename);
 324              $this->error[] = $user->lang($this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR', $this->destination_file);
 325              $this->file_moved = false;
 326              return false;
 327          }
 328          else
 329          {
 330              if (file_exists($this->destination_file))
 331              {
 332                  @unlink($this->destination_file);
 333              }
 334  
 335              switch ($upload_mode)
 336              {
 337                  case 'copy':
 338  
 339                      if (!@copy($this->filename, $this->destination_file))
 340                      {
 341                          if (!@move_uploaded_file($this->filename, $this->destination_file))
 342                          {
 343                              $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR'], $this->destination_file);
 344                          }
 345                      }
 346  
 347                  break;
 348  
 349                  case 'move':
 350  
 351                      if (!@move_uploaded_file($this->filename, $this->destination_file))
 352                      {
 353                          if (!@copy($this->filename, $this->destination_file))
 354                          {
 355                              $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR'], $this->destination_file);
 356                          }
 357                      }
 358  
 359                  break;
 360  
 361                  case 'local':
 362  
 363                      if (!@copy($this->filename, $this->destination_file))
 364                      {
 365                          $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR'], $this->destination_file);
 366                      }
 367  
 368                  break;
 369              }
 370  
 371              // Remove temporary filename
 372              @unlink($this->filename);
 373  
 374              if (sizeof($this->error))
 375              {
 376                  return false;
 377              }
 378  
 379              phpbb_chmod($this->destination_file, $chmod);
 380          }
 381  
 382          // Try to get real filesize from destination folder
 383          $this->filesize = (@filesize($this->destination_file)) ? @filesize($this->destination_file) : $this->filesize;
 384  
 385          // Get mimetype of supplied file
 386          $this->mimetype = $this->get_mimetype($this->destination_file);
 387  
 388          if ($this->is_image() && !$skip_image_check)
 389          {
 390              $this->width = $this->height = 0;
 391  
 392              if (($this->image_info = @getimagesize($this->destination_file)) !== false)
 393              {
 394                  $this->width = $this->image_info[0];
 395                  $this->height = $this->image_info[1];
 396  
 397                  if (!empty($this->image_info['mime']))
 398                  {
 399                      $this->mimetype = $this->image_info['mime'];
 400                  }
 401  
 402                  // Check image type
 403                  $types = fileupload::image_types();
 404  
 405                  if (!isset($types[$this->image_info[2]]) || !in_array($this->extension, $types[$this->image_info[2]]))
 406                  {
 407                      if (!isset($types[$this->image_info[2]]))
 408                      {
 409                          $this->error[] = sprintf($user->lang['IMAGE_FILETYPE_INVALID'], $this->image_info[2], $this->mimetype);
 410                      }
 411                      else
 412                      {
 413                          $this->error[] = sprintf($user->lang['IMAGE_FILETYPE_MISMATCH'], $types[$this->image_info[2]][0], $this->extension);
 414                      }
 415                  }
 416  
 417                  // Make sure the dimensions match a valid image
 418                  if (empty($this->width) || empty($this->height))
 419                  {
 420                      $this->error[] = $user->lang['ATTACHED_IMAGE_NOT_IMAGE'];
 421                  }
 422              }
 423              else
 424              {
 425                  $this->error[] = $user->lang['UNABLE_GET_IMAGE_SIZE'];
 426              }
 427          }
 428  
 429          $this->file_moved = true;
 430          $this->additional_checks();
 431          unset($this->upload);
 432  
 433          return true;
 434      }
 435  
 436      /**
 437      * Performing additional checks
 438      */
 439  	function additional_checks()
 440      {
 441          global $user;
 442  
 443          if (!$this->file_moved)
 444          {
 445              return false;
 446          }
 447  
 448          // Filesize is too big or it's 0 if it was larger than the maxsize in the upload form
 449          if ($this->upload->max_filesize && ($this->get('filesize') > $this->upload->max_filesize || $this->filesize == 0))
 450          {
 451              $max_filesize = get_formatted_filesize($this->upload->max_filesize, false);
 452  
 453              $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']);
 454  
 455              return false;
 456          }
 457  
 458          if (!$this->upload->valid_dimensions($this))
 459          {
 460              $this->error[] = $user->lang($this->upload->error_prefix . 'WRONG_SIZE',
 461                  $user->lang('PIXELS', (int) $this->upload->min_width),
 462                  $user->lang('PIXELS', (int) $this->upload->min_height),
 463                  $user->lang('PIXELS', (int) $this->upload->max_width),
 464                  $user->lang('PIXELS', (int) $this->upload->max_height),
 465                  $user->lang('PIXELS', (int) $this->width),
 466                  $user->lang('PIXELS', (int) $this->height));
 467  
 468              return false;
 469          }
 470  
 471          return true;
 472      }
 473  }
 474  
 475  /**
 476  * Class for assigning error messages before a real filespec class can be assigned
 477  */
 478  class fileerror extends filespec
 479  {
 480  	function fileerror($error_msg)
 481      {
 482          $this->error[] = $error_msg;
 483      }
 484  }
 485  
 486  /**
 487  * File upload class
 488  * Init class (all parameters optional and able to be set/overwritten separately) - scope is global and valid for all uploads
 489  */
 490  class fileupload
 491  {
 492      var $allowed_extensions = array();
 493      var $disallowed_content = array('body', 'head', 'html', 'img', 'plaintext', 'a href', 'pre', 'script', 'table', 'title');
 494      var $max_filesize = 0;
 495      var $min_width = 0;
 496      var $min_height = 0;
 497      var $max_width = 0;
 498      var $max_height = 0;
 499      var $error_prefix = '';
 500  
 501      /** @var int Timeout for remote upload */
 502      var $upload_timeout = 6;
 503  
 504      /**
 505      * Init file upload class.
 506      *
 507      * @param string $error_prefix Used error messages will get prefixed by this string
 508      * @param array $allowed_extensions Array of allowed extensions, for example array('jpg', 'jpeg', 'gif', 'png')
 509      * @param int $max_filesize Maximum filesize
 510      * @param int $min_width Minimum image width (only checked for images)
 511      * @param int $min_height Minimum image height (only checked for images)
 512      * @param int $max_width Maximum image width (only checked for images)
 513      * @param int $max_height Maximum image height (only checked for images)
 514      * @param bool|array $disallowed_content If enabled, the first 256 bytes of the file must not
 515      *                                        contain any of its values. Defaults to false.
 516      *
 517      */
 518  	function fileupload($error_prefix = '', $allowed_extensions = false, $max_filesize = false, $min_width = false, $min_height = false, $max_width = false, $max_height = false, $disallowed_content = false)
 519      {
 520          $this->set_allowed_extensions($allowed_extensions);
 521          $this->set_max_filesize($max_filesize);
 522          $this->set_allowed_dimensions($min_width, $min_height, $max_width, $max_height);
 523          $this->set_error_prefix($error_prefix);
 524          $this->set_disallowed_content($disallowed_content);
 525      }
 526  
 527      /**
 528      * Reset vars
 529      */
 530  	function reset_vars()
 531      {
 532          $this->max_filesize = 0;
 533          $this->min_width = $this->min_height = $this->max_width = $this->max_height = 0;
 534          $this->error_prefix = '';
 535          $this->allowed_extensions = array();
 536          $this->disallowed_content = array();
 537      }
 538  
 539      /**
 540      * Set allowed extensions
 541      */
 542  	function set_allowed_extensions($allowed_extensions)
 543      {
 544          if ($allowed_extensions !== false && is_array($allowed_extensions))
 545          {
 546              $this->allowed_extensions = $allowed_extensions;
 547          }
 548      }
 549  
 550      /**
 551      * Set allowed dimensions
 552      */
 553  	function set_allowed_dimensions($min_width, $min_height, $max_width, $max_height)
 554      {
 555          $this->min_width = (int) $min_width;
 556          $this->min_height = (int) $min_height;
 557          $this->max_width = (int) $max_width;
 558          $this->max_height = (int) $max_height;
 559      }
 560  
 561      /**
 562      * Set maximum allowed filesize
 563      */
 564  	function set_max_filesize($max_filesize)
 565      {
 566          if ($max_filesize !== false && (int) $max_filesize)
 567          {
 568              $this->max_filesize = (int) $max_filesize;
 569          }
 570      }
 571  
 572      /**
 573      * Set disallowed strings
 574      */
 575  	function set_disallowed_content($disallowed_content)
 576      {
 577          if ($disallowed_content !== false && is_array($disallowed_content))
 578          {
 579              $this->disallowed_content = array_diff($disallowed_content, array(''));
 580          }
 581      }
 582  
 583      /**
 584      * Set error prefix
 585      */
 586  	function set_error_prefix($error_prefix)
 587      {
 588          $this->error_prefix = $error_prefix;
 589      }
 590  
 591      /**
 592      * Form upload method
 593      * Upload file from users harddisk
 594      *
 595      * @param string $form_name Form name assigned to the file input field (if it is an array, the key has to be specified)
 596      * @param \phpbb\mimetype\guesser $mimetype_guesser Mimetype guesser
 597      * @param \phpbb\plupload\plupload $plupload The plupload object
 598      *
 599      * @return object $file Object "filespec" is returned, all further operations can be done with this object
 600      * @access public
 601      */
 602  	function form_upload($form_name, \phpbb\mimetype\guesser $mimetype_guesser = null, \phpbb\plupload\plupload $plupload = null)
 603      {
 604          global $user, $request;
 605  
 606          $upload = $request->file($form_name);
 607          unset($upload['local_mode']);
 608  
 609          if ($plupload)
 610          {
 611              $result = $plupload->handle_upload($form_name);
 612              if (is_array($result))
 613              {
 614                  $upload = array_merge($upload, $result);
 615              }
 616          }
 617  
 618          $file = new filespec($upload, $this, $mimetype_guesser, $plupload);
 619  
 620          if ($file->init_error)
 621          {
 622              $file->error[] = '';
 623              return $file;
 624          }
 625  
 626          // Error array filled?
 627          if (isset($upload['error']))
 628          {
 629              $error = $this->assign_internal_error($upload['error']);
 630  
 631              if ($error !== false)
 632              {
 633                  $file->error[] = $error;
 634                  return $file;
 635              }
 636          }
 637  
 638          // Check if empty file got uploaded (not catched by is_uploaded_file)
 639          if (isset($upload['size']) && $upload['size'] == 0)
 640          {
 641              $file->error[] = $user->lang[$this->error_prefix . 'EMPTY_FILEUPLOAD'];
 642              return $file;
 643          }
 644  
 645          // PHP Upload filesize exceeded
 646          if ($file->get('filename') == 'none')
 647          {
 648              $max_filesize = @ini_get('upload_max_filesize');
 649              $unit = 'MB';
 650  
 651              if (!empty($max_filesize))
 652              {
 653                  $unit = strtolower(substr($max_filesize, -1, 1));
 654                  $max_filesize = (int) $max_filesize;
 655  
 656                  $unit = ($unit == 'k') ? 'KB' : (($unit == 'g') ? 'GB' : 'MB');
 657              }
 658  
 659              $file->error[] = (empty($max_filesize)) ? $user->lang[$this->error_prefix . 'PHP_SIZE_NA'] : sprintf($user->lang[$this->error_prefix . 'PHP_SIZE_OVERRUN'], $max_filesize, $user->lang[$unit]);
 660              return $file;
 661          }
 662  
 663          // Not correctly uploaded
 664          if (!$file->is_uploaded())
 665          {
 666              $file->error[] = $user->lang[$this->error_prefix . 'NOT_UPLOADED'];
 667              return $file;
 668          }
 669  
 670          $this->common_checks($file);
 671  
 672          return $file;
 673      }
 674  
 675      /**
 676      * Move file from another location to phpBB
 677      */
 678  	function local_upload($source_file, $filedata = false, \phpbb\mimetype\guesser $mimetype_guesser = null)
 679      {
 680          global $user, $request;
 681  
 682          $upload = array();
 683  
 684          $upload['local_mode'] = true;
 685          $upload['tmp_name'] = $source_file;
 686  
 687          if ($filedata === false)
 688          {
 689              $upload['name'] = utf8_basename($source_file);
 690              $upload['size'] = 0;
 691          }
 692          else
 693          {
 694              $upload['name'] = $filedata['realname'];
 695              $upload['size'] = $filedata['size'];
 696              $upload['type'] = $filedata['type'];
 697          }
 698  
 699          $file = new filespec($upload, $this, $mimetype_guesser);
 700  
 701          if ($file->init_error)
 702          {
 703              $file->error[] = '';
 704              return $file;
 705          }
 706  
 707          if (isset($upload['error']))
 708          {
 709              $error = $this->assign_internal_error($upload['error']);
 710  
 711              if ($error !== false)
 712              {
 713                  $file->error[] = $error;
 714                  return $file;
 715              }
 716          }
 717  
 718          // PHP Upload filesize exceeded
 719          if ($file->get('filename') == 'none')
 720          {
 721              $max_filesize = @ini_get('upload_max_filesize');
 722              $unit = 'MB';
 723  
 724              if (!empty($max_filesize))
 725              {
 726                  $unit = strtolower(substr($max_filesize, -1, 1));
 727                  $max_filesize = (int) $max_filesize;
 728  
 729                  $unit = ($unit == 'k') ? 'KB' : (($unit == 'g') ? 'GB' : 'MB');
 730              }
 731  
 732              $file->error[] = (empty($max_filesize)) ? $user->lang[$this->error_prefix . 'PHP_SIZE_NA'] : sprintf($user->lang[$this->error_prefix . 'PHP_SIZE_OVERRUN'], $max_filesize, $user->lang[$unit]);
 733              return $file;
 734          }
 735  
 736          // Not correctly uploaded
 737          if (!$file->is_uploaded())
 738          {
 739              $file->error[] = $user->lang[$this->error_prefix . 'NOT_UPLOADED'];
 740              return $file;
 741          }
 742  
 743          $this->common_checks($file);
 744          $request->overwrite('local', $upload, \phpbb\request\request_interface::FILES);
 745  
 746          return $file;
 747      }
 748  
 749      /**
 750      * Remote upload method
 751      * Uploads file from given url
 752      *
 753      * @param string $upload_url URL pointing to file to upload, for example http://www.foobar.com/example.gif
 754      * @param \phpbb\mimetype\guesser $mimetype_guesser Mimetype guesser
 755      * @return object $file Object "filespec" is returned, all further operations can be done with this object
 756      * @access public
 757      */
 758  	function remote_upload($upload_url, \phpbb\mimetype\guesser $mimetype_guesser = null)
 759      {
 760          global $user, $phpbb_root_path;
 761  
 762          $upload_ary = array();
 763          $upload_ary['local_mode'] = true;
 764  
 765          if (!preg_match('#^(https?://).*?\.(' . implode('|', $this->allowed_extensions) . ')$#i', $upload_url, $match))
 766          {
 767              $file = new fileerror($user->lang[$this->error_prefix . 'URL_INVALID']);
 768              return $file;
 769          }
 770  
 771          if (empty($match[2]))
 772          {
 773              $file = new fileerror($user->lang[$this->error_prefix . 'URL_INVALID']);
 774              return $file;
 775          }
 776  
 777          $url = parse_url($upload_url);
 778  
 779          $default_port = 80;
 780          $hostname = $url['host'];
 781  
 782          if ($url['scheme'] == 'https')
 783          {
 784              $default_port = 443;
 785              $hostname = 'tls://' . $url['host'];
 786          }
 787  
 788          $host = $url['host'];
 789          $path = $url['path'];
 790          $port = (!empty($url['port'])) ? (int) $url['port'] : $default_port;
 791  
 792          $upload_ary['type'] = 'application/octet-stream';
 793  
 794          $url['path'] = explode('.', $url['path']);
 795          $ext = array_pop($url['path']);
 796  
 797          $url['path'] = implode('', $url['path']);
 798          $upload_ary['name'] = utf8_basename($url['path']) . (($ext) ? '.' . $ext : '');
 799          $filename = $url['path'];
 800          $filesize = 0;
 801  
 802          $remote_max_filesize = $this->max_filesize;
 803          if (!$remote_max_filesize)
 804          {
 805              $max_filesize = @ini_get('upload_max_filesize');
 806  
 807              if (!empty($max_filesize))
 808              {
 809                  $unit = strtolower(substr($max_filesize, -1, 1));
 810                  $remote_max_filesize = (int) $max_filesize;
 811  
 812                  switch ($unit)
 813                  {
 814                      case 'g':
 815                          $remote_max_filesize *= 1024;
 816                      // no break
 817                      case 'm':
 818                          $remote_max_filesize *= 1024;
 819                      // no break
 820                      case 'k':
 821                          $remote_max_filesize *= 1024;
 822                      // no break
 823                  }
 824              }
 825          }
 826  
 827          $errno = 0;
 828          $errstr = '';
 829  
 830          if (!($fsock = @fsockopen($hostname, $port, $errno, $errstr)))
 831          {
 832              $file = new fileerror($user->lang[$this->error_prefix . 'NOT_UPLOADED']);
 833              return $file;
 834          }
 835  
 836          // Make sure $path not beginning with /
 837          if (strpos($path, '/') === 0)
 838          {
 839              $path = substr($path, 1);
 840          }
 841  
 842          fputs($fsock, 'GET /' . $path . " HTTP/1.1\r\n");
 843          fputs($fsock, "HOST: " . $host . "\r\n");
 844          fputs($fsock, "Connection: close\r\n\r\n");
 845  
 846          // Set a proper timeout for the socket
 847          socket_set_timeout($fsock, $this->upload_timeout);
 848  
 849          $get_info = false;
 850          $data = '';
 851          $length = false;
 852          $timer_stop = time() + $this->upload_timeout;
 853  
 854          while ((!$length || $filesize < $length) && !@feof($fsock))
 855          {
 856              if ($get_info)
 857              {
 858                  if ($length)
 859                  {
 860                      // Don't attempt to read past end of file if server indicated length
 861                      $block = @fread($fsock, min($length - $filesize, 1024));
 862                  }
 863                  else
 864                  {
 865                      $block = @fread($fsock, 1024);
 866                  }
 867  
 868                  $filesize += strlen($block);
 869  
 870                  if ($remote_max_filesize && $filesize > $remote_max_filesize)
 871                  {
 872                      $max_filesize = get_formatted_filesize($remote_max_filesize, false);
 873  
 874                      $file = new fileerror(sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']));
 875                      return $file;
 876                  }
 877  
 878                  $data .= $block;
 879              }
 880              else
 881              {
 882                  $line = @fgets($fsock, 1024);
 883  
 884                  if ($line == "\r\n")
 885                  {
 886                      $get_info = true;
 887                  }
 888                  else
 889                  {
 890                      if (stripos($line, 'content-type: ') !== false)
 891                      {
 892                          $upload_ary['type'] = rtrim(str_replace('content-type: ', '', strtolower($line)));
 893                      }
 894                      else if ($this->max_filesize && stripos($line, 'content-length: ') !== false)
 895                      {
 896                          $length = (int) str_replace('content-length: ', '', strtolower($line));
 897  
 898                          if ($remote_max_filesize && $length && $length > $remote_max_filesize)
 899                          {
 900                              $max_filesize = get_formatted_filesize($remote_max_filesize, false);
 901  
 902                              $file = new fileerror(sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']));
 903                              return $file;
 904                          }
 905                      }
 906                      else if (stripos($line, '404 not found') !== false)
 907                      {
 908                          $file = new fileerror($user->lang[$this->error_prefix . 'URL_NOT_FOUND']);
 909                          return $file;
 910                      }
 911                  }
 912              }
 913  
 914              $stream_meta_data = stream_get_meta_data($fsock);
 915  
 916              // Cancel upload if we exceed timeout
 917              if (!empty($stream_meta_data['timed_out']) || time() >= $timer_stop)
 918              {
 919                  $file = new fileerror($user->lang[$this->error_prefix . 'REMOTE_UPLOAD_TIMEOUT']);
 920                  return $file;
 921              }
 922          }
 923          @fclose($fsock);
 924  
 925          if (empty($data))
 926          {
 927              $file = new fileerror($user->lang[$this->error_prefix . 'EMPTY_REMOTE_DATA']);
 928              return $file;
 929          }
 930  
 931          $tmp_path = (!@ini_get('safe_mode') || strtolower(@ini_get('safe_mode')) == 'off') ? sys_get_temp_dir() : $phpbb_root_path . 'cache';
 932          $filename = tempnam($tmp_path, unique_id() . '-');
 933  
 934          if (!($fp = @fopen($filename, 'wb')))
 935          {
 936              $file = new fileerror($user->lang[$this->error_prefix . 'NOT_UPLOADED']);
 937              return $file;
 938          }
 939  
 940          $upload_ary['size'] = fwrite($fp, $data);
 941          fclose($fp);
 942          unset($data);
 943  
 944          $upload_ary['tmp_name'] = $filename;
 945  
 946          $file = new filespec($upload_ary, $this, $mimetype_guesser);
 947          $this->common_checks($file);
 948  
 949          return $file;
 950      }
 951  
 952      /**
 953      * Assign internal error
 954      * @access private
 955      */
 956  	function assign_internal_error($errorcode)
 957      {
 958          global $user;
 959  
 960          switch ($errorcode)
 961          {
 962              case 1:
 963                  $max_filesize = @ini_get('upload_max_filesize');
 964                  $unit = 'MB';
 965  
 966                  if (!empty($max_filesize))
 967                  {
 968                      $unit = strtolower(substr($max_filesize, -1, 1));
 969                      $max_filesize = (int) $max_filesize;
 970  
 971                      $unit = ($unit == 'k') ? 'KB' : (($unit == 'g') ? 'GB' : 'MB');
 972                  }
 973  
 974                  $error = (empty($max_filesize)) ? $user->lang[$this->error_prefix . 'PHP_SIZE_NA'] : sprintf($user->lang[$this->error_prefix . 'PHP_SIZE_OVERRUN'], $max_filesize, $user->lang[$unit]);
 975              break;
 976  
 977              case 2:
 978                  $max_filesize = get_formatted_filesize($this->max_filesize, false);
 979  
 980                  $error = sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']);
 981              break;
 982  
 983              case 3:
 984                  $error = $user->lang[$this->error_prefix . 'PARTIAL_UPLOAD'];
 985              break;
 986  
 987              case 4:
 988                  $error = $user->lang[$this->error_prefix . 'NOT_UPLOADED'];
 989              break;
 990  
 991              case 6:
 992                  $error = 'Temporary folder could not be found. Please check your PHP installation.';
 993              break;
 994  
 995              default:
 996                  $error = false;
 997              break;
 998          }
 999  
1000          return $error;
1001      }
1002  
1003      /**
1004      * Perform common checks
1005      */
1006  	function common_checks(&$file)
1007      {
1008          global $user;
1009  
1010          // Filesize is too big or it's 0 if it was larger than the maxsize in the upload form
1011          if ($this->max_filesize && ($file->get('filesize') > $this->max_filesize || $file->get('filesize') == 0))
1012          {
1013              $max_filesize = get_formatted_filesize($this->max_filesize, false);
1014  
1015              $file->error[] = sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']);
1016          }
1017  
1018          // check Filename
1019          if (preg_match("#[\\/:*?\"<>|]#i", $file->get('realname')))
1020          {
1021              $file->error[] = sprintf($user->lang[$this->error_prefix . 'INVALID_FILENAME'], $file->get('realname'));
1022          }
1023  
1024          // Invalid Extension
1025          if (!$this->valid_extension($file))
1026          {
1027              $file->error[] = sprintf($user->lang[$this->error_prefix . 'DISALLOWED_EXTENSION'], $file->get('extension'));
1028          }
1029  
1030          // MIME Sniffing
1031          if (!$this->valid_content($file))
1032          {
1033              $file->error[] = sprintf($user->lang[$this->error_prefix . 'DISALLOWED_CONTENT']);
1034          }
1035      }
1036  
1037      /**
1038      * Check for allowed extension
1039      */
1040  	function valid_extension(&$file)
1041      {
1042          return (in_array($file->get('extension'), $this->allowed_extensions)) ? true : false;
1043      }
1044  
1045      /**
1046      * Check for allowed dimension
1047      */
1048  	function valid_dimensions(&$file)
1049      {
1050          if (!$this->max_width && !$this->max_height && !$this->min_width && !$this->min_height)
1051          {
1052              return true;
1053          }
1054  
1055          if (($file->get('width') > $this->max_width && $this->max_width) ||
1056              ($file->get('height') > $this->max_height && $this->max_height) ||
1057              ($file->get('width') < $this->min_width && $this->min_width) ||
1058              ($file->get('height') < $this->min_height && $this->min_height))
1059          {
1060              return false;
1061          }
1062  
1063          return true;
1064      }
1065  
1066      /**
1067      * Check if form upload is valid
1068      */
1069  	function is_valid($form_name)
1070      {
1071          global $request;
1072          $upload = $request->file($form_name);
1073  
1074          return (!empty($upload) && $upload['name'] !== 'none');
1075      }
1076  
1077  
1078      /**
1079      * Check for bad content (IE mime-sniffing)
1080      */
1081  	function valid_content(&$file)
1082      {
1083          return ($file->check_content($this->disallowed_content));
1084      }
1085  
1086      /**
1087      * Get image type/extension mapping
1088      *
1089      * @return array Array containing the image types and their extensions
1090      */
1091  	static public function image_types()
1092      {
1093          $result = array(
1094              IMAGETYPE_GIF        => array('gif'),
1095              IMAGETYPE_JPEG        => array('jpg', 'jpeg'),
1096              IMAGETYPE_PNG        => array('png'),
1097              IMAGETYPE_SWF        => array('swf'),
1098              IMAGETYPE_PSD        => array('psd'),
1099              IMAGETYPE_BMP        => array('bmp'),
1100              IMAGETYPE_TIFF_II    => array('tif', 'tiff'),
1101              IMAGETYPE_TIFF_MM    => array('tif', 'tiff'),
1102              IMAGETYPE_JPC        => array('jpg', 'jpeg'),
1103              IMAGETYPE_JP2        => array('jpg', 'jpeg'),
1104              IMAGETYPE_JPX        => array('jpg', 'jpeg'),
1105              IMAGETYPE_JB2        => array('jpg', 'jpeg'),
1106              IMAGETYPE_IFF        => array('iff'),
1107              IMAGETYPE_WBMP        => array('wbmp'),
1108              IMAGETYPE_XBM        => array('xbm'),
1109          );
1110  
1111          if (defined('IMAGETYPE_SWC'))
1112          {
1113              $result[IMAGETYPE_SWC] = array('swc');
1114          }
1115  
1116          return $result;
1117      }
1118  }


Generated: Thu Jan 11 00:25:41 2018 Cross-referenced by PHPXref 0.7.1