File.class.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. <?php
  2. class File{
  3. //Gère l'upload d'un fichier des vérifications au stockage dans le dossier file
  4. public static function upload($index, $path, $maxSize=1048576, $extensions=array('jpg','png','jpeg','gif','bmp'), $trimParentDir=true){
  5. if($trimParentDir) $path = str_replace('..','',$path);
  6. if(!isset($_FILES[$index])) throw new Exception("L'index fichier '".$index."' n'existe pas");
  7. if($_FILES[$index]['error'] != 0) throw new Exception("Erreur lors de l'envois du fichier : N° ".$_FILES[$index]['error']);
  8. $extension = getExt($_FILES[$index]['name']);
  9. if($_FILES[$index]['size'] > $maxSize) throw new Exception("Taille du fichier trop grande, taille maximum :".readable_size($maxSize).' ('.$maxSize.' octets)');
  10. if(is_array($extensions) && !in_array($extension , $extensions)) throw new Exception("Extension '".$extension."' du fichier non permise, autorisé :".implode(', ',$extensions));
  11. $filePath = str_replace(array('/','\\','{{ext}}'),array(SLASH,SLASH,$extension),$path);
  12. $fileName = basename($filePath);
  13. $folderPath = dirname($filePath);
  14. $folderAbsolutePath = self::dir().$folderPath;
  15. $fileAbsolutePath = $folderAbsolutePath.SLASH.$fileName;
  16. if(!file_exists($folderAbsolutePath)) mkdir($folderAbsolutePath,0755,true);
  17. if(!move_uploaded_file($_FILES[$index]['tmp_name'], $fileAbsolutePath)) throw new Exception("Impossible de déplacer le fichier envoyé");
  18. return array(
  19. 'absolute' => $fileAbsolutePath,
  20. 'relative' => $filePath,
  21. 'name' => $fileName
  22. );
  23. }
  24. //récupere le type mime du fichier
  25. public static function mime($path){
  26. $infos = new finfo();
  27. $mime = $infos->file($path, FILEINFO_MIME_TYPE);
  28. if($mime == 'text/x-asm') $mime = 'text/css';
  29. return $mime;
  30. }
  31. public static function move($file,$path,$trimParentDir = true){
  32. if($trimParentDir){
  33. $file = str_replace('..','',$file);
  34. $path = str_replace('..','',$path);
  35. }
  36. $extension = getExt($path);
  37. $filePath = str_replace(array('/','\\','{{ext}}'),array(SLASH,SLASH,$extension),$path);
  38. $fileName = basename($filePath);
  39. $folderPath = dirname($filePath);
  40. $folderAbsolutePath = self::dir().$folderPath;
  41. $fileAbsolutePath = $folderAbsolutePath.SLASH.$fileName;
  42. if(!file_exists($folderAbsolutePath)) mkdir($folderAbsolutePath,0755,true);
  43. if(!file_exists($file)) throw new Exception("Le fichier ".$file." n'existe pas",404);
  44. if(!rename($file, $fileAbsolutePath)) throw new Exception("Impossible de déplacer le fichier envoyé");
  45. return array(
  46. 'absolute' => (get_OS() === 'WIN' ? iconv('UTF-8', 'UTF-8//IGNORE', utf8_encode($fileAbsolutePath)) : $fileAbsolutePath),
  47. 'relative' => (get_OS() === 'WIN' ? iconv('UTF-8', 'UTF-8//IGNORE', utf8_encode($filePath)) : $filePath),
  48. 'name' => (get_OS() === 'WIN' ? iconv('UTF-8', 'UTF-8//IGNORE', utf8_encode($fileName)) : $fileName)
  49. );
  50. }
  51. public static function delete($namespace,$file,$trimParentDir = true,$ignoreExistence = false){
  52. if($trimParentDir) $file = str_replace('..','',$file);
  53. $namespace = trim($namespace, SLASH);
  54. $file = $namespace.SLASH.substr($file, strlen($namespace)+1);
  55. $file = File::dir().$file;
  56. $file = str_replace(array('\\','/'),array(SLASH,SLASH),$file);
  57. if(!file_exists($file)){
  58. if($ignoreExistence){
  59. return;
  60. }else{
  61. throw new Exception("Le fichier '".$file."' n'existe pas");
  62. }
  63. }
  64. if(is_file($file)){
  65. unlink($file);
  66. }else{
  67. delete_folder_tree($file, true);
  68. }
  69. }
  70. public static function downloadFile($path,$name=null,$mime = null,$forceDownload = null,$trimParentDir = true,$cache = true){
  71. if($trimParentDir) $path = str_replace('..','',$path);
  72. $hasFile = glob($path);
  73. if(count($hasFile)==0) throw new Exception("Fichier inexistant :".$path);
  74. $path = $hasFile[0];
  75. $stream = file_get_contents($path);
  76. $mime = !isset($mime) ? self::mime($path) : $mime;
  77. if(!isset($name)){
  78. $name = (get_OS() === 'WIN') ? utf8_encode(basename($path)) : basename($path);
  79. }
  80. if (ob_get_contents()) ob_end_clean();
  81. header("Content-Type: ".$mime);
  82. header("Content-Length: " . strlen($stream));
  83. header("Content-Disposition: ".($forceDownload?"attachment":"inline")."; filename=\"".utf8_decode($name)."\"");
  84. if($cache){
  85. header('Expires: Sun, 24 Jan 1988 00:00:00 GMT');
  86. header('Cache-Control: no-store, no-cache, must-revalidate');
  87. header('Cache-Control: post-check=0, pre-check=0', FALSE);
  88. header('Pragma: no-cache');
  89. header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
  90. }
  91. echo $stream;
  92. }
  93. public static function downloadStream($stream, $name='Sans titre', $mime='application/octet-stream'){
  94. if (ob_get_contents()) ob_end_clean();
  95. header("Content-Type: ".$mime);
  96. header("Content-Length: " . strlen($stream));
  97. header('Expires: Sun, 01 Jan 2014 00:00:00 GMT');
  98. header('Cache-Control: no-store, no-cache, must-revalidate');
  99. header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
  100. header('Cache-Control: post-check=0, pre-check=0', FALSE);
  101. header('Pragma: no-cache');
  102. header("Content-Disposition: attachment; filename=\"".$name."\"");
  103. echo $stream;
  104. }
  105. public static function dir(){
  106. return __ROOT__.FILE_PATH;
  107. }
  108. //Return core folder's path
  109. public static function core(){
  110. return self::dir().'core';
  111. }
  112. public static function temp(){
  113. $path = self::dir().SLASH.'tmp'.SLASH;
  114. if(!file_exists($path)) mkdir($path,0755,true);
  115. return $path;
  116. }
  117. public static function clear_temp(){
  118. $time = time();
  119. foreach(glob(self::temp().'*.*') as $file){
  120. if($time - filemtime($file) <= 3600) return;
  121. !is_dir($file) ? unlink($file) : delete_folder_tree($file, true);
  122. }
  123. }
  124. public static function copy($source,$destination,$trimParentDir = true){
  125. if($trimParentDir) $source = str_replace('..','',$source);
  126. if($trimParentDir) $destination = str_replace('..','',$destination);
  127. $result = true;
  128. if(is_file($source)) return copy($source,$destination);
  129. $dir = opendir($source);
  130. if(!file_exists($destination)) mkdir($destination,0755,true);
  131. while(false !== ( $file = readdir($dir)) ) {
  132. if (( $file != '.' ) && ( $file != '..' )) {
  133. if ( is_dir($source . SLASH . $file) ) {
  134. $result = self::copy($source.SLASH.$file,$destination.SLASH.$file);
  135. }
  136. else {
  137. $copyResult = copy($source.SLASH.$file,$destination.SLASH.$file);
  138. if(!$copyResult) $result = false;
  139. }
  140. }
  141. }
  142. closedir($dir);
  143. return $result;
  144. }
  145. //Fusionne deux repertoires
  146. //N'ecrase rien : Si deux fichiers sont identiques, ajoute un (2...) a la fin d'un des deux fichiers
  147. //originalDirectory -> Destination
  148. //toMerge -> Source (celui qui se fait delete)
  149. public static function merge($originalDirectory,$toMergeDirectory, $delete = true){
  150. if(!file_exists($toMergeDirectory)) return;
  151. foreach(glob($toMergeDirectory.SLASH.'*') as $element){
  152. if(is_file($element)){
  153. $name = explode('.',basename($element));
  154. $ext = strtolower(array_pop($name));
  155. $name = $name[0];
  156. $destination = $originalDirectory.SLASH.$name.'.'.$ext;
  157. $increment = 1;
  158. while(file_exists($destination)){
  159. $increment++;
  160. $destination = $originalDirectory.SLASH.$name.'('.$increment.').'.$ext;
  161. }
  162. copy($element, $destination);
  163. }else{
  164. $name = basename($element);
  165. $destination = $originalDirectory.SLASH.$name;
  166. if(!file_exists($destination)) mkdir($destination,0755,true);
  167. self::merge($destination,$element,$delete);
  168. }
  169. }
  170. if ($delete) delete_folder_tree($toMergeDirectory, true);
  171. }
  172. //retourne un tableau avec les meta infos déduits du fichier
  173. public static function toArray($path,$label=null){
  174. $label = isset($label) ? $label : basename($path);
  175. $extension = getExt($label);
  176. $size = filesize($path);
  177. return array(
  178. 'path' => str_replace(self::dir(),'',$path),
  179. 'label' => $label,
  180. 'extension' => $extension,
  181. 'readableSize' => readable_size($size),
  182. 'size' => $size,
  183. 'icon' => getExtIcon($extension)
  184. );
  185. }
  186. public static function save_component($index,$destination){
  187. global $_;
  188. if(!isset($_[$index])) return;
  189. $destinationTpl = str_replace('/',SLASH,$destination);
  190. $saveds = array();
  191. foreach($_[$index] as $file){
  192. $destination = template($destinationTpl,$file,true);
  193. $file = self::dir().$file['path'];
  194. if(file_exists($file))
  195. self::move($file,$destination);
  196. $saveds[] = array(
  197. 'absolute' => self::dir().$destination,
  198. 'relative' => $destination,
  199. 'name' => basename($destination)
  200. );
  201. }
  202. return $saveds;
  203. }
  204. public static function handle_component($options,&$response){
  205. global $myUser,$_;
  206. $options = array_merge(array(
  207. 'action' => $_['action'],
  208. 'extension' => 'jpg,png,svg,bmp,gif,jpeg,doc,xls,ppt,docx,xlsx,pptx,pdf,msg,eml',
  209. 'size' => 2000000,
  210. 'limit' => 0
  211. ),$options);
  212. switch($_['type']){
  213. case 'search':
  214. User::check_access($options['access'],'read');
  215. $response['options'] = array(
  216. 'extension' => $options['extension'],
  217. 'size' => $options['size'],
  218. );
  219. $response['files'] = array();
  220. $storage = str_replace('/',SLASH,$options['storage']);
  221. $storage = self::dir().template($storage,$_,true);
  222. //si l'url contient // on considere qu'il lui manque des élements de masque et on annule le browse
  223. //utile quand l'action est appellée alors qu'un parametre manque (ex: id de l'entité liée au fichier)
  224. if(strpos($storage, '//') === false){
  225. foreach(glob($storage, GLOB_BRACE) as $i=>$file){
  226. if(!is_file($file)) continue;
  227. $fileArray = self::toArray($file);
  228. $fileArray['url'] = 'action.php?action='.$options['action'].'&type=download&name='.urlencode($fileArray['label']).'&path='.base64_encode($fileArray['path']);
  229. if( in_array($fileArray['extension'], array('png','gif','jpg','jpeg','bmp')) ) $fileArray['preview'] = $fileArray['url'];
  230. $response['files'][] = $fileArray;
  231. }
  232. }
  233. break;
  234. case 'download':
  235. User::check_access($options['access'],'read');
  236. $name = isset($_['name']) ? $_['name'] : null;
  237. $path = self::dir().base64_decode($_['path']);
  238. try{
  239. self::downloadFile($path,$name);
  240. }catch(Exception $e){
  241. self::downloadFile(__ROOT__.SLASH.'img'.SLASH.'image-not-found.jpg',$name);
  242. }
  243. break;
  244. case 'delete':
  245. User::check_access($options['access'],'delete');
  246. if(!isset($_['path']) ) throw new Exception("Chemin non spécifié");
  247. $namespace = $options['namespace'];
  248. if(strlen($_['path'])>5 && substr($_['path'],0,5) == '/tmp/' ) $namespace = 'tmp';
  249. self::delete($namespace,$_['path']);
  250. break;
  251. case 'upload':
  252. User::check_access($options['access'],'edit');
  253. try{
  254. self::clear_temp();
  255. $file = $_FILES[$_['index']];
  256. $tempPath = self::temp().basename($file['tmp_name']);
  257. move_uploaded_file($file['tmp_name'], $tempPath);
  258. $response = self::toArray($tempPath,$file['name']);
  259. $response['url'] = 'action.php?action='.$options['action'].'&type=download&name='.urlencode($response['label']).'&path='.base64_encode($response['path']);
  260. $response['sort'] = $_['sort'];
  261. if( in_array($response['extension'], array('png','gif','jpg','jpeg','bmp')) ) $response['preview'] = $response['url'];
  262. }catch(Exception $e){
  263. $response['error'] = $e->getMessage();
  264. }
  265. break;
  266. }
  267. return $response;
  268. }
  269. public static function convert_encoding($path){
  270. return get_OS() === 'WIN' ? utf8_encode($path) : $path;
  271. }
  272. public static function convert_decoding($path){
  273. return get_OS() === 'WIN' ? utf8_decode($path) : $path;
  274. }
  275. }
  276. ?>