Classes

File io/Upload.class.php

File io/Upload.class.php

  1:   2:   3:   4:   5:   6:   7:   8:   9:  10:  11:  12:  13:  14:  15:  16:  17:  18:  19:  20:  21:  22:  23:  24:  25:  26:  27:  28:  29:  30:  31:  32:  33:  34:  35:  36:  37:  38:  39:  40:  41:  42:  43:  44:  45:  46:  47:  48:  49:  50:  51:  52:  53:  54:  55:  56:  57:  58:  59:  60:  61:  62:  63:  64:  65:  66:  67:  68:  69:  70:  71:  72:  73:  74:  75:  76:  77:  78:  79:  80:  81:  82:  83:  84:  85:  86:  87:  88:  89:  90:  91:  92:  93:  94:  95:  96:  97:  98:  99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 
<?php
/**
 * This class provides you methods to upload easily files to the ftp.
 * @package     IO
 * @copyright   &copy; 2005-2019 PHPBoost
 * @license     https://www.gnu.org/licenses/gpl-3.0.html GNU/GPL-3.0
 * @author      Regis VIARRE <crowkait@phpboost.com>
 * @version     PHPBoost 5.2 - last update: 2018 03 23
 * @since       PHPBoost 1.6 - 2007 01 27
 * @contributor Julien BRISWALTER <j1.seth@phpboost.com>
 * @contributor Arnaud GENET <elenwii@phpboost.com>
 * @contributor mipel <mipel@phpboost.com>
 * @contributor janus57 <janus57@janus57.fr>
*/

class Upload
{
    private $error = '';
    private $base_directory;
    private $extension = '';
    private $filename = '';
    private $original_filename = '';
    private $size = 0;
    private $contentCheck = true;

    const UNIQ_NAME = true;
    const NO_UNIQ_NAME = false;
    const CHECK_EXIST = true;
    const DELETE_ON_ERROR = true;
    const NO_DELETE_ON_ERROR = false;

    /**
     * constructor
     * @param string $base_directory Set the directory to upload the files.
     */
    public function __construct($base_directory = 'upload')
    {
        $this->base_directory = $base_directory;
    }

    /**
     * Uploads a file.
     * @param string $filepostname Name in the input file formulary.
     * @param string $regexp Regular expression to specify file format.
     * @param boolean $uniq_name If true assign a new name if a file with same name already exist. Otherwise previous file is overwrite.
     * @param int $weight_max The maximum file size.
     * @param boolean $check_exist If true verify if a file with the same name exist on the ftp. Otherwise previous file is overwrite.
     * @return boolean True if the file has been succefully uploaded. Error code if an error occured.
     */
    public function file($filepostname, $regexp = '', $uniq_name = false, $weight_max = 100000000, $check_exist = true)
    {
        $file = $_FILES[$filepostname];
        $this->size = $file['size'];
        $this->original_filename = $file['name'];

        if (!empty($file) && $this->size > 0)
        {
            if (($this->size/1024) <= $weight_max)
            {
                //Récupération des infos sur le fichier à traiter.
                $this->generate_file_info($uniq_name);
                if ($this->check_file_path($regexp))
                {
                    if (!$check_exist || !file_exists($this->base_directory . $this->filename)) //Autorisation d'écraser le fichier?
                    {
                        $this->error = self::error_manager($file['error']);
                        if (empty($this->error))
                        {
                            if (!empty($this->filename) && !empty($file['tmp_name']))
                            {
                                if ($this->contentCheck && !$this->check_file_content($file['tmp_name']))
                                {
                                    $this->error = 'e_upload_php_code';
                                    return false;
                                }

                                if (!move_uploaded_file($file['tmp_name'], $this->base_directory . $this->filename))
                                {
                                    $this->error = 'e_upload_error';
                                }
                                else
                                {
                                    return true;
                                }
                            }
                            else
                            {
                                $this->error = 'e_upload_error';
                            }
                        }
                    }
                    else
                    {
                        $this->error = 'e_upload_already_exist';
                    }
                }
                else
                    $this->error = 'e_upload_invalid_format';
            }
            else
                $this->error = 'e_upload_max_weight';
        }
        else
            $this->error = 'e_upload_error';

        return false;
    }

