PageRenderTime 26ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/mod/rafl/includes/common/lib/file_upload/KT_FileUpload.class.php

https://github.com/nadavkav/MoodleTAO
PHP | 464 lines | 299 code | 12 blank | 153 comment | 36 complexity | 395e4d33a8f3389e63b3035b8964da23 MD5 | raw file
  1. <?php
  2. /*
  3. Copyright (c) InterAKT Online 2000-2005
  4. */
  5. /**
  6. * Provides functionalities for handling file uploads
  7. * @access public
  8. **/
  9. class KT_fileUpload
  10. {
  11. /**
  12. * the file upload information
  13. * @var string tNG_dispatcher
  14. * @access public
  15. */
  16. var $fileInfo;
  17. /**
  18. * @var boolean
  19. * @access public
  20. */
  21. var $fileExists;
  22. /**
  23. * destination folder for upload
  24. * @var string
  25. * @access public
  26. */
  27. var $folder;
  28. /**
  29. * specifies if the file is required for upload or not
  30. * @var bollean
  31. * @access public
  32. */
  33. var $isRequired;
  34. /**
  35. * the allowed types for upload
  36. * @var array tNG_dispatcher
  37. * @access public
  38. */
  39. var $allowedExtensions;
  40. /**
  41. * @var boolean
  42. * @access public
  43. */
  44. var $autoRename;
  45. /**
  46. * minimum allowed size of the uploaded file in KB;
  47. * @var integer
  48. * @access public
  49. */
  50. var $minSize;
  51. /**
  52. * maximum allowed size of the uploaded file in KB;
  53. * @var integer
  54. * @access public
  55. */
  56. var $maxSize;
  57. /**
  58. * Specifies the old file name that is allowed to be overwritten in case that its name is the same as the file to be uploaded (fileName)
  59. * @var string
  60. * @access public
  61. */
  62. var $oldFileName;
  63. /**
  64. * the name under which the file was saved after upload
  65. * @var string tNG_dispatcher
  66. * @access public
  67. */
  68. var $destinationName;
  69. /**
  70. * error message to be displayed as User Error
  71. * @var array
  72. * @access public
  73. */
  74. var $errorType = array();
  75. /**
  76. * error message to be displayed as Developer Error
  77. * @var array
  78. * @access public
  79. */
  80. var $develErrorMessage = array();
  81. /**
  82. * Constructor.
  83. * sets initialise some class members;
  84. * @access public
  85. */
  86. function KT_fileUpload()
  87. {
  88. $this->folder = '';
  89. $this->isRequired = false;
  90. $this->allowedExtensions = array();
  91. $this->autoRename = false;
  92. $this->minSize= 1;
  93. $this->maxSize=-1;
  94. $this->error = 0;
  95. $this->errorType = array();
  96. $this->develErrorMessage = array();
  97. }
  98. /**
  99. * setter. set the fileinfo array
  100. * @param string $fileInfo the name of the form field;
  101. * @return nothing;
  102. * @access public
  103. */
  104. function setFileInfo($fileInfo)
  105. {
  106. if (isset($_FILES[$fileInfo])) {
  107. $this->fileInfo = $_FILES[$fileInfo];
  108. } else {
  109. $this->setError('PHP_UPLOAD_NO_UPLOAD', array(), array($fileInfo));
  110. if (count($_POST) == 0) {
  111. $this->setError('PHP_UPLOAD_NO_POST', array(), array());
  112. }
  113. $file_uploads = @ini_get('file_uploads');
  114. if (strlen(trim($file_uploads)) == 0) {
  115. $this->setError('PHP_UPLOAD_UPLOAD_DISABLED', array(), array());
  116. }
  117. }
  118. }
  119. /**
  120. * setter. set the destination folder
  121. * @param string $folder the name of the folder;
  122. * @return nothing;
  123. * @access public
  124. */
  125. function setFolder($folder)
  126. {
  127. $this->folder = $folder;
  128. if (strtolower(substr(PHP_OS, 0, 1))=='w') {
  129. $this->folder = str_replace('/', '\\', $this->folder);
  130. } else {
  131. $this->folder = str_replace('\\', '/', $this->folder);
  132. }
  133. }
  134. /**
  135. * setter.
  136. * @param boolean $isRequired the name of the form field;
  137. * @return nothing;
  138. * @access public
  139. */
  140. function setRequired($isRequired)
  141. {
  142. $this->isRequired = $isRequired;
  143. }
  144. /**
  145. * setter. set the allowed extendions
  146. * @param array ;
  147. * @return nothing;
  148. * @access public
  149. */
  150. function setAllowedExtensions($allowedExtensions)
  151. {
  152. $this->allowedExtensions = $allowedExtensions;
  153. }
  154. /**
  155. * setter.
  156. * @param boolean ;
  157. * @return nothing;
  158. * @access public
  159. */
  160. function setAutoRename($autoRename)
  161. {
  162. $this->autoRename = $autoRename;
  163. }
  164. /**
  165. * setter.
  166. * @param integer the minimum size of the files in KB;
  167. * @return nothing;
  168. * @access public
  169. */
  170. function setMinSize($minSize)
  171. {
  172. $this->minSize = $minSize;
  173. }
  174. /**
  175. * setter.
  176. * @param integer the maximum size of the file in KB;
  177. * @return nothing;
  178. * @access public
  179. */
  180. function setMaxSize($maxSize)
  181. {
  182. $this->maxSize = $maxSize;
  183. }
  184. /**
  185. * Handle the uploaded file by moving it to a destination file.
  186. * The destination file = folder + fileName
  187. * @param string fileName the name for saving the uploaded file;
  188. * @param string $oldFileName the previous file name, or null on insert
  189. * @return string file name if succeded or null if not;
  190. * @access public
  191. */
  192. function uploadFile($fileName, $oldFileName="")
  193. {
  194. if ($this->hasError()) {
  195. return;
  196. }
  197. $this->checkUpload();
  198. $this->checkFolder();
  199. $this->checkSize();
  200. $this->checkExtensions();
  201. $this->checkFileName($fileName);
  202. if ($this->hasError()) {
  203. return;
  204. }
  205. if ($this->fileExists) {
  206. $folder = KT_realpath($this->folder);
  207. $fileName = KT_replaceSpecialChars($fileName, 'filter');
  208. $destinationName = KT_realpath($folder . $fileName, false);
  209. if (file_exists($destinationName)) {
  210. if (strtolower($fileName) != strtolower($oldFileName)) {
  211. // if the destination file really exists
  212. if (!$this->autoRename) {
  213. $this->setError('UPLOAD_FILE_EXISTS', array(), array($fileName));
  214. return;
  215. } else {
  216. $destinationName = $this->getTempName($destinationName);
  217. }
  218. }
  219. }
  220. if ($oldFileName!='') {
  221. @unlink($folder . DIRECTORY_SEPARATOR . $oldFileName);
  222. }
  223. if (!@move_uploaded_file($this->fileInfo['tmp_name'], $destinationName)) {
  224. unlink($this->fileInfo['tmp_name']);
  225. $this->setError('PHP_UPLOAD_MOVE_TMP_ERROR', array(), array());
  226. return;
  227. } else {
  228. $arr = split("[\\/]", $destinationName);
  229. $this->destinationName = $destinationName;
  230. KT_setFilePermissions($this->destinationName);
  231. return array_pop($arr);
  232. }
  233. }
  234. }
  235. /**
  236. * Gets a temporary file name starting from the given file name.
  237. * Ex: filename = 'zone.jpg', and zone_1.jpg alreagy exists, the new file name is zone_2.jpg.
  238. * @param string $filename the filename on which to create the new temporary file name.
  239. * @return string the temporary file name;
  240. * @access public
  241. */
  242. function getTempName($filename) {
  243. $pos = strrpos($filename,'.');
  244. if ($pos !== false) {
  245. $tmpName = substr($filename,0,$pos);
  246. $tmpExt = substr($filename, $pos);
  247. } else {
  248. $tmpName = $filename;
  249. $tmpExt = '';
  250. }
  251. $i=1;
  252. while (file_exists($tmpName.'_'.$i.$tmpExt) && $i < 1000) {
  253. $i++;
  254. }
  255. $retVar = $tmpName.'_'.$i.$tmpExt;
  256. return $retVar;
  257. }
  258. /**
  259. * Check if the uploaded folder exists and has write permissions.
  260. * If the folder does not exists, try to create it.
  261. * If the folder does not have write permissions or if could not create it, set error.
  262. * @return nothing;
  263. * @access public
  264. */
  265. function checkFolder() {
  266. if ($this->fileExists) {
  267. $folder = new KT_folder();
  268. $folder->createFolder($this->folder);
  269. $right = $folder->checkRights($this->folder, 'write');
  270. if ($folder->hasError()) {
  271. $arr = $folder->getError();
  272. $this->setError('PHP_UPLOAD_FOLDER_ERROR', array($arr[0]), array($arr[1]));
  273. }
  274. if ($right !== true) {
  275. $this->setError('PHP_UPLOAD_CHECK_FOLDER_ERROR', array(), array($this->folder));
  276. }
  277. }
  278. }
  279. /**
  280. * Checks the size of the uploaded folder.
  281. * The size is checked against the this.minSize and this.maxSize
  282. * @return nothing;
  283. * @access public
  284. */
  285. function checkSize() {
  286. if ($this->fileExists) {
  287. if ($this->minSize >0 && $this->fileInfo['size'] < $this->minSize) {
  288. $this->setError('UPLOAD_CHECK_SIZE_S', array($this->minSize-1), array($this->minSize-1));
  289. return;
  290. }
  291. if ($this->maxSize >0 && $this->fileInfo['size'] > $this->maxSize * 1024) {
  292. $this->setError('UPLOAD_CHECK_SIZE_G', array($this->maxSize), array($this->maxSize));
  293. return;
  294. }
  295. }
  296. }
  297. /**
  298. * Checks the type of the uploaded folder.
  299. * The name is checked against the this.allowedTypes array.
  300. * @return nothing;
  301. * @access public
  302. */
  303. function checkExtensions() {
  304. if ($this->fileExists) {
  305. $path_info = KT_pathinfo($this->fileInfo['name']);
  306. foreach ($this->allowedExtensions as $key => $extension) {
  307. if (strtolower($extension) == strtolower($path_info['extension'])) {
  308. return;
  309. }
  310. if ($extension == '*') {
  311. return ;
  312. }
  313. }
  314. $this->setError('UPLOAD_EXT_NOT_ALLOWED', array(), array($path_info['extension']));
  315. }
  316. }
  317. /**
  318. * check if a filename is valid. invalid chars: .., \, /, :, *, ?, ", <, >, |
  319. * @param string $filename the name of the form field;
  320. * @return nothing;
  321. * @access public
  322. */
  323. function checkFileName($fileName) {
  324. if ($this->fileExists) {
  325. $arrInvalid = array('..','\\','/',':','*','?','"','<','>','|');
  326. if ((string)$fileName == '') {
  327. $this->setError('PHP_UPLOAD_FILENAME_EMPTY', array(), array());
  328. return;
  329. }
  330. foreach($arrInvalid as $key => $tmp) {
  331. if (strpos($fileName,$tmp) !== false) {
  332. $this->setError('PHP_UPLOAD_FILENAME_INV', array(), array($tmp));
  333. return;
  334. }
  335. }
  336. }
  337. }
  338. /**
  339. * Checks if the upload has performed OK and if the file is required.
  340. * @return nothing;
  341. * @access public
  342. */
  343. function checkUpload() {
  344. if ($this->fileInfo['tmp_name'] == '') {
  345. $this->fileExists = false;
  346. if (isset($this->fileInfo['error']) && !is_array($this->fileInfo['error']) && $this->fileInfo['error'] >0) {
  347. switch ($this->fileInfo['error']){
  348. case 1:
  349. $this->setError('PHP_UPLOAD_ERR_INI_SIZE', array(), array());
  350. return;
  351. case 2:
  352. $this->setError('PHP_UPLOAD_ERR_FORM_SIZE', array(), array());
  353. return;
  354. case 3:
  355. $this->setError('PHP_UPLOAD_ERR_PARTIAL', array(), array());
  356. return;
  357. case 4:
  358. break;
  359. case 6:
  360. $this->setError('PHP_UPLOAD_ERR_NO_TMP_DIR', array(), array());
  361. return;
  362. case 7:
  363. $this->setError('PHP_UPLOAD_ERR_CANT_WRITE', array(), array());
  364. return;
  365. default:
  366. $this->setError('PHP_UPLOAD_ERR_UNKNOWN', array(), array($this->fileInfo['error']));
  367. return;
  368. }
  369. } else {
  370. $this->setError('PHP_UPLOAD_ERR_TMP_DIR', array(), array());
  371. }
  372. } else {
  373. $this->fileExists = true;
  374. if (isset($this->fileInfo['size']) && $this->fileInfo['size'] == 0) {
  375. $this->fileExists = false;
  376. }
  377. }
  378. if (!is_uploaded_file($this->fileInfo['tmp_name'])) {
  379. if($this->isRequired) {
  380. if ($this->fileInfo['tmp_name'] != ''){
  381. $this->setError('PHP_UPLOAD_ERR_TMP_FILE', array(), array($this->fileInfo['tmp_name']));
  382. return;
  383. } elseif ($this->fileInfo['error'] == 4) {
  384. $this->setError('PHP_UPLOAD_FILE_REQUIRED', array(), array());
  385. return;
  386. }
  387. }
  388. }
  389. }
  390. /**
  391. * Makes RollBack if transaction failed.
  392. * @return nothing;
  393. * @access public
  394. */
  395. function RollBack() {
  396. @unlink($this->destinationName);
  397. }
  398. /**
  399. * Setter. set error for developper and user.
  400. * @var string $errorCode error message code;
  401. * @var array $arrArgsUsr array with optional parameters for sprintf functions;
  402. * @var array $arrArgsDev array with optional parameters for sprintf functions.
  403. * @return nothing;
  404. * @access private
  405. */
  406. function setError($errorCode, $arrArgsUsr, $arrArgsDev)
  407. {
  408. $errorCodeDev = $errorCode;
  409. if ( !in_array($errorCodeDev, array('', '%s')) ) {
  410. $errorCodeDev .= '_D';
  411. }
  412. if ($errorCode!='') {
  413. $this->errorType[] = KT_getResource($errorCode, 'FileUpload', $arrArgsUsr);
  414. } else {
  415. $this->errorType = array();
  416. }
  417. if ($errorCodeDev!='') {
  418. $this->develErrorMessage[] = KT_getResource($errorCodeDev, 'FileUpload', $arrArgsDev);
  419. } else {
  420. $this->develErrorMessage = array();
  421. }
  422. }
  423. /**
  424. * check if an error was setted.
  425. * @return boolean true if error is set or false if not;
  426. * @access public
  427. */
  428. function hasError()
  429. {
  430. if (count($this->errorType)>0 || count($this->develErrorMessage)>0) {
  431. return 1;
  432. }
  433. return 0;
  434. }
  435. /**
  436. * Getter. return the errors setted.
  437. * @return array array - 0=>error for user, 1=>error for developer;
  438. * @access public
  439. */
  440. function getError()
  441. {
  442. return array(implode('<br />', $this->errorType), implode('<br />', $this->develErrorMessage));
  443. }
  444. }
  445. ?>