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. // This software is licensed by the LGPL
  4. // -> http://www.gnu.org/copyleft/lesser.txt 
  5. // (c) 2001- 2004 by Tomas Von Veschler Cox //
  6. // ********************************************** //
  7.  // $Id: Upload.php 287177 2009-08-12 20:03:01Z cweiske $
  8.  
  9. /**
  10.  * Pear File Uploader class. Easy and secure managment of files
  11.  * submitted via HTML Forms.
  12.  *
  13.  * Leyend:
  14.  * - you can add error msgs in your language in the HTTP_Upload_Error class
  15.  *
  16.  * TODO:
  17.  * - try to think a way of having all the Error system in other
  18.  *   file and only include it when an error ocurrs
  19.  *
  20.  * -- Notes for users HTTP_Upload >= 0.9.0 --
  21.  *
  22.  *  Error detection was enhanced, so you no longer need to
  23.  *  check for PEAR::isError() in $upload->getFiles() or call
  24.  *  $upload->isMissing(). Instead you'll
  25.  *  get the error when do a check for $file->isError().
  26.  *
  27.  *  Example:
  28.  *
  29.  *  $upload = new HTTP_Upload('en');
  30.  *  $file = $upload->getFiles('i_dont_exist_in_form_definition');
  31.  *  if ($file->isError()) {
  32.  *      die($file->getMessage());
  33.  *  }
  34.  *
  35.  *  --
  36.  *
  37.  */
  38.  
  39. require_once 'PEAR.php';
  40.  
  41. /**
  42.  * defines default chmod
  43.  */
  44. define('HTTP_UPLOAD_DEFAULT_CHMOD'0660);
  45.  
  46. /**
  47.  * Error Class for HTTP_Upload
  48.  *
  49.  * @author  Tomas V.V.Cox <cox@idecnet.com>
  50.  * @see http://vulcanonet.com/soft/index.php?pack=uploader
  51.  * @package HTTP_Upload
  52.  * @category HTTP
  53.  * @access public
  54.  */
  55. class HTTP_Upload_Error extends PEAR
  56. {
  57.     /**
  58.      * Selected language for error messages
  59.      * @var string 
  60.      */
  61.     var $lang = 'en';
  62.  
  63.     /**
  64.      * Whether HTML entities shall be encoded automatically
  65.      * @var boolean 
  66.      */
  67.     var $html = false;
  68.  
  69.     /**
  70.      * Constructor
  71.      *
  72.      * Creates a new PEAR_Error
  73.      *
  74.      * @param string $lang The language selected for error code messages
  75.      * @access public
  76.      */
  77.     function HTTP_Upload_Error($lang = null$html = false)
  78.     {
  79.         $this->lang = ($lang !== null$lang $this->lang;
  80.         $this->html = ($html !== false$html $this->html;
  81.         $raw_size ini_get('upload_max_filesize');
  82.         $ini_size intval($raw_size);
  83.         switch (strtoupper(substr($raw_size-1))) {
  84.             case 'G'$ini_size *= 1024;
  85.             case 'M'$ini_size *= 1024;
  86.             case 'K'$ini_size *= 1024;
  87.         }
  88.  
  89.         if (function_exists('version_compare'&&
  90.             version_compare(phpversion()'4.1''ge')) {
  91.             $maxsize (isset($_POST['MAX_FILE_SIZE'])) ?
  92.                 $_POST['MAX_FILE_SIZE': null;
  93.         else {
  94.             global $HTTP_POST_VARS;
  95.             $maxsize (isset($HTTP_POST_VARS['MAX_FILE_SIZE'])) ?
  96.                 $HTTP_POST_VARS['MAX_FILE_SIZE': null;
  97.         }
  98.  
  99.         if (empty($maxsize|| ($maxsize $ini_size)) {
  100.             $maxsize $ini_size;
  101.         }
  102.         // XXXXX Add here error messages in your language
  103.         $this->error_codes = array(
  104.             'TOO_LARGE' => array(
  105.                 'es'    => "Fichero demasiado largo. El maximo permitido es: $maxsize bytes.",
  106.                 'en'    => "File size too large. The maximum permitted size is: $maxsize bytes.",
  107.                 'et'    => "Fail on liiga suur. Maksimaalne lubatud suurus on $maxsize baiti.",
  108.                 'de'    => "Datei zu gro&szlig;. Die zul&auml;ssige Maximalgr&ouml;&szlig;e ist: $maxsize Bytes.",
  109.                 'nl'    => "Het bestand is te groot, de maximale grootte is: $maxsize bytes.",
  110.                 'fr'    => "Le fichier est trop gros. La taille maximum autoris&eacute;e est: $maxsize bytes.",
  111.                 'it'    => "Il file &eacute; troppo grande. Il massimo permesso &eacute: $maxsize bytes.",
  112.                 'pt_BR' => "Arquivo muito grande. O tamanho m&aacute;ximo permitido &eacute; $maxsize bytes.",
  113.                 'ru'    => "&#x424;&#x430;&#x439;&#x43b; &#x441;&#x43b;&#x438;&#x448;&#x43a;&#x43e;&#x43c; &#x432;&#x435;&#x43b;&#x438;&#x43a;. &#x41c;&#x430;&#x43a;&#x441;&#x438;&#x43c;&#x430;&#x43b;&#x44c;&#x43d;&#x44b;&#x439; &#x440;&#x430;&#x437;&#x440;&#x435;&#x448;&#x451;&#x43d;&#x43d;&#x44b;&#x439; &#x43e;&#x431;&#x44a;&#x451;&#x43c;: $maxsize &#x431;&#x430;&#x439;&#x442;.",
  114.                 'sv'    => "Filen &auml;r f&ouml;r stor. St&ouml;rsta till&aring;tna filstorlek &auml;r: $maxsize bytes.",
  115.                 'da'    => "Filen er for stor. St&oslash;rste tilladte filst&oslash;rrelse er : $maxsize bytes."
  116.                 ),
  117.             'MISSING_DIR' => array(
  118.                 'es'    => 'Falta directorio destino.',
  119.                 'en'    => 'Missing destination directory.',
  120.                 'et'    => 'Puudub sihtkataloog.',
  121.                 'de'    => 'Kein Zielverzeichnis definiert.',
  122.                 'nl'    => 'Geen bestemmings directory.',
  123.                 'fr'    => 'Le r&eacute;pertoire de destination n\'est pas d&eacute;fini.',
  124.                 'it'    => 'Manca la directory di destinazione.',
  125.                 'pt_BR' => 'Aus&ecirc;ncia de diret&oacute;rio de destino.',
  126.                 'ru'    => '&#x41d;&#x435; &#x443;&#x43a;&#x430;&#x437;&#x430;&#x43d; &#x446;&#x435;&#x43b;&#x435;&#x432;&#x43e;&#x439; &#x43a;&#x430;&#x442;&#x430;&#x43b;&#x43e;&#x433;.',
  127.                 'sv'    => 'Saknar destinationskatalog.',
  128.                 'da'    => 'Mangler destinationskatalog.'
  129. ),
  130.             'IS_NOT_DIR' => array(
  131.                 'es'    => 'El directorio destino no existe o es un fichero regular.',
  132.                 'en'    => 'The destination directory doesn\'t exist or is a regular file.',
  133.                 'et'    => 'Sihtkataloogi pole olemas v&otilde;i ta on tavaline fail.',
  134.                 'de'    => 'Das angebene Zielverzeichnis existiert nicht oder ist eine Datei.',
  135.                 'nl'    => 'De doeldirectory bestaat niet, of is een gewoon bestand.',
  136.                 'fr'    => 'Le r&eacute;pertoire de destination n\'existe pas ou il s\'agit d\'un fichier r&eacute;gulier.',
  137.                 'it'    => 'La directory di destinazione non esiste o &eacute; un file.',
  138.                 'pt_BR' => 'O diret&oacute;rio de destino n&atilde;o existe ou &eacute; um arquivo.',
  139.                 'ru'    => '&#x426;&#x435;&#x43b;&#x435;&#x432;&#x43e;&#x439; &#x43a;&#x430;&#x442;&#x430;&#x43b;&#x43e;&#x433; &#x43d;&#x435; &#x441;&#x443;&#x449;&#x435;&#x441;&#x442;&#x432;&#x443;&#x435;&#x442; &#x438;&#x43b;&#x438; &#x44f;&#x432;&#x43b;&#x44f;&#x435;&#x442;&#x441;&#x44f; &#x43e;&#x431;&#x44b;&#x447;&#x43d;&#x44b;&#x43c; &#x444;&#x430;&#x439;&#x43b;&#x43e;&#x43c;.',
  140.                 'sv'    => 'Destinationskatalogen existerar inte, eller &auml;r en vanlig fil.',
  141.                 'da'    => 'Destinationskatalogen eksisterer ikke, eller er en almindelig fil.'
  142.                 ),
  143.             'NO_WRITE_PERMS' => array(
  144.                 'es'    => 'El directorio destino no tiene permisos de escritura.',
  145.                 'en'    => 'The destination directory doesn\'t have write perms.',
  146.                 'et'    => 'Valitud kataloogi ei saa kirjutada.',
  147.                 'de'    => 'Fehlende Schreibrechte f&uuml;r das Zielverzeichnis.',
  148.                 'nl'    => 'Geen toestemming om te schrijven in de doeldirectory.',
  149.                 'fr'    => 'Le r&eacute;pertoire de destination n\'a pas les droits en &eacute;criture.',
  150.                 'it'    => 'Non si hanno i permessi di scrittura sulla directory di destinazione.',
  151.                 'pt_BR' => 'O diret&oacute;rio de destino n&atilde;o possui permiss&atilde;o para escrita.',
  152.                 'ru'    => '&#x41d;&#x435;&#x442; &#x43f;&#x440;&#x430;&#x432; &#x43d;&#x430; &#x437;&#x430;&#x43f;&#x438;&#x441;&#x44c; &#x432; &#x446;&#x435;&#x43b;&#x435;&#x432;&#x43e;&#x439; &#x43a;&#x430;&#x442;&#x430;&#x43b;&#x43e;&#x433;.',
  153.                 'sv'    => 'Destinationskatalogen har inte skrivr&auml;ttigheter.',
  154.                 'da'    => 'Destinationskatalogen har ikke skrivrettigheder.'
  155.                 ),
  156.             'NO_USER_FILE' => array(
  157.                 'es'    => 'No se ha escogido fichero para el upload.',
  158.                 'en'    => 'You haven\'t selected any file for uploading.',
  159.                 'et'    => '&Uuml;leslaetav fail j&auml;i valimata.',
  160.                 'de'    => 'Es wurde keine Datei f&uuml;r den Upload ausgew&auml;hlt.',
  161.                 'nl'    => 'Er is geen bestand opgegeven om te uploaden.',
  162.                 'fr'    => 'Vous n\'avez pas s&eacute;lectionn&eacute; de fichier &agrave; envoyer.',
  163.                 'it'    => 'Nessun file selezionato per l\'upload.',
  164.                 'pt_BR' => 'Nenhum arquivo selecionado para upload.',
  165.                 'ru'    => '&#x412;&#x44b; &#x43d;&#x435; &#x432;&#x44b;&#x431;&#x440;&#x430;&#x43b;&#x438; &#x444;&#x430;&#x439;&#x43b; &#x434;&#x43b;&#x44f; &#x437;&#x430;&#x433;&#x440;&#x443;&#x437;&#x43a;&#x438;.',
  166.                 'sv'    => 'Du har inte valt n&aring;gon fil att ladda upp.',
  167.                 'da'    => 'Du har ikke valgt nogen fil at uploade.'
  168.                 ),
  169.             'BAD_FORM' => array(
  170.                 'es'    => 'El formulario no contiene method="post" enctype="multipart/form-data" requerido.',
  171.                 'en'    => 'The html form doesn\'t contain the required method="post" enctype="multipart/form-data".',
  172.                 'et'    => 'Html-vorm ei sisalda n&otilde;utud method="post" enctype="multipart/form-data".',
  173.                 'de'    => 'Das HTML-Formular enth&auml;lt nicht die Angabe method="post" enctype="multipart/form-data" '.
  174.                            'im &gt;form&lt;-Tag.',
  175.                 'nl'    => 'Het HTML-formulier bevat niet de volgende benodigde '.
  176.                            'eigenschappen: method="post" enctype="multipart/form-data".',
  177.                 'fr'    => 'Le formulaire HTML ne contient pas les attributs requis : '.
  178.                            ' method="post" enctype="multipart/form-data".',
  179.                 'it'    => 'Il modulo HTML non contiene gli attributi richiesti: "'.
  180.                            ' method="post" enctype="multipart/form-data".',
  181.                 'pt_BR' => 'O formul&aacute;rio HTML n&atilde;o possui o method="post" enctype="multipart/form-data" requerido.',
  182.                 'ru'    => '&#x412; &#x444;&#x43e;&#x440;&#x43c;&#x435; HTML &#x43d;&#x435; &#x443;&#x43a;&#x430;&#x437;&#x430;&#x43d;&#x44b; &#x43d;&#x435;&#x43e;&#x431;&#x445;&#x43e;&#x434;&#x438;&#x43c;&#x44b;&#x435; &#x430;&#x442;&#x440;&#x438;&#x431;&#x443;&#x442;&#x44b;: method="post" enctype="multipart/form-data".',
  183.                 'sv'    => 'HTML-formul&auml;ret inneh&aring;ller inte de attribut som kr&auml;vs: '.
  184.                         ' method="post" enctype="multipart/form-data"',
  185.                 'da'    => 'HTML-formularen mangler disse indstillinger: '.
  186.                         ' method="post" enctype="multipart/form-data"'
  187.                 ),
  188.             'E_FAIL_COPY' => array(
  189.                 'es'    => 'Fallo al copiar el fichero temporal.',
  190.                 'en'    => 'Failed to copy the temporary file.',
  191.                 'de'    => 'Tempor&auml;re Datei konnte nicht kopiert werden.',
  192.                 'et'    => 'Ajutise faili kopeerimine eba&otilde;nnestus.',
  193.                 'nl'    => 'Het tijdelijke bestand kon niet gekopieerd worden.',
  194.                 'fr'    => 'L\'enregistrement du fichier temporaire a &eacute;chou&eacute;.',
  195.                 'it'    => 'Copia del file temporaneo fallita.',
  196.                 'pt_BR' => 'Falha ao copiar o arquivo tempor&aacute;rio.',
  197.                 'ru'    => '&#x41d;&#x435; &#x443;&#x434;&#x430;&#x43b;&#x43e;&#x441;&#x44c; &#x441;&#x43a;&#x43e;&#x43f;&#x438;&#x440;&#x43e;&#x432;&#x430;&#x442;&#x44c; &#x432;&#x440;&#x435;&#x43c;&#x435;&#x43d;&#x43d;&#x44b;&#x439; &#x444;&#x430;&#x439;&#x43b;.',
  198.                 'sv'    => 'Misslyckades med att kopiera den tempor&auml;ra filen.',
  199.                 'da'    => 'Det lykkedes ikke at kopiere den tempor&aelig;re fil.'
  200.                 ),
  201.             'E_FAIL_MOVE' => array(
  202.                 'es'    => 'No puedo mover el fichero.',
  203.                 'en'    => 'Impossible to move the file.',
  204.                 'et'    => 'Faili asukohta ei saa muuta.',
  205.                 'de'    => 'Datei kann nicht verschoben werden.',
  206.                 'nl'    => 'Het bestand kon niet verplaatst worden.',
  207.                 'fr'    => 'Impossible de d&eacute;placer le fichier.',
  208.                 'pt_BR' => 'N&atilde;o foi poss&iacute;vel mover o arquivo.',
  209.                 'ru'    => '&#x41d;&#x435; &#x443;&#x434;&#x430;&#x43b;&#x43e;&#x441;&#x44c; &#x43f;&#x435;&#x440;&#x435;&#x43c;&#x435;&#x441;&#x442;&#x438;&#x442;&#x44c; &#x444;&#x430;&#x439;&#x43b;',
  210.                 'sv'    => 'Misslyckades med att flytta den tempor&auml;ra filen.',
  211.                 'da'    => 'Det lykkedes ikke at flytta den tempor&aelig;re fil.'
  212.                 ),
  213.             'FILE_EXISTS' => array(
  214.                 'es'    => 'El fichero destino ya existe.',
  215.                 'en'    => 'The destination file already exists.',
  216.                 'et'    => 'Sihtfail on juba olemas.',
  217.                 'de'    => 'Die zu erzeugende Datei existiert bereits.',
  218.                 'nl'    => 'Het doelbestand bestaat al.',
  219.                 'fr'    => 'Le fichier de destination existe d&eacute;j&agrave;.',
  220.                 'it'    => 'File destinazione gi&agrave; esistente.',
  221.                 'pt_BR' => 'O arquivo de destino j&aacute; existe.',
  222.                 'ru'    => '&#x426;&#x435;&#x43b;&#x435;&#x432;&#x43e;&#x439; &#x444;&#x430;&#x439;&#x43b; &#x443;&#x436;&#x435; &#x441;&#x443;&#x449;&#x435;&#x441;&#x442;&#x432;&#x443;&#x435;&#x442;.',
  223.                 'sv'    => 'Destinationsfilen existerar redan.',
  224.                 'da'    => 'Destinationsfilen findes allerede.'
  225.                 ),
  226.             'CANNOT_OVERWRITE' => array(
  227.                 'es'    => 'El fichero destino ya existe y no se puede sobreescribir.',
  228.                 'en'    => 'The destination file already exists and could not be overwritten.',
  229.                 'de'    => 'Die zu erzeugende Datei existiert bereits und konnte nicht &uuml;berschrieben werden.',
  230.                 'et'    => 'Sihtfail on juba olemas. Seda ei saa &uuml;le kirjutada.',
  231.                 'nl'    => 'Het doelbestand bestaat al, en kon niet worden overschreven.',
  232.                 'fr'    => 'Le fichier de destination existe d&eacute;j&agrave; et ne peux pas &ecirc;tre remplac&eacute;.',
  233.                 'it'    => 'File destinazione gi&agrave; esistente e non si pu&ograve; sovrascrivere.',
  234.                 'pt_BR' => 'O arquivo de destino j&aacute; existe e n&atilde;o p&ocirc;de ser sobrescrito.',
  235.                 'ru'    => '&#x426;&#x435;&#x43b;&#x435;&#x432;&#x43e;&#x439; &#x444;&#x430;&#x439;&#x43b; &#x443;&#x436;&#x435; &#x441;&#x443;&#x449;&#x435;&#x441;&#x442;&#x432;&#x443;&#x435;&#x442; &#x438; &#x43d;&#x435; &#x43c;&#x43e;&#x436;&#x435;&#x442; &#x431;&#x44b;&#x442;&#x44c; &#x43f;&#x435;&#x440;&#x435;&#x437;&#x430;&#x43f;&#x438;&#x441;&#x430;&#x43d;.',
  236.                 'sv'    => 'Destinationsfilen existerar redan och kunde inte skrivas &ouml;ver.',
  237.                 'da'    => 'Destinationsfilen findes allerede og kunne ikke overskrives.'
  238.                 ),
  239.             'NOT_ALLOWED_EXTENSION' => array(
  240.                 'es'    => 'Extension de fichero no permitida.',
  241.                 'en'    => 'File extension not permitted.',
  242.                 'et'    => 'Faili laiend pole lubatud.',
  243.                 'de'    => 'Unerlaubte Dateiendung.',
  244.                 'nl'    => 'Niet toegestane bestands-extensie.',
  245.                 'fr'    => 'Le fichier a une extension non autoris&eacute;e.',
  246.                 'it'    => 'Estensione del File non permessa.',
  247.                 'pt_BR' => 'Extens&atilde;o de arquivo n&atilde;o permitida.',
  248.                 'ru'    => '&#x41d;&#x435;&#x434;&#x43e;&#x43f;&#x443;&#x441;&#x442;&#x438;&#x43c;&#x43e;&#x435; &#x440;&#x430;&#x441;&#x448;&#x438;&#x440;&#x435;&#x43d;&#x438;&#x435; &#x444;&#x430;&#x439;&#x43b;&#x430;.',
  249.                 'sv'    => 'Ej till&aring;ten fil&auml;ndelse.',
  250.                 'da'    => 'Ikke tilladt filformat.'
  251.                 ),
  252.             'PARTIAL' => array(
  253.                 'es'    => 'El fichero fue parcialmente subido',
  254.                 'en'    => 'The file was only partially uploaded.',
  255.                 'et'    => 'Faili &uuml;leslaadimine oli poolik.',
  256.                 'de'    => 'Die Datei wurde unvollst&auml;ndig &uuml;bertragen.',
  257.                 'nl'    => 'Het bestand is slechts gedeeltelijk geupload.',
  258.                 'pt_BR' => 'O arquivo n&atilde;o foi enviado por completo.',
  259.                 'ru'    => '&#x424;&#x430;&#x439;&#x43b; &#x431;&#x44b;&#x43b; &#x437;&#x430;&#x433;&#x440;&#x443;&#x436;&#x435;&#x43d; &#x43b;&#x438;&#x448;&#x44c; &#x447;&#x430;&#x441;&#x442;&#x438;&#x447;&#x43d;&#x43e;.',
  260.                 'sv'    => 'Filen blev endast delvis uppladdad.',
  261.                 'da'    => 'Filen blev kun delvis uploadet.'
  262.                 ),
  263.             'ERROR' => array(
  264.                 'es'    => 'Error en subida:',
  265.                 'en'    => 'Upload error:',
  266.                 'et'    => 'Viga &uuml;leslaadimisel:',
  267.                 'de'    => 'Fehler beim Upload:',
  268.                 'nl'    => 'Upload fout:',
  269.                 'pt_BR' => 'Erro de upload:',
  270.                 'ru'    => '&#x41e;&#x448;&#x438;&#x431;&#x43a;&#x430; &#x437;&#x430;&#x433;&#x440;&#x443;&#x437;&#x43a;&#x438;:',
  271.                 'sv'    => 'Fel vid upladdning:',
  272.                 'da'    => 'Fejl ved upload:'
  273.                 ),
  274.             'DEV_NO_DEF_FILE' => array(
  275.                 'es'    => 'No est&aacute; definido en el formulario este nombre de fichero como &lt;input type="file" name=?&gt;.',
  276.                 'en'    => 'This filename is not defined in the form as &lt;input type="file" name=?&gt;.',
  277.                 'et'    => 'Failinimi ei olnud vormistatud htmlis &lt;input type="file" name=?&gt;.',
  278.                 'de'    => 'Dieser Dateiname ist im Formular nicht als &lt;input type="file" name=?&gt; definiert.',
  279.                 'nl'    => 'Deze bestandsnaam is niett gedefineerd in het formulier als &lt;input type="file" name=?&gt;.',
  280.                 'pt_BR' => 'Este arquivo n&atilde;o foi definido no formul&aacute;rio como  &lt;input type="file" name=?&gt;.',
  281.                 'ru'    => '&#x42d;&#x442;&#x43e; &#x438;&#x43c;&#x44f; &#x444;&#x430;&#x439;&#x43b;&#x430; &#x43e;&#x442;&#x441;&#x443;&#x442;&#x441;&#x442;&#x432;&#x43e;&#x432;&#x430;&#x43b;&#x43e; &#x432; &#x444;&#x43e;&#x440;&#x43c;&#x435; &#x43a;&#x430;&#x43a; &#x43f;&#x43e;&#x43b;&#x435; &lt;input type="file" name=?&gt;.',
  282.                 'sv'    => 'Detta filnamn &auml;r inte definierat i formul&auml;ret som &lt;input type="file" name=?&gt;.',
  283.                 'da'    => 'Dette filnavn er ikke definieret i formularen som &lt;input type="file" name=?&gt;.'
  284.                 )
  285.         );
  286.     }
  287.  
  288.     /**
  289.      * returns the error code
  290.      *
  291.      * @param    string $e_code  type of error
  292.      * @return   string          Error message
  293.      */
  294.     function errorCode($e_code)
  295.     {
  296.         if (!empty($this->error_codes[$e_code][$this->lang])) {
  297.             $msg $this->html ?
  298.                 html_entity_decode($this->error_codes[$e_code][$this->lang]:
  299.                 $this->error_codes[$e_code][$this->lang];
  300.         else {
  301.             $msg $e_code;
  302.         }
  303.  
  304.         if (!empty($this->error_codes['ERROR'][$this->lang])) {
  305.             $error $this->error_codes['ERROR'][$this->lang];
  306.         else {
  307.             $error $this->error_codes['ERROR']['en'];
  308.         }
  309.         return $error.' '.$msg;
  310.     }
  311.  
  312.     /**
  313.      * Overwrites the PEAR::raiseError method
  314.      *
  315.      * @param    string $e_code      type of error
  316.      * @return   object PEAR_Error   a PEAR-Error object
  317.      * @access   public
  318.      */
  319.     function raiseError($e_code)
  320.     {
  321.         return PEAR::raiseError($this->errorCode($e_code)$e_code);
  322.     }
  323. }
  324.  
  325. /**
  326.  * This class provides an advanced file uploader system
  327.  * for file uploads made from html forms
  328.  
  329.  *
  330.  * @author  Tomas V.V.Cox <cox@idecnet.com>
  331.  * @see http://vulcanonet.com/soft/index.php?pack=uploader
  332.  * @package  HTTP_Upload
  333.  * @category HTTP
  334.  * @access   public
  335.  */
  336. {
  337.     /**
  338.      * Contains an array of "uploaded files" objects
  339.      * @var array 
  340.      */
  341.     var $files = array();
  342.     
  343.     /**
  344.      * Whether the files array has already been built or not
  345.      * @var int 
  346.      * @access private
  347.      */
  348.     var $is_built = false;
  349.  
  350.     /**
  351.      * Contains the desired chmod for uploaded files
  352.      * @var int 
  353.      * @access private
  354.      */
  355.     var $_chmod = HTTP_UPLOAD_DEFAULT_CHMOD;
  356.  
  357.     /**
  358.      * Specially used if the naming mode is 'seq'
  359.      * Contains file naming information
  360.      * 
  361.      * @var array 
  362.      * @access private
  363.      */
  364.     var $_modeNameSeq = array(
  365.         'flag' => false,
  366.         'prepend' => '',
  367.         'append' => '',
  368.     )
  369.  
  370.     /**
  371.      * Constructor
  372.      *
  373.      * @param string $lang Language to use for reporting errors
  374.      * @see Upload_Error::error_codes
  375.      * @access public
  376.      */
  377.     function HTTP_Upload($lang = null)
  378.     {
  379.         $this->HTTP_Upload_Error($lang);
  380.         if (function_exists('version_compare'&&
  381.             version_compare(phpversion()'4.1''ge'))
  382.         {
  383.             $this->post_files $_FILES;
  384.             if (isset($_SERVER['CONTENT_TYPE'])) {
  385.                 $this->content_type $_SERVER['CONTENT_TYPE'];
  386.             }
  387.         else {
  388.             global $HTTP_POST_FILES$HTTP_SERVER_VARS;
  389.             $this->post_files $HTTP_POST_FILES;
  390.             if (isset($HTTP_SERVER_VARS['CONTENT_TYPE'])) {
  391.                 $this->content_type $HTTP_SERVER_VARS['CONTENT_TYPE'];
  392.             }
  393.         }
  394.     }
  395.  
  396.     /**
  397.      * Get files
  398.      *
  399.      * @param mixed $file If:
  400.      *     - not given, function will return array of upload_file objects
  401.      *     - is int, will return the $file position in upload_file objects array
  402.      *     - is string, will return the upload_file object corresponding
  403.      *         to $file name of the form. For ex:
  404.      *         if form is <input type="file" name="userfile">
  405.      *         to get this file use: $upload->getFiles('userfile')
  406.      *
  407.      * @return mixed array or object (see @param $file above) or Pear_Error
  408.      * @access public
  409.      */
  410.     function &getFiles($file = null)
  411.     {
  412.         //build only once for multiple calls
  413.         if (!$this->is_built{
  414.             $files &$this->_buildFiles();
  415.             if (PEAR::isError($files)) {
  416.                 // there was an error with the form.
  417.                 // Create a faked upload embedding the error
  418.                 $files_code $files->getCode();
  419.                 $this->files['_error'=  &new HTTP_Upload_File(
  420.                                                        '_error'null,
  421.                                                        nullnull,
  422.                                                        null$files_code,
  423.                                                        $this->lang$this->_chmod);
  424.             else {
  425.                 $this->files = $files;
  426.             }
  427.             $this->is_built = true;
  428.         }
  429.         if ($file !== null{
  430.             if (is_int($file)) {
  431.                 $pos = 0;
  432.                 foreach ($this->files as $obj{
  433.                     if ($pos == $file{
  434.                         return $obj;
  435.                     }
  436.                     $pos++;
  437.                 }
  438.             elseif (is_string($file&& isset($this->files[$file])) {
  439.                 return $this->files[$file];
  440.             }
  441.             if (isset($this->files['_error'])) {
  442.                 return $this->files['_error'];
  443.             else {
  444.                 // developer didn't specify this name in the form
  445.                 // warn him about it with a faked upload
  446.                 $huf =&  new HTTP_Upload_File(
  447.                                              '_error'null,
  448.                                              nullnull,
  449.                                              null'DEV_NO_DEF_FILE',
  450.                                              $this->lang);
  451.                 return $huf;
  452.             }
  453.         }
  454.         return $this->files;
  455.     }
  456.  
  457.     /**
  458.      * Creates the list of the uploaded file
  459.      *
  460.      * @return array of HTTP_Upload_File objects for every file
  461.      */
  462.     function &_buildFiles()
  463.     {
  464.         // Form method check
  465.         if (!isset($this->content_type||
  466.             strpos($this->content_type'multipart/form-data'!== 0)
  467.         {
  468.             $error =$this->raiseError('BAD_FORM');
  469.             return $error;
  470.         }
  471.         // In 4.1 $_FILES isn't initialized when no uploads
  472.         // XXX (cox) afaik, in >= 4.1 and < 4.3 only
  473.         if (function_exists('version_compare'&&
  474.             version_compare(PHP_VERSION'4.1''ge'&&
  475.             version_compare(PHP_VERSION'4.3''lt'))
  476.         {
  477.             $error $this->isMissing();
  478.             if (PEAR::isError($error)) {
  479.                 return $error;
  480.             }
  481.         }
  482.  
  483.         // map error codes from 4.2.0 $_FILES['userfile']['error']
  484.         if (function_exists('version_compare'&&
  485.             version_compare(phpversion()'4.2.0''ge')) {
  486.             $uploadError = array(
  487.                 1 => 'TOO_LARGE',
  488.                 2 => 'TOO_LARGE',
  489.                 3 => 'PARTIAL',
  490.                 4 => 'NO_USER_FILE'
  491.                 );
  492.         }
  493.  
  494.  
  495.         // Parse $_FILES (or $HTTP_POST_FILES)
  496.         $files = array();
  497.         foreach ($this->post_files as $userfile => $value{
  498.             if (is_array($value['name'])) {
  499.                 foreach ($value['name'as $key => $val{
  500.                     $err $value['error'][$key];
  501.                     if (isset($err&& $err !== 0 && isset($uploadError[$err])) {
  502.                         $error $uploadError[$err];
  503.                     else {
  504.                         $error = null;
  505.                     }
  506.                     $name basename($value['name'][$key]);
  507.                     $tmp_name $value['tmp_name'][$key];
  508.                     $size $value['size'][$key];
  509.                     $type $value['type'][$key];
  510.                     $formname $userfile . "[$key]";
  511.                     $files[$formname= new HTTP_Upload_File($name$tmp_name,
  512.                                                              $formname$type$size$error$this->lang$this->_chmod);
  513.                 }
  514.                 // One file
  515.             else {
  516.                 $err $value['error'];
  517.                 if (isset($err&& $err !== 0 && isset($uploadError[$err])) {
  518.                     $error $uploadError[$err];
  519.                 else {
  520.                     $error = null;
  521.                 }
  522.                 $name basename($value['name']);
  523.                 $tmp_name $value['tmp_name'];
  524.                 $size $value['size'];
  525.                 $type $value['type'];
  526.                 $formname $userfile;
  527.                 $files[$formname= new HTTP_Upload_File($name$tmp_name,
  528.                                                          $formname$type$size$error$this->lang$this->_chmod);
  529.             }
  530.         }
  531.         return $files;
  532.     }
  533.  
  534.     /**
  535.      * Checks if the user submited or not some file
  536.      *
  537.      * @return mixed False when are files or PEAR_Error when no files
  538.      * @access public
  539.      * @see Read the note in the source code about this function
  540.      */
  541.     function isMissing()
  542.     {
  543.         if (count($this->post_files< 1{
  544.             $error =$this->raiseError('NO_USER_FILE');
  545.             return $error;
  546.         }
  547.         //we also check if at least one file has more than 0 bytes :)
  548.         $files = array();
  549.         $size = 0;
  550.         $error = null;
  551.  
  552.         foreach ($this->post_files as $userfile => $value{
  553.             if (is_array($value['name'])) {
  554.                 foreach ($value['name'as $key => $val{
  555.                     $size += $value['size'][$key];
  556.                 }
  557.             elseif (!empty($value['name'])) {  //one file
  558.                 $size += $value['size'];
  559.                 $error $value['error'];
  560.             }
  561.         }
  562.         if ($error !== null && $error != 2 && $size == 0{
  563.             $error =$this->raiseError('NO_USER_FILE');
  564.             return $error;
  565.         }
  566.         return false;
  567.     }
  568.  
  569.     /**
  570.      * Sets the chmod to be used for uploaded files
  571.      *
  572.      * @param int Desired mode
  573.      */
  574.     function setChmod($mode)
  575.     {
  576.         $this->_chmod $mode;
  577.     }
  578. }
  579.  
  580. /**
  581.  * This class provides functions to work with the uploaded file
  582.  *
  583.  * @author  Tomas V.V.Cox <cox@idecnet.com>
  584.  * @see http://vulcanonet.com/soft/index.php?pack=uploader
  585.  * @package  HTTP_Upload
  586.  * @category HTTP
  587.  * @access   public
  588.  */
  589. {
  590.     /**
  591.      * Assoc array with file properties
  592.      * @var array 
  593.      */
  594.     var $upload = array();
  595.  
  596.     /**
  597.      * If user haven't selected a mode, by default 'safe' will be used
  598.      * @var boolean 
  599.      */
  600.     var $mode_name_selected = false;
  601.  
  602.     /**
  603.      * It's a common security risk in pages who has the upload dir
  604.      * under the document root (remember the hack of the Apache web?)
  605.      *
  606.      * @var array 
  607.      * @access private
  608.      * @see HTTP_Upload_File::setValidExtensions()
  609.      */
  610.     var $_extensionsCheck = array('php''phtm''phtml''php3''inc');
  611.  
  612.     /**
  613.      * @see HTTP_Upload_File::setValidExtensions()
  614.      * @var string 
  615.      * @access private
  616.      */
  617.     var $_extensionsMode  'deny';
  618.  
  619.     /**
  620.      * Whether to use case-sensitive extension checks or not
  621.      * @see HTTP_Upload_File::setValidExtensions()
  622.      * @var bool 
  623.      * @access private
  624.      */
  625.      var $_extensionsCaseSensitive = true;
  626.  
  627.     /**
  628.      * Contains the desired chmod for uploaded files
  629.      * @var int 
  630.      * @access private
  631.      */
  632.     var $_chmod = HTTP_UPLOAD_DEFAULT_CHMOD;
  633.  
  634.     /**
  635.      * Constructor
  636.      *
  637.      * @param   string  $name       destination file name
  638.      * @param   string  $tmp        temp file name
  639.      * @param   string  $formname   name of the form
  640.      * @param   string  $type       Mime type of the file
  641.      * @param   string  $size       size of the file
  642.      * @param   string  $error      error on upload
  643.      * @param   string  $lang       used language for errormessages
  644.      * @access  public
  645.      */
  646.     function HTTP_Upload_File($name = null$tmp = null,  $formname = null,
  647.                               $type = null$size = null$error = null
  648.                               $lang = null$chmod = HTTP_UPLOAD_DEFAULT_CHMOD)
  649.     {
  650.         $this->HTTP_Upload_Error($lang);
  651.         $ext = null;
  652.  
  653.         if (empty($name|| ($error != 'TOO_LARGE' && $size == 0)) {
  654.             $error 'NO_USER_FILE';
  655.         elseif ($tmp == 'none'{
  656.             $error 'TOO_LARGE';
  657.         else {
  658.             // strpos needed to detect files without extension
  659.             if (($pos strrpos($name'.')) !== false{
  660.                 $ext substr($name$pos + 1);
  661.             }
  662.         }
  663.  
  664.         if (function_exists('version_compare'&&
  665.             version_compare(phpversion()'4.1''ge')) {
  666.             if (isset($_POST['MAX_FILE_SIZE']&&
  667.                 $size $_POST['MAX_FILE_SIZE']{
  668.                 $error 'TOO_LARGE';
  669.             }
  670.         else {
  671.             global $HTTP_POST_VARS;
  672.             if (isset($HTTP_POST_VARS['MAX_FILE_SIZE']&&
  673.                 $size $HTTP_POST_VARS['MAX_FILE_SIZE']{
  674.                 $error 'TOO_LARGE';
  675.             }
  676.         }
  677.  
  678.         $this->upload = array(
  679.             'real'      => $name,
  680.             'name'      => $name,
  681.             'form_name' => $formname,
  682.             'ext'       => $ext,
  683.             'tmp_name'  => $tmp,
  684.             'size'      => $size,
  685.             'type'      => $type,
  686.             'error'     => $error
  687.         );
  688.  
  689.         $this->_chmod $chmod;
  690.     }
  691.  
  692.     /**
  693.      * Sets the name of the destination file
  694.      *
  695.      * @param string $mode     A valid mode: 'uniq', 'seq', 'safe' or 'real' or a file name
  696.      * @param string $prepend  A string to prepend to the name
  697.      * @param string $append   A string to append to the name
  698.      *
  699.      * @return string The modified name of the destination file
  700.      * @access public
  701.      */
  702.     function setName($mode$prepend = null$append = null)
  703.     {
  704.         switch ($mode{
  705.             case 'uniq':
  706.                 $name $this->nameToUniq();
  707.                 $this->upload['ext'$this->nameToSafe($this->upload['ext']10);
  708.                 $name .= '.' $this->upload['ext'];
  709.                 break;
  710.             case 'safe':
  711.                 $name $this->nameToSafe($this->upload['real']);
  712.                 if (($pos strrpos($name'.')) !== false{
  713.                     $this->upload['ext'substr($name$pos + 1);
  714.                 else {
  715.                     $this->upload['ext''';
  716.                 }
  717.                 break;
  718.             case 'real':
  719.                 $name $this->upload['real'];
  720.                 break;
  721.             case 'seq':
  722.                 $this->_modeNameSeq['flag'= true;
  723.                 $this->_modeNameSeq['prepend'$prepend;
  724.                 $this->_modeNameSeq['append'$append;
  725.                 break;
  726.             default:
  727.                 $name $mode;
  728.         }
  729.         $this->upload['name'$prepend $name $append;
  730.         $this->mode_name_selected = true;
  731.         return $this->upload['name'];
  732.     }
  733.  
  734.     /**
  735.      * Sequence file names in the form: userGuide[1].pdf, userGuide[2].pdf ...
  736.      *
  737.      * @param string $dir  Destination directory
  738.      */
  739.     function nameToSeq($dir)
  740.     {
  741.         //Check if a file with the same name already exists
  742.         $name $dir . DIRECTORY_SEPARATOR . $this->upload['real'];
  743.         if (!@is_file($name)) {
  744.             return $this->upload['real'];
  745.         else {
  746.             //we need to strip out the extension and the '.' of the file
  747.             //e.g 'userGuide.pdf' becomes 'userGuide'
  748.             $baselength strlen($this->upload['real']strlen($this->upload['ext']- 1;
  749.             $basename substr$this->upload['real'],0$baselength );
  750.  
  751.             //here's the pattern we're looking for
  752.             $pattern '(\[)([[:digit:]]+)(\])$';
  753.  
  754.             //just incase the original filename had a sequence, we take it out 
  755.             // e.g: 'userGuide[3]' should become 'userGuide'
  756.             $basename =  ereg_replace($pattern''$basename);
  757.             
  758.             /*
  759.              * attempt to find a unique sequence file name
  760.              */
  761.             $i = 1;
  762.             
  763.             while (true{
  764.                 $filename $basename '[' $i '].' $this->upload['ext'];
  765.                 $check $dir . DIRECTORY_SEPARATOR . $filename;
  766.                 if (!@is_file($check)) {
  767.                     return $filename;
  768.                 }
  769.                 $i++;
  770.             }
  771.         }
  772.     }
  773.  
  774.     /**
  775.      * Unique file names in the form: 9022210413b75410c28bef.html
  776.      * @see HTTP_Upload_File::setName()
  777.      */
  778.     function nameToUniq()
  779.     {
  780.         $uniq uniqid(rand());
  781.         return $uniq;
  782.     }
  783.  
  784.     /**
  785.      * Format a file name to be safe
  786.      *
  787.      * @param    string $file   The string file name
  788.      * @param    int    $maxlen Maximun permited string lenght
  789.      * @return   string Formatted file name
  790.      * @see HTTP_Upload_File::setName()
  791.      */
  792.     function nameToSafe($name$maxlen=250)
  793.     {
  794.         $noalpha 'ÁÉÍÓÚÝáéíóúýÂÊÎÔÛâêîôûÀÈÌÒÙàèìòùÄËÏÖÜäëïöüÿÃãÕõÅåÑñÇç@°ºªÞþÆæ';
  795.         $alpha   'AEIOUYaeiouyAEIOUaeiouAEIOUaeiouAEIOUaeiouyAaOoAaNnCcaooaTtAa';
  796.  
  797.         $name substr($name0$maxlen);
  798.         $name strtr($name$noalpha$alpha);
  799.         // not permitted chars are replaced with "_"
  800.         return preg_replace('/[^a-zA-Z0-9,._\+\()\-]/''_'$name);
  801.     }
  802.  
  803.     /**
  804.      * The upload was valid
  805.      *
  806.      * @return bool If the file was submitted correctly
  807.      * @access public
  808.      */
  809.     function isValid()
  810.     {
  811.         if ($this->upload['error'=== null{
  812.             return true;
  813.         }
  814.         return false;
  815.     }
  816.  
  817.     /**
  818.      * User haven't submit a file
  819.      *
  820.      * @return bool If the user submitted a file or not
  821.      * @access public
  822.      */
  823.     function isMissing()
  824.     {
  825.         if ($this->upload['error'== 'NO_USER_FILE'{
  826.             return true;
  827.         }
  828.         return false;
  829.     }
  830.  
  831.     /**
  832.      * Some error occured during upload (most common due a file size problem,
  833.      * like max size exceeded or 0 bytes long).
  834.      * @return bool If there were errors submitting the file (probably
  835.      *               because the file excess the max permitted file size)
  836.      * @access public
  837.      */
  838.     function isError()
  839.     {
  840.         if (in_array($this->upload['error']array('TOO_LARGE''BAD_FORM','DEV_NO_DEF_FILE'))) {
  841.             return true;
  842.         }
  843.         return false;
  844.     }
  845.  
  846.     /**
  847.      * Moves the uploaded file to its destination directory.
  848.      *
  849.      * @param  string  $dir  Destination directory
  850.      * @param  bool    $overwrite Overwrite if destination file exists?
  851.      * @return mixed   True on success or PEAR_Error object on error
  852.      * @access public
  853.      */
  854.     function moveTo($dir$overwrite = true)
  855.     {
  856.         if (!$this->isValid()) {
  857.             $error =$this->raiseError($this->upload['error']);
  858.             return $error;
  859.         }
  860.  
  861.         //Valid extensions check
  862.         if (!$this->_evalValidExtensions()) {
  863.             $error =$this->raiseError('NOT_ALLOWED_EXTENSION');
  864.             return $error;
  865.         }
  866.  
  867.         $err_code $this->_chkDirDest($dir);
  868.         if ($err_code !== false{
  869.             $error =$this->raiseError($err_code);
  870.             return $error;
  871.         }
  872.         // Use 'safe' mode by default if no other was selected
  873.         if (!$this->mode_name_selected{
  874.             $this->setName('safe');
  875.         }
  876.  
  877.         //test to see if we're working with sequence naming mode
  878.         if (isset($this->_modeNameSeq&& isset($this->_modeNameSeq['flag']&& $this->_modeNameSeq['flag'=== true{
  879.             $this->upload['name'$this->_modeNameSeq['prepend'$this->nameToSeq($dir$this->_modeNameSeq['append'];
  880.         }
  881.  
  882.         $name $dir . DIRECTORY_SEPARATOR . $this->upload['name'];
  883.  
  884.         if (@is_file($name)) {
  885.             if ($overwrite !== true{
  886.                 $error =$this->raiseError('FILE_EXISTS');
  887.                 return $error;
  888.             elseif (!is_writable($name)) {
  889.                 $error =$this->raiseError('CANNOT_OVERWRITE');
  890.                 return $error;
  891.             }
  892.         }
  893.  
  894.         // copy the file and let php clean the tmp
  895.         if (!@move_uploaded_file($this->upload['tmp_name']$name)) {
  896.             $error =$this->raiseError('E_FAIL_MOVE');
  897.             return $error
  898.         }
  899.         @chmod($name$this->_chmod);
  900.         $prop =$this->getProp('name');
  901.         return $prop;
  902.     }
  903.  
  904.     /**
  905.      * Check for a valid destination dir
  906.      *
  907.      * @param    string  $dir_dest Destination dir
  908.      * @return   mixed   False on no errors or error code on error
  909.      */
  910.     function _chkDirDest($dir_dest)
  911.     {
  912.         if (!$dir_dest{
  913.             return 'MISSING_DIR';
  914.         }
  915.         if (!@is_dir($dir_dest)) {
  916.             return 'IS_NOT_DIR';
  917.         }
  918.         if (!is_writeable($dir_dest)) {
  919.             return 'NO_WRITE_PERMS';
  920.         }
  921.         return false;
  922.     }
  923.     /**
  924.      * Retrive properties of the uploaded file
  925.      * @param string $name   The property name. When null an assoc array with
  926.      *                        all the properties will be returned
  927.      * @return mixed         A string or array
  928.      * @see HTTP_Upload_File::HTTP_Upload_File()
  929.      * @access public
  930.      */
  931.     function getProp($name = null)
  932.     {
  933.         if ($name === null{
  934.             return $this->upload;
  935.         }
  936.         return $this->upload[$name];
  937.     }
  938.  
  939.     /**
  940.      * Returns a error message, if a error occured
  941.      * (deprecated) Use getMessage() instead
  942.      * @return string    a Error message
  943.      * @access public
  944.      */
  945.     function errorMsg()
  946.     {
  947.         return $this->errorCode($this->upload['error']);
  948.     }
  949.  
  950.     /**
  951.      * Returns a error message, if a error occured
  952.      * @return string    a Error message
  953.      * @access public
  954.      */
  955.     function getMessage()
  956.     {
  957.         return $this->errorCode($this->upload['error']);
  958.     }
  959.  
  960.     /**
  961.      * Function to restrict the valid extensions on file uploads
  962.      *
  963.      * @param array $exts File extensions to validate
  964.      * @param string $mode The type of validation:
  965.      *                        1) 'deny'   Will deny only the supplied extensions
  966.      *                        2) 'accept' Will accept only the supplied extensions
  967.      *                                    as valid
  968.      * @param bool $case_sensitive whether extension check is case sensitive.
  969.      * @access public
  970.      */
  971.     function setValidExtensions($exts$mode 'deny'$case_sensitive = null)
  972.     {
  973.         $this->_extensionsCheck $exts;
  974.         $this->_extensionsMode  $mode;
  975.         if ($case_sensitive != null{
  976.             $this->_extensionsCaseSensitive  $case_sensitive;
  977.         }
  978.     }
  979.  
  980.     /**
  981.      * Evaluates the validity of the extensions set by setValidExtensions
  982.      *
  983.      * @return bool False on non valid extension, true if they are valid
  984.      * @access private
  985.      */
  986.     function _evalValidExtensions()
  987.     {
  988.         $exts $this->_extensionsCheck;
  989.         settype($exts'array');
  990.         $ext $this->getProp('ext');
  991.         if (!$this->_extensionsCaseSensitive{
  992.             $ext strtolower($ext);
  993.         }
  994.         if ($this->_extensionsMode == 'deny'{
  995.             if (in_array($ext$exts)) {
  996.                 return false;
  997.             }
  998.         // mode == 'accept'
  999.         else {
  1000.             if (!in_array($ext$exts)) {
  1001.                 return false;
  1002.             }
  1003.         }
  1004.         return true;
  1005.     }
  1006. }
  1007. ?>

Documentation generated on Sun, 16 Aug 2009 09:30:02 +0000 by phpDocumentor 1.4.2. PEAR Logo Copyright © PHP Group 2004.