file.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP version 4.0 |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.0 of the PHP license, |
  9. // | that is bundled with this package in the file LICENSE, and is |
  10. // | available at through the world-wide-web at |
  11. // | http://www.php.net/license/2_02.txt. |
  12. // | If you did not receive a copy of the PHP license and are unable to |
  13. // | obtain it through the world-wide-web, please send a note to |
  14. // | license@php.net so we can mail you a copy immediately. |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Adam Daniel <adaniel1@eesus.jnj.com> |
  17. // | Bertrand Mansion <bmansion@mamasam.com> |
  18. // +----------------------------------------------------------------------+
  19. //
  20. // $Id: file.php 9612 2006-10-20 11:56:44Z bmol $
  21. require_once("HTML/QuickForm/input.php");
  22. // register file-related rules
  23. if (class_exists('HTML_QuickForm')) {
  24. HTML_QuickForm::registerRule('uploadedfile', 'callback', '_ruleIsUploadedFile', 'HTML_QuickForm_file');
  25. HTML_QuickForm::registerRule('maxfilesize', 'callback', '_ruleCheckMaxFileSize', 'HTML_QuickForm_file');
  26. HTML_QuickForm::registerRule('mimetype', 'callback', '_ruleCheckMimeType', 'HTML_QuickForm_file');
  27. HTML_QuickForm::registerRule('filename', 'callback', '_ruleCheckFileName', 'HTML_QuickForm_file');
  28. }
  29. /**
  30. * HTML class for a file type element
  31. *
  32. * @author Adam Daniel <adaniel1@eesus.jnj.com>
  33. * @author Bertrand Mansion <bmansion@mamasam.com>
  34. * @version 1.0
  35. * @since PHP4.04pl1
  36. * @access public
  37. */
  38. class HTML_QuickForm_file extends HTML_QuickForm_input
  39. {
  40. // {{{ properties
  41. /**
  42. * Uploaded file data, from $_FILES
  43. * @var array
  44. */
  45. var $_value = null;
  46. // }}}
  47. // {{{ constructor
  48. /**
  49. * Class constructor
  50. *
  51. * @param string Input field name attribute
  52. * @param string Input field label
  53. * @param mixed (optional)Either a typical HTML attribute string
  54. * or an associative array
  55. * @since 1.0
  56. * @access public
  57. */
  58. function HTML_QuickForm_file($elementName=null, $elementLabel=null, $attributes=null)
  59. {
  60. HTML_QuickForm_input::HTML_QuickForm_input($elementName, $elementLabel, $attributes);
  61. $this->setType('file');
  62. } //end constructor
  63. // }}}
  64. // {{{ setSize()
  65. /**
  66. * Sets size of file element
  67. *
  68. * @param int Size of file element
  69. * @since 1.0
  70. * @access public
  71. */
  72. function setSize($size)
  73. {
  74. $this->updateAttributes(array('size' => $size));
  75. } //end func setSize
  76. // }}}
  77. // {{{ getSize()
  78. /**
  79. * Returns size of file element
  80. *
  81. * @since 1.0
  82. * @access public
  83. * @return int
  84. */
  85. function getSize()
  86. {
  87. return $this->getAttribute('size');
  88. } //end func getSize
  89. // }}}
  90. // {{{ freeze()
  91. /**
  92. * Freeze the element so that only its value is returned
  93. *
  94. * @access public
  95. * @return bool
  96. */
  97. function freeze()
  98. {
  99. return false;
  100. } //end func freeze
  101. // }}}
  102. // {{{ setValue()
  103. /**
  104. * Sets value for file element.
  105. *
  106. * Actually this does nothing. The function is defined here to override
  107. * HTML_Quickform_input's behaviour of setting the 'value' attribute. As
  108. * no sane user-agent uses <input type="file">'s value for anything
  109. * (because of security implications) we implement file's value as a
  110. * read-only property with a special meaning.
  111. *
  112. * @param mixed Value for file element
  113. * @since 3.0
  114. * @access public
  115. */
  116. function setValue($value)
  117. {
  118. return null;
  119. } //end func setValue
  120. // }}}
  121. // {{{ getValue()
  122. /**
  123. * Returns information about the uploaded file
  124. *
  125. * @since 3.0
  126. * @access public
  127. * @return array
  128. */
  129. function getValue()
  130. {
  131. return $this->_value;
  132. } // end func getValue
  133. // }}}
  134. // {{{ onQuickFormEvent()
  135. /**
  136. * Called by HTML_QuickForm whenever form event is made on this element
  137. *
  138. * @param string Name of event
  139. * @param mixed event arguments
  140. * @param object calling object
  141. * @since 1.0
  142. * @access public
  143. * @return bool
  144. */
  145. function onQuickFormEvent($event, $arg, &$caller)
  146. {
  147. switch ($event) {
  148. case 'updateValue':
  149. if ($caller->getAttribute('method') == 'get') {
  150. return PEAR::raiseError('Cannot add a file upload field to a GET method form');
  151. }
  152. $this->_value = $this->_findValue();
  153. $caller->updateAttributes(array('enctype' => 'multipart/form-data'));
  154. $caller->setMaxFileSize();
  155. break;
  156. case 'addElement':
  157. $this->onQuickFormEvent('createElement', $arg, $caller);
  158. return $this->onQuickFormEvent('updateValue', null, $caller);
  159. break;
  160. case 'createElement':
  161. $className = get_class($this);
  162. $this->$className($arg[0], $arg[1], $arg[2]);
  163. break;
  164. }
  165. return true;
  166. } // end func onQuickFormEvent
  167. // }}}
  168. // {{{ moveUploadedFile()
  169. /**
  170. * Moves an uploaded file into the destination
  171. *
  172. * @param string Destination directory path
  173. * @param string New file name
  174. * @access public
  175. * @return bool Whether the file was moved successfully
  176. */
  177. function moveUploadedFile($dest, $fileName = '')
  178. {
  179. if ($dest != '' && substr($dest, -1) != '/') {
  180. $dest .= '/';
  181. }
  182. $fileName = ($fileName != '') ? $fileName : basename($this->_value['name']);
  183. return move_uploaded_file($this->_value['tmp_name'], $dest . $fileName);
  184. } // end func moveUploadedFile
  185. // }}}
  186. // {{{ isUploadedFile()
  187. /**
  188. * Checks if the element contains an uploaded file
  189. *
  190. * @access public
  191. * @return bool true if file has been uploaded, false otherwise
  192. */
  193. function isUploadedFile()
  194. {
  195. return $this->_ruleIsUploadedFile($this->_value);
  196. } // end func isUploadedFile
  197. // }}}
  198. // {{{ _ruleIsUploadedFile()
  199. /**
  200. * Checks if the given element contains an uploaded file
  201. *
  202. * @param array Uploaded file info (from $_FILES)
  203. * @access private
  204. * @return bool true if file has been uploaded, false otherwise
  205. */
  206. function _ruleIsUploadedFile($elementValue)
  207. {
  208. if ((isset($elementValue['error']) && $elementValue['error'] == 0) ||
  209. (!empty($elementValue['tmp_name']) && $elementValue['tmp_name'] != 'none')) {
  210. return is_uploaded_file($elementValue['tmp_name']);
  211. } else {
  212. return false;
  213. }
  214. } // end func _ruleIsUploadedFile
  215. // }}}
  216. // {{{ _ruleCheckMaxFileSize()
  217. /**
  218. * Checks that the file does not exceed the max file size
  219. *
  220. * @param array Uploaded file info (from $_FILES)
  221. * @param int Max file size
  222. * @access private
  223. * @return bool true if filesize is lower than maxsize, false otherwise
  224. */
  225. function _ruleCheckMaxFileSize($elementValue, $maxSize)
  226. {
  227. if (!empty($elementValue['error']) &&
  228. (UPLOAD_ERR_FORM_SIZE == $elementValue['error'] || UPLOAD_ERR_INI_SIZE == $elementValue['error'])) {
  229. return false;
  230. }
  231. if (!HTML_QuickForm_file::_ruleIsUploadedFile($elementValue)) {
  232. return true;
  233. }
  234. return ($maxSize >= @filesize($elementValue['tmp_name']));
  235. } // end func _ruleCheckMaxFileSize
  236. // }}}
  237. // {{{ _ruleCheckMimeType()
  238. /**
  239. * Checks if the given element contains an uploaded file of the right mime type
  240. *
  241. * @param array Uploaded file info (from $_FILES)
  242. * @param mixed Mime Type (can be an array of allowed types)
  243. * @access private
  244. * @return bool true if mimetype is correct, false otherwise
  245. */
  246. function _ruleCheckMimeType($elementValue, $mimeType)
  247. {
  248. if (!HTML_QuickForm_file::_ruleIsUploadedFile($elementValue)) {
  249. return true;
  250. }
  251. if (is_array($mimeType)) {
  252. return in_array($elementValue['type'], $mimeType);
  253. }
  254. return $elementValue['type'] == $mimeType;
  255. } // end func _ruleCheckMimeType
  256. // }}}
  257. // {{{ _ruleCheckFileName()
  258. /**
  259. * Checks if the given element contains an uploaded file of the filename regex
  260. *
  261. * @param array Uploaded file info (from $_FILES)
  262. * @param string Regular expression
  263. * @access private
  264. * @return bool true if name matches regex, false otherwise
  265. */
  266. function _ruleCheckFileName($elementValue, $regex)
  267. {
  268. if (!HTML_QuickForm_file::_ruleIsUploadedFile($elementValue)) {
  269. return true;
  270. }
  271. return preg_match($regex, $elementValue['name']);
  272. } // end func _ruleCheckFileName
  273. // }}}
  274. // {{{ _findValue()
  275. /**
  276. * Tries to find the element value from the values array
  277. *
  278. * Needs to be redefined here as $_FILES is populated differently from
  279. * other arrays when element name is of the form foo[bar]
  280. *
  281. * @access private
  282. * @return mixed
  283. */
  284. function _findValue()
  285. {
  286. if (empty($_FILES)) {
  287. return null;
  288. }
  289. $elementName = $this->getName();
  290. if (isset($_FILES[$elementName])) {
  291. return $_FILES[$elementName];
  292. } elseif (false !== ($pos = strpos($elementName, '['))) {
  293. $base = str_replace(
  294. array('\\', '\''), array('\\\\', '\\\''),
  295. substr($elementName, 0, $pos)
  296. );
  297. $idx = "['" . str_replace(
  298. array('\\', '\'', ']', '['), array('\\\\', '\\\'', '', "']['"),
  299. substr($elementName, $pos + 1, -1)
  300. ) . "']";
  301. $props = array('name', 'type', 'size', 'tmp_name', 'error');
  302. $code = "if (!isset(\$_FILES['{$base}']['name']{$idx})) {\n" .
  303. " return null;\n" .
  304. "} else {\n" .
  305. " \$value = array();\n";
  306. foreach ($props as $prop) {
  307. $code .= " \$value['{$prop}'] = \$_FILES['{$base}']['{$prop}']{$idx};\n";
  308. }
  309. return eval($code . " return \$value;\n}\n");
  310. } else {
  311. return null;
  312. }
  313. }
  314. // }}}
  315. } // end class HTML_QuickForm_file
  316. ?>