diff --git a/src/vitis/vas/rest/class/vmlib/files/Files.interface.inc b/src/vitis/vas/rest/class/vmlib/files/Files.interface.inc new file mode 100644 index 0000000000000000000000000000000000000000..070378f5e227ae2c017812444b676802bc31de1e --- /dev/null +++ b/src/vitis/vas/rest/class/vmlib/files/Files.interface.inc @@ -0,0 +1,34 @@ +<?php + +interface Files{ + // File + // PHP native functions + public function file_exists ($sFilePath); + public function file_put_contents ($sFilePath, $sData, $iFlags = 0, $mContext = null); + public function file_get_contents ($sFilePath, $bUseIncludePath = FALSE, $mContext = null, $iOffset = 0, $iMaxLen = -1); + public function file_get_contents_with_etag ($sFilePath, $sEtag ,$bUseIncludePath = FALSE, $mContext = null, $iOffset = 0, $iMaxLen = -1); + public function copy ($sSourceFilePath, $sDestFilePath); + public function filesize ($sFilePath); + public function readfile ($sFilePath, $bUseIncludePath = FALSE, $mContext = null); + public function rename ($sSourceFilePath, $sDestFilePath, $mContext = null); + public function unlink ($sFilePath, $mContext = null); + public function filemtime ($sFilePath); + public function filemtime_formated ($sFilePath, $sFormat); + // Veremes functions + public function getFileInfos ($sFilePath); + public function getProxyPassUrl ($sFilePath); + public function getFileEtag($sFilePath); + + // Directory + // PHP native functions + public function scandir($sDirPath, $iSortOrder = SCANDIR_SORT_ASCENDING, $mContext = null); + public function mkdir($sDirPath, $iMode = 0777, $bRecursive = FALSE, $mContext = null); + public function rmdir($sDirPath, $mContext = null); + public function is_dir($sDirPath); + // Veremes functions + public function getFolderInfos($sDirPath); + public function clearDir($sDirPath); + public function copyDirectory($sDirPathSrc, $sDirPathDest); + +} +?> diff --git a/src/vitis/vas/rest/class/vmlib/files/Files_manager.class.inc b/src/vitis/vas/rest/class/vmlib/files/Files_manager.class.inc new file mode 100644 index 0000000000000000000000000000000000000000..13183cc36b572741466350223a553448457fe0e3 --- /dev/null +++ b/src/vitis/vas/rest/class/vmlib/files/Files_manager.class.inc @@ -0,0 +1,403 @@ +<?php + +require_once ("S3_files.class.inc"); +require_once ("Local_files.class.inc"); + +require_once ("vmlib/phpUtil.inc"); +require_once ("vmlib/logUtil.inc"); + +class Files_manager{ + + public $oFileInterface; + private $oProperties; + private $oLocalInterface; + //private $oS3Interface; + + private static $sFolderLib = "vmlib"; + + function __construct($oProperties){ + $this->oProperties = $oProperties; + // Dans tous les cas on peut avoir besoin d'accéder au système local + $this->$oLocalInterface = new Local_files ($oProperties); + // Séléction du mode principal + switch ($oProperties["filesystem"]) { + case 'fs': + $this->oFileInterface = $this->$oLocalInterface; + break; + case 's3': + $this->oFileInterface = new S3_files ($oProperties); + break; + default: + writeToErrorLog("The file system " . $oProperties["filesystem"] . " is not available on this server"); + break; + } + } + /** + *This method allow to upload a file on a server. + *@file vmlib/phpUtil.inc + *@param $sNomObjet Name of the object. + *@param $sFileType Type of file needed. + *@param $sServerPath New path of the file. + *@param $sMaxSize Maximal size of the file. + *@param $aFileValues File structure generated by extractFileStruct. + *@return $sErrorMsg The error message or the final file path on success. + */ + private function upload_file($sNomObjet, $sFileType, $sServerPath, $sMaxSize, $aFileValues){ + loadLang($this->sFolderLib, $this->oProperties["language"], $this->sFolderLib . "/"); + + $aExtension = array( + "image" => array('gif', 'jpg', 'jpeg', 'png'), + "image-pdf" => array('gif', 'jpg', 'jpeg', 'png', 'pdf'), + "document" => array('pdf', 'gif', 'jpg', 'jpeg', 'png', 'txt'), + "pdf" => array('pdf'), + "zip" => array('zip', 'gex'), + "fmw" => array('fmw') + ); + $aForbiddenExtension = explode('|', str_replace("*.", "", $this->oProperties['forbidden_extension'])); + $sTmpFile = ""; + $sErrorMsg = ""; + // si pas de aValues il y a eu une erreur pendant l'upload dans tmp du PUT + if (!empty($aFileValues)){ + $sTmpFile = $aFileValues['tmp_name']; + + // Si l'utilisateur n'a indiqué aucun fichier à uploader, il ne se passe rien + if ($sTmpFile == '') { + if ($aFileValues['name'] != "") { + switch ($aFileValues['error']) { + case "1" : + $sErrorMsg = ERROR_DOWNLOAD_FILE . $aFileValues['name'] . " : " . ERROR_UPLOAD_MAX_FILE_SIZE; + break; + case "2" : + $sErrorMsg = ERROR_DOWNLOAD_FILE . $aFileValues['name'] . " : " . ERROR_MAX_FILE_SIZE; + break; + case "3" : + $sErrorMsg = ERROR_DOWNLOAD_FILE . $aFileValues['name'] . " : " . ERROR_PARTIAL_DOWNLOAD; + break; + case "4" : + $sErrorMsg = ERROR_NO_FILE_DOWNLOADED; + break; + case "6" : + $sErrorMsg = ERROR_DOWNLOAD_FILE . $aFileValues['name'] . " : " . ERROR_MISSING_TEMP_FOLDER; + break; + case "7" : + $sErrorMsg = ERROR_DOWNLOAD_FILE . $aFileValues['name'] . " : " . ERROR_WRITING_DISK; + break; + case "8" : + $sErrorMsg = ERROR_DOWNLOAD_FILE . $aFileValues['name'] . " : " . ERROR_PHP_EXT_SEND; + break; + } + writeToErrorLog($sErrorMsg); + } + return $sErrorMsg; + } + + $aTemp = explode("/", $sServerPath); + + $sFileName = end($aTemp); + $sFileExtension = $this->extension($sFileName); + + if (!in_array($sFileExtension, $aForbiddenExtension)) { + //Teste si le fichier correspont au format voulu. + $bAllowUpload = false; + $sFormat = ""; + + if (in_array($sFileType, array_keys($aExtension))){ + if (in_array($sFileExtension, $aExtension[$sFileType])) { + $bAllowUpload = true; + } else { + foreach ($aExtensionPicture as $sValue) { + $sFormat .= " " . $sValue; + } + writeToErrorLog(ERROR_FILE . $aFileValues['name'] . ERROR_NOT_FILE . $sFileType); + $sErrorMsg = FILE_LABEL_PHPUTIL . $aFileValues['name'] . ERROR_NOT_FILE . $sFileType . ERROR_VALID_FILE . $sFormat . '.'; + } + } else { + $bAllowUpload = true; + } + + //Teste si le fichier n'est pas de trop grande taille. + if ($aFileValues['size'] > $sMaxSize || $aFileValues['error'] == 1) { + $bAllowUpload = false; + if ($aFileValues['size'] > $sMaxSize) + $sErrorMsg .= FILE_LABEL_PHPUTIL . $aFileValues['name'] . OF_LABEL_PHPUTIL . $aFileValues['size'] . ERROR_EXCEED_MAX_SIZE . ' (' . $sMaxSize . LABEL_BYTES_PHPUTIL . ').'; + if ($aFileValues['error'] > $sMaxSize) + $sErrorMsg .= FILE_LABEL_PHPUTIL . $aFileValues['name'] . ERROR_EXCEED_MAX_SIZE_PHP . ' (' . $sMaxSize . LABEL_BYTES_PHPUTIL . ').'; + } + + // si c'est une image avec les infos de taille final on resample + if($sFileType === "image" && (isset($aFileValues["width"]) && isset($aFileValues["height"]))){ + $sTmpFile = pictureResampler($sTmpFile, $aFileValues["width"], $aFileValues["height"], 0, 0, 0, 0, $sFileExtension); + if(!$sTmpFile){ + $bAllowUpload = false; + writeToErrorLog(ERROR_COPYING_FILE . $aFileValues['name'] . ON_SERVER_PHPUTIL . ', while resampling picture, ' . $sServerPath); + $sErrorMsg = ERROR_COPYING_FILE . $aFileValues['name'] . ON_SERVER_PHPUTIL . '.'; + } + } + + //Lance l'upload. + if ($bAllowUpload) { + $sFileContent = file_get_contents($sTmpFile); + $this->oFileInterface->file_put_contents($sServerPath, $sFileContent); + unlink($sTmpFile); + $sErrorMsg = $sServerPath; + } + } else { + writeToErrorLog(ERROR_FILE . $aFileValues['name'] . ERROR_NOT_FILE . $sFileType); + $sErrorMsg = FILE_LABEL_PHPUTIL . $aFileValues['name'] . ERROR_NOT_FILE . $sFileType . ERROR_VALID_FILE . $sFormat . '.'; + } + } else { + writeToErrorLog(ERROR_FILE . "File" . ERROR_DOWNLOAD_SERVER); + $sErrorMsg = FILE_LABEL_PHPUTIL . "File" . ERROR_DOWNLOAD_SERVER . '.'; + } + + return $sErrorMsg; + } + //} + + /** + *This method convert $_FILE struct or the aValues File to a File Struct usable by uploadFile. + *@file vmlib/phpUtil.inc + *@param $sField Name of the field. + *@param $aValues $aValues to copy file in tmp. + *@return $aFileStruct FileStuct or null if an error block the write in tmp. + */ + private function extractFileStruct ($sField, $aValues = null){ + $aFileStruc = array(); + if (!isset($aValues[$sField . "_name"])){ + // Extract From Post $File Struct + $aFileStruc = array( + "name" => $_FILES[$sField]['name'], + "tmp_name" => $_FILES[$sField]['tmp_name'], + "error" => $_FILES[$sField]['error'], + "size" => $_FILES[$sField]['size'] + ); + } else { + // Extraction de $aValues, on le met dans tmp pour préparer la copie dans upload file + $sTmpFile = $this->oProperties['extract_dir'] . "/" . getUniqRandomId(); + $oFile = fopen($sTmpFile, 'w+'); + if (!$oFile){ + writeToErrorLog("Can't open file in " . $this->oProperties['extract_dir']); + return null; + }else{ + fwrite($oFile, $aValues[$sField . "_file"]); + fclose($oFile); + $aFileStruc = array( + "name" => $aValues[$sField . "_name"], + "tmp_name" => $sTmpFile, + "error" => "0", + "size" => filesize($sTmpFile) + ); + } + } + + if(isset($aValues[$sField . "_width"]) && isset($aValues[$sField . "_height"])){ + $aFileStruc["width"] = $aValues[$sField . "_width"]; + $aFileStruc["height"] = $aValues[$sField . "_height"]; + } + + return $aFileStruc; + } + /** + *This method upload a file in ws_data. + *@param $sModule Name of the module. + *@param $sObject Name of the object. + *@param $mId Id of the current object. + *@param $sField field name (generally DB column name). + *@param $aValues Vitis $aValues. + *@param $iMaxSize Maximum size to upload on server. (set to -1 to disable this control) + *@param $sFileTypeCtrl Type of the document. (set to all to disable this control) + *@return $sErrorMsg The error message. + */ + function uploadInWsDataDir ($sModule, $sObject, $mId, $sField, $aValues, $iMaxSize = -1, $sFileTypeCtrl = "all"){ + // on controle les attributs pour éviter les mauvais placements + if (strpos($sModule, '/') > -1){ + writeToErrorLog("Module can't contain path : " . $sModule); + return "Module can't contain path : " . $sModule; + } + + if (strpos($sObject, "/") > -1){ + writeToErrorLog("Object can't contain path : " . $sObject); + return "Object can't contain path : " . $sObject; + } + + if (strpos($mId, "/") > -1){ + writeToErrorLog("Id can't contain path : " . $mId); + return "Id can't contain path : " . $mId; + } + + if (strpos($sField, "/") > -1){ + writeToErrorLog("Field can't contain path : " . $sField); + return "Field can't contain path : " . $sField; + } + // on génére la Structure fichier + $aFileStruct = $this->extractFileStruct ($sField, $aValues); + // on génére la destination + $sDestDir = $this->oProperties['ws_data_dir'] . "/" . $sModule . "/" . $sObject . "/" . $mId; + if(!empty($sField)){ + $sDestDir .= "/" . $sField; + } + $sDestPath = $sDestDir . "/" . $aFileStruct["name"]; + + // on controle la destination pour éviter les mauvais placements + if (strpos($sDestPath, "/\.\./") > -1){ + writeToErrorLog("This function doesn't accept relative reference : " . $sDestPath); + return "This function doesn't accept relative reference : " . $sDestPath; + } + // si taille max vaut -1 alors taille max = taille fichier + 1 + if ($iMaxSize == -1){ + $iMaxSize = $aFileStruct["size"] + 1; + } + // création du fichier si besoin + if (!is_dir($sDestDir)){ + if(!mkdir($sDestDir, 0777, true)){ + writeToErrorLog('ERROR_CREATING_DIRECTORY ' . $sDestDir); + return 'ERROR_CREATING_DIRECTORY ' . $sDestDir; + } + } + // Upload du fichier + return $this->uploadFile($sField, $sFileTypeCtrl, $sDestPath, $iMaxSize, $aFileStruct); + } + /** + *This method upload a file in Public. + *@file vmlib/phpUtil.inc + *@param $sModule Name of the module. + *@param $sField field name (generally DB column name). + *@param $aValues Vitis $aValues. + *@param $sRandomUniqId random folder to write the file.(set to auto to let the function create the folder) + *@param $iMaxSize Maximum size to upload on server. (set to -1 to disable this control) + *@param $sFileTypeCtrl Type of the document. (set to all to disable this control) + *@return $sErrorMsg The error message. + */ + function uploadInPublicDir($sModule, $sField, $aValues, $sRandomUniqId = "auto", $iMaxSize = -1, $sFileTypeCtrl = "all"){ + // on controle les attributs pour éviter les mauvais placements + if (strpos($sModule, '/') > -1){ + writeToErrorLog("Module can't contain path : " . $sModule); + return "Module can't contain path : " . $sModule; + } + if (strpos($sField, "/") > -1){ + writeToErrorLog("Field can't contain path : " . $sField); + return "Field can't contain path : " . $sField; + } + // on génére la Structure fichier + $aFileStruct = $this->extractFileStruct ($sField, $aValues); + // on génére le dossier unique si besoin + if($sRandomUniqId == "auto"){ + $sRandomUniqId = getUniqRandomId(); + } + // on génére la destination + $sDestDir = $this->oProperties['dir_export'] . "/" . $sModule . "/" . $sRandomUniqId; + $sDestPath = $sDestDir . "/" . $aFileStruct["name"]; + + // on controle la destination pour éviter les mauvais placements + if (strpos($sDestPath, "/\.\./") > -1){ + writeToErrorLog("This function doesn't accept relative reference : " . $sDestPath); + return "This function doesn't accept relative reference : " . $sDestPath; + } + // si taille max vaut -1 alors taille max = taille fichier + 1 + if ($iMaxSize == -1){ + $iMaxSize = $aFileStruct["size"] + 1; + } + + // création du fichier si besoin + if (!is_dir($sDestDir)){ + if(!mkdir($sDestDir, 0777, true)){ + writeToErrorLog('ERROR_CREATING_DIRECTORY ' . $sDestDir); + return 'ERROR_CREATING_DIRECTORY ' . $sDestDir; + } + } + // Upload du fichier + return $this->uploadFile($sField, $sFileTypeCtrl, $sDestPath, $iMaxSize, $aFileStruct); + } + /** + *This method upload a file in Upload. + *@file vmlib/phpUtil.inc + *@param $sModule Name of the module. + *@param $sField field name (generally DB column name). + *@param $aValues Vitis $aValues. + *@param $sRandomUniqId random folder to write the file.(set to auto to let the function create the folder) + *@param $iMaxSize Maximum size to upload on server. (set to -1 to disable this control) + *@param $sFileTypeCtrl Type of the document. (set to all to disable this control) + *@return $sErrorMsg The error message. + */ + function uploadInUploadDir($sModule, $sField, $aValues, $sRandomUniqId = "auto", $iMaxSize = -1, $sFileTypeCtrl = "all"){ + // on controle les attributs pour éviter les mauvais placements + if (strpos($sModule, '/') > -1){ + writeToErrorLog("Module can't contain path : " . $sModule); + return "Module can't contain path : " . $sModule; + } + if (strpos($sField, "/") > -1){ + writeToErrorLog("Field can't contain path : " . $sField); + return "Field can't contain path : " . $sField; + } + // on génére la Structure fichier + $aFileStruct = $this->extractFileStruct ($sField, $aValues); + // on génére le dossier unique si besoin + if($sRandomUniqId == "auto"){ + $sRandomUniqId = getUniqRandomId(); + } + // on génére la destination + $sDestDir = $this->oProperties['upload_dir'] . "/" . $sModule . "/" . $sRandomUniqId; + $sDestPath = $sDestDir . "/" . $aFileStruct["name"]; + + // on controle la destination pour éviter les mauvais placements + if (strpos($sDestPath, "/\.\./") > -1){ + writeToErrorLog("This function doesn't accept relative reference : " . $sDestPath); + return "This function doesn't accept relative reference : " . $sDestPath; + } + // si taille max vaut -1 alors taille max = taille fichier + 1 + if ($iMaxSize == -1){ + $iMaxSize = $aFileStruct["size"] + 1; + } + + // création du fichier si besoin + if (!is_dir($sDestDir)){ + if(!mkdir($sDestDir, 0777, true)){ + writeToErrorLog('ERROR_CREATING_DIRECTORY ' . $sDestDir); + return 'ERROR_CREATING_DIRECTORY ' . $sDestDir; + } + } + // Upload du fichier + return $this->uploadFile($sField, $sFileTypeCtrl, $sDestPath, $iMaxSize, $aFileStruct); + } + /** + *This method return the extension of a file. + *@file vmlib/phpUtil.inc + *@param $sString Full name of a file. + *@return Retourne une chaine. + */ + public function extension($sPath) { + $aTemp = explode(".", $sString); + $sString = strtolower($aTemp[count($aTemp) - 1]); + + return $sString; + } + + /** + *This method return the name of a file from its full path. + *@file vmlib/phpUtil.inc + *@param $sFullFileName Full path of a file. + *@return $aTemp2 The file name. + */ + public function getFileName($sFullFileName) { + $aTemp = explode("/", $sFullFileName); + $aTemp2 = explode("\\", $aTemp[(count($aTemp) - 1)]); + + return $aTemp2[(count($aTemp2) - 1)]; + } + + public function uploadInLocalFs ($sFilePath, $sField, $aValues) { + if (strpos($sField, "/") > -1){ + writeToErrorLog("Field can't contain path : " . $sField); + return "Field can't contain path : " . $sField; + } + // on génére la Structure fichier + $aFileStruct = $this->extractFileStruct ($sField, $aValues); + $sTmpFile = $aFileStruct['tmp_name']; + + $sFileContent = file_get_contents($sTmpFile); + $this->$oLocalInterface->file_put_contents($sFilePath, $sFileContent); + unlink($sTmpFile); + } +} + +?> diff --git a/src/vitis/vas/rest/class/vmlib/files/Local_files.class.inc b/src/vitis/vas/rest/class/vmlib/files/Local_files.class.inc new file mode 100644 index 0000000000000000000000000000000000000000..d70ae3ba70ada4412fcc31916c4e7cd8160e83c8 --- /dev/null +++ b/src/vitis/vas/rest/class/vmlib/files/Local_files.class.inc @@ -0,0 +1,275 @@ +<?php + +require_once ("Files.interface.inc"); + +class Local_files implements Files{ + + private $oProperties; + + function __construct($properties){ + $this->oProperties = $properties; + } + + /** + *This method return the extension of a file. + *@param string $sFilePath File's path. + *@return string|boolean hash sha1 of file content or false if the file doesn't exist. + */ + public function getFileEtag($sFilePath){ + if(file_exists($sFilePath)){ + return sha1(file_get_contents($sFilePath), false); + } else { + return false; + } + + } + + /** + *verify if a file exists. + *@param string $sFilePath File's path. + *@return boolean true if file exists, false else. + */ + public function file_exists ($sFilePath){ + return file_exists($sFilePath); + } + /** + *Write a string in a file. + *@param string $sFilePath File's path. + *@param string $sData string to write in this file. + *@param integer $iFlags flags to write in file (http://php.net/manual/fr/function.file-put-contents.php) Default : 0. + *@param resource $mContext result de stream_context_create(). + *@return integer|boolean number of byte written, or false if the process encounter an error. + */ + public function file_put_contents ($sFilePath, $sData, $iFlags = 0, $mContext = null){ + return file_put_contents($sFilePath, $sData, $iFlags, $mContext); + } + /** + *read a file and return content in a string. + *@param string $sFilePath File's path. + *@param boolean $bUseIncludePath use include var to resolve a relative path. + *@param resource $mContext result de stream_context_create(). + *@param integer $iOffset offset in bytes to begin file reading, Default : 0. + *@param integer $iMaxLen Number of byte to read from the file, Default : -1 = read until the file's end. + *@return string|boolean file content, or false if the process encounter an error. + */ + public function file_get_contents ($sFilePath, $bUseIncludePath = FALSE, $mContext = null, $iOffset = 0, $iMaxLen = -1){ + if ($iMaxLen == -1){ + return file_get_contents ($sFilePath, $bUseIncludePath, null, $iOffset); + } else { + return file_get_contents ($sFilePath, $bUseIncludePath, null, $iOffset, $iMaxLen); + } + } + /** + *read a file and return content in a string if eTag matches. + *@param string $sFilePath File's path. + *@param string $sEtag Hash Sha1 of file's content. + *@param boolean $bUseIncludePath use include var to resolve a relative path. + *@param resource $mContext result de stream_context_create(). + *@param integer $iOffset offset in bytes to begin file reading, Default : 0. + *@param integer $iMaxLen Number of byte to read from the file, Default : -1 = read until the file's end. + *@return string|boolean file content, or false if the process encounter an error. + */ + public function file_get_contents_with_etag ($sFilePath, $sEtag ,$bUseIncludePath = FALSE, $mContext = null, $iOffset = 0, $iMaxLen = -1){ + $sProcessedEtag = $this->getFileEtag($sFilePath); + if ($sEtag == $sProcessedEtag){ + return $this->file_get_contents($sFilePath, $bUseIncludePath, $mContext, $iOffset, $iMaxLen); + } else { + return false; + } + } + /** + *copy a file. + *@param string $sSourceFilePath File's path to copy. + *@param string $sDestFilePath File's destination. + *@return boolean true on sucess or false if the process encounter an error. + */ + public function copy ($sSourceFilePath, $sDestFilePath){ + return copy ($sSourceFilePath, $sDestFilePath); + } + /** + *return the size of a file in bytes. + *@param string $sFilePath File's path. + *@return integer|boolean File's size in bytes or false if the process encounter an error. + */ + public function filesize ($sFilePath){ + return filesize($sFilePath); + } + /** + *send file's content into stdout. + *@param string $sFilePath File's path. + *@param boolean $bUseIncludePath use include var to resolve a relative path. + *@param resource $mContext result de stream_context_create(). + *@return integer|boolean File's size in bytes or false if the process encounter an error. + */ + public function readfile ($sFilePath, $bUseIncludePath = FALSE, $mContext = null){ + return readfile($sFilePath, $bUseIncludePath, $mContext); + } + /** + *move a file. + *@param string $sSourceFilePath File's path to copy. + *@param string $sDestFilePath File's destination. + *@param resource $mContext result de stream_context_create(). + *@return boolean true on sucess or false if the process encounter an error. + */ + public function rename ($sSourceFilePath, $sDestFilePath, $mContext = null){ + if(empty($mContext)){ + return rename($sSourceFilePath, $sDestFilePath); + }else{ + return rename($sSourceFilePath, $sDestFilePath, $mContext); + } + } + /** + *remove a file. + *@param string $sFilePath File's path. + *@param resource $mContext result de stream_context_create(). + *@return boolean true on sucess or false if the process encounter an error. + */ + public function unlink ($sFilePath, $mContext = null){ + if(empty($mContext)){ + return unlink($sFilePath); + } else { + return unlink($sFilePath, $mContext); + } + } + /** + *return the number of second UNIX of the last modification on a file. + *@param string $sFilePath File's path. + *@return integer|boolean timestamp on sucess or false if the process encounter an error. + */ + public function filemtime ($sFilePath){ + return filemtime($sFilePath); + } + /** + *return the fomrated date of the last modification on a file. + *@param string $sFilePath File's path. + *@param string $sFormat Format to convert the timestamp. + *@return string|boolean date string on sucess or false if the process encounter an error. + */ + public function filemtime_formated($sFilePath, $sFormat){ + return date ($sFormat, $this->filemtime($sFilePath)); + } + /** + *return the metadata structure of a file. + *@param string $sFilePath File's path. + *@return array filename, size, lastModification, href. + */ + public function getFileInfos ($sFilePath){ + $iFileSize = $this->filesize($sFilePath); + + $sFileSize = $iFileSize . " octets"; + if($iFileSize > 1024){ + if($iFileSize > 1024*1024){ + if($iFileSize > 1024*1024*1024){ + $sFileSize = "-"; + } else { + $sFileSize = (ceil($iFileSize/(1024*1024))) . "Mo"; + } + }else{ + $sFileSize = (ceil($iFileSize/1024)) . "Ko"; + } + } + + $aFileName = explode("/", $sFilePath); + + return array("filename"=>$aFileName[count($aFileName) - 1], "size"=>$sFileSize, "lastModification"=> $this->filemtime_formated ($sFilePath, "d/m/Y H:i:s"), "href" => $this->getProxyPassUrl($sFilePath)); + } + /** + *return an url to download the file through Vitis API . + *@param string $sFilePath File's path. + *@return string url. + */ + public function getProxyPassUrl ($sFilePath){ + $date = new DateTime(); + $sDataUrl = $this->oProperties['web_server_name'] . "/rest/vitis/file_downloader?key=[KEY]&eTag=[ETAG]&d=" . $date->getTimestamp(); + + $sFileUrl = str_replace("[KEY]", str_replace($this->oProperties['ws_data_dir'], "ws_data" , $sFilePath), $sDataUrl); + $sFileUrl = str_replace("[ETAG]", sha1(file_get_contents($sFilePath), false), $sFileUrl); + + return $sFileUrl; + } + public function scandir($sDirPath, $iSortOrder = SCANDIR_SORT_ASCENDING, $mContext = null){ + if(empty($mContext)){ + return scandir($sDirPath, $iSortOrder); + }else{ + return scandir($sDirPath, $iSortOrder, $mContext); + } + } + public function mkdir($sDirPath, $iMode = 0777, $bRecursive = FALSE, $mContext = null){ + if(empty($mContext)){ + return mkdir($sDirPath, $iMode, $bRecursive); + }else{ + return mkdir($sDirPath, $iMode, $bRecursive, $mContext); + } + } + public function rmdir($sDirPath, $mContext = null){ + if(empty($mContext)){ + return rmdir($sDirPath); + }else{ + return rmdir($sDirPath, $mContext); + } + } + public function is_dir($sDirPath){ + return is_dir($sDirPath); + } + public function getFolderInfos($sDirPath){ + if($this->is_dir($sDirPath)){ + $aContentDir = $this->scandir($sDirPath); + $aTree = $this->getFileInfos($sDirPath); + $aDir = array(); + for ($i =0 ; $i < count($aContentDir); $i++){ + if($aContentDir[$i] !== "." && $aContentDir[$i] !== ".."){ + array_push($aDir, $this->getFolderInfos($sDirPath . "/" . $aContentDir[$i])); + } + } + + $aTree["content"] = $aDir; + unset($aTree["href"]); + return $aTree; + } else { + return $this->getFileInfos($sDirPath); + } + } + public function clearDir($sDirPath){ + $ouverture = @opendir($sDossier); + if (!$ouverture) + return; + while ($sFichier = readdir($ouverture)) { + + if ($sFichier == '.' || $sFichier == '..') + continue; + if ($this->is_dir($sDossier . "/" . $sFichier)) { + $bCleared = $this->clearDir($sDossier . "/" . $sFichier); + if (!$bCleared) + return false; + } + else { + $bCleared = @unlink($sDossier . "/" . $sFichier); + if (!$bCleared) + return false; + } + } + closedir($ouverture); + $bCleared = @rmdir($sDossier); + if (!$bCleared) + return false; + return true; + } + public function copyDirectory($sDirPathSrc, $sDirPathDest){ + $dir = opendir($src); + @mkdir($dst); + while(false !== ( $file = readdir($dir)) ) { + if (( $file != '.' ) && ( $file != '..' )) { + if ( is_dir($src . '/' . $file) ) { + $this->copyDirectory($src . '/' . $file,$dst . '/' . $file); + } + else { + copy($src . '/' . $file,$dst . '/' . $file); + } + } + } + closedir($dir); + } +} + + +?> diff --git a/src/vitis/vas/rest/class/vmlib/files/S3_files.class.inc b/src/vitis/vas/rest/class/vmlib/files/S3_files.class.inc new file mode 100644 index 0000000000000000000000000000000000000000..8287713ad3db09a0b78c73e2b510919391255113 --- /dev/null +++ b/src/vitis/vas/rest/class/vmlib/files/S3_files.class.inc @@ -0,0 +1,534 @@ +<?php + +require_once ("Files.interface.inc"); +require_once ("vmlib/phpUtil.inc"); +require_once ("vmlib/logUtil.inc"); +require_once ("aws_sdk/aws-autoloader.php"); + +use Aws\Credentials\CredentialProvider; + +class S3_files implements Files{ + + private $oProperties; + private $oS3Client; + + function __construct($properties){ + $this->oProperties = $properties; + + $oProvider = CredentialProvider::ini($properties['fileS3UploaderProfil'], $properties['AWSCredentialsFilePath']); + $oProvider = CredentialProvider::memoize($oProvider); + // create client s3 + $this->oS3Client = new Aws\S3\S3Client(array( + 'version'=>'latest', + 'region'=> $properties['fileS3UploaderRegion'], + //'profile'=> $properties['fileS3UploaderProfil'], + 'credentials' => $oProvider, + 'debug' => false + )); + } + /** + *parse vitis properties ti extract bucket name and bucket prefix. + *@private + *@return array bucket'name, prefix. + */ + private function getBucketConst(){ + $sBucket = $this->oProperties['fileS3UploaderBucket']; + $sPrefix = ""; + + if (strpos($sBucket, "/") > -1){ + $aBucket = explode("/", $sBucket ); + $sBucket = $aBucket[0]; + $sPrefix = implode("/", array_slice($aBucket, 1)); + } + + return array($sBucket, $sPrefix); + } + /** + *This method return the extension of a file. + *@param string $sFilePath File's path. + *@return string|boolean hash md5 of file content or false if the file doesn't exist. + */ + public function getFileEtag($sFilePath){ + list($sBucket, $sPrefix) = $this->getBucketConst(); + $sFilePath = str_replace($this->oProperties["vas_home"], $sPrefix , $sFilePath); + + try { + $oResult = $this->oS3Client->headObject(array( + 'Bucket' => $sBucket, + 'Key' => $sFilePath) + ); + + return str_replace('"', '', $oResult["ETag"]); + }catch (Aws\S3\Exception\S3Exception $e){ + writeToErrorLog($e->getMessage()); + return false; + } + } + /** + *verify if a file exists. + *@param string $sFilePath File's path. + *@return boolean true if file exists, false else. + */ + public function file_exists ($sFilePath){ + + list($sBucket, $sPrefix) = $this->getBucketConst(); + $sFilePath = str_replace($this->oProperties["vas_home"], $sPrefix , $sFilePath); + + try { + $this->oS3Client->headObject(array( + 'Bucket' => $sBucket, + 'Key' => $sFilePath) + ); + }catch (Aws\S3\Exception\S3Exception $e){ + writeToErrorLog($e->getMessage()); + return false; + } + return true; + } + /** + *Write a string in a file. + *@param string $sFilePath File's path. + *@param string $sData string to write in this file. + *@param integer $iFlags flags to write in file (http://php.net/manual/fr/function.file-put-contents.php) Default : 0. + *@param resource $mContext result de stream_context_create(). + *@return integer|boolean number of byte written, or false if the process encounter an error. + */ + public function file_put_contents ($sFilePath, $sData, $iFlags = 0, $mContext = null){ + list($sBucket, $sPrefix) = $this->getBucketConst(); + $sFilePath = str_replace($this->oProperties["vas_home"], $sPrefix , $sFilePath); + + try { + $this->oS3Client->putObject(array( + 'Bucket' => $sBucket, + 'Key' => $sFilePath, + 'Body' => $sData, + ) + ); + }catch (Aws\S3\Exception\S3Exception $e){ + writeToErrorLog($e->getMessage()); + return false; + } + return strlen($sData); + } + /** + *read a file and return content in a string. + *@param string $sFilePath File's path. + *@param boolean $bUseIncludePath use include var to resolve a relative path. + *@param resource $mContext result de stream_context_create(). + *@param integer $iOffset offset in bytes to begin file reading, Default : 0. + *@param integer $iMaxLen Number of byte to read from the file, Default : -1 = read until the file's end. + *@return string|boolean file content, or false if the process encounter an error. + */ + public function file_get_contents ($sFilePath, $bUseIncludePath = FALSE, $mContext = null, $iOffset = 0, $iMaxLen = -1){ + + list($sBucket, $sPrefix) = $this->getBucketConst(); + $sFilePath = str_replace($this->oProperties["vas_home"], $sPrefix , $sFilePath); + + $sPath = $this->oProperties['extract_dir'] . "/" . getUniqRandomId(); + + try{ + $this->oS3Client->getObject(array( + 'Bucket' => $sBucket, + 'Key' => $sFilePath, + 'SaveAs' => $sPath + )); + }catch (Aws\S3\Exception\S3Exception $e){ + writeToErrorLog($e->getMessage()); + unlink($sPath); + return false; + } + + $sFile = ""; + + if ($iMaxLen == -1){ + $sFile = file_get_contents ($sPath, $bUseIncludePath, null, $iOffset); + } else { + $sFile = file_get_contents ($sPath, $bUseIncludePath, null, $iOffset, $iMaxLen); + } + unlink($sPath); + return $sFile; + } + /** + *read a file and return content in a string if eTag matches. + *@param string $sFilePath File's path. + *@param string $sEtag Hash Sha1 of file's content. + *@param boolean $bUseIncludePath use include var to resolve a relative path. + *@param resource $mContext result de stream_context_create(). + *@param integer $iOffset offset in bytes to begin file reading, Default : 0. + *@param integer $iMaxLen Number of byte to read from the file, Default : -1 = read until the file's end. + *@return string|boolean file content, or false if the process encounter an error. + */ + public function file_get_contents_with_etag ($sFilePath, $sEtag ,$bUseIncludePath = FALSE, $mContext = null, $iOffset = 0, $iMaxLen = -1){ + list($sBucket, $sPrefix) = $this->getBucketConst(); + $sFilePath = str_replace($this->oProperties["vas_home"], $sPrefix , $sFilePath); + + $sPath = $this->oProperties['extract_dir'] . "/" . getUniqRandomId(); + + try{ + $this->oS3Client->getObject(array( + 'Bucket' => $sBucket, + 'Key' => $sFilePath, + 'IfMatch' => $sEtag, + 'SaveAs' => $sPath + )); + }catch (Aws\S3\Exception\S3Exception $e){ + writeToErrorLog($e->getMessage()); + unlink($sPath); + return false; + } + $sFile = ""; + + if ($iMaxLen == -1){ + $sFile = file_get_contents ($sPath, $bUseIncludePath, null, $iOffset); + } else { + $sFile = file_get_contents ($sPath, $bUseIncludePath, null, $iOffset, $iMaxLen); + } + unlink($sPath); + return $sFile; + } + /** + *copy a file in the same bucket. + *@param string $sSourceFilePath Object's key to copy. + *@param string $sDestFilePath Object's destination key. + *@return boolean true on sucess or false if the process encounter an error. + */ + public function copy ($sSourceFilePath, $sDestFilePath){ + list($sBucket, $sPrefix) = $this->getBucketConst(); + $sDestFilePath = str_replace($this->oProperties["vas_home"], $sPrefix , $sDestFilePath); + $sSourceFilePath = str_replace($this->oProperties["vas_home"], $sPrefix , $sSourceFilePath); + + try{ + $this->oS3Client->copyObject(array( + 'Bucket' => $sBucket, + 'Key' => $sDestFilePath, + 'CopySource' => $sBucket . "/" . $sSourceFilePath + )); + return true; + }catch (Aws\S3\Exception\S3Exception $e){ + writeToErrorLog($e->getMessage()); + return false; + } + } + /** + *copy a file in another bucket. + *@param string $sSourceFilePath Object's key to copy. + *@param string $sDests3Key Object's destination key. + *@param string $sDestBucket Object's destination bucket. + *@return boolean true on sucess or false if the process encounter an error. + */ + public function copyInAnotherBucket ($sSourceFilePath, $sDests3Key, $sDestBucket){ + list($sBucket, $sPrefix) = $this->getBucketConst(); + $sSourceFilePath = str_replace($this->oProperties["vas_home"], $sPrefix , $sSourceFilePath); + + try{ + $this->oS3Client->copyObject(array( + 'Bucket' => $sDestBucket, + 'Key' => $sDests3Key, + 'CopySource' => $sBucket . "/" . $sSourceFilePath + )); + return true; + }catch (Aws\S3\Exception\S3Exception $e){ + writeToErrorLog($e->getMessage()); + return false; + } + } + /** + *send a local file to S3. + *@param string $sSourceFilePath File's path to copy. + *@param string $sDestFilePath Object's destination key. + *@return boolean true on sucess or false if the process encounter an error. + */ + public function copyLocalToS3 ($sSourceFilePath, $sDestFilePath){ + list($sBucket, $sPrefix) = $this->getBucketConst(); + $sDestFilePath = str_replace($this->oProperties["vas_home"], $sPrefix , $sDestFilePath); + + try { + $this->oS3Client->putObject(array( + 'Bucket' => $sBucket, + 'Key' => $sDestFilePath, + 'Body' => file_get_contents($sSourceFilePath), + ) + ); + }catch (Aws\S3\Exception\S3Exception $e){ + writeToErrorLog($e->getMessage()); + return false; + } + return true; + } + /** + *return the size of a file in bytes. + *@param string $sFilePath File's path. + *@return integer|boolean File's size in bytes or false if the process encounter an error. + */ + public function filesize ($sFilePath){ + list($sBucket, $sPrefix) = $this->getBucketConst(); + $sFilePath = str_replace($this->oProperties["vas_home"], $sPrefix , $sFilePath); + + try { + $oResult = $this->oS3Client->headObject(array( + 'Bucket' => $sBucket, + 'Key' => $sFilePath) + ); + + return $oResult["ContentLength"]; + }catch (Aws\S3\Exception\S3Exception $e){ + writeToErrorLog($e->getMessage()); + return false; + } + } + /** + *send file's content into stdout. + *@param string $sFilePath File's path. + *@param boolean $bUseIncludePath use include var to resolve a relative path. + *@param resource $mContext result de stream_context_create(). + *@return integer|boolean File's size in bytes or false if the process encounter an error. + */ + public function readfile ($sFilePath, $bUseIncludePath = FALSE, $mContext = null){ + list($sBucket, $sPrefix) = $this->getBucketConst(); + $sFilePath = str_replace($this->oProperties["vas_home"], $sPrefix , $sFilePath); + + $sPath = $this->oProperties['extract_dir'] . "/" . getUniqRandomId(); + + try{ + $this->oS3Client->getObject(array( + 'Bucket' => $sBucket, + 'Key' => $sFilePath, + 'SaveAs' => $sPath + )); + }catch (Aws\S3\Exception\S3Exception $e){ + writeToErrorLog($e->getMessage()); + unlink($sPath); + return false; + } + + $iLength = readfile($sPath, $bUseIncludePath, $mContext); + unlink($sPath); + return $iLength; + } + /** + *move a file. + *@param string $sSourceFilePath File's path to copy. + *@param string $sDestFilePath File's destination. + *@param resource $mContext result de stream_context_create(). + *@return boolean true on sucess or false if the process encounter an error. + */ + public function rename ($sSourceFilePath, $sDestFilePath, $mContext = null){ + $bReturn = $this->copy($sSourceFilePath, $sDestFilePath); + if ($bReturn) + $bReturn = $this->unlink($sSourceFilePath, $mContext); + return $bReturn; + } + /** + *remove a file. + *@param string $sFilePath File's path. + *@param resource $mContext result de stream_context_create(). + *@return boolean true on sucess or false if the process encounter an error. + */ + public function unlink ($sFilePath, $mContext = null){ + list($sBucket, $sPrefix) = $this->getBucketConst(); + $sFilePath = str_replace($this->oProperties["vas_home"], $sPrefix , $sFilePath); + + try{ + $this->oS3Client->deleteObject(array( + 'Bucket' => $sBucket, + 'Key' => $sFilePath + )); + return true; + }catch (Aws\S3\Exception\S3Exception $e){ + writeToErrorLog($e->getMessage()); + return false; + } + } + /** + *return the number of second UNIX of the last modification on a file. + *@param string $sFilePath File's path. + *@return integer|boolean timestamp on sucess or false if the process encounter an error. + */ + public function filemtime ($sFilePath){ + list($sBucket, $sPrefix) = $this->getBucketConst(); + $sFilePath = str_replace($this->oProperties["vas_home"], $sPrefix , $sFilePath); + + try { + $oResult = $this->oS3Client->headObject(array( + 'Bucket' => $sBucket, + 'Key' => $sFilePath) + ); + + return $oResult["LastModified"]->format("U"); + }catch (Aws\S3\Exception\S3Exception $e){ + writeToErrorLog($e->getMessage()); + return false; + } + } + /** + *return the fomrated date of the last modification on a file. + *@param string $sFilePath File's path. + *@param string $sFormat Format to convert the timestamp. + *@return string|boolean date string on sucess or false if the process encounter an error. + */ + public function filemtime_formated ($sFilePath, $sFormat){ + return date ($sFormat, $this->filemtime($sFilePath)); + } + /** + *return the metadata structure of a file. + *@param string $sFilePath File's path. + *@return array filename, size, lastModification, href. + */ + public function getFileInfos ($sFilePath){ + $iFileSize = $this->filesize($sFilePath); + + $sFileSize = $iFileSize . " octets"; + if($iFileSize > 1024){ + if($iFileSize > 1024*1024){ + if($iFileSize > 1024*1024*1024){ + $sFileSize = "-"; + } else { + $sFileSize = (ceil($iFileSize/(1024*1024))) . "Mo"; + } + }else{ + $sFileSize = (ceil($iFileSize/1024)) . "Ko"; + } + } + + $aFileName = explode("/", $sFilePath); + + return array("filename"=>$aFileName[count($aFileName) - 1], "size"=>$sFileSize, "lastModification"=> $this->filemtime_formated ($sFilePath, "d/m/Y H:i:s"), "href" => $this->getProxyPassUrl($sFilePath)); + } + /** + *return an url to download the file through Vitis API . + *@param string $sFilePath File's path. + *@return string url. + */ + public function getProxyPassUrl ($sFilePath){ + $sEtag = $this->getFileEtag($sFilePath); + list($sBucket, $sPrefix) = $this->getBucketConst(); + $sFilePath = str_replace($this->oProperties["vas_home"], $sPrefix , $sFilePath); + $date = new DateTime(); + $sDataUrl = $this->oProperties['web_server_name'] . "/rest/vitis/file_downloader?key=[KEY]&eTag=[ETAG]&d=" . $date->getTimestamp(); + + $sFileUrl = str_replace("[KEY]", str_replace($this->oProperties['ws_data_dir'], "ws_data" , $sFilePath), $sDataUrl); + $sFileUrl = str_replace("[ETAG]", $sEtag, $sFileUrl); + + return $sFileUrl; + } + /** + *scan a directory with a depth of 1. + *@param string $sDirPath Directory's path. + *@param integer $iSortOrder flag (http://php.net/manual/fr/function.scandir.php). + *@param resource $mContext result de stream_context_create(). + *@return array list of file and subdirectoy . + */ + public function scandir($sDirPath, $iSortOrder = SCANDIR_SORT_ASCENDING, $mContext = null){ + $aReturn = array(".", ".."); + // traitement du bucket et de ses sous-dossiers + list($sBucket, $sPrefix) = $this->getBucketConst(); + $sListPrefix = str_replace($this->oProperties["vas_home"], $sPrefix , $sDirPath); + // Suppression du slash de début de ligne (sinon création d'un répertoire vide sur S3). + if (strpos($sListPrefix, '/') === 0){ + $sListPrefix = substr($sListPrefix, 1); + } + if (substr($sListPrefix, -1) !== "/"){ + $sListPrefix .= "/"; + } + try{ + $aList = $this->oS3Client->listObjectsV2(array( + 'Bucket' => $sBucket, + 'Prefix' => $sListPrefix + )); + + if ($aList["KeyCount"] > 0){ + foreach ($aList["Contents"] as $aObject){ + $sObjectPath = str_replace($sListPrefix, "", $aObject["Key"]); + $aObjectPath = explode("/", $sObjectPath); + if(!empty($aObjectPath[0])){ + array_push($aReturn, $aObjectPath[0]); + } + } + } + if($iSortOrder === SCANDIR_SORT_ASCENDING){ + sort($aReturn); + } + if($iSortOrder === SCANDIR_SORT_DESCENDING){ + rsort($aReturn); + } + return $aReturn; + }catch(Aws\S3\Exception\S3Exception $e){ + writeToErrorLog($e->getMessage()); + return false; + } + } + public function mkdir($sDirPath, $iMode = 0777, $bRecursive = FALSE, $mContext = null){ + // ne sert à rien dans un stockage d'objet + return false; + } + public function rmdir($sDirPath, $mContext = null){ + // ne sert à rien dans un stockage d'objet (pas de dossier vide ou peu favoriser clearDir) + return false; + } + /** + *define if the path is a directory or a file . + *@param string $sDirPath directory's path. + *@return boolean true if it's a dir, false else. + */ + public function is_dir($sDirPath){ + // traitement du bucket et de ses sous-dossiers + list($sBucket, $sPrefix) = $this->getBucketConst(); + $sListPrefix = str_replace($this->oProperties["vas_home"], $sPrefix , $sDirPath); + // Suppression du slash de début de ligne (sinon création d'un répertoire vide sur S3). + if (strpos($sListPrefix, '/') === 0){ + $sListPrefix = substr($sListPrefix, 1); + } + try{ + $aList = $this->oS3Client->listObjectsV2(array( + 'Bucket' => $sBucket, + 'Prefix' => $sListPrefix + )); + + if ($aList["KeyCount"] > 1){ + return true; + } else if ($aList["KeyCount"] == 1){ + $iPrefixPathCount = count(explode("/", $sListPrefix)); + $iKeyCount = count(explode("/", $aList["Contents"][0]["Key"])); + if ($iKeyCount > $iPrefixPathCount){ + return true; + } else { + return false; + } + + } else { + return false; + } + }catch(Aws\S3\Exception\S3Exception $e){ + writeToErrorLog($e->getMessage()); + return false; + } + } + /** + *scan a directory without depth limitation and return metadata usefull for treeview. + *@param string $sDirPath Directory's path. + *@return array list of file and subdirectory . + */ + public function getFolderInfos($sDirPath){ + if($this->is_dir($sDirPath)){ + $aContentDir = $this->scandir($sDirPath); + $aTree = array( + "filename"=> end(explode("/",$sDirPath)), + "lastModification" => "none", + "size"=> "", + "content" => array() + ); + for ($i =0 ; $i < count($aContentDir); $i++){ + if($aContentDir[$i] !== "." && $aContentDir[$i] !== ".."){ + array_push($aTree["content"], $this->getFolderInfos($sDirPath . "/" . $aContentDir[$i])); + } + } + + return $aTree; + } else { + return $this->getFileInfos($sDirPath); + } + } +} + + +?>