    /**
     * Checks whether an image is compliant to an maximum width and height, otherwise is $delete value is true delete it.
     * @param string $filepath Path to the image.
     * @param int $width_max Max width
     * @param int $height_max Max height
     * @param boolean $delete
     * @return string Error code.
     */
    public function check_img($width_max, $height_max, $delete = true)
    {
        $error = '';
        if (!empty($this->filename))
        {
            $filepath = $this->base_directory . $this->filename;

            list($width, $height, $ext) = function_exists('getimagesize') ? @getimagesize($filepath) : array(0, 0, 0);
            if ($width > $width_max || $height > $height_max ) //Hauteur et largeur max.
            {
                $error = 'e_upload_max_dimension';
            }

            if (!empty($error) && $delete)
            {
                @unlink($filepath);
            }
        }

        return $error;
    }

    /**
     * Check the file content for php tags to avoid illegal uploads
     * @param tmp file path
     */
    private function check_file_content($file) {
        $file_content = file_get_contents($file);

        if (TextHelper::strpos($file_content, "<?php") === false) {
            return true;
        }
        if (TextHelper::strpos($file_content, "<?") === false) {
            return true;
        }

        //Fail to validate, remove tmp file
        @unlink($file);
        return false;
    }

    /**
     * Checks the validity of a file with regular expression.
     * @param string $filename The file name
     * @param string $regexp Regular expression
     * @return boolean The result of the regular expression test.
     */
    private function check_file_path($regexp)
    {
        if (!empty($regexp))
        {
            //Valide, sinon supprimé
            if (preg_match($regexp, $this->original_filename) && TextHelper::strpos($this->original_filename, '.php') === false
                 && TextHelper::strpos($this->original_filename, '.phtml') === false) {//Valide, sinon supprimé
                return true;
            }
            return false;
        }
        return true;
    }

    /**
     * Generates a unique file name. Completes informations on the file.
     * @param string $filename The filename
     * @param boolean $uniq_name
     */
    private function generate_file_info($uniq_name)
    {
        $filename = $this->original_filename;

        $this->extension = TextHelper::strtolower(TextHelper::substr(TextHelper::strrchr($filename, '.'), 1));
        if (TextHelper::strrpos($filename, '.') !== FALSE)
        {
            $filename = TextHelper::mb_substr($filename, 0, TextHelper::strrpos($filename, '.'));
        }
        $filename = str_replace('.', '_', $filename);
        $filename = self::clean_filename($filename);

        if ($uniq_name)
        {
            $filename_tmp = $filename;
            if (!empty($this->extension))
                $filename_tmp .= '.' . $this->extension;
            $filename1 = $filename;
            while (file_exists($this->base_directory . $filename_tmp))
            {
                $filename1 = $filename . '_' . KeyGenerator::generate_key(5);
                $filename_tmp = $filename1;
                if (!empty($this->extension))
                    $filename_tmp .= '.' . $this->extension;
            }
            $filename = $filename1;
        }

        if (!empty($this->extension))
            $filename .= '.' . $this->extension;
        $this->filename = $filename;
    }

    /**
     * Clean the url, replace special characters with underscore.
     * @param string The file name.
     * @return string The cleaned file name.
     */
    private static function clean_filename($string)
    {
        $string = utf8_decode(TextHelper::html_entity_decode($string));
        $string = TextHelper::strtolower(strtr($string, utf8_decode('²ÀÁÂÃÄÅàáâãäåÒÓÔÕÖØòóôõöøÈÉÊËèéêëÇçÌÍÎÏìíîïÙÚÛÜùúûüÿÑñ()[]\'"~$&%*@ç!?;,:/\^¨€{}<>|+.- #'),  '2aaaaaaaaaaaaooooooooooooeeeeeeeecciiiiiiiiuuuuuuuuynn    __      c  ___    e       -_ '));
        $string = str_replace(' ', '', $string);
        $string = str_replace('___', '_', $string);
        $string = str_replace('__', '_', $string);
        $string = trim($string,'_');

        return $string;
    }

    /**
     * Manages error code during upload.
     * @param string $error
     * @return string Error code.
     */
    private static function error_manager($error)
    {
        switch ($error)
        {
            //Ok
            case 0:
                return '';
            break;
            //Fichier trop volumineux.
            case 1:
            case 2:
                return 'e_upload_max_weight';
            break;
            //Upload partiel.
            case 3:
                return 'e_upload_error';
            break;
            default:
                return 'e_upload_error';
        }
    }

    /**
     * Returns filesize in human readable representation.
     * @param int $round The number of decimal points
     * @return float filesize
     */
    public function get_human_readable_size($round = 1)
    {
        return (float)NumberHelper::round($this->size/1024, $round);
    }

    public function disableContentCheck() {
        $this->contentCheck = false;
    }

    public function get_error() { return $this->error; }
    public function get_extension() { return $this->extension; }
    public function get_original_filename() { return $this->original_filename; }
    public function get_filename() { return $this->filename; }
    public function get_size() { return $this->size; }
}
?>