[ Index ]

PHP Cross Reference of phpBB-3.2.8-deutsch

title

Body

[close]

/phpbb/plupload/ -> plupload.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  namespace phpbb\plupload;
  15  
  16  /**
  17  * This class handles all server-side plupload functions
  18  */
  19  class plupload
  20  {
  21      /**
  22      * @var string
  23      */
  24      protected $phpbb_root_path;
  25  
  26      /**
  27      * @var \phpbb\config\config
  28      */
  29      protected $config;
  30  
  31      /**
  32      * @var \phpbb\request\request_interface
  33      */
  34      protected $request;
  35  
  36      /**
  37      * @var \phpbb\user
  38      */
  39      protected $user;
  40  
  41      /**
  42      * @var \bantu\IniGetWrapper\IniGetWrapper
  43      */
  44      protected $php_ini;
  45  
  46      /**
  47      * @var \phpbb\mimetype\guesser
  48      */
  49      protected $mimetype_guesser;
  50  
  51      /**
  52      * Final destination for uploaded files, i.e. the "files" directory.
  53      * @var string
  54      */
  55      protected $upload_directory;
  56  
  57      /**
  58      * Temporary upload directory for plupload uploads.
  59      * @var string
  60      */
  61      protected $temporary_directory;
  62  
  63      /**
  64      * Constructor.
  65      *
  66      * @param string $phpbb_root_path
  67      * @param \phpbb\config\config $config
  68      * @param \phpbb\request\request_interface $request
  69      * @param \phpbb\user $user
  70      * @param \bantu\IniGetWrapper\IniGetWrapper $php_ini
  71      * @param \phpbb\mimetype\guesser $mimetype_guesser
  72      */
  73  	public function __construct($phpbb_root_path, \phpbb\config\config $config, \phpbb\request\request_interface $request, \phpbb\user $user, \bantu\IniGetWrapper\IniGetWrapper $php_ini, \phpbb\mimetype\guesser $mimetype_guesser)
  74      {
  75          $this->phpbb_root_path = $phpbb_root_path;
  76          $this->config = $config;
  77          $this->request = $request;
  78          $this->user = $user;
  79          $this->php_ini = $php_ini;
  80          $this->mimetype_guesser = $mimetype_guesser;
  81  
  82          $this->set_default_directories();
  83      }
  84  
  85      /**
  86      * Plupload allows for chunking so we must check for that and assemble
  87      * the whole file first before performing any checks on it.
  88      *
  89      * @param string $form_name The name of the file element in the upload form
  90      *
  91      * @return array|null    null if there are no chunks to piece together
  92      *                        otherwise array containing the path to the
  93      *                        pieced-together file and its size
  94      */
  95  	public function handle_upload($form_name)
  96      {
  97          $chunks_expected = $this->request->variable('chunks', 0);
  98  
  99          // If chunking is disabled or we are not using plupload, just return
 100          // and handle the file as usual
 101          if ($chunks_expected < 2)
 102          {
 103              return;
 104          }
 105  
 106          $file_name = $this->request->variable('name', '');
 107          $chunk = $this->request->variable('chunk', 0);
 108  
 109          $this->user->add_lang('plupload');
 110          $this->prepare_temporary_directory();
 111  
 112          $file_path = $this->temporary_filepath($file_name);
 113          $this->integrate_uploaded_file($form_name, $chunk, $file_path);
 114  
 115          // If we are done with all the chunks, strip the .part suffix and then
 116          // handle the resulting file as normal, otherwise die and await the
 117          // next chunk.
 118          if ($chunk == $chunks_expected - 1)
 119          {
 120              rename("{$file_path}.part", $file_path);
 121  
 122              // Reset upload directories to defaults once completed
 123              $this->set_default_directories();
 124  
 125              // Need to modify some of the $_FILES values to reflect the new file
 126              return array(
 127                  'tmp_name' => $file_path,
 128                  'name' => $this->request->variable('real_filename', '', true),
 129                  'size' => filesize($file_path),
 130                  'type' => $this->mimetype_guesser->guess($file_path, $file_name),
 131              );
 132          }
 133          else
 134          {
 135              $json_response = new \phpbb\json_response();
 136              $json_response->send(array(
 137                  'jsonrpc' => '2.0',
 138                  'id' => 'id',
 139                  'result' => null,
 140              ));
 141          }
 142      }
 143  
 144      /**
 145      * Fill in the plupload configuration options in the template
 146      *
 147      * @param \phpbb\cache\service        $cache
 148      * @param \phpbb\template\template    $template
 149      * @param string                        $s_action The URL to submit the POST data to
 150      * @param int                        $forum_id The ID of the forum
 151      * @param int                        $max_files Maximum number of files allowed. 0 for unlimited.
 152      *
 153      * @return null
 154      */
 155  	public function configure(\phpbb\cache\service $cache, \phpbb\template\template $template, $s_action, $forum_id, $max_files)
 156      {
 157          $filters = $this->generate_filter_string($cache, $forum_id);
 158          $chunk_size = $this->get_chunk_size();
 159          $resize = $this->generate_resize_string();
 160  
 161          $template->assign_vars(array(
 162              'S_RESIZE'            => $resize,
 163              'S_PLUPLOAD'        => true,
 164              'FILTERS'            => $filters,
 165              'CHUNK_SIZE'        => $chunk_size,
 166              'S_PLUPLOAD_URL'    => htmlspecialchars_decode($s_action),
 167              'MAX_ATTACHMENTS'    => $max_files,
 168              'ATTACH_ORDER'        => ($this->config['display_order']) ? 'asc' : 'desc',
 169              'L_TOO_MANY_ATTACHMENTS'    => $this->user->lang('TOO_MANY_ATTACHMENTS', $max_files),
 170          ));
 171  
 172          $this->user->add_lang('plupload');
 173      }
 174  
 175      /**
 176      * Checks whether the page request was sent by plupload or not
 177      *
 178      * @return bool
 179      */
 180  	public function is_active()
 181      {
 182          return $this->request->header('X-PHPBB-USING-PLUPLOAD', false);
 183      }
 184  
 185      /**
 186      * Returns whether the current HTTP request is a multipart request.
 187      *
 188      * @return bool
 189      */
 190  	public function is_multipart()
 191      {
 192          $content_type = $this->request->server('CONTENT_TYPE');
 193  
 194          return strpos($content_type, 'multipart') === 0;
 195      }
 196  
 197      /**
 198      * Sends an error message back to the client via JSON response
 199      *
 200      * @param int $code        The error code
 201      * @param string $msg    The translation string of the message to be sent
 202      *
 203      * @return null
 204      */
 205  	public function emit_error($code, $msg)
 206      {
 207          $json_response = new \phpbb\json_response();
 208          $json_response->send(array(
 209              'jsonrpc' => '2.0',
 210              'id' => 'id',
 211              'error' => array(
 212                  'code' => $code,
 213                  'message' => $this->user->lang($msg),
 214              ),
 215          ));
 216      }
 217  
 218      /**
 219      * Looks at the list of allowed extensions and generates a string
 220      * appropriate for use in configuring plupload with
 221      *
 222      * @param \phpbb\cache\service $cache
 223      * @param string $forum_id The ID of the forum
 224      *
 225      * @return string
 226      */
 227  	public function generate_filter_string(\phpbb\cache\service $cache, $forum_id)
 228      {
 229          $attach_extensions = $cache->obtain_attach_extensions($forum_id);
 230          unset($attach_extensions['_allowed_']);
 231          $groups = array();
 232  
 233          // Re-arrange the extension array to $groups[$group_name][]
 234          foreach ($attach_extensions as $extension => $extension_info)
 235          {
 236              if (!isset($groups[$extension_info['group_name']]))
 237              {
 238                  $groups[$extension_info['group_name']] = array();
 239              }
 240  
 241              $groups[$extension_info['group_name']][] = $extension;
 242          }
 243  
 244          $filters = array();
 245          foreach ($groups as $group => $extensions)
 246          {
 247              $filters[] = sprintf(
 248                  "{title: '%s', extensions: '%s'}",
 249                  addslashes(ucfirst(strtolower($group))),
 250                  addslashes(implode(',', $extensions))
 251              );
 252          }
 253  
 254          return implode(',', $filters);
 255      }
 256  
 257      /**
 258      * Generates a string that is used to tell plupload to automatically resize
 259      * files before uploading them.
 260      *
 261      * @return string
 262      */
 263  	public function generate_resize_string()
 264      {
 265          $resize = '';
 266          if ($this->config['img_max_height'] > 0 && $this->config['img_max_width'] > 0)
 267          {
 268              $resize = sprintf(
 269                  'resize: {width: %d, height: %d, quality: 85},',
 270                  (int) $this->config['img_max_width'],
 271                  (int) $this->config['img_max_height']
 272              );
 273          }
 274  
 275          return $resize;
 276      }
 277  
 278      /**
 279      * Checks various php.ini values and the maximum file size to determine
 280      * the maximum size chunks a file can be split up into for upload
 281      *
 282      * @return int
 283      */
 284  	public function get_chunk_size()
 285      {
 286          $max = min(
 287              $this->php_ini->getBytes('upload_max_filesize'),
 288              $this->php_ini->getBytes('post_max_size'),
 289              max(1, $this->php_ini->getBytes('memory_limit')),
 290              $this->config['max_filesize']
 291          );
 292  
 293          // Use half of the maximum possible to leave plenty of room for other
 294          // POST data.
 295          return floor($max / 2);
 296      }
 297  
 298  	protected function temporary_filepath($file_name)
 299      {
 300          // Must preserve the extension for plupload to work.
 301          return sprintf(
 302              '%s/%s_%s%s',
 303              $this->temporary_directory,
 304              $this->config['plupload_salt'],
 305              md5($file_name),
 306              \phpbb\files\filespec::get_extension($file_name)
 307          );
 308      }
 309  
 310      /**
 311      * Checks whether the chunk we are about to deal with was actually uploaded
 312      * by PHP and actually exists, if not, it generates an error
 313      *
 314      * @param string $form_name The name of the file in the form data
 315      *
 316      * @return null
 317      */
 318  	protected function integrate_uploaded_file($form_name, $chunk, $file_path)
 319      {
 320          $is_multipart = $this->is_multipart();
 321          $upload = $this->request->file($form_name);
 322          if ($is_multipart && (!isset($upload['tmp_name']) || !is_uploaded_file($upload['tmp_name'])))
 323          {
 324              $this->emit_error(103, 'PLUPLOAD_ERR_MOVE_UPLOADED');
 325          }
 326  
 327          $tmp_file = $this->temporary_filepath($upload['tmp_name']);
 328  
 329          if (!phpbb_is_writable($this->temporary_directory) || !move_uploaded_file($upload['tmp_name'], $tmp_file))
 330          {
 331              $this->emit_error(103, 'PLUPLOAD_ERR_MOVE_UPLOADED');
 332          }
 333  
 334          $out = fopen("{$file_path}.part", $chunk == 0 ? 'wb' : 'ab');
 335          if (!$out)
 336          {
 337              $this->emit_error(102, 'PLUPLOAD_ERR_OUTPUT');
 338          }
 339  
 340          $in = fopen(($is_multipart) ? $tmp_file : 'php://input', 'rb');
 341          if (!$in)
 342          {
 343              $this->emit_error(101, 'PLUPLOAD_ERR_INPUT');
 344          }
 345  
 346          while ($buf = fread($in, 4096))
 347          {
 348              fwrite($out, $buf);
 349          }
 350  
 351          fclose($in);
 352          fclose($out);
 353  
 354          if ($is_multipart)
 355          {
 356              unlink($tmp_file);
 357          }
 358      }
 359  
 360      /**
 361      * Creates the temporary directory if it does not already exist.
 362      *
 363      * @return null
 364      */
 365  	protected function prepare_temporary_directory()
 366      {
 367          if (!file_exists($this->temporary_directory))
 368          {
 369              mkdir($this->temporary_directory);
 370  
 371              copy(
 372                  $this->upload_directory . '/index.htm',
 373                  $this->temporary_directory . '/index.htm'
 374              );
 375          }
 376      }
 377  
 378      /**
 379      * Sets the default directories for uploads
 380      *
 381      * @return null
 382      */
 383  	protected function set_default_directories()
 384      {
 385          $this->upload_directory = $this->phpbb_root_path . $this->config['upload_path'];
 386          $this->temporary_directory = $this->upload_directory . '/plupload';
 387      }
 388  
 389      /**
 390      * Sets the upload directories to the specified paths
 391      *
 392      * @param string $upload_directory Upload directory
 393      * @param string $temporary_directory Temporary directory
 394      *
 395      * @return null
 396      */
 397  	public function set_upload_directories($upload_directory, $temporary_directory)
 398      {
 399          $this->upload_directory = $upload_directory;
 400          $this->temporary_directory = $temporary_directory;
 401      }
 402  }


Generated: Tue Apr 7 19:42:26 2020 Cross-referenced by PHPXref 0.7.1