Verzeichnisstruktur phpBB-3.1.0


Veröffentlicht
27.10.2014

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

plupload.php

Zuletzt modifiziert: 09.10.2024, 12:52 - Dateigröße: 9.72 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\plupload;
 015   
 016  /**
 017  * This class handles all server-side plupload functions
 018  */
 019  class plupload
 020  {
 021      /**
 022      * @var string
 023      */
 024      protected $phpbb_root_path;
 025   
 026      /**
 027      * @var \phpbb\config\config
 028      */
 029      protected $config;
 030   
 031      /**
 032      * @var \phpbb\request\request_interface
 033      */
 034      protected $request;
 035   
 036      /**
 037      * @var \phpbb\user
 038      */
 039      protected $user;
 040   
 041      /**
 042      * @var \phpbb\php\ini
 043      */
 044      protected $php_ini;
 045   
 046      /**
 047      * @var \phpbb\mimetype\guesser
 048      */
 049      protected $mimetype_guesser;
 050   
 051      /**
 052      * Final destination for uploaded files, i.e. the "files" directory.
 053      * @var string
 054      */
 055      protected $upload_directory;
 056   
 057      /**
 058      * Temporary upload directory for plupload uploads.
 059      * @var string
 060      */
 061      protected $temporary_directory;
 062   
 063      /**
 064      * Constructor.
 065      *
 066      * @param string $phpbb_root_path
 067      * @param \phpbb\config\config $config
 068      * @param \phpbb\request\request_interface $request
 069      * @param \phpbb\user $user
 070      * @param \phpbb\php\ini $php_ini
 071      * @param \phpbb\mimetype\guesser $mimetype_guesser
 072      */
 073      public function __construct($phpbb_root_path, \phpbb\config\config $config, \phpbb\request\request_interface $request, \phpbb\user $user, \phpbb\php\ini $php_ini, \phpbb\mimetype\guesser $mimetype_guesser)
 074      {
 075          $this->phpbb_root_path = $phpbb_root_path;
 076          $this->config = $config;
 077          $this->request = $request;
 078          $this->user = $user;
 079          $this->php_ini = $php_ini;
 080          $this->mimetype_guesser = $mimetype_guesser;
 081   
 082          $this->set_default_directories();
 083      }
 084   
 085      /**
 086      * Plupload allows for chunking so we must check for that and assemble
 087      * the whole file first before performing any checks on it.
 088      *
 089      * @param string $form_name The name of the file element in the upload form
 090      *
 091      * @return array|null    null if there are no chunks to piece together
 092      *                        otherwise array containing the path to the
 093      *                        pieced-together file and its size
 094      */
 095      public function handle_upload($form_name)
 096      {
 097          $chunks_expected = $this->request->variable('chunks', 0);
 098   
 099          // 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', ''),
 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: 100},',
 270                  (int) $this->config['img_max_height'],
 271                  (int) $this->config['img_max_width']
 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->get_bytes('upload_max_filesize'),
 288              $this->php_ini->get_bytes('post_max_size'),
 289              max(1, $this->php_ini->get_bytes('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              \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 (!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  }
 403