HTTP_Upload
[ class tree: HTTP_Upload ] [ index: HTTP_Upload ] [ all elements ]

Source for file Upload.php

Documentation is available at Upload.php

  1. <?php
  2. // **********************************************
  3. //
  4. // This software is licensed by the LGPL
  5. // -> http://www.gnu.org/copyleft/lesser.txt
  6. // (c) 2001-2004 by Tomas Von Veschler Cox
  7. //
  8. // **********************************************
  9. //
  10. // $Id: Upload.php,v 1.42 2004/08/08 09:37:50 wenz Exp $
  11.  
  12. /*
  13.  * Pear File Uploader class. Easy and secure managment of files
  14.  * submitted via HTML Forms.
  15.  *
  16.  * Leyend:
  17.  * - you can add error msgs in your language in the HTTP_Upload_Error class
  18.  *
  19.  * TODO:
  20.  * - try to think a way of having all the Error system in other
  21.  *   file and only include it when an error ocurrs
  22.  *
  23.  * -- Notes for users HTTP_Upload >= 0.9.0 --
  24.  *
  25.  *  Error detection was enhanced, so you no longer need to
  26.  *  check for PEAR::isError() in $upload->getFiles() or call
  27.  *  $upload->isMissing(). Instead you'll
  28.  *  get the error when do a check for $file->isError().
  29.  *
  30.  *  Example:
  31.  *
  32.  *  $upload = new HTTP_Upload('en');
  33.  *  $file = $upload->getFiles('i_dont_exist_in_form_definition');
  34.  *  if ($file->isError()) {
  35.  *      die($file->getMessage());
  36.  *  }
  37.  *
  38.  *  --
  39.  *
  40.  */
  41.  
  42. require_once 'PEAR.php';
  43.  
  44. /**
  45.  * defines default chmod
  46.  */
  47. define('HTTP_UPLOAD_DEFAULT_CHMOD'0660);
  48.  
  49. /**
  50.  * Error Class for HTTP_Upload
  51.  *
  52.  * @author  Tomas V.V.Cox <cox@idecnet.com>
  53.  * @see http://vulcanonet.com/soft/index.php?pack=uploader
  54.  * @package HTTP_Upload
  55.  * @category HTTP
  56.  * @access public
  57.  */
  58. class HTTP_Upload_Error extends PEAR
  59. {
  60.     /**
  61.      * Selected language for error messages
  62.      * @var string 
  63.      */
  64.     var $lang = 'en';
  65.  
  66.     /**
  67.      * Whether HTML entities shall be encoded automatically
  68.      * @var boolean 
  69.      */
  70.     var $html = false;
  71.  
  72.     /**
  73.      * Constructor
  74.      *
  75.      * Creates a new PEAR_Error
  76.      *
  77.      * @param string $lang The language selected for error code messages
  78.      * @access public
  79.      */
  80.     function HTTP_Upload_Error($lang = null$html = false)
  81.     {
  82.         $this->lang = ($lang !== null$lang $this->lang;
  83.         $this->html = ($html !== false$html $this->html;
  84.         $ini_size preg_replace('/m/i''000000'ini_get('upload_max_filesize'));
  85.  
  86.         if (function_exists('version_compare'&&
  87.             version_compare(phpversion()'4.1''ge')) {
  88.             $maxsize (isset($_POST['MAX_FILE_SIZE'])) ?
  89.                 $_POST['MAX_FILE_SIZE': null;
  90.         else {
  91.             global $HTTP_POST_VARS;
  92.             $maxsize (isset($HTTP_POST_VARS['MAX_FILE_SIZE'])) ?
  93.                 $HTTP_POST_VARS['MAX_FILE_SIZE': null;
  94.         }
  95.  
  96.         if (empty($maxsize|| ($maxsize $ini_size)) {
  97.             $maxsize $ini_size;
  98.         }
  99.         // XXXXX Add here error messages in your language
  100.         $this->error_codes = array(
  101.             'TOO_LARGE' => array(
  102.                 'es'    => "Fichero demasiado largo. El maximo permitido es: $maxsize bytes.",
  103.                 'en'    => "File size too large. The maximum permitted size is: $maxsize bytes.",
  104.                 'de'    => "Datei zu gro&szlig;. Die zul&auml;ssige Maximalgr&ouml;&szlig;e ist: $maxsize Bytes.",
  105.                 'nl'    => "Het bestand is te groot, de maximale grootte is: $maxsize bytes.",
  106.                 'fr'    => "Le fichier est trop gros. La taille maximum autoris&eacute;e est: $maxsize bytes.",
  107.                 'it'    => "Il file &eacute; troppo grande. Il massimo permesso &eacute: $maxsize bytes.",
  108.                 'pt_BR' => "Arquivo muito grande. O tamanho m&aacute;ximo permitido &eacute; $maxsize bytes."
  109.                 ),
  110.             'MISSING_DIR' => array(
  111.                 'es'    => 'Falta directorio destino.',
  112.                 'en'    => 'Missing destination directory.',
  113.                 'de'    => 'Kein Zielverzeichnis definiert.',
  114.                 'nl'    => 'Geen bestemmings directory.',
  115.                 'fr'    => 'Le r&eacute;pertoire de destination n\'est pas d&eacute;fini.',
  116.                 'it'    => 'Manca la directory di destinazione.',
  117.                 'pt_BR' => 'Aus&ecirc;ncia de diret&oacute;rio de destino.'
  118.                 ),
  119.             'IS_NOT_DIR' => array(
  120.                 'es'    => 'El directorio destino no existe o es un fichero regular.',
  121.                 'en'    => 'The destination directory doesn\'t exist or is a regular file.',
  122.                 'de'    => 'Das angebene Zielverzeichnis existiert nicht oder ist eine Datei.',
  123.                 'nl'    => 'De doeldirectory bestaat niet, of is een gewoon bestand.',
  124.                 'fr'    => 'Le r&eacute;pertoire de destination n\'existe pas ou il s\'agit d\'un fichier r&eacute;gulier.',
  125.                 'it'    => 'La directory di destinazione non esiste o &eacute; un file.',
  126.                 'pt_BR' => 'O diret&oacute;rio de destino n&atilde;o existe ou &eacute; um arquivo.'
  127.                 ),
  128.             'NO_WRITE_PERMS' => array(
  129.                 'es'    => 'El directorio destino no tiene permisos de escritura.',
  130.                 'en'    => 'The destination directory doesn\'t have write perms.',
  131.                 'de'    => 'Fehlende Schreibrechte f&uuml;r das Zielverzeichnis.',
  132.                 'nl'    => 'Geen toestemming om te schrijven in de doeldirectory.',
  133.                 'fr'    => 'Le r&eacute;pertoire de destination n\'a pas les droits en &eacute;criture.',
  134.                 'it'    => 'Non si hanno i permessi di scrittura sulla directory di destinazione.',
  135.                 'pt_BR' => 'O diret&oacute;rio de destino n&atilde;o possui permiss&atilde;o para escrita.'
  136.                 ),
  137.             'NO_USER_FILE' => array(
  138.                 'es'    => 'No se ha escogido fichero para el upload.',
  139.                 'en'    => 'You haven\'t selected any file for uploading.',
  140.                 'de'    => 'Es wurde keine Datei f&uuml;r den Upload ausgew&auml;hlt.',
  141.                 'nl'    => 'Er is geen bestand opgegeven om te uploaden.',
  142.                 'fr'    => 'Vous n\'avez pas s&eacute;lectionn&eacute; de fichier &agrave; envoyer.',
  143.                 'it'    => 'Nessun file selezionato per l\'upload.',
  144.                 'pt_BR' => 'Nenhum arquivo selecionado para upload.'
  145.                 ),
  146.             'BAD_FORM' => array(
  147.                 'es'    => 'El formulario no contiene method="post" enctype="multipart/form-data" requerido.',
  148.                 'en'    => 'The html form doesn\'t contain the required method="post" enctype="multipart/form-data".',
  149.                 'de'    => 'Das HTML-Formular enth&auml;lt nicht die Angabe method="post" enctype="multipart/form-data" '.
  150.                            'im &gt;form&lt;-Tag.',
  151.                 'nl'    => 'Het HTML-formulier bevat niet de volgende benodigde '.
  152.                            'eigenschappen: method="post" enctype="multipart/form-data".',
  153.                 'fr'    => 'Le formulaire HTML ne contient pas les attributs requis : '.
  154.                            ' method="post" enctype="multipart/form-data".',
  155.                 'it'    => 'Il modulo HTML non contiene gli attributi richiesti: "'.
  156.                            ' method="post" enctype="multipart/form-data".',
  157.                 'pt_BR' => 'O formul&aacute;rio HTML n&atilde;o possui o method="post" enctype="multipart/form-data" requerido.'
  158.                 ),
  159.             'E_FAIL_COPY' => array(
  160.                 'es'    => 'Fallo al copiar el fichero temporal.',
  161.                 'en'    => 'Failed to copy the temporary file.',
  162.                 'de'    => 'Tempor&auml;re Datei konnte nicht kopiert werden.',
  163.                 'nl'    => 'Het tijdelijke bestand kon niet gekopieerd worden.',
  164.                 'fr'    => 'L\'enregistrement du fichier temporaire a &eacute;chou&eacute;.',
  165.                 'it'    => 'Copia del file temporaneo fallita.',
  166.                 'pt_BR' => 'Falha ao copiar o arquivo tempor&aacute;rio.'
  167.                 ),
  168.             'E_FAIL_MOVE' => array(
  169.                 'es'    => 'No puedo mover el fichero.',
  170.                 'en'    => 'Impossible to move the file.',
  171.                 'de'    => 'Datei kann nicht verschoben werden.',
  172.                 'nl'    => 'Het bestand kon niet verplaatst worden.',
  173.                 'fr'    => 'Impossible de d&eacute;placer le fichier.',
  174.                 'pt_BR' => 'N&atilde;o foi poss&iacute;vel mover o arquivo.'
  175.                 ),
  176.             'FILE_EXISTS' => array(
  177.                 'es'    => 'El fichero destino ya existe.',
  178.                 'en'    => 'The destination file already exists.',
  179.                 'de'    => 'Die zu erzeugende Datei existiert bereits.',
  180.                 'nl'    => 'Het doelbestand bestaat al.',
  181.                 'fr'    => 'Le fichier de destination existe d&eacute;j&agrave;.',
  182.                 'it'    => 'File destinazione gi&agrave; esistente.',
  183.                 'pt_BR' => 'O arquivo de destino j&aacute; existe.'
  184.                 ),
  185.             'CANNOT_OVERWRITE' => array(
  186.                 'es'    => 'El fichero destino ya existe y no se puede sobreescribir.',
  187.                 'en'    => 'The destination file already exists and could not be overwritten.',
  188.                 'de'    => 'Die zu erzeugende Datei existiert bereits und konnte nicht &uuml;berschrieben werden.',
  189.                 'nl'    => 'Het doelbestand bestaat al, en kon niet worden overschreven.',
  190.                 'fr'    => 'Le fichier de destination existe d&eacute;j&agrave; et ne peux pas &ecirc;tre remplac&eacute;.',
  191.                 'it'    => 'File destinazione gi&agrave; esistente e non si pu&ograve; sovrascrivere.',
  192.                 'pt_BR' => 'O arquivo de destino j&aacute; existe e n&atilde;o p&ocirc;de ser sobrescrito.'
  193.                 ),
  194.             'NOT_ALLOWED_EXTENSION' => array(
  195.                 'es'    => 'Extension de fichero no permitida.',
  196.                 'en'    => 'File extension not permitted.',
  197.                 'de'    => 'Unerlaubte Dateiendung.',
  198.                 'nl'    => 'Niet toegestane bestands-extensie.',
  199.                 'fr'    => 'Le fichier a une extension non autoris&eacute;e.',
  200.                 'it'    => 'Estensione del File non permessa.',
  201.                 'pt_BR' => 'Extens&atilde;o de arquivo n&atilde;o permitida.'
  202.                 ),
  203.             'PARTIAL' => array(
  204.                 'es'    => 'El fichero fue parcialmente subido',
  205.                 'en'    => 'The file was only partially uploaded.',
  206.                 'de'    => 'Die Datei wurde unvollst&auml;ndig &uuml;bertragen.',
  207.                 'nl'    => 'Het bestand is slechts gedeeltelijk geupload.',
  208.                 'pt_BR' => 
  209.                 ),
  210.             'ERROR' => array(
  211.                 'es'    => 'Error en subida:',
  212.                 'en'    => 'Upload error:',
  213.                 'de'    => 'Fehler beim Upload:',
  214.                 'nl'    => 'Upload fout:',
  215.                 'pt_BR' => 'Erro de upload:'
  216.                 ),
  217.             'DEV_NO_DEF_FILE' => array(
  218.                 'es'    => ,
  219.                 'en'    => 'This filename is not defined in the form as &lt;input type="file" name=?&gt;.',
  220.                 'de'    => 'Dieser Dateiname ist im Formular nicht als &lt;input type="file" name=?&gt; definiert.',
  221.                 'nl'    => 'Deze bestandsnaam is niett gedefineerd in het formulier als &lt;input type="file" name=?&gt;.'
  222.                 )
  223.         );
  224.     }
  225.  
  226.     /**
  227.      * returns the error code
  228.      *
  229.      * @param    string $e_code  type of error
  230.      * @return   string          Error message
  231.      */
  232.     function errorCode($e_code)
  233.     {
  234.         if (!empty($this->error_codes[$e_code][$this->lang])) {
  235.             $msg $this->html ?
  236.                 html_entity_decode($this->error_codes[$e_code][$this->lang]:
  237.                 $this->error_codes[$e_code][$this->lang];
  238.         else {
  239.             $msg $e_code;
  240.         }
  241.  
  242.         if (!empty($this->error_codes['ERROR'][$this->lang])) {
  243.             $error $this->error_codes['ERROR'][$this->lang];
  244.         else {
  245.             $error $this->error_codes['ERROR']['en'];
  246.         }
  247.         return $error.' '.$msg;
  248.     }
  249.  
  250.     /**
  251.      * Overwrites the PEAR::raiseError method
  252.      *
  253.      * @param    string $e_code      type of error
  254.      * @return   object PEAR_Error   a PEAR-Error object
  255.      * @access   public
  256.      */
  257.     function raiseError($e_code)
  258.     {
  259.         return PEAR::raiseError($this->errorCode($e_code)$e_code);
  260.     }
  261. }
  262.  
  263. /**
  264.  * This class provides an advanced file uploader system
  265.  * for file uploads made from html forms
  266.  
  267.  *
  268.  * @author  Tomas V.V.Cox <cox@idecnet.com>
  269.  * @see http://vulcanonet.com/soft/index.php?pack=uploader
  270.  * @package  HTTP_Upload
  271.  * @category HTTP
  272.  * @access   public
  273.  */
  274. {
  275.     /**
  276.      * Contains an array of "uploaded files" objects
  277.      * @var array 
  278.      */
  279.     var $files = array();
  280.     
  281.     /**
  282.      * Contains the desired chmod for uploaded files
  283.      * @var int 
  284.      * @access private
  285.      */
  286.     var $_chmod = HTTP_UPLOAD_DEFAULT_CHMOD;
  287.  
  288.     /**
  289.      * Constructor
  290.      *
  291.      * @param string $lang Language to use for reporting errors
  292.      * @see Upload_Error::error_codes
  293.      * @access public
  294.      */
  295.     function HTTP_Upload($lang = null)
  296.     {
  297.         $this->HTTP_Upload_Error($lang);
  298.         if (function_exists('version_compare'&&
  299.             version_compare(phpversion()'4.1''ge'))
  300.         {
  301.             $this->post_files $_FILES;
  302.             if (isset($_SERVER['CONTENT_TYPE'])) {
  303.                 $this->content_type $_SERVER['CONTENT_TYPE'];
  304.             }
  305.         else {
  306.             global $HTTP_POST_FILES$HTTP_SERVER_VARS;
  307.             $this->post_files $HTTP_POST_FILES;
  308.             if (isset($HTTP_SERVER_VARS['CONTENT_TYPE'])) {
  309.                 $this->content_type $HTTP_SERVER_VARS['CONTENT_TYPE'];
  310.             }
  311.         }
  312.     }
  313.  
  314.     /**
  315.      * Get files
  316.      *
  317.      * @param mixed $file If:
  318.      *     - not given, function will return array of upload_file objects
  319.      *     - is int, will return the $file position in upload_file objects array
  320.      *     - is string, will return the upload_file object corresponding
  321.      *         to $file name of the form. For ex:
  322.      *         if form is <input type="file" name="userfile">
  323.      *         to get this file use: $upload->getFiles('userfile')
  324.      *
  325.      * @return mixed array or object (see @param $file above) or Pear_Error
  326.      * @access public
  327.      */
  328.     function &getFiles($file = null)
  329.     {
  330.         static $is_built = false;
  331.         //build only once for multiple calls
  332.         if (!$is_built{
  333.             $files &$this->_buildFiles();
  334.             if (PEAR::isError($files)) {
  335.                 // there was an error with the form.
  336.                 // Create a faked upload embedding the error
  337.                 $this->files['_error'=  &new HTTP_Upload_File(
  338.                                                        '_error'null,
  339.                                                        nullnull,
  340.                                                        null$files->getCode(),
  341.                                                        $this->lang$this->_chmod);
  342.             else {
  343.                 $this->files = $files;
  344.             }
  345.             $is_built = true;
  346.         }
  347.         if ($file !== null{
  348.             if (is_int($file)) {
  349.                 $pos = 0;
  350.                 foreach ($this->files as $obj{
  351.                     if ($pos == $file{
  352.                         return $obj;
  353.                     }
  354.                     $pos++;
  355.                 }
  356.             elseif (is_string($file&& isset($this->files[$file])) {
  357.                 return $this->files[$file];
  358.             }
  359.             if (isset($this->files['_error'])) {
  360.                 return $this->files['_error'];
  361.             else {
  362.                 // developer didn't specify this name in the form
  363.                 // warn him about it with a faked upload
  364.                 return new HTTP_Upload_File(
  365.                                            '_error'null,
  366.                                            nullnull,
  367.                                            null'DEV_NO_DEF_FILE',
  368.                                            $this->lang);
  369.             }
  370.         }
  371.         return $this->files;
  372.     }
  373.  
  374.     /**
  375.      * Creates the list of the uploaded file
  376.      *
  377.      * @return array of HTTP_Upload_File objects for every file
  378.      */
  379.     function &_buildFiles()
  380.     {
  381.         // Form method check
  382.         if (!isset($this->content_type||
  383.             strpos($this->content_type'multipart/form-data'!== 0)
  384.         {
  385.             return $this->raiseError('BAD_FORM');
  386.         }
  387.         // In 4.1 $_FILES isn't initialized when no uploads
  388.         // XXX (cox) afaik, in >= 4.1 and <= 4.3 only
  389.         if (function_exists('version_compare'&&
  390.             version_compare(phpversion()'4.1''ge'))
  391.         {
  392.             $error $this->isMissing();
  393.             if (PEAR::isError($error)) {
  394.                 return $error;
  395.             }
  396.         }
  397.  
  398.         // map error codes from 4.2.0 $_FILES['userfile']['error']
  399.         if (function_exists('version_compare'&&
  400.             version_compare(phpversion()'4.2.0''ge')) {
  401.             $uploadError = array(
  402.                 1 => 'TOO_LARGE',
  403.                 2 => 'TOO_LARGE',
  404.                 3 => 'PARTIAL',
  405.                 4 => 'NO_USER_FILE'
  406.                 );
  407.         }
  408.  
  409.  
  410.         // Parse $_FILES (or $HTTP_POST_FILES)
  411.         $files = array();
  412.         foreach ($this->post_files as $userfile => $value{
  413.             if (is_array($value['name'])) {
  414.                 foreach ($value['name'as $key => $val{
  415.                     $err $value['error'][$key];
  416.                     if (isset($err&& $err !== 0 && isset($uploadError[$err])) {
  417.                         $error $uploadError[$err];
  418.                     else {
  419.                         $error = null;
  420.                     }
  421.                     $name basename($value['name'][$key]);
  422.                     $tmp_name $value['tmp_name'][$key];
  423.                     $size $value['size'][$key];
  424.                     $type $value['type'][$key];
  425.                     $formname $userfile . "[$key]";
  426.                     $files[$formname= new HTTP_Upload_File($name$tmp_name,
  427.                                                              $formname$type$size$error$this->lang$this->_chmod);
  428.                 }
  429.                 // One file
  430.             else {
  431.                 $err $value['error'];
  432.                 if (isset($err&& $err !== 0 && isset($uploadError[$err])) {
  433.                     $error $uploadError[$err];
  434.                 else {
  435.                     $error = null;
  436.                 }
  437.                 $name basename($value['name']);
  438.                 $tmp_name $value['tmp_name'];
  439.                 $size $value['size'];
  440.                 $type $value['type'];
  441.                 $formname $userfile;
  442.                 $files[$formname= new HTTP_Upload_File($name$tmp_name,
  443.                                                          $formname$type$size$error$this->lang$this->_chmod);
  444.             }
  445.         }
  446.         return $files;
  447.     }
  448.  
  449.     /**
  450.      * Checks if the user submited or not some file
  451.      *
  452.      * @return mixed False when are files or PEAR_Error when no files
  453.      * @access public
  454.      * @see Read the note in the source code about this function
  455.      */
  456.     function isMissing()
  457.     {
  458.         if (count($this->post_files< 1{
  459.             return $this->raiseError('NO_USER_FILE');
  460.         }
  461.         //we also check if at least one file has more than 0 bytes :)
  462.         $files = array();
  463.         $size = 0;
  464.         foreach ($this->post_files as $userfile => $value{
  465.             if (is_array($value['name'])) {
  466.                 foreach ($value['name'as $key => $val{
  467.                     $size += $value['size'][$key];
  468.                 }
  469.             else {  //one file
  470.                 $size $value['size'];
  471.             }
  472.         }
  473.         if ($size == 0{
  474.             $this->raiseError('NO_USER_FILE');
  475.         }
  476.         return false;
  477.     }
  478.  
  479.     /**
  480.      * Sets the chmod to be used for uploaded files
  481.      *
  482.      * @param int Desired mode
  483.      */
  484.     function setChmod($mode)
  485.     {
  486.         $this->_chmod = $mode;
  487.     }
  488. }
  489.  
  490. /**
  491.  * This class provides functions to work with the uploaded file
  492.  *
  493.  * @author  Tomas V.V.Cox <cox@idecnet.com>
  494.  * @see http://vulcanonet.com/soft/index.php?pack=uploader
  495.  * @package  HTTP_Upload
  496.  * @category HTTP
  497.  * @access   public
  498.  */
  499. {
  500.     /**
  501.      * If the random seed was initialized before or not
  502.      * @var  boolean; 
  503.      */
  504.     var $_seeded = 0;
  505.  
  506.     /**
  507.      * Assoc array with file properties
  508.      * @var array 
  509.      */
  510.     var $upload = array();
  511.  
  512.     /**
  513.      * If user haven't selected a mode, by default 'safe' will be used
  514.      * @var boolean 
  515.      */
  516.     var $mode_name_selected = false;
  517.  
  518.     /**
  519.      * It's a common security risk in pages who has the upload dir
  520.      * under the document root (remember the hack of the Apache web?)
  521.      *
  522.      * @var array 
  523.      * @access private
  524.      * @see HTTP_Upload_File::setValidExtensions()
  525.      */
  526.     var $_extensions_check = array('php''phtm''phtml''php3''inc');
  527.  
  528.     /**
  529.      * @see HTTP_Upload_File::setValidExtensions()
  530.      * @var string 
  531.      * @access private
  532.      */
  533.     var $_extensions_mode  'deny';
  534.  
  535.     /**
  536.      * Contains the desired chmod for uploaded files
  537.      * @var int 
  538.      * @access private
  539.      */
  540.     var $_chmod = HTTP_UPLOAD_DEFAULT_CHMOD;
  541.  
  542.     /**
  543.      * Constructor
  544.      *
  545.      * @param   string  $name       destination file name
  546.      * @param   string  $tmp        temp file name
  547.      * @param   string  $formname   name of the form
  548.      * @param   string  $type       Mime type of the file
  549.      * @param   string  $size       size of the file
  550.      * @param   string  $error      error on upload
  551.      * @param   string  $lang       used language for errormessages
  552.      * @access  public
  553.      */
  554.     function HTTP_Upload_File($name = null$tmp = null,  $formname = null,
  555.                               $type = null$size = null$error = null
  556.                               $lang = null$chmod = HTTP_UPLOAD_DEFAULT_CHMOD)
  557.     {
  558.         $this->HTTP_Upload_Error($lang);
  559.         $ext = null;
  560.  
  561.         if (empty($name|| $size == 0{
  562.             $error 'NO_USER_FILE';
  563.         elseif ($tmp == 'none'{
  564.             $error 'TOO_LARGE';
  565.         else {
  566.             // strpos needed to detect files without extension
  567.             if (($pos strrpos($name'.')) !== false{
  568.                 $ext substr($name$pos + 1);
  569.             }
  570.         }
  571.  
  572.         if (function_exists('version_compare'&&
  573.             version_compare(phpversion()'4.1''ge')) {
  574.             if (isset($_POST['MAX_FILE_SIZE']&&
  575.                 $size $_POST['MAX_FILE_SIZE']{
  576.                 $error 'TOO_LARGE';
  577.             }
  578.         else {
  579.             global $HTTP_POST_VARS;
  580.             if (isset($HTTP_POST_VARS['MAX_FILE_SIZE']&&
  581.                 $size $HTTP_POST_VARS['MAX_FILE_SIZE']{
  582.                 $error 'TOO_LARGE';
  583.             }
  584.         }
  585.  
  586.         $this->upload = array(
  587.             'real'      => $name,
  588.             'name'      => $name,
  589.             'form_name' => $formname,
  590.             'ext'       => $ext,
  591.             'tmp_name'  => $tmp,
  592.             'size'      => $size,
  593.             'type'      => $type,
  594.             'error'     => $error
  595.         );
  596.  
  597.         $this->_chmod $chmod;
  598.     }
  599.  
  600.     /**
  601.      * Sets the name of the destination file
  602.      *
  603.      * @param string $mode     A valid mode: 'uniq', 'safe' or 'real' or a file name
  604.      * @param string $prepend  A string to prepend to the name
  605.      * @param string $append   A string to append to the name
  606.      *
  607.      * @return string The modified name of the destination file
  608.      * @access public
  609.      */
  610.     function setName($mode$prepend = null$append = null)
  611.     {
  612.         switch ($mode{
  613.             case 'uniq':
  614.                 $name $this->nameToUniq();
  615.                 $this->upload['ext'$this->nameToSafe($this->upload['ext']10);
  616.                 $name .= '.' $this->upload['ext'];
  617.                 break;
  618.             case 'safe':
  619.                 $name $this->nameToSafe($this->upload['real']);
  620.                 if (($pos strrpos($name'.')) !== false{
  621.                     $this->upload['ext'substr($name$pos + 1);
  622.                 else {
  623.                     $this->upload['ext''';
  624.                 }
  625.                 break;
  626.             case 'real':
  627.                 $name $this->upload['real'];
  628.                 break;
  629.             default:
  630.                 $name $mode;
  631.         }
  632.         $this->upload['name'$prepend $name $append;
  633.         $this->mode_name_selected = true;
  634.         return $this->upload['name'];
  635.     }
  636.  
  637.     /**
  638.      * Unique file names in the form: 9022210413b75410c28bef.html
  639.      * @see HTTP_Upload_File::setName()
  640.      */
  641.     function nameToUniq()
  642.     {
  643.         if ($this->_seeded{
  644.             srand((double) microtime(* 1000000);
  645.             $this->_seeded = 1;
  646.         }
  647.         $uniq uniqid(rand());
  648.         return $uniq;
  649.     }
  650.  
  651.     /**
  652.      * Format a file name to be safe
  653.      *
  654.      * @param    string $file   The string file name
  655.      * @param    int    $maxlen Maximun permited string lenght
  656.      * @return   string Formatted file name
  657.      * @see HTTP_Upload_File::setName()
  658.      */
  659.     function nameToSafe($name$maxlen=250)
  660.     {
  661.         $noalpha ;
  662.         $alpha   'AEIOUYaeiouyAEIOUaeiouAEIOUaeiouAEIOUaeiouyAaOoAaNnCcaooa';
  663.  
  664.         $name substr($name0$maxlen);
  665.         $name strtr($name$noalpha$alpha);
  666.         // not permitted chars are replaced with "_"
  667.         return preg_replace('/[^a-zA-Z0-9,._\+\()\-]/''_'$name);
  668.     }
  669.  
  670.     /**
  671.      * The upload was valid
  672.      *
  673.      * @return bool If the file was submitted correctly
  674.      * @access public
  675.      */
  676.     function isValid()
  677.     {
  678.         if ($this->upload['error'=== null{
  679.             return true;
  680.         }
  681.         return false;
  682.     }
  683.  
  684.     /**
  685.      * User haven't submit a file
  686.      *
  687.      * @return bool If the user submitted a file or not
  688.      * @access public
  689.      */
  690.     function isMissing()
  691.     {
  692.         if ($this->upload['error'== 'NO_USER_FILE'{
  693.             return true;
  694.         }
  695.         return false;
  696.     }
  697.  
  698.     /**
  699.      * Some error occured during upload (most common due a file size problem,
  700.      * like max size exceeded or 0 bytes long).
  701.      * @return bool If there were errors submitting the file (probably
  702.      *               because the file excess the max permitted file size)
  703.      * @access public
  704.      */
  705.     function isError()
  706.     {
  707.         if (in_array($this->upload['error']array('TOO_LARGE''BAD_FORM','DEV_NO_DEF_FILE'))) {
  708.             return true;
  709.         }
  710.         return false;
  711.     }
  712.  
  713.     /**
  714.      * Moves the uploaded file to its destination directory.
  715.      *
  716.      * @param    string  $dir_dest  Destination directory
  717.      * @param    bool    $overwrite Overwrite if destination file exists?
  718.      * @return   mixed   True on success or Pear_Error object on error
  719.      * @access public
  720.      */
  721.     function moveTo($dir_dest$overwrite = true)
  722.     {
  723.         if (!$this->isValid()) {
  724.             return $this->raiseError($this->upload['error']);
  725.         }
  726.  
  727.         //Valid extensions check
  728.         if (!$this->_evalValidExtensions()) {
  729.             return $this->raiseError('NOT_ALLOWED_EXTENSION');
  730.         }
  731.  
  732.         $err_code $this->_chk_dir_dest($dir_dest);
  733.         if ($err_code !== false{
  734.             return $this->raiseError($err_code);
  735.         }
  736.         // Use 'safe' mode by default if no other was selected
  737.         if (!$this->mode_name_selected{
  738.             $this->setName('safe');
  739.         }
  740.  
  741.         $name_dest $dir_dest . DIRECTORY_SEPARATOR . $this->upload['name'];
  742.  
  743.         if (@is_file($name_dest)) {
  744.             if ($overwrite !== true{
  745.                 return $this->raiseError('FILE_EXISTS');
  746.             elseif (!is_writable($name_dest)) {
  747.                 return $this->raiseError('CANNOT_OVERWRITE');
  748.             }
  749.         }
  750.  
  751.         // copy the file and let php clean the tmp
  752.         if (!@move_uploaded_file($this->upload['tmp_name']$name_dest)) {
  753.             return $this->raiseError('E_FAIL_MOVE');
  754.         }
  755.         @chmod($name_dest$this->_chmod);
  756.         return $this->getProp('name');
  757.     }
  758.  
  759.     /**
  760.      * Check for a valid destination dir
  761.      *
  762.      * @param    string  $dir_dest Destination dir
  763.      * @return   mixed   False on no errors or error code on error
  764.      */
  765.     function _chk_dir_dest($dir_dest)
  766.     {
  767.         if (!$dir_dest{
  768.             return 'MISSING_DIR';
  769.         }
  770.         if (!@is_dir ($dir_dest)) {
  771.             return 'IS_NOT_DIR';
  772.         }
  773.         if (!is_writeable ($dir_dest)) {
  774.             return 'NO_WRITE_PERMS';
  775.         }
  776.         return false;
  777.     }
  778.     /**
  779.      * Retrive properties of the uploaded file
  780.      * @param string $name   The property name. When null an assoc array with
  781.      *                        all the properties will be returned
  782.      * @return mixed         A string or array
  783.      * @see HTTP_Upload_File::HTTP_Upload_File()
  784.      * @access public
  785.      */
  786.     function getProp($name = null)
  787.     {
  788.         if ($name === null{
  789.             return $this->upload;
  790.         }
  791.         return $this->upload[$name];
  792.     }
  793.  
  794.     /**
  795.      * Returns a error message, if a error occured
  796.      * (deprecated) Use getMessage() instead
  797.      * @return string    a Error message
  798.      * @access public
  799.      */
  800.     function errorMsg()
  801.     {
  802.         return $this->errorCode($this->upload['error']);
  803.     }
  804.  
  805.     /**
  806.      * Returns a error message, if a error occured
  807.      * @return string    a Error message
  808.      * @access public
  809.      */
  810.     function getMessage()
  811.     {
  812.         return $this->errorCode($this->upload['error']);
  813.     }
  814.  
  815.     /**
  816.      * Function to restrict the valid extensions on file uploads
  817.      *
  818.      * @param array $exts File extensions to validate
  819.      * @param string $mode The type of validation:
  820.      *                        1) 'deny'   Will deny only the supplied extensions
  821.      *                        2) 'accept' Will accept only the supplied extensions
  822.      *                                    as valid
  823.      * @access public
  824.      */
  825.     function setValidExtensions($exts$mode 'deny')
  826.     {
  827.         $this->_extensions_check $exts;
  828.         $this->_extensions_mode  $mode;
  829.     }
  830.  
  831.     /**
  832.      * Evaluates the validity of the extensions set by setValidExtensions
  833.      *
  834.      * @return bool False on non valid extension, true if they are valid
  835.      * @access private
  836.      */
  837.     function _evalValidExtensions()
  838.     {
  839.         $exts $this->_extensions_check;
  840.         settype($exts'array');
  841.         if ($this->_extensions_mode == 'deny'{
  842.             if (in_array($this->getProp('ext')$exts)) {
  843.                 return false;
  844.             }
  845.         // mode == 'accept'
  846.         else {
  847.             if (!in_array($this->getProp('ext')$exts)) {
  848.                 return false;
  849.             }
  850.         }
  851.         return true;
  852.     }
  853. }
  854. ?>

Documentation generated on Mon, 11 Mar 2019 13:54:34 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.