2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
 
   5  * HTML class for a file upload field
 
   9  * LICENSE: This source file is subject to version 3.01 of the PHP license
 
  10  * that is available through the world-wide-web at the following URI:
 
  11  * http://www.php.net/license/3_01.txt If you did not receive a copy of
 
  12  * the PHP License and are unable to obtain it through the web, please
 
  13  * send a note to license@php.net so we can mail you a copy immediately.
 
  16  * @package     HTML_QuickForm
 
  17  * @author      Adam Daniel <adaniel1@eesus.jnj.com>
 
  18  * @author      Bertrand Mansion <bmansion@mamasam.com>
 
  19  * @author      Alexey Borzov <avb@php.net>
 
  20  * @copyright   2001-2011 The PHP Group
 
  21  * @license     http://www.php.net/license/3_01.txt PHP License 3.01
 
  23  * @link        http://pear.php.net/package/HTML_QuickForm
 
  27  * Base class for <input /> form elements
 
  29 require_once 'HTML/QuickForm/input.php';
 
  31 // register file-related rules
 
  32 if (class_exists('HTML_QuickForm')) {
 
  33     HTML_QuickForm::registerRule('uploadedfile', 'callback', '_ruleIsUploadedFile', 'HTML_QuickForm_file');
 
  34     HTML_QuickForm::registerRule('maxfilesize', 'callback', '_ruleCheckMaxFileSize', 'HTML_QuickForm_file');
 
  35     HTML_QuickForm::registerRule('mimetype', 'callback', '_ruleCheckMimeType', 'HTML_QuickForm_file');
 
  36     HTML_QuickForm::registerRule('filename', 'callback', '_ruleCheckFileName', 'HTML_QuickForm_file');
 
  40  * HTML class for a file upload field
 
  43  * @package     HTML_QuickForm
 
  44  * @author      Adam Daniel <adaniel1@eesus.jnj.com>
 
  45  * @author      Bertrand Mansion <bmansion@mamasam.com>
 
  46  * @author      Alexey Borzov <avb@php.net>
 
  47  * @version     Release: 3.2.16
 
  50 class HTML_QuickForm_file extends HTML_QuickForm_input
 
  55     * Uploaded file data, from $_FILES
 
  66      * @param     string    Input field name attribute
 
  67      * @param     string    Input field label
 
  68      * @param     mixed     (optional)Either a typical HTML attribute string 
 
  69      *                      or an associative array
 
  73     function HTML_QuickForm_file($elementName=null, $elementLabel=null, $attributes=null)
 
  75         HTML_QuickForm_input::HTML_QuickForm_input($elementName, $elementLabel, $attributes);
 
  76         $this->setType('file');
 
  83      * Sets size of file element
 
  85      * @param     int    Size of file element
 
  89     function setSize($size)
 
  91         $this->updateAttributes(array('size' => $size));
 
  98      * Returns size of file element
 
 106         return $this->getAttribute('size');
 
 113      * Freeze the element so that only its value is returned
 
 127      * Sets value for file element.
 
 129      * Actually this does nothing. The function is defined here to override
 
 130      * HTML_Quickform_input's behaviour of setting the 'value' attribute. As
 
 131      * no sane user-agent uses <input type="file">'s value for anything 
 
 132      * (because of security implications) we implement file's value as a 
 
 133      * read-only property with a special meaning.
 
 135      * @param     mixed    Value for file element
 
 139     function setValue($value)
 
 142     } //end func setValue
 
 148      * Returns information about the uploaded file
 
 156         return $this->_value;
 
 157     } // end func getValue
 
 160     // {{{ onQuickFormEvent()
 
 163      * Called by HTML_QuickForm whenever form event is made on this element
 
 165      * @param     string    Name of event
 
 166      * @param     mixed     event arguments
 
 167      * @param     object    calling object
 
 172     function onQuickFormEvent($event, $arg, &$caller)
 
 176                 if ($caller->getAttribute('method') == 'get') {
 
 177                     return PEAR::raiseError('Cannot add a file upload field to a GET method form');
 
 179                 $this->_value = $this->_findValue();
 
 180                 $caller->updateAttributes(array('enctype' => 'multipart/form-data'));
 
 181                 $caller->setMaxFileSize();
 
 184                 $this->onQuickFormEvent('createElement', $arg, $caller);
 
 185                 return $this->onQuickFormEvent('updateValue', null, $caller);
 
 187             case 'createElement':
 
 188                 $className = get_class($this);
 
 189                 $this->$className($arg[0], $arg[1], $arg[2]);
 
 193     } // end func onQuickFormEvent
 
 196     // {{{ moveUploadedFile()
 
 199      * Moves an uploaded file into the destination 
 
 201      * @param    string  Destination directory path
 
 202      * @param    string  New file name
 
 204      * @return   bool    Whether the file was moved successfully
 
 206     function moveUploadedFile($dest, $fileName = '')
 
 208         if ($dest != ''  && substr($dest, -1) != '/') {
 
 211         $fileName = ($fileName != '') ? $fileName : basename($this->_value['name']);
 
 212         return move_uploaded_file($this->_value['tmp_name'], $dest . $fileName); 
 
 213     } // end func moveUploadedFile
 
 216     // {{{ isUploadedFile()
 
 219      * Checks if the element contains an uploaded file
 
 222      * @return    bool      true if file has been uploaded, false otherwise
 
 224     function isUploadedFile()
 
 226         return $this->_ruleIsUploadedFile($this->_value);
 
 227     } // end func isUploadedFile
 
 230     // {{{ _ruleIsUploadedFile()
 
 233      * Checks if the given element contains an uploaded file
 
 235      * @param     array     Uploaded file info (from $_FILES)
 
 237      * @return    bool      true if file has been uploaded, false otherwise
 
 239     function _ruleIsUploadedFile($elementValue)
 
 241         if ((isset($elementValue['error']) && $elementValue['error'] == 0) ||
 
 242             (!empty($elementValue['tmp_name']) && $elementValue['tmp_name'] != 'none')) {
 
 243             return is_uploaded_file($elementValue['tmp_name']);
 
 247     } // end func _ruleIsUploadedFile
 
 250     // {{{ _ruleCheckMaxFileSize()
 
 253      * Checks that the file does not exceed the max file size
 
 255      * @param     array     Uploaded file info (from $_FILES)
 
 256      * @param     int       Max file size
 
 258      * @return    bool      true if filesize is lower than maxsize, false otherwise
 
 260     function _ruleCheckMaxFileSize($elementValue, $maxSize)
 
 262         if (!empty($elementValue['error']) && 
 
 263             (UPLOAD_ERR_FORM_SIZE == $elementValue['error'] || UPLOAD_ERR_INI_SIZE == $elementValue['error'])) {
 
 266         if (!HTML_QuickForm_file::_ruleIsUploadedFile($elementValue)) {
 
 269         return ($maxSize >= @filesize($elementValue['tmp_name']));
 
 270     } // end func _ruleCheckMaxFileSize
 
 273     // {{{ _ruleCheckMimeType()
 
 276      * Checks if the given element contains an uploaded file of the right mime type
 
 278      * @param     array     Uploaded file info (from $_FILES)
 
 279      * @param     mixed     Mime Type (can be an array of allowed types)
 
 281      * @return    bool      true if mimetype is correct, false otherwise
 
 283     function _ruleCheckMimeType($elementValue, $mimeType)
 
 285         if (!HTML_QuickForm_file::_ruleIsUploadedFile($elementValue)) {
 
 288         if (is_array($mimeType)) {
 
 289             return in_array($elementValue['type'], $mimeType);
 
 291         return $elementValue['type'] == $mimeType;
 
 292     } // end func _ruleCheckMimeType
 
 295     // {{{ _ruleCheckFileName()
 
 298      * Checks if the given element contains an uploaded file of the filename regex
 
 300      * @param     array     Uploaded file info (from $_FILES)
 
 301      * @param     string    Regular expression
 
 303      * @return    bool      true if name matches regex, false otherwise
 
 305     function _ruleCheckFileName($elementValue, $regex)
 
 307         if (!HTML_QuickForm_file::_ruleIsUploadedFile($elementValue)) {
 
 310         return (bool)preg_match($regex, $elementValue['name']);
 
 311     } // end func _ruleCheckFileName
 
 317     * Tries to find the element value from the values array
 
 319     * Needs to be redefined here as $_FILES is populated differently from 
 
 320     * other arrays when element name is of the form foo[bar]
 
 322     * @param bool $sc1   unused, for signature compatibility
 
 327     function _findValue(&$sc1 = null)
 
 329         if (empty($_FILES)) {
 
 332         $elementName = $this->getName();
 
 333         if (isset($_FILES[$elementName])) {
 
 334             return $_FILES[$elementName];
 
 335         } elseif (false !== ($pos = strpos($elementName, '['))) {
 
 337                         array('\\', '\''), array('\\\\', '\\\''),
 
 338                         substr($elementName, 0, $pos)
 
 340             $idx   = "['" . str_replace(
 
 341                         array('\\', '\'', ']', '['), array('\\\\', '\\\'', '', "']['"),
 
 342                         substr($elementName, $pos + 1, -1)
 
 344             $props = array('name', 'type', 'size', 'tmp_name', 'error');
 
 345             $code  = "if (!isset(\$_FILES['{$base}']['name']{$idx})) {\n" .
 
 348                      "    \$value = array();\n";
 
 349             foreach ($props as $prop) {
 
 350                 $code .= "    \$value['{$prop}'] = \$_FILES['{$base}']['{$prop}']{$idx};\n";
 
 352             return eval($code . "    return \$value;\n}\n");
 
 359 } // end class HTML_QuickForm_file