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. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
functions_upload.php
0001 <?php
0002 /**
0003 *
0004 * This file is part of the phpBB Forum Software package.
0005 *
0006 * @copyright (c) phpBB Limited <https://www.phpbb.com>
0007 * @license GNU General Public License, version 2 (GPL-2.0)
0008 *
0009 * For full copyright and license information, please see
0010 * the docs/CREDITS.txt file.
0011 *
0012 */
0013
0014 /**
0015 * @ignore
0016 */
0017 if (!defined('IN_PHPBB'))
0018 {
0019 exit;
0020 }
0021
0022 /**
0023 * Responsible for holding all file relevant information, as well as doing file-specific operations.
0024 * The {@link fileupload fileupload class} can be used to upload several files, each of them being this object to operate further on.
0025 */
0026 class filespec
0027 {
0028 var $filename = '';
0029 var $realname = '';
0030 var $uploadname = '';
0031 var $mimetype = '';
0032 var $extension = '';
0033 var $filesize = 0;
0034 var $width = 0;
0035 var $height = 0;
0036 var $image_info = array();
0037
0038 var $destination_file = '';
0039 var $destination_path = '';
0040
0041 var $file_moved = false;
0042 var $init_error = false;
0043 var $local = false;
0044
0045 var $error = array();
0046
0047 var $upload = '';
0048
0049 /**
0050 * The plupload object
0051 * @var \phpbb\plupload\plupload
0052 */
0053 protected $plupload;
0054
0055 /**
0056 * phpBB Mimetype guesser
0057 * @var \phpbb\mimetype\guesser
0058 */
0059 protected $mimetype_guesser;
0060
0061 /**
0062 * File Class
0063 * @access private
0064 */
0065 function filespec($upload_ary, $upload_namespace, \phpbb\mimetype\guesser $mimetype_guesser = null, \phpbb\plupload\plupload $plupload = null)
0066 {
0067 if (!isset($upload_ary))
0068 {
0069 $this->init_error = true;
0070 return;
0071 }
0072
0073 $this->filename = $upload_ary['tmp_name'];
0074 $this->filesize = $upload_ary['size'];
0075 $name = (STRIP) ? stripslashes($upload_ary['name']) : $upload_ary['name'];
0076 $name = trim(utf8_basename($name));
0077 $this->realname = $this->uploadname = $name;
0078 $this->mimetype = $upload_ary['type'];
0079
0080 // Opera adds the name to the mime type
0081 $this->mimetype = (strpos($this->mimetype, '; name') !== false) ? str_replace(strstr($this->mimetype, '; name'), '', $this->mimetype) : $this->mimetype;
0082
0083 if (!$this->mimetype)
0084 {
0085 $this->mimetype = 'application/octet-stream';
0086 }
0087
0088 $this->extension = strtolower(self::get_extension($this->realname));
0089
0090 // Try to get real filesize from temporary folder (not always working) ;)
0091 $this->filesize = (@filesize($this->filename)) ? @filesize($this->filename) : $this->filesize;
0092
0093 $this->width = $this->height = 0;
0094 $this->file_moved = false;
0095
0096 $this->local = (isset($upload_ary['local_mode'])) ? true : false;
0097 $this->upload = $upload_namespace;
0098 $this->plupload = $plupload;
0099 $this->mimetype_guesser = $mimetype_guesser;
0100 }
0101
0102 /**
0103 * Cleans destination filename
0104 *
0105 * @param real|unique|unique_ext $mode real creates a realname, filtering some characters, lowering every character. Unique creates an unique filename
0106 * @param string $prefix Prefix applied to filename
0107 * @param string $user_id The user_id is only needed for when cleaning a user's avatar
0108 * @access public
0109 */
0110 function clean_filename($mode = 'unique', $prefix = '', $user_id = '')
0111 {
0112 if ($this->init_error)
0113 {
0114 return;
0115 }
0116
0117 switch ($mode)
0118 {
0119 case 'real':
0120 // Remove every extension from filename (to not let the mime bug being exposed)
0121 if (strpos($this->realname, '.') !== false)
0122 {
0123 $this->realname = substr($this->realname, 0, strpos($this->realname, '.'));
0124 }
0125
0126 // Replace any chars which may cause us problems with _
0127 $bad_chars = array("'", "\\", ' ', '/', ':', '*', '?', '"', '<', '>', '|');
0128
0129 $this->realname = rawurlencode(str_replace($bad_chars, '_', strtolower($this->realname)));
0130 $this->realname = preg_replace("/%(\w{2})/", '_', $this->realname);
0131
0132 $this->realname = $prefix . $this->realname . '.' . $this->extension;
0133 break;
0134
0135 case 'unique':
0136 $this->realname = $prefix . md5(unique_id());
0137 break;
0138
0139 case 'avatar':
0140 $this->extension = strtolower($this->extension);
0141 $this->realname = $prefix . $user_id . '.' . $this->extension;
0142
0143 break;
0144
0145 case 'unique_ext':
0146 default:
0147 $this->realname = $prefix . md5(unique_id()) . '.' . $this->extension;
0148 break;
0149 }
0150 }
0151
0152 /**
0153 * Get property from file object
0154 */
0155 function get($property)
0156 {
0157 if ($this->init_error || !isset($this->$property))
0158 {
0159 return false;
0160 }
0161
0162 return $this->$property;
0163 }
0164
0165 /**
0166 * Check if file is an image (mimetype)
0167 *
0168 * @return true if it is an image, false if not
0169 */
0170 function is_image()
0171 {
0172 return (strpos($this->mimetype, 'image/') === 0);
0173 }
0174
0175 /**
0176 * Check if the file got correctly uploaded
0177 *
0178 * @return true if it is a valid upload, false if not
0179 */
0180 function is_uploaded()
0181 {
0182 $is_plupload = $this->plupload && $this->plupload->is_active();
0183
0184 if (!$this->local && !$is_plupload && !is_uploaded_file($this->filename))
0185 {
0186 return false;
0187 }
0188
0189 if (($this->local || $is_plupload) && !file_exists($this->filename))
0190 {
0191 return false;
0192 }
0193
0194 return true;
0195 }
0196
0197 /**
0198 * Remove file
0199 */
0200 function remove()
0201 {
0202 if ($this->file_moved)
0203 {
0204 @unlink($this->destination_file);
0205 }
0206 }
0207
0208 /**
0209 * Get file extension
0210 *
0211 * @param string Filename that needs to be checked
0212 * @return string Extension of the supplied filename
0213 */
0214 static public function get_extension($filename)
0215 {
0216 if (strpos($filename, '.') === false)
0217 {
0218 return '';
0219 }
0220
0221 $filename = explode('.', $filename);
0222 return array_pop($filename);
0223 }
0224
0225 /**
0226 * Get mimetype
0227 *
0228 * @param string $filename Filename that needs to be checked
0229 * @return string Mimetype of supplied filename
0230 */
0231 function get_mimetype($filename)
0232 {
0233 if ($this->mimetype_guesser !== null)
0234 {
0235 $mimetype = $this->mimetype_guesser->guess($filename, $this->uploadname);
0236
0237 if ($mimetype !== 'application/octet-stream')
0238 {
0239 $this->mimetype = $mimetype;
0240 }
0241 }
0242
0243 return $this->mimetype;
0244 }
0245
0246 /**
0247 * Get filesize
0248 */
0249 function get_filesize($filename)
0250 {
0251 return @filesize($filename);
0252 }
0253
0254
0255 /**
0256 * Check the first 256 bytes for forbidden content
0257 */
0258 function check_content($disallowed_content)
0259 {
0260 if (empty($disallowed_content))
0261 {
0262 return true;
0263 }
0264
0265 $fp = @fopen($this->filename, 'rb');
0266
0267 if ($fp !== false)
0268 {
0269 $ie_mime_relevant = fread($fp, 256);
0270 fclose($fp);
0271 foreach ($disallowed_content as $forbidden)
0272 {
0273 if (stripos($ie_mime_relevant, '<' . $forbidden) !== false)
0274 {
0275 return false;
0276 }
0277 }
0278 }
0279 return true;
0280 }
0281
0282 /**
0283 * Move file to destination folder
0284 * The phpbb_root_path variable will be applied to the destination path
0285 *
0286 * @param string $destination Destination path, for example $config['avatar_path']
0287 * @param bool $overwrite If set to true, an already existing file will be overwritten
0288 * @param bool $skip_image_check If set to true, the check for the file to be a valid image is skipped
0289 * @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()}
0290 *
0291 * @access public
0292 */
0293 function move_file($destination, $overwrite = false, $skip_image_check = false, $chmod = false)
0294 {
0295 global $user, $phpbb_root_path;
0296
0297 if (sizeof($this->error))
0298 {
0299 return false;
0300 }
0301
0302 $chmod = ($chmod === false) ? CHMOD_READ | CHMOD_WRITE : $chmod;
0303
0304 // We need to trust the admin in specifying valid upload directories and an attacker not being able to overwrite it...
0305 $this->destination_path = $phpbb_root_path . $destination;
0306
0307 // Check if the destination path exist...
0308 if (!file_exists($this->destination_path))
0309 {
0310 @unlink($this->filename);
0311 return false;
0312 }
0313
0314 $upload_mode = (@ini_get('open_basedir') || @ini_get('safe_mode') || strtolower(@ini_get('safe_mode')) == 'on') ? 'move' : 'copy';
0315 $upload_mode = ($this->local) ? 'local' : $upload_mode;
0316 $this->destination_file = $this->destination_path . '/' . utf8_basename($this->realname);
0317
0318 // Check if the file already exist, else there is something wrong...
0319 if (file_exists($this->destination_file) && !$overwrite)
0320 {
0321 @unlink($this->filename);
0322 $this->error[] = $user->lang($this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR', $this->destination_file);
0323 $this->file_moved = false;
0324 return false;
0325 }
0326 else
0327 {
0328 if (file_exists($this->destination_file))
0329 {
0330 @unlink($this->destination_file);
0331 }
0332
0333 switch ($upload_mode)
0334 {
0335 case 'copy':
0336
0337 if (!@copy($this->filename, $this->destination_file))
0338 {
0339 if (!@move_uploaded_file($this->filename, $this->destination_file))
0340 {
0341 $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR'], $this->destination_file);
0342 }
0343 }
0344
0345 break;
0346
0347 case 'move':
0348
0349 if (!@move_uploaded_file($this->filename, $this->destination_file))
0350 {
0351 if (!@copy($this->filename, $this->destination_file))
0352 {
0353 $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR'], $this->destination_file);
0354 }
0355 }
0356
0357 break;
0358
0359 case 'local':
0360
0361 if (!@copy($this->filename, $this->destination_file))
0362 {
0363 $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR'], $this->destination_file);
0364 }
0365
0366 break;
0367 }
0368
0369 // Remove temporary filename
0370 @unlink($this->filename);
0371
0372 if (sizeof($this->error))
0373 {
0374 return false;
0375 }
0376
0377 phpbb_chmod($this->destination_file, $chmod);
0378 }
0379
0380 // Try to get real filesize from destination folder
0381 $this->filesize = (@filesize($this->destination_file)) ? @filesize($this->destination_file) : $this->filesize;
0382
0383 // Get mimetype of supplied file
0384 $this->mimetype = $this->get_mimetype($this->destination_file);
0385
0386 if ($this->is_image() && !$skip_image_check)
0387 {
0388 $this->width = $this->height = 0;
0389
0390 if (($this->image_info = @getimagesize($this->destination_file)) !== false)
0391 {
0392 $this->width = $this->image_info[0];
0393 $this->height = $this->image_info[1];
0394
0395 if (!empty($this->image_info['mime']))
0396 {
0397 $this->mimetype = $this->image_info['mime'];
0398 }
0399
0400 // Check image type
0401 $types = fileupload::image_types();
0402
0403 if (!isset($types[$this->image_info[2]]) || !in_array($this->extension, $types[$this->image_info[2]]))
0404 {
0405 if (!isset($types[$this->image_info[2]]))
0406 {
0407 $this->error[] = sprintf($user->lang['IMAGE_FILETYPE_INVALID'], $this->image_info[2], $this->mimetype);
0408 }
0409 else
0410 {
0411 $this->error[] = sprintf($user->lang['IMAGE_FILETYPE_MISMATCH'], $types[$this->image_info[2]][0], $this->extension);
0412 }
0413 }
0414
0415 // Make sure the dimensions match a valid image
0416 if (empty($this->width) || empty($this->height))
0417 {
0418 $this->error[] = $user->lang['ATTACHED_IMAGE_NOT_IMAGE'];
0419 }
0420 }
0421 else
0422 {
0423 $this->error[] = $user->lang['UNABLE_GET_IMAGE_SIZE'];
0424 }
0425 }
0426
0427 $this->file_moved = true;
0428 $this->additional_checks();
0429 unset($this->upload);
0430
0431 return true;
0432 }
0433
0434 /**
0435 * Performing additional checks
0436 */
0437 function additional_checks()
0438 {
0439 global $user;
0440
0441 if (!$this->file_moved)
0442 {
0443 return false;
0444 }
0445
0446 // Filesize is too big or it's 0 if it was larger than the maxsize in the upload form
0447 if ($this->upload->max_filesize && ($this->get('filesize') > $this->upload->max_filesize || $this->filesize == 0))
0448 {
0449 $max_filesize = get_formatted_filesize($this->upload->max_filesize, false);
0450
0451 $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']);
0452
0453 return false;
0454 }
0455
0456 if (!$this->upload->valid_dimensions($this))
0457 {
0458 $this->error[] = $user->lang($this->upload->error_prefix . 'WRONG_SIZE',
0459 $user->lang('PIXELS', (int) $this->upload->min_width),
0460 $user->lang('PIXELS', (int) $this->upload->min_height),
0461 $user->lang('PIXELS', (int) $this->upload->max_width),
0462 $user->lang('PIXELS', (int) $this->upload->max_height),
0463 $user->lang('PIXELS', (int) $this->width),
0464 $user->lang('PIXELS', (int) $this->height));
0465
0466 return false;
0467 }
0468
0469 return true;
0470 }
0471 }
0472
0473 /**
0474 * Class for assigning error messages before a real filespec class can be assigned
0475 */
0476 class fileerror extends filespec
0477 {
0478 function fileerror($error_msg)
0479 {
0480 $this->error[] = $error_msg;
0481 }
0482 }
0483
0484 /**
0485 * File upload class
0486 * Init class (all parameters optional and able to be set/overwritten separately) - scope is global and valid for all uploads
0487 */
0488 class fileupload
0489 {
0490 var $allowed_extensions = array();
0491 var $disallowed_content = array('body', 'head', 'html', 'img', 'plaintext', 'a href', 'pre', 'script', 'table', 'title');
0492 var $max_filesize = 0;
0493 var $min_width = 0;
0494 var $min_height = 0;
0495 var $max_width = 0;
0496 var $max_height = 0;
0497 var $error_prefix = '';
0498
0499 /** @var int Timeout for remote upload */
0500 var $upload_timeout = 6;
0501
0502 /**
0503 * Init file upload class.
0504 *
0505 * @param string $error_prefix Used error messages will get prefixed by this string
0506 * @param array $allowed_extensions Array of allowed extensions, for example array('jpg', 'jpeg', 'gif', 'png')
0507 * @param int $max_filesize Maximum filesize
0508 * @param int $min_width Minimum image width (only checked for images)
0509 * @param int $min_height Minimum image height (only checked for images)
0510 * @param int $max_width Maximum image width (only checked for images)
0511 * @param int $max_height Maximum image height (only checked for images)
0512 * @param bool|array $disallowed_content If enabled, the first 256 bytes of the file must not
0513 * contain any of its values. Defaults to false.
0514 *
0515 */
0516 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)
0517 {
0518 $this->set_allowed_extensions($allowed_extensions);
0519 $this->set_max_filesize($max_filesize);
0520 $this->set_allowed_dimensions($min_width, $min_height, $max_width, $max_height);
0521 $this->set_error_prefix($error_prefix);
0522 $this->set_disallowed_content($disallowed_content);
0523 }
0524
0525 /**
0526 * Reset vars
0527 */
0528 function reset_vars()
0529 {
0530 $this->max_filesize = 0;
0531 $this->min_width = $this->min_height = $this->max_width = $this->max_height = 0;
0532 $this->error_prefix = '';
0533 $this->allowed_extensions = array();
0534 $this->disallowed_content = array();
0535 }
0536
0537 /**
0538 * Set allowed extensions
0539 */
0540 function set_allowed_extensions($allowed_extensions)
0541 {
0542 if ($allowed_extensions !== false && is_array($allowed_extensions))
0543 {
0544 $this->allowed_extensions = $allowed_extensions;
0545 }
0546 }
0547
0548 /**
0549 * Set allowed dimensions
0550 */
0551 function set_allowed_dimensions($min_width, $min_height, $max_width, $max_height)
0552 {
0553 $this->min_width = (int) $min_width;
0554 $this->min_height = (int) $min_height;
0555 $this->max_width = (int) $max_width;
0556 $this->max_height = (int) $max_height;
0557 }
0558
0559 /**
0560 * Set maximum allowed filesize
0561 */
0562 function set_max_filesize($max_filesize)
0563 {
0564 if ($max_filesize !== false && (int) $max_filesize)
0565 {
0566 $this->max_filesize = (int) $max_filesize;
0567 }
0568 }
0569
0570 /**
0571 * Set disallowed strings
0572 */
0573 function set_disallowed_content($disallowed_content)
0574 {
0575 if ($disallowed_content !== false && is_array($disallowed_content))
0576 {
0577 $this->disallowed_content = array_diff($disallowed_content, array(''));
0578 }
0579 }
0580
0581 /**
0582 * Set error prefix
0583 */
0584 function set_error_prefix($error_prefix)
0585 {
0586 $this->error_prefix = $error_prefix;
0587 }
0588
0589 /**
0590 * Form upload method
0591 * Upload file from users harddisk
0592 *
0593 * @param string $form_name Form name assigned to the file input field (if it is an array, the key has to be specified)
0594 * @param \phpbb\mimetype\guesser $mimetype_guesser Mimetype guesser
0595 * @param \phpbb\plupload\plupload $plupload The plupload object
0596 *
0597 * @return object $file Object "filespec" is returned, all further operations can be done with this object
0598 * @access public
0599 */
0600 function form_upload($form_name, \phpbb\mimetype\guesser $mimetype_guesser = null, \phpbb\plupload\plupload $plupload = null)
0601 {
0602 global $user, $request;
0603
0604 $upload = $request->file($form_name);
0605 unset($upload['local_mode']);
0606
0607 if ($plupload)
0608 {
0609 $result = $plupload->handle_upload($form_name);
0610 if (is_array($result))
0611 {
0612 $upload = array_merge($upload, $result);
0613 }
0614 }
0615
0616 $file = new filespec($upload, $this, $mimetype_guesser, $plupload);
0617
0618 if ($file->init_error)
0619 {
0620 $file->error[] = '';
0621 return $file;
0622 }
0623
0624 // Error array filled?
0625 if (isset($upload['error']))
0626 {
0627 $error = $this->assign_internal_error($upload['error']);
0628
0629 if ($error !== false)
0630 {
0631 $file->error[] = $error;
0632 return $file;
0633 }
0634 }
0635
0636 // Check if empty file got uploaded (not catched by is_uploaded_file)
0637 if (isset($upload['size']) && $upload['size'] == 0)
0638 {
0639 $file->error[] = $user->lang[$this->error_prefix . 'EMPTY_FILEUPLOAD'];
0640 return $file;
0641 }
0642
0643 // PHP Upload filesize exceeded
0644 if ($file->get('filename') == 'none')
0645 {
0646 $max_filesize = @ini_get('upload_max_filesize');
0647 $unit = 'MB';
0648
0649 if (!empty($max_filesize))
0650 {
0651 $unit = strtolower(substr($max_filesize, -1, 1));
0652 $max_filesize = (int) $max_filesize;
0653
0654 $unit = ($unit == 'k') ? 'KB' : (($unit == 'g') ? 'GB' : 'MB');
0655 }
0656
0657 $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]);
0658 return $file;
0659 }
0660
0661 // Not correctly uploaded
0662 if (!$file->is_uploaded())
0663 {
0664 $file->error[] = $user->lang[$this->error_prefix . 'NOT_UPLOADED'];
0665 return $file;
0666 }
0667
0668 $this->common_checks($file);
0669
0670 return $file;
0671 }
0672
0673 /**
0674 * Move file from another location to phpBB
0675 */
0676 function local_upload($source_file, $filedata = false, \phpbb\mimetype\guesser $mimetype_guesser = null)
0677 {
0678 global $user, $request;
0679
0680 $upload = array();
0681
0682 $upload['local_mode'] = true;
0683 $upload['tmp_name'] = $source_file;
0684
0685 if ($filedata === false)
0686 {
0687 $upload['name'] = utf8_basename($source_file);
0688 $upload['size'] = 0;
0689 }
0690 else
0691 {
0692 $upload['name'] = $filedata['realname'];
0693 $upload['size'] = $filedata['size'];
0694 $upload['type'] = $filedata['type'];
0695 }
0696
0697 $file = new filespec($upload, $this, $mimetype_guesser);
0698
0699 if ($file->init_error)
0700 {
0701 $file->error[] = '';
0702 return $file;
0703 }
0704
0705 if (isset($upload['error']))
0706 {
0707 $error = $this->assign_internal_error($upload['error']);
0708
0709 if ($error !== false)
0710 {
0711 $file->error[] = $error;
0712 return $file;
0713 }
0714 }
0715
0716 // PHP Upload filesize exceeded
0717 if ($file->get('filename') == 'none')
0718 {
0719 $max_filesize = @ini_get('upload_max_filesize');
0720 $unit = 'MB';
0721
0722 if (!empty($max_filesize))
0723 {
0724 $unit = strtolower(substr($max_filesize, -1, 1));
0725 $max_filesize = (int) $max_filesize;
0726
0727 $unit = ($unit == 'k') ? 'KB' : (($unit == 'g') ? 'GB' : 'MB');
0728 }
0729
0730 $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]);
0731 return $file;
0732 }
0733
0734 // Not correctly uploaded
0735 if (!$file->is_uploaded())
0736 {
0737 $file->error[] = $user->lang[$this->error_prefix . 'NOT_UPLOADED'];
0738 return $file;
0739 }
0740
0741 $this->common_checks($file);
0742 $request->overwrite('local', $upload, \phpbb\request\request_interface::FILES);
0743
0744 return $file;
0745 }
0746
0747 /**
0748 * Remote upload method
0749 * Uploads file from given url
0750 *
0751 * @param string $upload_url URL pointing to file to upload, for example http://www.foobar.com/example.gif
0752 * @param \phpbb\mimetype\guesser $mimetype_guesser Mimetype guesser
0753 * @return object $file Object "filespec" is returned, all further operations can be done with this object
0754 * @access public
0755 */
0756 function remote_upload($upload_url, \phpbb\mimetype\guesser $mimetype_guesser = null)
0757 {
0758 global $user, $phpbb_root_path;
0759
0760 $upload_ary = array();
0761 $upload_ary['local_mode'] = true;
0762
0763 if (!preg_match('#^(https?://).*?\.(' . implode('|', $this->allowed_extensions) . ')$#i', $upload_url, $match))
0764 {
0765 $file = new fileerror($user->lang[$this->error_prefix . 'URL_INVALID']);
0766 return $file;
0767 }
0768
0769 if (empty($match[2]))
0770 {
0771 $file = new fileerror($user->lang[$this->error_prefix . 'URL_INVALID']);
0772 return $file;
0773 }
0774
0775 $url = parse_url($upload_url);
0776
0777 $host = $url['host'];
0778 $path = $url['path'];
0779 $port = (!empty($url['port'])) ? (int) $url['port'] : 80;
0780
0781 $upload_ary['type'] = 'application/octet-stream';
0782
0783 $url['path'] = explode('.', $url['path']);
0784 $ext = array_pop($url['path']);
0785
0786 $url['path'] = implode('', $url['path']);
0787 $upload_ary['name'] = utf8_basename($url['path']) . (($ext) ? '.' . $ext : '');
0788 $filename = $url['path'];
0789 $filesize = 0;
0790
0791 $remote_max_filesize = $this->max_filesize;
0792 if (!$remote_max_filesize)
0793 {
0794 $max_filesize = @ini_get('upload_max_filesize');
0795
0796 if (!empty($max_filesize))
0797 {
0798 $unit = strtolower(substr($max_filesize, -1, 1));
0799 $remote_max_filesize = (int) $max_filesize;
0800
0801 switch ($unit)
0802 {
0803 case 'g':
0804 $remote_max_filesize *= 1024;
0805 // no break
0806 case 'm':
0807 $remote_max_filesize *= 1024;
0808 // no break
0809 case 'k':
0810 $remote_max_filesize *= 1024;
0811 // no break
0812 }
0813 }
0814 }
0815
0816 $errno = 0;
0817 $errstr = '';
0818
0819 if (!($fsock = @fsockopen($host, $port, $errno, $errstr)))
0820 {
0821 $file = new fileerror($user->lang[$this->error_prefix . 'NOT_UPLOADED']);
0822 return $file;
0823 }
0824
0825 // Make sure $path not beginning with /
0826 if (strpos($path, '/') === 0)
0827 {
0828 $path = substr($path, 1);
0829 }
0830
0831 fputs($fsock, 'GET /' . $path . " HTTP/1.1\r\n");
0832 fputs($fsock, "HOST: " . $host . "\r\n");
0833 fputs($fsock, "Connection: close\r\n\r\n");
0834
0835 // Set a proper timeout for the socket
0836 socket_set_timeout($fsock, $this->upload_timeout);
0837
0838 $get_info = false;
0839 $data = '';
0840 $length = false;
0841 $timer_stop = time() + $this->upload_timeout;
0842
0843 while ((!$length || $filesize < $length) && !@feof($fsock))
0844 {
0845 if ($get_info)
0846 {
0847 if ($length)
0848 {
0849 // Don't attempt to read past end of file if server indicated length
0850 $block = @fread($fsock, min($length - $filesize, 1024));
0851 }
0852 else
0853 {
0854 $block = @fread($fsock, 1024);
0855 }
0856
0857 $filesize += strlen($block);
0858
0859 if ($remote_max_filesize && $filesize > $remote_max_filesize)
0860 {
0861 $max_filesize = get_formatted_filesize($remote_max_filesize, false);
0862
0863 $file = new fileerror(sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']));
0864 return $file;
0865 }
0866
0867 $data .= $block;
0868 }
0869 else
0870 {
0871 $line = @fgets($fsock, 1024);
0872
0873 if ($line == "\r\n")
0874 {
0875 $get_info = true;
0876 }
0877 else
0878 {
0879 if (stripos($line, 'content-type: ') !== false)
0880 {
0881 $upload_ary['type'] = rtrim(str_replace('content-type: ', '', strtolower($line)));
0882 }
0883 else if ($this->max_filesize && stripos($line, 'content-length: ') !== false)
0884 {
0885 $length = (int) str_replace('content-length: ', '', strtolower($line));
0886
0887 if ($remote_max_filesize && $length && $length > $remote_max_filesize)
0888 {
0889 $max_filesize = get_formatted_filesize($remote_max_filesize, false);
0890
0891 $file = new fileerror(sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']));
0892 return $file;
0893 }
0894 }
0895 else if (stripos($line, '404 not found') !== false)
0896 {
0897 $file = new fileerror($user->lang[$this->error_prefix . 'URL_NOT_FOUND']);
0898 return $file;
0899 }
0900 }
0901 }
0902
0903 $stream_meta_data = stream_get_meta_data($fsock);
0904
0905 // Cancel upload if we exceed timeout
0906 if (!empty($stream_meta_data['timed_out']) || time() >= $timer_stop)
0907 {
0908 $file = new fileerror($user->lang[$this->error_prefix . 'REMOTE_UPLOAD_TIMEOUT']);
0909 return $file;
0910 }
0911 }
0912 @fclose($fsock);
0913
0914 if (empty($data))
0915 {
0916 $file = new fileerror($user->lang[$this->error_prefix . 'EMPTY_REMOTE_DATA']);
0917 return $file;
0918 }
0919
0920 $tmp_path = (!@ini_get('safe_mode') || strtolower(@ini_get('safe_mode')) == 'off') ? false : $phpbb_root_path . 'cache';
0921 $filename = tempnam($tmp_path, unique_id() . '-');
0922
0923 if (!($fp = @fopen($filename, 'wb')))
0924 {
0925 $file = new fileerror($user->lang[$this->error_prefix . 'NOT_UPLOADED']);
0926 return $file;
0927 }
0928
0929 $upload_ary['size'] = fwrite($fp, $data);
0930 fclose($fp);
0931 unset($data);
0932
0933 $upload_ary['tmp_name'] = $filename;
0934
0935 $file = new filespec($upload_ary, $this, $mimetype_guesser);
0936 $this->common_checks($file);
0937
0938 return $file;
0939 }
0940
0941 /**
0942 * Assign internal error
0943 * @access private
0944 */
0945 function assign_internal_error($errorcode)
0946 {
0947 global $user;
0948
0949 switch ($errorcode)
0950 {
0951 case 1:
0952 $max_filesize = @ini_get('upload_max_filesize');
0953 $unit = 'MB';
0954
0955 if (!empty($max_filesize))
0956 {
0957 $unit = strtolower(substr($max_filesize, -1, 1));
0958 $max_filesize = (int) $max_filesize;
0959
0960 $unit = ($unit == 'k') ? 'KB' : (($unit == 'g') ? 'GB' : 'MB');
0961 }
0962
0963 $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]);
0964 break;
0965
0966 case 2:
0967 $max_filesize = get_formatted_filesize($this->max_filesize, false);
0968
0969 $error = sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']);
0970 break;
0971
0972 case 3:
0973 $error = $user->lang[$this->error_prefix . 'PARTIAL_UPLOAD'];
0974 break;
0975
0976 case 4:
0977 $error = $user->lang[$this->error_prefix . 'NOT_UPLOADED'];
0978 break;
0979
0980 case 6:
0981 $error = 'Temporary folder could not be found. Please check your PHP installation.';
0982 break;
0983
0984 default:
0985 $error = false;
0986 break;
0987 }
0988
0989 return $error;
0990 }
0991
0992 /**
0993 * Perform common checks
0994 */
0995 function common_checks(&$file)
0996 {
0997 global $user;
0998
0999 // Filesize is too big or it's 0 if it was larger than the maxsize in the upload form
1000 if ($this->max_filesize && ($file->get('filesize') > $this->max_filesize || $file->get('filesize') == 0))
1001 {
1002 $max_filesize = get_formatted_filesize($this->max_filesize, false);
1003
1004 $file->error[] = sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']);
1005 }
1006
1007 // check Filename
1008 if (preg_match("#[\\/:*?\"<>|]#i", $file->get('realname')))
1009 {
1010 $file->error[] = sprintf($user->lang[$this->error_prefix . 'INVALID_FILENAME'], $file->get('realname'));
1011 }
1012
1013 // Invalid Extension
1014 if (!$this->valid_extension($file))
1015 {
1016 $file->error[] = sprintf($user->lang[$this->error_prefix . 'DISALLOWED_EXTENSION'], $file->get('extension'));
1017 }
1018
1019 // MIME Sniffing
1020 if (!$this->valid_content($file))
1021 {
1022 $file->error[] = sprintf($user->lang[$this->error_prefix . 'DISALLOWED_CONTENT']);
1023 }
1024 }
1025
1026 /**
1027 * Check for allowed extension
1028 */
1029 function valid_extension(&$file)
1030 {
1031 return (in_array($file->get('extension'), $this->allowed_extensions)) ? true : false;
1032 }
1033
1034 /**
1035 * Check for allowed dimension
1036 */
1037 function valid_dimensions(&$file)
1038 {
1039 if (!$this->max_width && !$this->max_height && !$this->min_width && !$this->min_height)
1040 {
1041 return true;
1042 }
1043
1044 if (($file->get('width') > $this->max_width && $this->max_width) ||
1045 ($file->get('height') > $this->max_height && $this->max_height) ||
1046 ($file->get('width') < $this->min_width && $this->min_width) ||
1047 ($file->get('height') < $this->min_height && $this->min_height))
1048 {
1049 return false;
1050 }
1051
1052 return true;
1053 }
1054
1055 /**
1056 * Check if form upload is valid
1057 */
1058 function is_valid($form_name)
1059 {
1060 global $request;
1061 $upload = $request->file($form_name);
1062
1063 return (!empty($upload) && $upload['name'] !== 'none');
1064 }
1065
1066
1067 /**
1068 * Check for bad content (IE mime-sniffing)
1069 */
1070 function valid_content(&$file)
1071 {
1072 return ($file->check_content($this->disallowed_content));
1073 }
1074
1075 /**
1076 * Get image type/extension mapping
1077 *
1078 * @return array Array containing the image types and their extensions
1079 */
1080 static public function image_types()
1081 {
1082 $result = array(
1083 IMAGETYPE_GIF => array('gif'),
1084 IMAGETYPE_JPEG => array('jpg', 'jpeg'),
1085 IMAGETYPE_PNG => array('png'),
1086 IMAGETYPE_SWF => array('swf'),
1087 IMAGETYPE_PSD => array('psd'),
1088 IMAGETYPE_BMP => array('bmp'),
1089 IMAGETYPE_TIFF_II => array('tif', 'tiff'),
1090 IMAGETYPE_TIFF_MM => array('tif', 'tiff'),
1091 IMAGETYPE_JPC => array('jpg', 'jpeg'),
1092 IMAGETYPE_JP2 => array('jpg', 'jpeg'),
1093 IMAGETYPE_JPX => array('jpg', 'jpeg'),
1094 IMAGETYPE_JB2 => array('jpg', 'jpeg'),
1095 IMAGETYPE_IFF => array('iff'),
1096 IMAGETYPE_WBMP => array('wbmp'),
1097 IMAGETYPE_XBM => array('xbm'),
1098 );
1099
1100 if (defined('IMAGETYPE_SWC'))
1101 {
1102 $result[IMAGETYPE_SWC] = array('swc');
1103 }
1104
1105 return $result;
1106 }
1107 }
1108