Guest User

Untitled

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