PageRenderTime 28ms CodeModel.GetById 48ms RepoModel.GetById 0ms app.codeStats 0ms

/system/classes/QuarkUpload.php

https://github.com/sahibalejandro/Quark-PHP-Framework
PHP | 294 lines | 125 code | 28 blank | 141 comment | 20 complexity | 06973edbd13111b5d984d81091ffe41a MD5 | raw file
  1. <?php
  2. /**
  3. * QuarkPHP Framework
  4. * Copyright 2012-2013 Sahib Alejandro Jaramillo Leo
  5. *
  6. * @author Sahib J. Leo <sahib.alejandro@gmail.com>
  7. * @license GNU General Public License (http://www.gnu.org/licenses/gpl.html)
  8. * @link http://quarkphp.com
  9. */
  10. /**
  11. * Clase para manejar las tareas con upload
  12. * @author Sahib J. Leo <sahib.alejandro@gmail.com>
  13. */
  14. class QuarkUpload
  15. {
  16. /**
  17. * Permisos que se aplicarán a los archivos despues
  18. * de ser copiados al directorio destino.
  19. *
  20. * @var octal
  21. */
  22. private $_chmod = 0666;
  23. /**
  24. * Flag especificar si se van a ignorar los input files vacios o no.
  25. * por default son ignorados (true)
  26. *
  27. * @see QuarkUpload::setIgnoreEmpty()
  28. * @var bool
  29. */
  30. private $_ignore_empty = true;
  31. /**
  32. * Flag para especificar si se sobre escriben los archivos en el
  33. * directorio destnio, por default se sobre escriben (true)
  34. *
  35. * @see QuarkUpload::setOverwrite()
  36. * @var bool
  37. */
  38. private $_overwrite = true;
  39. /**
  40. * Flag para especificar si se van a utilizar las funciones finfo_*
  41. * para obtener el mime type del archivo, solo valido para PHP 5.3 o PECL finfo.
  42. * El valor de este flag es establecido internamente.
  43. *
  44. * @var bool
  45. */
  46. private $_use_finfo;
  47. /**
  48. * Lista de extensiones validas para los archivos enviados, solo serán
  49. * utilizadas si no se ha definido ningun mime type con QuarkUpload::setValidMimeTypes()
  50. *
  51. * @see QuarkUpload::setValidExtensions()
  52. * @var array
  53. */
  54. private $_valid_extensions = array();
  55. /**
  56. * Lista de mime types validos para los archivos enviados,
  57. * si es definido algun mime type se ignoraran las listas
  58. * de extensiones definidas con QuarkUpload::setValidExtensions()
  59. *
  60. * @see QuarkUpload::setValidMimeTypes()
  61. * @var array
  62. */
  63. private $_valid_mime_types = array();
  64. /**
  65. * Constructor
  66. * @return QuarkUpload
  67. */
  68. public function __construct()
  69. {
  70. $this->_use_finfo = function_exists('finfo_open');
  71. }
  72. /**
  73. * Define la lista de mime types validos para los archivos enviados
  74. * Si los mime types son definidos, se ignorarán las extensiones
  75. * defindas con QuarkUpload::setValidExtensions()
  76. *
  77. * @see QuarkUpload::setValidExtensions()
  78. */
  79. public function setValidMimeTypes()
  80. {
  81. $args = func_get_args();
  82. $this->_valid_mime_types = $args;
  83. }
  84. /**
  85. * Define la lista de extensiones validas para los archivos enviados
  86. * Si los mime types son definidos con QuarkUpload::setValidMimeTypes()
  87. * se ignorarán las extensiones.
  88. *
  89. * @see QuarkUpload::setValidMimeTypes()
  90. */
  91. public function setValidExtensions()
  92. {
  93. $args = func_get_args();
  94. $this->_valid_extensions = array_map('strtolower', $args);
  95. }
  96. /**
  97. * Establece si se va a ignorar los input files vacios o no
  98. * @param bool $ignore
  99. */
  100. public function setIgnoreEmpty($ignore)
  101. {
  102. $this->_ignore_empty = $ignore;
  103. }
  104. /**
  105. * Establece si se va a sobre escribir los archivos existentes en el directorio destino
  106. * @param bool $overwrite
  107. */
  108. public function setOverwrite($overwrite)
  109. {
  110. $this->_overwrite = $overwrite;
  111. }
  112. /**
  113. * Establece el valor para los permisos que se aplicaran a los archivos
  114. * movidos al directorio destino.
  115. *
  116. * @param octal $chmod
  117. */
  118. public function setChmod($chmod)
  119. {
  120. $this->_chmod = $chmod;
  121. }
  122. /**
  123. * Mueve los archivos enviados por POST con el nombre $input_file_name
  124. * al directorio destino $upload_path.
  125. * Devuelve un resultado de copiado para single upload o un array de resultados un upload multiple.
  126. *
  127. * @see QuarkUpload::setChmod()
  128. * @see QuarkUpload::setIgnoreEmpty()
  129. * @see QuarkUpload::setOverwrite()
  130. * @see QuarkUpload::setValidExtensions()
  131. * @see QuarkUpload::setValidMimeTypes()
  132. *
  133. * @param string $input_file_name
  134. * @param string $upload_path
  135. * @return object|array(object)
  136. */
  137. public function moveUploads($input_file_name, $upload_path)
  138. {
  139. /* Acceso directo! */
  140. $F = &$_FILES[$input_file_name];
  141. if (!is_array($F['tmp_name'])) {
  142. return $this->_moveUploadedFile($F, $upload_path);
  143. } else {
  144. $results = array();
  145. foreach ( $F['tmp_name'] as $i => $tmp_name ) {
  146. $results[] = $this->_moveUploadedFile(array(
  147. 'name' => $F['name'][$i],
  148. 'type' => $F['type'][$i],
  149. 'size' => $F['size'][$i],
  150. 'error' => $F['error'][$i],
  151. 'tmp_name' => $F['tmp_name'][$i]
  152. ), $upload_path);
  153. }
  154. return $results;
  155. }
  156. }
  157. /**
  158. * Mueve un archivo definido por $file_info (al estilo $_FILES) al
  159. * directorio $upload_path
  160. * Devuelve un objeto resultado que tiene las propiedades:
  161. * error: Si ocurrio algun error al copiar el archivo, de lo contrario false.
  162. * empty: Si el input file esta vacio y el flag QuarkUpload::_ignore_empty
  163. * es true.
  164. * file_name: Nombre del archivo enviado.
  165. * final_file_name: Nombre del archivo copiado.
  166. *
  167. * @param array $file_info
  168. * @param string $upload_path
  169. * @return object
  170. */
  171. private function _moveUploadedFile($file_info, $upload_path)
  172. {
  173. $Result = (object)array(
  174. 'error' => false,
  175. 'empty' => false,
  176. 'file_name' => $file_info['name'],
  177. 'final_file_name' => $file_info['name']
  178. );
  179. /*
  180. * Verificar errores de upload
  181. */
  182. if ($file_info['error'] != UPLOAD_ERR_OK) {
  183. switch ($file_info['error']) {
  184. case UPLOAD_ERR_INI_SIZE:
  185. $Result->error = 'El archivo excede el tamaño máximo.';
  186. break;
  187. case UPLOAD_ERR_NO_FILE:
  188. if ($this->_ignore_empty) {
  189. $Result->empty = true;
  190. } else {
  191. $Result->error = 'No se envió ningún archivo.';
  192. }
  193. break;
  194. default :
  195. $Result->error = 'Error al enviar el archivo.';
  196. break;
  197. }
  198. }
  199. /*
  200. * Si ocurrio algun error o esta vacio, terminamos.
  201. */
  202. if ($Result->error || $Result->empty) {
  203. return $Result;
  204. }
  205. if (!empty($this->_valid_mime_types)) {
  206. /*
  207. * Validar el mime type del archivo contra los definidos
  208. * por el usuario utilizando QuarkUpload::setMimeTypes()
  209. */
  210. if (!$this->_use_finfo) {
  211. $mime_type = mime_content_type($file_info['tmp_name']);
  212. } else {
  213. $finfo_handler = finfo_open(FILEINFO_MIME_TYPE);
  214. $mime_type = finfo_file($finfo_handler, $file_info['tmp_name']);
  215. finfo_close($finfo_handler);
  216. }
  217. if (false === array_search($mime_type, $this->_valid_mime_types)) {
  218. $Result->error = 'Tipo de archivo inválido.';
  219. }
  220. } elseif (!empty($this->_valid_extensions)) {
  221. /*
  222. * Validar extension del archivo contra las definidas por
  223. * el usuario con QuarkUpload::setValidExtensions()
  224. */
  225. $file_ext = strtolower(pathinfo($Result->file_name, PATHINFO_EXTENSION));
  226. if (false === array_search($file_ext, $this->_valid_extensions)) {
  227. $Result->error = 'Extension de archivo inválida.';
  228. }
  229. }
  230. /*
  231. * Si ocurrio algun error terminamos el metodo.
  232. */
  233. if ($Result->error != false) {
  234. return $Result;
  235. }
  236. /*
  237. * Continua si no hay errores...
  238. */
  239. if (!$this->_overwrite) {
  240. /* Buscar un nombre de archivo disponible */
  241. $file_name_parts = explode('.', $Result->file_name);
  242. $file_ext = array_pop($file_name_parts);
  243. $safe_file_name_tmp = $safe_file_name = implode('.', $file_name_parts);
  244. unset($file_name_parts);
  245. $file_counter = 0;
  246. while ( is_file($upload_path . '/' . $safe_file_name_tmp . '.' . $file_ext) ) {
  247. $safe_file_name_tmp = $safe_file_name . '[' . (++$file_counter) . ']';
  248. }
  249. /* Este es el nombre de archivo disponible */
  250. $Result->final_file_name = $safe_file_name_tmp . '.' . $file_ext;
  251. } /* if (!$this->_overwrite) */
  252. /*
  253. * Mover archivo al directorio final
  254. */
  255. if (@move_uploaded_file(
  256. $file_info['tmp_name'],
  257. $upload_path . '/' . $Result->final_file_name
  258. )
  259. ) {
  260. @chmod($upload_path . '/' . $Result->final_file_name, $this->_chmod);
  261. } else {
  262. $Result->error = 'No se pudo copiar el archivo al directorio destino, verifique los permisos.';
  263. }
  264. return $Result;
  265. }
  266. }