$maxSize) throw new Exception("Taille du fichier trop grande, taille maximum :".readable_size($maxSize).' ('.$maxSize.' octets)'); if(is_array($extensions) && !in_array($extension , $extensions)) throw new Exception("Extension '".$extension."' du fichier non permise, autorisé :".implode(', ',$extensions)); $filePath = str_replace(array('/','\\','{{ext}}'),array(SLASH,SLASH,$extension),$path); $fileName = basename($filePath); $folderPath = dirname($filePath); $folderAbsolutePath = self::dir().$folderPath; $fileAbsolutePath = $folderAbsolutePath.SLASH.$fileName; if(!file_exists($folderAbsolutePath)) mkdir($folderAbsolutePath,0755,true); if(!move_uploaded_file($_FILES[$index]['tmp_name'], $fileAbsolutePath)) throw new Exception("Impossible de déplacer le fichier envoyé"); return array( 'absolute' => $fileAbsolutePath, 'relative' => $filePath, 'name' => $fileName ); } //récupere le type mime du fichier public static function mime($path){ $infos = new finfo(); $mime = $infos->file($path, FILEINFO_MIME_TYPE); if($mime == 'text/x-asm') $mime = 'text/css'; return $mime; } public static function move($file,$path,$trimParentDir = true){ if($trimParentDir){ $file = str_replace('..','',$file); $path = str_replace('..','',$path); } $extension = getExt($path); $filePath = str_replace(array('/','\\','{{ext}}'),array(SLASH,SLASH,$extension),$path); $fileName = basename($filePath); $folderPath = dirname($filePath); $folderAbsolutePath = self::dir().$folderPath; $fileAbsolutePath = $folderAbsolutePath.SLASH.$fileName; if(!file_exists($folderAbsolutePath)) mkdir($folderAbsolutePath,0755,true); if(!file_exists($file)) throw new Exception("Le fichier ".$file." n'existe pas",404); if(!rename($file, $fileAbsolutePath)) throw new Exception("Impossible de déplacer le fichier envoyé"); return array( 'absolute' => (get_OS() === 'WIN' ? iconv('UTF-8', 'UTF-8//IGNORE', utf8_encode($fileAbsolutePath)) : $fileAbsolutePath), 'relative' => (get_OS() === 'WIN' ? iconv('UTF-8', 'UTF-8//IGNORE', utf8_encode($filePath)) : $filePath), 'name' => (get_OS() === 'WIN' ? iconv('UTF-8', 'UTF-8//IGNORE', utf8_encode($fileName)) : $fileName) ); } public static function delete($namespace,$file,$trimParentDir = true,$ignoreExistence = false){ if($trimParentDir) $file = str_replace('..','',$file); $namespace = trim($namespace, SLASH); $file = $namespace.SLASH.substr($file, strlen($namespace)+1); $file = File::dir().$file; $file = str_replace(array('\\','/'),array(SLASH,SLASH),$file); if(!file_exists($file)){ if($ignoreExistence){ return; }else{ throw new Exception("Le fichier '".$file."' n'existe pas"); } } if(is_file($file)){ unlink($file); }else{ delete_folder_tree($file, true); } } public static function downloadFile($path,$name=null,$mime = null,$forceDownload = null,$trimParentDir = true,$cache = true){ if($trimParentDir) $path = str_replace('..','',$path); $hasFile = glob($path); if(count($hasFile)==0) throw new Exception("Fichier inexistant :".$path); $path = $hasFile[0]; $stream = file_get_contents($path); $mime = !isset($mime) ? self::mime($path) : $mime; if(!isset($name)){ $name = (get_OS() === 'WIN') ? utf8_encode(basename($path)) : basename($path); } if (ob_get_contents()) ob_end_clean(); header("Content-Type: ".$mime); header("Content-Length: " . strlen($stream)); header("Content-Disposition: ".($forceDownload?"attachment":"inline")."; filename=\"".utf8_decode($name)."\""); if($cache){ header('Expires: Sun, 24 Jan 1988 00:00:00 GMT'); header('Cache-Control: no-store, no-cache, must-revalidate'); header('Cache-Control: post-check=0, pre-check=0', FALSE); header('Pragma: no-cache'); header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); } echo $stream; } public static function downloadStream($stream, $name='Sans titre', $mime='application/octet-stream'){ if (ob_get_contents()) ob_end_clean(); header("Content-Type: ".$mime); header("Content-Length: " . strlen($stream)); header('Expires: Sun, 01 Jan 2014 00:00:00 GMT'); header('Cache-Control: no-store, no-cache, must-revalidate'); header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); header('Cache-Control: post-check=0, pre-check=0', FALSE); header('Pragma: no-cache'); header("Content-Disposition: attachment; filename=\"".$name."\""); echo $stream; } public static function dir(){ return __ROOT__.FILE_PATH; } //Return core folder's path public static function core(){ return self::dir().'core'; } public static function temp(){ $path = self::dir().SLASH.'tmp'.SLASH; if(!file_exists($path)) mkdir($path,0755,true); return $path; } public static function clear_temp(){ $time = time(); foreach(glob(self::temp().'*.*') as $file){ if($time - filemtime($file) <= 3600) return; !is_dir($file) ? unlink($file) : delete_folder_tree($file, true); } } public static function copy($source,$destination,$trimParentDir = true){ if($trimParentDir) $source = str_replace('..','',$source); if($trimParentDir) $destination = str_replace('..','',$destination); $result = true; if(is_file($source)) return copy($source,$destination); $dir = opendir($source); if(!file_exists($destination)) mkdir($destination,0755,true); while(false !== ( $file = readdir($dir)) ) { if (( $file != '.' ) && ( $file != '..' )) { if ( is_dir($source . SLASH . $file) ) { $result = self::copy($source.SLASH.$file,$destination.SLASH.$file); } else { $copyResult = copy($source.SLASH.$file,$destination.SLASH.$file); if(!$copyResult) $result = false; } } } closedir($dir); return $result; } //Fusionne deux repertoires //N'ecrase rien : Si deux fichiers sont identiques, ajoute un (2...) a la fin d'un des deux fichiers //originalDirectory -> Destination //toMerge -> Source (celui qui se fait delete) public static function merge($originalDirectory,$toMergeDirectory, $delete = true){ if(!file_exists($toMergeDirectory)) return; foreach(glob($toMergeDirectory.SLASH.'*') as $element){ if(is_file($element)){ $name = explode('.',basename($element)); $ext = strtolower(array_pop($name)); $name = $name[0]; $destination = $originalDirectory.SLASH.$name.'.'.$ext; $increment = 1; while(file_exists($destination)){ $increment++; $destination = $originalDirectory.SLASH.$name.'('.$increment.').'.$ext; } copy($element, $destination); }else{ $name = basename($element); $destination = $originalDirectory.SLASH.$name; if(!file_exists($destination)) mkdir($destination,0755,true); self::merge($destination,$element,$delete); } } if ($delete) delete_folder_tree($toMergeDirectory, true); } //retourne un tableau avec les meta infos déduits du fichier public static function toArray($path,$label=null){ $label = isset($label) ? $label : basename($path); $extension = getExt($label); $size = filesize($path); return array( 'path' => str_replace(self::dir(),'',$path), 'label' => $label, 'extension' => $extension, 'readableSize' => readable_size($size), 'size' => $size, 'icon' => getExtIcon($extension) ); } public static function save_component($index,$destination){ global $_; if(!isset($_[$index])) return; $destinationTpl = str_replace('/',SLASH,$destination); $saveds = array(); foreach($_[$index] as $file){ $destination = template($destinationTpl,$file,true); $file = self::dir().$file['path']; if(file_exists($file)) self::move($file,$destination); $saveds[] = array( 'absolute' => self::dir().$destination, 'relative' => $destination, 'name' => basename($destination) ); } return $saveds; } public static function handle_component($options,&$response){ global $myUser,$_; $options = array_merge(array( 'action' => $_['action'], 'extension' => 'jpg,png,svg,bmp,gif,jpeg,doc,xls,ppt,docx,xlsx,pptx,pdf,msg,eml', 'size' => 2000000, 'limit' => 0 ),$options); switch($_['type']){ case 'search': User::check_access($options['access'],'read'); $response['options'] = array( 'extension' => $options['extension'], 'size' => $options['size'], ); $response['files'] = array(); $storage = str_replace('/',SLASH,$options['storage']); $storage = self::dir().template($storage,$_,true); //si l'url contient // on considere qu'il lui manque des élements de masque et on annule le browse //utile quand l'action est appellée alors qu'un parametre manque (ex: id de l'entité liée au fichier) if(strpos($storage, '//') === false){ foreach(glob($storage, GLOB_BRACE) as $i=>$file){ if(!is_file($file)) continue; $fileArray = self::toArray($file); $fileArray['url'] = 'action.php?action='.$options['action'].'&type=download&name='.urlencode($fileArray['label']).'&path='.base64_encode($fileArray['path']); if( in_array($fileArray['extension'], array('png','gif','jpg','jpeg','bmp')) ) $fileArray['preview'] = $fileArray['url']; $response['files'][] = $fileArray; } } break; case 'download': User::check_access($options['access'],'read'); $name = isset($_['name']) ? $_['name'] : null; $path = self::dir().base64_decode($_['path']); try{ self::downloadFile($path,$name); }catch(Exception $e){ self::downloadFile(__ROOT__.SLASH.'img'.SLASH.'image-not-found.jpg',$name); } break; case 'delete': User::check_access($options['access'],'delete'); if(!isset($_['path']) ) throw new Exception("Chemin non spécifié"); $namespace = $options['namespace']; if(strlen($_['path'])>5 && substr($_['path'],0,5) == '/tmp/' ) $namespace = 'tmp'; self::delete($namespace,$_['path']); break; case 'upload': User::check_access($options['access'],'edit'); try{ self::clear_temp(); $file = $_FILES[$_['index']]; $tempPath = self::temp().basename($file['tmp_name']); move_uploaded_file($file['tmp_name'], $tempPath); $response = self::toArray($tempPath,$file['name']); $response['url'] = 'action.php?action='.$options['action'].'&type=download&name='.urlencode($response['label']).'&path='.base64_encode($response['path']); $response['sort'] = $_['sort']; if( in_array($response['extension'], array('png','gif','jpg','jpeg','bmp')) ) $response['preview'] = $response['url']; }catch(Exception $e){ $response['error'] = $e->getMessage(); } break; } return $response; } public static function convert_encoding($path){ return get_OS() === 'WIN' ? utf8_encode($path) : $path; } public static function convert_decoding($path){ return get_OS() === 'WIN' ? utf8_decode($path) : $path; } } ?>