Index: branches/5.3.x/core/ckeditor/ckfinder/plugins/zip/plugin.php =================================================================== diff -u -N -r15908 -r16252 --- branches/5.3.x/core/ckeditor/ckfinder/plugins/zip/plugin.php (.../plugin.php) (revision 15908) +++ branches/5.3.x/core/ckeditor/ckfinder/plugins/zip/plugin.php (.../plugin.php) (revision 16252) @@ -1,945 +1,945 @@ -_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST); - } - - if (!extension_loaded('zip')) { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_COMMAND); - } - - $this->checkConnector(); - $this->checkRequest(); - - if ( !$this->_currentFolder->checkAcl(CKFINDER_CONNECTOR_ACL_FILE_UPLOAD)) { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED); - } - - if (!isset($_POST["fileName"])) { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_NAME); - } - - $fileName = CKFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding($_POST["fileName"]); - $resourceTypeInfo = $this->_currentFolder->getResourceTypeConfig(); - - if (!$resourceTypeInfo->checkExtension($fileName)) { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_EXTENSION); - } - - if (!CKFinder_Connector_Utils_FileSystem::checkFileName($fileName) || $resourceTypeInfo->checkIsHiddenFile($fileName)) { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST); - } - - $filePath = CKFinder_Connector_Utils_FileSystem::combinePaths($this->_currentFolder->getServerPath(), $fileName); - - if (!file_exists($filePath) || !is_file($filePath)) { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_FILE_NOT_FOUND); - } - - if (!is_writable(dirname($filePath))) { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_ACCESS_DENIED); - } - - if ( strtolower(pathinfo($fileName, PATHINFO_EXTENSION)) !== 'zip'){ - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_EXTENSION); - } - - $zip = new ZipArchive(); - $result = $zip->open($filePath); - if ($result !== TRUE) { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_UNKNOWN); - } - $this->zip = $zip; - $this->filePath = $filePath; - $this->_config =& CKFinder_Connector_Core_Factory::getInstance("Core_Config"); - - // list of unzipped nodes - $this->unzippedNodes = new CKFinder_Connector_Utils_XmlNode("UnzippedFiles"); - - // list of files which could not be unzipped - $this->skippedFilesNode = new CKFinder_Connector_Utils_XmlNode("Errors"); - $this->errorCode = CKFINDER_CONNECTOR_ERROR_NONE; - } - - /** - * Check one file for security reasons - * - * @param object $filePathInfo - * @param string $originalFileName - * @return mixed bool(false) - if security checks fails. Otherwise string - ralative zip archive path with secured filename. - */ - protected function checkOneFile($filePathInfo, $originalFileName ) - { - $resourceTypeInfo = $this->_currentFolder->getResourceTypeConfig(); - - // checked if it is a folder - $fileStat = $this->zip->statName($originalFileName); - if ( empty($filePathInfo['extension']) && empty($fileStat['size']) ){ - $sNewFolderName = CKFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding(rtrim($fileStat['name'],'/')); - if ($this->_config->forceAscii()) { - $sNewFolderName = CKFinder_Connector_Utils_FileSystem::convertToAscii($sNewFolderName); - } - if (!CKFinder_Connector_Utils_FileSystem::checkFolderPath($sNewFolderName) || $resourceTypeInfo->checkIsHiddenFolder($sNewFolderName)) { - $this->errorCode = CKFINDER_CONNECTOR_ERROR_INVALID_NAME; - $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $originalFileName); - return false; - } - - if (!is_writeable($this->_currentFolder->getServerPath())) { - $this->errorCode = CKFINDER_CONNECTOR_ERROR_ACCESS_DENIED; - $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $originalFileName); - return false; - } - - return $originalFileName; - } - - $fileName = CKFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding($filePathInfo['basename']); - $sFileName = CKFinder_Connector_Utils_FileSystem::secureFileName($fileName); - - // max file size - $maxSize = $resourceTypeInfo->getMaxSize(); - if ( $maxSize && $fileStat['size'] > $maxSize ) - { - $this->errorCode = CKFINDER_CONNECTOR_ERROR_UPLOADED_TOO_BIG; - $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $originalFileName); - return false; - } - // extension - if ( !$resourceTypeInfo->checkExtension($sFileName) ) - { - $this->errorCode = CKFINDER_CONNECTOR_ERROR_INVALID_EXTENSION; - $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $originalFileName); - return false; - } - // hidden file - if ( !CKFinder_Connector_Utils_FileSystem::checkFileName($sFileName) || $resourceTypeInfo->checkIsHiddenFile($sFileName) ){ - $this->errorCode = CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST; - $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $originalFileName); - return false; - } - - // unpack file to tmp dir for detecting html and valid image - $dir = CKFinder_Connector_Utils_FileSystem::getTmpDir().'/'; - if ( file_exists($dir.$sFileName) && !CKFinder_Connector_Utils_FileSystem::unlink($dir.$sFileName) ){ - $this->errorCode = CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST; - $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $originalFileName); - return false; - } - if ( copy('zip://'.$this->filePath.'#'.$originalFileName, $dir.$sFileName) ) - { - // html extensions - $htmlExtensions = $this->_config->getHtmlExtensions(); - $sExtension = CKFinder_Connector_Utils_FileSystem::getExtension( $dir.$sFileName ); - if ( $htmlExtensions - && !CKFinder_Connector_Utils_Misc::inArrayCaseInsensitive( $sExtension, $htmlExtensions ) - && CKFinder_Connector_Utils_FileSystem::detectHtml($dir.$sFileName) === true ) - { - $this->errorCode = CKFINDER_CONNECTOR_ERROR_UPLOADED_INVALID; - $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $originalFileName); - return false; - } - - // proper image - $secureImageUploads = $this->_config->getSecureImageUploads(); - if ( $secureImageUploads - && ( $isImageValid = CKFinder_Connector_Utils_FileSystem::isImageValid($dir.$sFileName, $sExtension) ) === false ) - { - $this->errorCode = CKFINDER_CONNECTOR_ERROR_UPLOADED_INVALID; - $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $originalFileName); - return false; - } - } - $sDirName = ($filePathInfo['dirname'] != '.')? $filePathInfo['dirname'].'/' : ''; - - return $sDirName.$sFileName; - } - - /** - * Add error node to the list - * @param obj $oErrorsNode - * @param int $errorCode - * @param string $name - * @param string $type - * @param string $path - */ - protected function appendErrorNode($oErrorsNode, $errorCode=0, $name, $type=null, $path=null) - { - $oErrorNode = new CKFinder_Connector_Utils_XmlNode("Error"); - $oErrorNode->addAttribute("code", $errorCode); - $oErrorNode->addAttribute("name", CKFinder_Connector_Utils_FileSystem::convertToConnectorEncoding($name)); - if ( $type ){ - $oErrorNode->addAttribute("type", $type); - } - if ( $path ){ - $oErrorNode->addAttribute("folder", $path); - } - $oErrorsNode->addChild($oErrorNode); - } - - /** - * Add unzipped node to the list - * @param obj $oUnzippedNodes - * @param string $name - * @param string $action - */ - protected function appendUnzippedNode($oUnzippedNodes, $name, $action='ok') - { - $oUnzippedNode = new CKFinder_Connector_Utils_XmlNode("File"); - $oUnzippedNode->addAttribute("name", CKFinder_Connector_Utils_FileSystem::convertToConnectorEncoding($name)); - $oUnzippedNode->addAttribute("action", $action ); - $oUnzippedNodes->addChild($oUnzippedNode); - } - - /** - * Extract one file from zip archive - * - * @param string $extractPath - * @param string $extractClientPath - * @param array $filePathInfo - * @param string $sFileName - * @param string $originalFileName - */ - protected function extractTo($extractPath, $extractClientPath, $filePathInfo, $sFileName, $originalFileName) - { - $sfilePathInfo = pathinfo($extractPath.$sFileName); - $extractClientPathDir = $filePathInfo['dirname']; - if ( $filePathInfo['dirname'] == '.' ){ - $extractClientPathDir = ''; - } - $folderPath = CKFinder_Connector_Utils_FileSystem::combinePaths($extractClientPath,$extractClientPathDir); - - $_aclConfig = $this->_config->getAccessControlConfig(); - $aclMask = $_aclConfig->getComputedMask($this->_currentFolder->getResourceTypeName(),$folderPath); - $canCreateFolder = (($aclMask & CKFINDER_CONNECTOR_ACL_FOLDER_CREATE ) == CKFINDER_CONNECTOR_ACL_FOLDER_CREATE ); - // create sub-directory of zip archive - if ( empty($sfilePathInfo['extension']) ) - { - $fileStat = $this->zip->statName($originalFileName); - $isDir = false; - if ( $fileStat && empty($fileStat['size']) ){ - $isDir = true; - } - if( !empty($sfilePathInfo['dirname']) && !empty($sfilePathInfo['basename']) && !file_exists($sfilePathInfo['dirname'].'/'.$sfilePathInfo['basename']) ) - { - if ( !$canCreateFolder ){ - return; - } - if ( $isDir ) { - CKFinder_Connector_Utils_FileSystem::createDirectoryRecursively( $sfilePathInfo['dirname'].'/'.$sfilePathInfo['basename'] ); - return; - } else { - CKFinder_Connector_Utils_FileSystem::createDirectoryRecursively( $sfilePathInfo['dirname']); - } - } else { - return; - } - } - - // extract file - if ( !file_exists($sfilePathInfo['dirname']) ){ - if ( !$canCreateFolder ){ - $this->errorCode = CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED; - $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $originalFileName ); - return; - } - CKFinder_Connector_Utils_FileSystem::createDirectoryRecursively($sfilePathInfo['dirname']); - } - $isAuthorized = (($aclMask & CKFINDER_CONNECTOR_ACL_FILE_UPLOAD ) == CKFINDER_CONNECTOR_ACL_FILE_UPLOAD ); - if ( !$isAuthorized ){ - $this->errorCode = CKFINDER_CONNECTOR_ERROR_COPY_FAILED; - $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $originalFileName); - return; - } - if ( copy('zip://'.$this->filePath.'#'.$originalFileName, $extractPath.$sFileName) ) - { - $this->appendUnzippedNode($this->unzippedNodes,$originalFileName); - // chmod extracted file - if ( is_file($extractPath.$sFileName) && ( $perms = $this->_config->getChmodFiles()) ) - { - $oldumask = umask(0); - chmod( $extractPath.$sFileName, $perms ); - umask( $oldumask ); - } - } - // file extraction failed, add to skipped - else - { - $this->errorCode = CKFINDER_CONNECTOR_ERROR_COPY_FAILED; - $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $originalFileName); - } - } - -} // end of CKFinder_Connector_CommandHandler_Unzip class - -class CKFinder_Connector_CommandHandler_UnzipHere extends CKFinder_Connector_CommandHandler_Unzip -{ - /** - * Handle request and build XML - */ - protected function buildXml() - { - parent::buildXml(); - - $checkedFiles = array(); - if ( !empty($_POST['files']) && is_array($_POST['files']) ){ - foreach ( $_POST['files'] as $file){ - $checkedFiles[$file['name']] = $file; - } - } - - for ($i = 0; $i < $this->zip->numFiles; $i++) - { - $fileName = $this->zip->getNameIndex($i); - if ( !empty($checkedFiles[$fileName]) && $checkedFiles[$fileName]['options'] == 'ok' ) - { - // file was sucessfully unzipped before - $this->appendUnzippedNode($this->unzippedNodes,$fileName); - continue; - } - - $filePathInfo = pathinfo($fileName); - $fileType = 'File'; - $fileStat = $this->zip->statName($i); - if ( empty($filePathInfo['extension']) && empty($fileStat['size']) ){ - $fileType = 'Folder'; - // check if we can create subfolder - if ( !$this->_currentFolder->checkAcl( CKFINDER_CONNECTOR_ACL_FOLDER_CREATE ) ){ - $this->errorCode = CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED; - $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $fileName, $fileType); - continue; - } - } - $extractPath = $this->_currentFolder->getServerPath(); - $extractClientPath = $this->_currentFolder->getClientPath(); - - $sFileName = $this->checkOneFile( $filePathInfo, $fileName ); - // security test failed, add to skipped - if ( false !== $sFileName ) - { - if ( file_exists($extractPath.$sFileName) ) - { - if ( !is_dir($extractPath.$sFileName) ) - { - // file was checked before - if ( !empty($checkedFiles[$fileName]['options']) ) - { - if ( $checkedFiles[$fileName]['options'] == 'autorename') - { - $sFileName = CKFinder_Connector_Utils_FileSystem::autoRename($extractPath,$sFileName); - $this->extractTo($extractPath,$extractClientPath,$filePathInfo,$sFileName,$fileName); - } - elseif ( $checkedFiles[$fileName]['options'] == 'overwrite') - { - if ( !$this->_currentFolder->checkAcl( CKFINDER_CONNECTOR_ACL_FILE_DELETE ) ){ - $this->errorCode = CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED; - $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $fileName, $fileType); - continue; - } - if (!CKFinder_Connector_Utils_FileSystem::unlink($extractPath.$sFileName)) - { - $this->errorCode = CKFINDER_CONNECTOR_ERROR_ACCESS_DENIED; - $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $fileName, $fileType); - } - else - { - $this->extractTo($extractPath,$extractClientPath,$filePathInfo,$sFileName,$fileName); - } - } - else - { - // add to skipped files - $this->appendUnzippedNode($this->unzippedNodes,$fileName,'skip'); - } - } - else - { - $this->errorCode = CKFINDER_CONNECTOR_ERROR_ALREADY_EXIST; - $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $fileName, $fileType); - } - } - } - // file doesn't exist yet - else - { - $this->extractTo($extractPath,$extractClientPath,$filePathInfo,$sFileName,$fileName); - } - } - } - $this->zip->close(); - - $this->_connectorNode->addChild($this->unzippedNodes); - - if ($this->errorCode != CKFINDER_CONNECTOR_ERROR_NONE) { - $this->_connectorNode->addChild($this->skippedFilesNode); - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_ZIP_FAILED); - } - } - - public function onBeforeExecuteCommand( &$command ) - { - if ( $command == 'ExtractHere' ) - { - $this->sendResponse(); - return false; - } - return true ; - } - -} // end of CKFinder_Connector_CommandHandler_UnzipHere class - -class CKFinder_Connector_CommandHandler_UnzipTo extends CKFinder_Connector_CommandHandler_Unzip -{ - /** - * Handle request and build XML - */ - protected function buildXml() - { - parent::buildXml(); - - $extractDir = ( !empty($_POST['extractDir']) ) ? ltrim($_POST['extractDir'],'/') : ''; - $extractDir = CKFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding($extractDir); - if ( preg_match(CKFINDER_REGEX_INVALID_PATH, $extractDir) ){ - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST); - } - $extractPath = CKFinder_Connector_Utils_FileSystem::combinePaths($this->_currentFolder->getServerPath(), $extractDir.'/'); - $extractClientPath = CKFinder_Connector_Utils_FileSystem::combinePaths($this->_currentFolder->getClientPath(),$extractDir); - // acl for upload dir - $_aclConfig = $this->_config->getAccessControlConfig(); - $aclMask = $_aclConfig->getComputedMask($this->_currentFolder->getResourceTypeName(),$extractDir); - - if ( !(($aclMask & CKFINDER_CONNECTOR_ACL_FOLDER_CREATE ) == CKFINDER_CONNECTOR_ACL_FOLDER_CREATE ) ){ - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED); - } - if ( empty( $_POST['force']) && file_exists($extractPath) && is_dir($extractPath) && !CKFinder_Connector_Utils_FileSystem::isEmptyDir($extractPath) ) - { - $dirExists = new CKFinder_Connector_Utils_XmlNode("FolderExists"); - $oErrorNode = new CKFinder_Connector_Utils_XmlNode("Folder"); - $oErrorNode->addAttribute("name", $extractDir); - $dirExists->addChild($oErrorNode); - $this->_connectorNode->addChild($dirExists); - return; - } - elseif ( !empty( $_POST['force']) && $_POST['force'] =='overwrite' ) - { - if ( !(($aclMask & CKFINDER_CONNECTOR_ACL_FILE_UPLOAD | CKFINDER_CONNECTOR_ACL_FILE_DELETE ) == CKFINDER_CONNECTOR_ACL_FILE_UPLOAD | CKFINDER_CONNECTOR_ACL_FILE_DELETE ) ){ - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED); - } - if ( $extractDir && file_exists($extractPath) && is_dir($extractPath) ) - { - if ( !(($aclMask & CKFINDER_CONNECTOR_ACL_FOLDER_CREATE | CKFINDER_CONNECTOR_ACL_FOLDER_DELETE ) == CKFINDER_CONNECTOR_ACL_FOLDER_CREATE | CKFINDER_CONNECTOR_ACL_FOLDER_DELETE ) ){ - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED); - } - if (!CKFinder_Connector_Utils_FileSystem::unlink($extractPath)) - { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_ACCESS_DENIED); - } - } - } - else if ( !empty( $_POST['force']) && $_POST['force'] !== 'merge' ) - { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST); - } - - for ($i = 0; $i < $this->zip->numFiles; $i++) - { - $fileName = $this->zip->getNameIndex($i); - $filePathInfo = pathinfo($fileName); - - $sFileName = $this->checkOneFile( $filePathInfo, $fileName ); - // security test failed, add to skipped - if ( $sFileName ) - { - $this->extractTo($extractPath,$extractClientPath,$filePathInfo,$sFileName,$fileName); - } - } - $this->zip->close(); - - - $this->_connectorNode->addChild($this->unzippedNodes); - - if ($this->errorCode != CKFINDER_CONNECTOR_ERROR_NONE) { - $this->_connectorNode->addChild($this->skippedFilesNode); - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_ZIP_FAILED); - } - } - - public function onBeforeExecuteCommand( &$command ) - { - if ( $command == 'ExtractTo'){ - $this->sendResponse(); - return false; - } - return true ; - } - -} // end of CKFinder_Connector_CommandHandler_UnzipTo class - - -class CKFinder_Connector_CommandHandler_CreateZip extends CKFinder_Connector_CommandHandler_XmlCommandHandlerBase -{ - protected $_config; - - /** - * Get private zip plugin config - * - * @access protected - * @return array - */ - protected function getConfig(){ - $config = array(); - - $config['zipMaxSize'] = 'default'; - if (isset($GLOBALS['config']['ZipMaxSize']) && (string)$GLOBALS['config']['ZipMaxSize']!='default' ){ - $config['zipMaxSize'] = CKFinder_Connector_Utils_Misc::returnBytes((string)$GLOBALS['config']['ZipMaxSize']); - } - - return $config; - } - - /** - * Checks given file for security - * - * @param SplFileInfo $file - * @access protected - * @return bool - */ - protected function checkOneFile($file) - { - $resourceTypeInfo = $this->_currentFolder->getResourceTypeConfig(); - $_aclConfig = $this->_config->getAccessControlConfig(); - $directory = str_replace('\\','/', $resourceTypeInfo->getDirectory()); - $fileName = CKFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding($file->getFilename()); - - if ($this->_config->forceAscii()) { - $fileName = CKFinder_Connector_Utils_FileSystem::convertToAscii($fileName); - } - $pathName = str_replace('\\','/', pathinfo($file->getPathname(), PATHINFO_DIRNAME) ); - $pathName = CKFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding($pathName); - - // acl - $aclMask = $_aclConfig->getComputedMask($this->_currentFolder->getResourceTypeName(), str_ireplace($directory,'',$pathName)); - $isAuthorized = (($aclMask & CKFINDER_CONNECTOR_ACL_FILE_VIEW) == CKFINDER_CONNECTOR_ACL_FILE_VIEW); - if ( !$isAuthorized ){ - return false; - } - - // if it is a folder fileName represents the dir - if ( $file->isDir() && ( !CKFinder_Connector_Utils_FileSystem::checkFolderPath($fileName) || $resourceTypeInfo->checkIsHiddenPath($fileName) ) ){ - return false; - } - // folder name - if ( !CKFinder_Connector_Utils_FileSystem::checkFolderPath($pathName) ){ - return false; - } - - // is hidden - if ( $resourceTypeInfo->checkIsHiddenPath($pathName) || $resourceTypeInfo->checkIsHiddenFile($fileName) ){ - return false; - } - - // extension - if ( !$resourceTypeInfo->checkExtension($fileName) || !CKFinder_Connector_Utils_FileSystem::checkFileName($fileName) ){ - return false; - } - - return true; - } - - /** - * Get list of all files in given directory, including sub-directories - * - * @param string $directory - * @param int $zipMaxSize Maximum zip file size - * @return array $allFiles - */ - protected function getFilesRecursively( $directory, $zipMaxSize ) - { - $allFiles = array(); - $_zipFilesSize = 0; - $serverPath = str_replace('\\','/',$directory); - - foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory), RecursiveIteratorIterator::CHILD_FIRST) as $file ) { - if ( !$this->checkOneFile($file) ){ - continue; - } - if ( !empty($zipMaxSize) ){ - clearstatcache(); - $_zipFilesSize += $file->getSize(); - if ( $_zipFilesSize > $zipMaxSize ) { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_CREATED_FILE_TOO_BIG); - } - } - $pathName = str_replace('\\','/',$file->getPathname()); - if ( $file->isDir() ){ - // skip dot folders on unix systems ( do not try to use isDot() as $file is not a DirectoryIterator obj ) - if ( in_array($file->getFilename(),array('..','.')) ){ - continue; - } - if ($pathName != rtrim($serverPath,'/')){ - $allFiles[ ltrim(str_ireplace(rtrim($serverPath,'/'),'',$pathName),'/') ] = ''; - } - } else { - $allFiles[$pathName] = str_ireplace($serverPath,'',$pathName); - } - } - - return $allFiles; - } - - /** - * Handle request and build XML - */ - public function buildXml() - { - if (!extension_loaded('zip')) { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_COMMAND); - } - - $this->checkConnector(); - $this->checkRequest(); - - if ( !$this->_currentFolder->checkAcl(CKFINDER_CONNECTOR_ACL_FILE_UPLOAD)) { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED); - } - - $this->_config =& CKFinder_Connector_Core_Factory::getInstance("Core_Config"); - $currentResourceTypeConfig = $this->_currentFolder->getResourceTypeConfig(); - $_sServerDir = $this->_currentFolder->getServerPath(); - - $files = array(); - - $_zipFilesSize = 0; - $config = $this->getConfig(); - $zipMaxSize = $config['zipMaxSize']; - if ( !empty($zipMaxSize) && $zipMaxSize == 'default' ){ - $zipMaxSize = $currentResourceTypeConfig->getMaxSize(); - } - - $_isBasket = ( isset($_POST['basket']) && $_POST['basket'] == 'true' )? true : false; - - if ( !empty($_POST['files'])) - { - - $_aclConfig = $this->_config->getAccessControlConfig(); - $aclMasks = array(); - $_resourceTypeConfig = array(); - - foreach ( $_POST['files'] as $arr ){ - if ( empty($arr['name']) || empty($arr['type']) || empty($arr['folder']) ) { - continue; - } - // file name - $name = CKFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding($arr['name']); - // resource type - $type = $arr['type']; - // client path - $path = CKFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding($arr['folder']); - - // check #1 (path) - if (!CKFinder_Connector_Utils_FileSystem::checkFileName($name) || preg_match(CKFINDER_REGEX_INVALID_PATH, $path)) { - continue; - } - - // get resource type config for current file - if (!isset($_resourceTypeConfig[$type])) { - $_resourceTypeConfig[$type] = $this->_config->getResourceTypeConfig($type); - } - - // check #2 (resource type) - if (is_null($_resourceTypeConfig[$type])) { - continue; - } - - // check #3 (extension) - if (!$_resourceTypeConfig[$type]->checkExtension($name, false)) { - continue; - } - - // check #4 (extension) - when moving to another resource type, double check extension - if ($currentResourceTypeConfig->getName() != $type && !$currentResourceTypeConfig->checkExtension($name, false)) { - continue; - } - - // check #5 (hidden folders) - // cache results - if (empty($checkedPaths[$path])) { - $checkedPaths[$path] = true; - - if ($_resourceTypeConfig[$type]->checkIsHiddenPath($path)) { - continue; - } - } - - // check #6 (hidden file name) - if ($currentResourceTypeConfig->checkIsHiddenFile($name)) { - continue; - } - - // check #7 (Access Control, need file view permission to source files) - if (!isset($aclMasks[$type."@".$path])) { - $aclMasks[$type."@".$path] = $_aclConfig->getComputedMask($type, $path); - } - - $isAuthorized = (($aclMasks[$type."@".$path] & CKFINDER_CONNECTOR_ACL_FILE_VIEW) == CKFINDER_CONNECTOR_ACL_FILE_VIEW); - if (!$isAuthorized) { - continue; - } - - $sourceFilePath = CKFinder_Connector_Utils_FileSystem::combinePaths($_resourceTypeConfig[$type]->getDirectory().$path,$name); - // check #8 (invalid file name) - if (!file_exists($sourceFilePath) || !is_file($sourceFilePath)) { - continue; - } - - // check #9 - max file size - if ( !empty($zipMaxSize) ){ - clearstatcache(); - $_zipFilesSize += filesize($sourceFilePath); - if ( $_zipFilesSize > $zipMaxSize ) { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_CREATED_FILE_TOO_BIG); - } - } - - $zipPathPart = ( $_isBasket ) ? CKFinder_Connector_Utils_FileSystem::combinePaths($type,$path) : ''; - - $files[$sourceFilePath] = $zipPathPart.pathinfo($sourceFilePath,PATHINFO_BASENAME); - } - } - else - { - if (!is_dir($_sServerDir)) { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_FOLDER_NOT_FOUND); - } - $files = $this->getFilesRecursively($_sServerDir,$zipMaxSize); - } - if ( sizeof($files)<1) { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_FILE_NOT_FOUND); - } - // default destination dir - temp - $dest_dir = CKFinder_Connector_Utils_FileSystem::getTmpDir(); - $resourceTypeInfo = $this->_currentFolder->getResourceTypeConfig(); - - // default file name - hash - $zip_filename = substr(md5(serialize($files)), 0, 16).$resourceTypeInfo->getHash().'.zip'; - - // compress files - do not download them - // change destination and name - if ( isset($_POST['download']) && $_POST['download'] == 'false'){ - $dest_dir = $_sServerDir; - if ( isset($_POST['zipName']) && !empty($_POST['zipName'])){ - $zip_filename = CKFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding($_POST['zipName']); - if (!$resourceTypeInfo->checkExtension($zip_filename)) { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_EXTENSION); - } - } - } - if (!CKFinder_Connector_Utils_FileSystem::checkFileName($zip_filename) || $resourceTypeInfo->checkIsHiddenFile($zip_filename)) { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_NAME); - } - if ($this->_config->forceAscii()) { - $zip_filename = CKFinder_Connector_Utils_FileSystem::convertToAscii($zip_filename); - } - - $zipFilePath = CKFinder_Connector_Utils_FileSystem::combinePaths($dest_dir, $zip_filename); - - if (!is_writable(dirname($zipFilePath))) { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_ACCESS_DENIED); - } - - // usually we would need to create zip? - $createZip = true; - - // only if file already exists and we want download it - // do not create new one - because hash of previously created is the same - existing archive is ok - if ( file_exists($zipFilePath) && isset($_POST['download']) && $_POST['download'] == 'true' ){ - $createZip = false; - } - // if we only want to create archive - else - { - if ( file_exists($zipFilePath) && ( !isset($_POST['fileExistsAction']) || !in_array($_POST['fileExistsAction'], array('autorename','overwrite')) ) ){ - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_ALREADY_EXIST); - } - - if ( !$this->_currentFolder->checkAcl( CKFINDER_CONNECTOR_ACL_FILE_UPLOAD )) { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED); - } - // check how to deal with existing file - if ( isset($_POST['fileExistsAction']) && $_POST['fileExistsAction'] == 'autorename' ) - { - if ( !$this->_currentFolder->checkAcl(CKFINDER_CONNECTOR_ACL_FILE_UPLOAD | CKFINDER_CONNECTOR_ACL_FILE_RENAME )) { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED); - } - $zip_filename = CKFinder_Connector_Utils_FileSystem::autoRename($dest_dir, $zip_filename); - $zipFilePath = CKFinder_Connector_Utils_FileSystem::combinePaths($dest_dir, $zip_filename); - } - elseif ( isset($_POST['fileExistsAction']) && $_POST['fileExistsAction'] == 'overwrite' ) - { - if ( !$this->_currentFolder->checkAcl(CKFINDER_CONNECTOR_ACL_FILE_RENAME | CKFINDER_CONNECTOR_ACL_FILE_DELETE)) { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED); - } - if (!CKFinder_Connector_Utils_FileSystem::unlink($zipFilePath)){ - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_ACCESS_DENIED); - } - } - } - - if ( $createZip ){ - $zip = new ZipArchive(); - $result = $zip->open( $zipFilePath, ZIPARCHIVE::CREATE); - if ( $result !== TRUE ) { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_UNKNOWN); - } - foreach ( $files as $pathname => $filename ){ - if ( !empty($filename) ){ - if ( file_exists($pathname) && is_readable($pathname) ){ - $zip->addFile( $pathname, $filename ); - } - } else { - $zip->addEmptyDir( $pathname ); - } - } - $zip->close(); - } - - $file = new CKFinder_Connector_Utils_XmlNode("ZipFile"); - $file->addAttribute("name", $zip_filename); - $this->_connectorNode->addChild($file); - } - - public function onBeforeExecuteCommand( &$command ) - { - if ( $command == 'CreateZip'){ - $this->sendResponse(); - return false; - } - return true ; - } - -} // end of CKFinder_Connector_CommandHandler_DownloadZip class - -class CKFinder_Connector_CommandHandler_DownloadZip extends CKFinder_Connector_CommandHandler_CreateZip -{ - /** - * Sends generated zip file to the user - */ - protected function sendZipFile() - { - if (!function_exists('ob_list_handlers') || ob_list_handlers()) { - @ob_end_clean(); - } - header("Content-Encoding: none"); - - $this->checkConnector(); - $this->checkRequest(); - - // empty wystarczy - if ( empty($_GET['FileName']) ){ - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_FILE_NOT_FOUND); - } - - $resourceTypeInfo = $this->_currentFolder->getResourceTypeConfig(); - $hash = $resourceTypeInfo->getHash(); - if ( $hash !== $_GET['hash'] || $hash !== substr($_GET['FileName'],16,16) ){ - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST); - } - - if (!$this->_currentFolder->checkAcl(CKFINDER_CONNECTOR_ACL_FILE_VIEW)) { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED); - } - - $fileName = CKFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding(trim($_GET['FileName'])); - - if (!CKFinder_Connector_Utils_FileSystem::checkFileName($fileName)) { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST); - } - - if ( strtolower(pathinfo($fileName, PATHINFO_EXTENSION)) !== 'zip'){ - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_EXTENSION); - } - - $dest_dir = CKFinder_Connector_Utils_FileSystem::getTmpDir(); - $filePath = CKFinder_Connector_Utils_FileSystem::combinePaths($dest_dir,$fileName); - if ( !file_exists($filePath) || !is_file($filePath)) { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_FILE_NOT_FOUND); - } - if (!is_readable($filePath)) { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_ACCESS_DENIED); - } - - $zipFileName = CKFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding(trim($_GET['ZipName'])); - if (!CKFinder_Connector_Utils_FileSystem::checkFileName($zipFileName)) { - $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST); - } - $fileFilename = pathinfo($zipFileName,PATHINFO_BASENAME ); - - header("Content-Encoding: none"); - header("Cache-Control: cache, must-revalidate"); - header("Pragma: public"); - header("Expires: 0"); - $user_agent = !empty($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ""; - $encodedName = str_replace("\"", "\\\"", $fileFilename); - if (strpos($user_agent, "MSIE") !== false) { - $encodedName = str_replace(array("+", "%2E"), array(" ", "."), urlencode($encodedName)); - } - header("Content-type: application/octet-stream; name=\"" . $fileFilename . "\""); - header("Content-Disposition: attachment; filename=\"" . $encodedName. "\""); - header("Content-Length: " . filesize($filePath)); - CKFinder_Connector_Utils_FileSystem::sendFile($filePath); - exit; - } - - public function onBeforeExecuteCommand( &$command ) - { - if ( $command == 'DownloadZip'){ - $this->sendZipFile(); - return false; - } - return true ; - } - -} // end of CKFinder_Connector_CommandHandler_DownloadZip - -if (extension_loaded('zip')) -{ - $CommandHandler_UnzipHere = new CKFinder_Connector_CommandHandler_UnzipHere(); - $CommandHandler_UnzipTo = new CKFinder_Connector_CommandHandler_UnzipTo(); - $CommandHandler_CreateZip = new CKFinder_Connector_CommandHandler_CreateZip(); - $CommandHandler_DownloadZip = new CKFinder_Connector_CommandHandler_DownloadZip(); - $config['Hooks']['BeforeExecuteCommand'][] = array($CommandHandler_UnzipHere, "onBeforeExecuteCommand"); - $config['Hooks']['BeforeExecuteCommand'][] = array($CommandHandler_UnzipTo, "onBeforeExecuteCommand"); - $config['Hooks']['BeforeExecuteCommand'][] = array($CommandHandler_CreateZip, "onBeforeExecuteCommand"); - $config['Hooks']['BeforeExecuteCommand'][] = array($CommandHandler_DownloadZip, "onBeforeExecuteCommand"); - $config['Plugins'][] = 'zip'; -} +_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST); + } + + if (!extension_loaded('zip')) { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_COMMAND); + } + + $this->checkConnector(); + $this->checkRequest(); + + if ( !$this->_currentFolder->checkAcl(CKFINDER_CONNECTOR_ACL_FILE_UPLOAD)) { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED); + } + + if (!isset($_POST["fileName"])) { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_NAME); + } + + $fileName = CKFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding($_POST["fileName"]); + $resourceTypeInfo = $this->_currentFolder->getResourceTypeConfig(); + + if (!$resourceTypeInfo->checkExtension($fileName)) { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_EXTENSION); + } + + if (!CKFinder_Connector_Utils_FileSystem::checkFileName($fileName) || $resourceTypeInfo->checkIsHiddenFile($fileName)) { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST); + } + + $filePath = CKFinder_Connector_Utils_FileSystem::combinePaths($this->_currentFolder->getServerPath(), $fileName); + + if (!file_exists($filePath) || !is_file($filePath)) { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_FILE_NOT_FOUND); + } + + if (!is_writable(dirname($filePath))) { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_ACCESS_DENIED); + } + + if ( strtolower(pathinfo($fileName, PATHINFO_EXTENSION)) !== 'zip'){ + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_EXTENSION); + } + + $zip = new ZipArchive(); + $result = $zip->open($filePath); + if ($result !== TRUE) { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_UNKNOWN); + } + $this->zip = $zip; + $this->filePath = $filePath; + $this->_config =& CKFinder_Connector_Core_Factory::getInstance("Core_Config"); + + // list of unzipped nodes + $this->unzippedNodes = new CKFinder_Connector_Utils_XmlNode("UnzippedFiles"); + + // list of files which could not be unzipped + $this->skippedFilesNode = new CKFinder_Connector_Utils_XmlNode("Errors"); + $this->errorCode = CKFINDER_CONNECTOR_ERROR_NONE; + } + + /** + * Check one file for security reasons + * + * @param object $filePathInfo + * @param string $originalFileName + * @return mixed bool(false) - if security checks fails. Otherwise string - ralative zip archive path with secured filename. + */ + protected function checkOneFile($filePathInfo, $originalFileName ) + { + $resourceTypeInfo = $this->_currentFolder->getResourceTypeConfig(); + + // checked if it is a folder + $fileStat = $this->zip->statName($originalFileName); + if ( empty($filePathInfo['extension']) && empty($fileStat['size']) ){ + $sNewFolderName = CKFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding(rtrim($fileStat['name'],'/')); + if ($this->_config->forceAscii()) { + $sNewFolderName = CKFinder_Connector_Utils_FileSystem::convertToAscii($sNewFolderName); + } + if (!CKFinder_Connector_Utils_FileSystem::checkFolderPath($sNewFolderName) || $resourceTypeInfo->checkIsHiddenFolder($sNewFolderName)) { + $this->errorCode = CKFINDER_CONNECTOR_ERROR_INVALID_NAME; + $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $originalFileName); + return false; + } + + if (!is_writeable($this->_currentFolder->getServerPath())) { + $this->errorCode = CKFINDER_CONNECTOR_ERROR_ACCESS_DENIED; + $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $originalFileName); + return false; + } + + return $originalFileName; + } + + $fileName = CKFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding($filePathInfo['basename']); + $sFileName = CKFinder_Connector_Utils_FileSystem::secureFileName($fileName); + + // max file size + $maxSize = $resourceTypeInfo->getMaxSize(); + if ( $maxSize && $fileStat['size'] > $maxSize ) + { + $this->errorCode = CKFINDER_CONNECTOR_ERROR_UPLOADED_TOO_BIG; + $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $originalFileName); + return false; + } + // extension + if ( !$resourceTypeInfo->checkExtension($sFileName) ) + { + $this->errorCode = CKFINDER_CONNECTOR_ERROR_INVALID_EXTENSION; + $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $originalFileName); + return false; + } + // hidden file + if ( !CKFinder_Connector_Utils_FileSystem::checkFileName($sFileName) || $resourceTypeInfo->checkIsHiddenFile($sFileName) ){ + $this->errorCode = CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST; + $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $originalFileName); + return false; + } + + // unpack file to tmp dir for detecting html and valid image + $dir = CKFinder_Connector_Utils_FileSystem::getTmpDir().'/'; + if ( file_exists($dir.$sFileName) && !CKFinder_Connector_Utils_FileSystem::unlink($dir.$sFileName) ){ + $this->errorCode = CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST; + $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $originalFileName); + return false; + } + if ( copy('zip://'.$this->filePath.'#'.$originalFileName, $dir.$sFileName) ) + { + // html extensions + $htmlExtensions = $this->_config->getHtmlExtensions(); + $sExtension = CKFinder_Connector_Utils_FileSystem::getExtension( $dir.$sFileName ); + if ( $htmlExtensions + && !CKFinder_Connector_Utils_Misc::inArrayCaseInsensitive( $sExtension, $htmlExtensions ) + && CKFinder_Connector_Utils_FileSystem::detectHtml($dir.$sFileName) === true ) + { + $this->errorCode = CKFINDER_CONNECTOR_ERROR_UPLOADED_INVALID; + $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $originalFileName); + return false; + } + + // proper image + $secureImageUploads = $this->_config->getSecureImageUploads(); + if ( $secureImageUploads + && ( $isImageValid = CKFinder_Connector_Utils_FileSystem::isImageValid($dir.$sFileName, $sExtension) ) === false ) + { + $this->errorCode = CKFINDER_CONNECTOR_ERROR_UPLOADED_INVALID; + $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $originalFileName); + return false; + } + } + $sDirName = ($filePathInfo['dirname'] != '.')? $filePathInfo['dirname'].'/' : ''; + + return $sDirName.$sFileName; + } + + /** + * Add error node to the list + * @param obj $oErrorsNode + * @param int $errorCode + * @param string $name + * @param string $type + * @param string $path + */ + protected function appendErrorNode($oErrorsNode, $errorCode=0, $name, $type=null, $path=null) + { + $oErrorNode = new CKFinder_Connector_Utils_XmlNode("Error"); + $oErrorNode->addAttribute("code", $errorCode); + $oErrorNode->addAttribute("name", CKFinder_Connector_Utils_FileSystem::convertToConnectorEncoding($name)); + if ( $type ){ + $oErrorNode->addAttribute("type", $type); + } + if ( $path ){ + $oErrorNode->addAttribute("folder", $path); + } + $oErrorsNode->addChild($oErrorNode); + } + + /** + * Add unzipped node to the list + * @param obj $oUnzippedNodes + * @param string $name + * @param string $action + */ + protected function appendUnzippedNode($oUnzippedNodes, $name, $action='ok') + { + $oUnzippedNode = new CKFinder_Connector_Utils_XmlNode("File"); + $oUnzippedNode->addAttribute("name", CKFinder_Connector_Utils_FileSystem::convertToConnectorEncoding($name)); + $oUnzippedNode->addAttribute("action", $action ); + $oUnzippedNodes->addChild($oUnzippedNode); + } + + /** + * Extract one file from zip archive + * + * @param string $extractPath + * @param string $extractClientPath + * @param array $filePathInfo + * @param string $sFileName + * @param string $originalFileName + */ + protected function extractTo($extractPath, $extractClientPath, $filePathInfo, $sFileName, $originalFileName) + { + $sfilePathInfo = pathinfo($extractPath.$sFileName); + $extractClientPathDir = $filePathInfo['dirname']; + if ( $filePathInfo['dirname'] == '.' ){ + $extractClientPathDir = ''; + } + $folderPath = CKFinder_Connector_Utils_FileSystem::combinePaths($extractClientPath,$extractClientPathDir); + + $_aclConfig = $this->_config->getAccessControlConfig(); + $aclMask = $_aclConfig->getComputedMask($this->_currentFolder->getResourceTypeName(),$folderPath); + $canCreateFolder = (($aclMask & CKFINDER_CONNECTOR_ACL_FOLDER_CREATE ) == CKFINDER_CONNECTOR_ACL_FOLDER_CREATE ); + // create sub-directory of zip archive + if ( empty($sfilePathInfo['extension']) ) + { + $fileStat = $this->zip->statName($originalFileName); + $isDir = false; + if ( $fileStat && empty($fileStat['size']) ){ + $isDir = true; + } + if( !empty($sfilePathInfo['dirname']) && !empty($sfilePathInfo['basename']) && !file_exists($sfilePathInfo['dirname'].'/'.$sfilePathInfo['basename']) ) + { + if ( !$canCreateFolder ){ + return; + } + if ( $isDir ) { + CKFinder_Connector_Utils_FileSystem::createDirectoryRecursively( $sfilePathInfo['dirname'].'/'.$sfilePathInfo['basename'] ); + return; + } else { + CKFinder_Connector_Utils_FileSystem::createDirectoryRecursively( $sfilePathInfo['dirname']); + } + } else { + return; + } + } + + // extract file + if ( !file_exists($sfilePathInfo['dirname']) ){ + if ( !$canCreateFolder ){ + $this->errorCode = CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED; + $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $originalFileName ); + return; + } + CKFinder_Connector_Utils_FileSystem::createDirectoryRecursively($sfilePathInfo['dirname']); + } + $isAuthorized = (($aclMask & CKFINDER_CONNECTOR_ACL_FILE_UPLOAD ) == CKFINDER_CONNECTOR_ACL_FILE_UPLOAD ); + if ( !$isAuthorized ){ + $this->errorCode = CKFINDER_CONNECTOR_ERROR_COPY_FAILED; + $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $originalFileName); + return; + } + if ( copy('zip://'.$this->filePath.'#'.$originalFileName, $extractPath.$sFileName) ) + { + $this->appendUnzippedNode($this->unzippedNodes,$originalFileName); + // chmod extracted file + if ( is_file($extractPath.$sFileName) && ( $perms = $this->_config->getChmodFiles()) ) + { + $oldumask = umask(0); + chmod( $extractPath.$sFileName, $perms ); + umask( $oldumask ); + } + } + // file extraction failed, add to skipped + else + { + $this->errorCode = CKFINDER_CONNECTOR_ERROR_COPY_FAILED; + $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $originalFileName); + } + } + +} // end of CKFinder_Connector_CommandHandler_Unzip class + +class CKFinder_Connector_CommandHandler_UnzipHere extends CKFinder_Connector_CommandHandler_Unzip +{ + /** + * Handle request and build XML + */ + protected function buildXml() + { + parent::buildXml(); + + $checkedFiles = array(); + if ( !empty($_POST['files']) && is_array($_POST['files']) ){ + foreach ( $_POST['files'] as $file){ + $checkedFiles[$file['name']] = $file; + } + } + + for ($i = 0; $i < $this->zip->numFiles; $i++) + { + $fileName = $this->zip->getNameIndex($i); + if ( !empty($checkedFiles[$fileName]) && $checkedFiles[$fileName]['options'] == 'ok' ) + { + // file was sucessfully unzipped before + $this->appendUnzippedNode($this->unzippedNodes,$fileName); + continue; + } + + $filePathInfo = pathinfo($fileName); + $fileType = 'File'; + $fileStat = $this->zip->statName($i); + if ( empty($filePathInfo['extension']) && empty($fileStat['size']) ){ + $fileType = 'Folder'; + // check if we can create subfolder + if ( !$this->_currentFolder->checkAcl( CKFINDER_CONNECTOR_ACL_FOLDER_CREATE ) ){ + $this->errorCode = CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED; + $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $fileName, $fileType); + continue; + } + } + $extractPath = $this->_currentFolder->getServerPath(); + $extractClientPath = $this->_currentFolder->getClientPath(); + + $sFileName = $this->checkOneFile( $filePathInfo, $fileName ); + // security test failed, add to skipped + if ( false !== $sFileName ) + { + if ( file_exists($extractPath.$sFileName) ) + { + if ( !is_dir($extractPath.$sFileName) ) + { + // file was checked before + if ( !empty($checkedFiles[$fileName]['options']) ) + { + if ( $checkedFiles[$fileName]['options'] == 'autorename') + { + $sFileName = CKFinder_Connector_Utils_FileSystem::autoRename($extractPath,$sFileName); + $this->extractTo($extractPath,$extractClientPath,$filePathInfo,$sFileName,$fileName); + } + elseif ( $checkedFiles[$fileName]['options'] == 'overwrite') + { + if ( !$this->_currentFolder->checkAcl( CKFINDER_CONNECTOR_ACL_FILE_DELETE ) ){ + $this->errorCode = CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED; + $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $fileName, $fileType); + continue; + } + if (!CKFinder_Connector_Utils_FileSystem::unlink($extractPath.$sFileName)) + { + $this->errorCode = CKFINDER_CONNECTOR_ERROR_ACCESS_DENIED; + $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $fileName, $fileType); + } + else + { + $this->extractTo($extractPath,$extractClientPath,$filePathInfo,$sFileName,$fileName); + } + } + else + { + // add to skipped files + $this->appendUnzippedNode($this->unzippedNodes,$fileName,'skip'); + } + } + else + { + $this->errorCode = CKFINDER_CONNECTOR_ERROR_ALREADY_EXIST; + $this->appendErrorNode($this->skippedFilesNode, $this->errorCode, $fileName, $fileType); + } + } + } + // file doesn't exist yet + else + { + $this->extractTo($extractPath,$extractClientPath,$filePathInfo,$sFileName,$fileName); + } + } + } + $this->zip->close(); + + $this->_connectorNode->addChild($this->unzippedNodes); + + if ($this->errorCode != CKFINDER_CONNECTOR_ERROR_NONE) { + $this->_connectorNode->addChild($this->skippedFilesNode); + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_ZIP_FAILED); + } + } + + public function onBeforeExecuteCommand( &$command ) + { + if ( $command == 'ExtractHere' ) + { + $this->sendResponse(); + return false; + } + return true ; + } + +} // end of CKFinder_Connector_CommandHandler_UnzipHere class + +class CKFinder_Connector_CommandHandler_UnzipTo extends CKFinder_Connector_CommandHandler_Unzip +{ + /** + * Handle request and build XML + */ + protected function buildXml() + { + parent::buildXml(); + + $extractDir = ( !empty($_POST['extractDir']) ) ? ltrim($_POST['extractDir'],'/') : ''; + $extractDir = CKFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding($extractDir); + if ( preg_match(CKFINDER_REGEX_INVALID_PATH, $extractDir) ){ + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST); + } + $extractPath = CKFinder_Connector_Utils_FileSystem::combinePaths($this->_currentFolder->getServerPath(), $extractDir.'/'); + $extractClientPath = CKFinder_Connector_Utils_FileSystem::combinePaths($this->_currentFolder->getClientPath(),$extractDir); + // acl for upload dir + $_aclConfig = $this->_config->getAccessControlConfig(); + $aclMask = $_aclConfig->getComputedMask($this->_currentFolder->getResourceTypeName(),$extractDir); + + if ( !(($aclMask & CKFINDER_CONNECTOR_ACL_FOLDER_CREATE ) == CKFINDER_CONNECTOR_ACL_FOLDER_CREATE ) ){ + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED); + } + if ( empty( $_POST['force']) && file_exists($extractPath) && is_dir($extractPath) && !CKFinder_Connector_Utils_FileSystem::isEmptyDir($extractPath) ) + { + $dirExists = new CKFinder_Connector_Utils_XmlNode("FolderExists"); + $oErrorNode = new CKFinder_Connector_Utils_XmlNode("Folder"); + $oErrorNode->addAttribute("name", $extractDir); + $dirExists->addChild($oErrorNode); + $this->_connectorNode->addChild($dirExists); + return; + } + elseif ( !empty( $_POST['force']) && $_POST['force'] =='overwrite' ) + { + if ( !(($aclMask & CKFINDER_CONNECTOR_ACL_FILE_UPLOAD | CKFINDER_CONNECTOR_ACL_FILE_DELETE ) == CKFINDER_CONNECTOR_ACL_FILE_UPLOAD | CKFINDER_CONNECTOR_ACL_FILE_DELETE ) ){ + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED); + } + if ( $extractDir && file_exists($extractPath) && is_dir($extractPath) ) + { + if ( !(($aclMask & CKFINDER_CONNECTOR_ACL_FOLDER_CREATE | CKFINDER_CONNECTOR_ACL_FOLDER_DELETE ) == CKFINDER_CONNECTOR_ACL_FOLDER_CREATE | CKFINDER_CONNECTOR_ACL_FOLDER_DELETE ) ){ + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED); + } + if (!CKFinder_Connector_Utils_FileSystem::unlink($extractPath)) + { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_ACCESS_DENIED); + } + } + } + else if ( !empty( $_POST['force']) && $_POST['force'] !== 'merge' ) + { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST); + } + + for ($i = 0; $i < $this->zip->numFiles; $i++) + { + $fileName = $this->zip->getNameIndex($i); + $filePathInfo = pathinfo($fileName); + + $sFileName = $this->checkOneFile( $filePathInfo, $fileName ); + // security test failed, add to skipped + if ( $sFileName ) + { + $this->extractTo($extractPath,$extractClientPath,$filePathInfo,$sFileName,$fileName); + } + } + $this->zip->close(); + + + $this->_connectorNode->addChild($this->unzippedNodes); + + if ($this->errorCode != CKFINDER_CONNECTOR_ERROR_NONE) { + $this->_connectorNode->addChild($this->skippedFilesNode); + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_ZIP_FAILED); + } + } + + public function onBeforeExecuteCommand( &$command ) + { + if ( $command == 'ExtractTo'){ + $this->sendResponse(); + return false; + } + return true ; + } + +} // end of CKFinder_Connector_CommandHandler_UnzipTo class + + +class CKFinder_Connector_CommandHandler_CreateZip extends CKFinder_Connector_CommandHandler_XmlCommandHandlerBase +{ + protected $_config; + + /** + * Get private zip plugin config + * + * @access protected + * @return array + */ + protected function getConfig(){ + $config = array(); + + $config['zipMaxSize'] = 'default'; + if (isset($GLOBALS['config']['ZipMaxSize']) && (string)$GLOBALS['config']['ZipMaxSize']!='default' ){ + $config['zipMaxSize'] = CKFinder_Connector_Utils_Misc::returnBytes((string)$GLOBALS['config']['ZipMaxSize']); + } + + return $config; + } + + /** + * Checks given file for security + * + * @param SplFileInfo $file + * @access protected + * @return bool + */ + protected function checkOneFile($file) + { + $resourceTypeInfo = $this->_currentFolder->getResourceTypeConfig(); + $_aclConfig = $this->_config->getAccessControlConfig(); + $directory = str_replace('\\','/', $resourceTypeInfo->getDirectory()); + $fileName = CKFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding($file->getFilename()); + + if ($this->_config->forceAscii()) { + $fileName = CKFinder_Connector_Utils_FileSystem::convertToAscii($fileName); + } + $pathName = str_replace('\\','/', pathinfo($file->getPathname(), PATHINFO_DIRNAME) ); + $pathName = CKFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding($pathName); + + // acl + $aclMask = $_aclConfig->getComputedMask($this->_currentFolder->getResourceTypeName(), str_ireplace($directory,'',$pathName)); + $isAuthorized = (($aclMask & CKFINDER_CONNECTOR_ACL_FILE_VIEW) == CKFINDER_CONNECTOR_ACL_FILE_VIEW); + if ( !$isAuthorized ){ + return false; + } + + // if it is a folder fileName represents the dir + if ( $file->isDir() && ( !CKFinder_Connector_Utils_FileSystem::checkFolderPath($fileName) || $resourceTypeInfo->checkIsHiddenPath($fileName) ) ){ + return false; + } + // folder name + if ( !CKFinder_Connector_Utils_FileSystem::checkFolderPath($pathName) ){ + return false; + } + + // is hidden + if ( $resourceTypeInfo->checkIsHiddenPath($pathName) || $resourceTypeInfo->checkIsHiddenFile($fileName) ){ + return false; + } + + // extension + if ( !$resourceTypeInfo->checkExtension($fileName) || !CKFinder_Connector_Utils_FileSystem::checkFileName($fileName) ){ + return false; + } + + return true; + } + + /** + * Get list of all files in given directory, including sub-directories + * + * @param string $directory + * @param int $zipMaxSize Maximum zip file size + * @return array $allFiles + */ + protected function getFilesRecursively( $directory, $zipMaxSize ) + { + $allFiles = array(); + $_zipFilesSize = 0; + $serverPath = str_replace('\\','/',$directory); + + foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory), RecursiveIteratorIterator::CHILD_FIRST) as $file ) { + if ( !$this->checkOneFile($file) ){ + continue; + } + if ( !empty($zipMaxSize) ){ + clearstatcache(); + $_zipFilesSize += $file->getSize(); + if ( $_zipFilesSize > $zipMaxSize ) { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_CREATED_FILE_TOO_BIG); + } + } + $pathName = str_replace('\\','/',$file->getPathname()); + if ( $file->isDir() ){ + // skip dot folders on unix systems ( do not try to use isDot() as $file is not a DirectoryIterator obj ) + if ( in_array($file->getFilename(),array('..','.')) ){ + continue; + } + if ($pathName != rtrim($serverPath,'/')){ + $allFiles[ ltrim(str_ireplace(rtrim($serverPath,'/'),'',$pathName),'/') ] = ''; + } + } else { + $allFiles[$pathName] = str_ireplace($serverPath,'',$pathName); + } + } + + return $allFiles; + } + + /** + * Handle request and build XML + */ + public function buildXml() + { + if (!extension_loaded('zip')) { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_COMMAND); + } + + $this->checkConnector(); + $this->checkRequest(); + + if ( !$this->_currentFolder->checkAcl(CKFINDER_CONNECTOR_ACL_FILE_UPLOAD)) { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED); + } + + $this->_config =& CKFinder_Connector_Core_Factory::getInstance("Core_Config"); + $currentResourceTypeConfig = $this->_currentFolder->getResourceTypeConfig(); + $_sServerDir = $this->_currentFolder->getServerPath(); + + $files = array(); + + $_zipFilesSize = 0; + $config = $this->getConfig(); + $zipMaxSize = $config['zipMaxSize']; + if ( !empty($zipMaxSize) && $zipMaxSize == 'default' ){ + $zipMaxSize = $currentResourceTypeConfig->getMaxSize(); + } + + $_isBasket = ( isset($_POST['basket']) && $_POST['basket'] == 'true' )? true : false; + + if ( !empty($_POST['files'])) + { + + $_aclConfig = $this->_config->getAccessControlConfig(); + $aclMasks = array(); + $_resourceTypeConfig = array(); + + foreach ( $_POST['files'] as $arr ){ + if ( empty($arr['name']) || empty($arr['type']) || empty($arr['folder']) ) { + continue; + } + // file name + $name = CKFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding($arr['name']); + // resource type + $type = $arr['type']; + // client path + $path = CKFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding($arr['folder']); + + // check #1 (path) + if (!CKFinder_Connector_Utils_FileSystem::checkFileName($name) || preg_match(CKFINDER_REGEX_INVALID_PATH, $path)) { + continue; + } + + // get resource type config for current file + if (!isset($_resourceTypeConfig[$type])) { + $_resourceTypeConfig[$type] = $this->_config->getResourceTypeConfig($type); + } + + // check #2 (resource type) + if (is_null($_resourceTypeConfig[$type])) { + continue; + } + + // check #3 (extension) + if (!$_resourceTypeConfig[$type]->checkExtension($name, false)) { + continue; + } + + // check #4 (extension) - when moving to another resource type, double check extension + if ($currentResourceTypeConfig->getName() != $type && !$currentResourceTypeConfig->checkExtension($name, false)) { + continue; + } + + // check #5 (hidden folders) + // cache results + if (empty($checkedPaths[$path])) { + $checkedPaths[$path] = true; + + if ($_resourceTypeConfig[$type]->checkIsHiddenPath($path)) { + continue; + } + } + + // check #6 (hidden file name) + if ($currentResourceTypeConfig->checkIsHiddenFile($name)) { + continue; + } + + // check #7 (Access Control, need file view permission to source files) + if (!isset($aclMasks[$type."@".$path])) { + $aclMasks[$type."@".$path] = $_aclConfig->getComputedMask($type, $path); + } + + $isAuthorized = (($aclMasks[$type."@".$path] & CKFINDER_CONNECTOR_ACL_FILE_VIEW) == CKFINDER_CONNECTOR_ACL_FILE_VIEW); + if (!$isAuthorized) { + continue; + } + + $sourceFilePath = CKFinder_Connector_Utils_FileSystem::combinePaths($_resourceTypeConfig[$type]->getDirectory().$path,$name); + // check #8 (invalid file name) + if (!file_exists($sourceFilePath) || !is_file($sourceFilePath)) { + continue; + } + + // check #9 - max file size + if ( !empty($zipMaxSize) ){ + clearstatcache(); + $_zipFilesSize += filesize($sourceFilePath); + if ( $_zipFilesSize > $zipMaxSize ) { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_CREATED_FILE_TOO_BIG); + } + } + + $zipPathPart = ( $_isBasket ) ? CKFinder_Connector_Utils_FileSystem::combinePaths($type,$path) : ''; + + $files[$sourceFilePath] = $zipPathPart.pathinfo($sourceFilePath,PATHINFO_BASENAME); + } + } + else + { + if (!is_dir($_sServerDir)) { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_FOLDER_NOT_FOUND); + } + $files = $this->getFilesRecursively($_sServerDir,$zipMaxSize); + } + if ( sizeof($files)<1) { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_FILE_NOT_FOUND); + } + // default destination dir - temp + $dest_dir = CKFinder_Connector_Utils_FileSystem::getTmpDir(); + $resourceTypeInfo = $this->_currentFolder->getResourceTypeConfig(); + + // default file name - hash + $zip_filename = substr(md5(serialize($files)), 0, 16).$resourceTypeInfo->getHash().'.zip'; + + // compress files - do not download them + // change destination and name + if ( isset($_POST['download']) && $_POST['download'] == 'false'){ + $dest_dir = $_sServerDir; + if ( isset($_POST['zipName']) && !empty($_POST['zipName'])){ + $zip_filename = CKFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding($_POST['zipName']); + if (!$resourceTypeInfo->checkExtension($zip_filename)) { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_EXTENSION); + } + } + } + if (!CKFinder_Connector_Utils_FileSystem::checkFileName($zip_filename) || $resourceTypeInfo->checkIsHiddenFile($zip_filename)) { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_NAME); + } + if ($this->_config->forceAscii()) { + $zip_filename = CKFinder_Connector_Utils_FileSystem::convertToAscii($zip_filename); + } + + $zipFilePath = CKFinder_Connector_Utils_FileSystem::combinePaths($dest_dir, $zip_filename); + + if (!is_writable(dirname($zipFilePath))) { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_ACCESS_DENIED); + } + + // usually we would need to create zip? + $createZip = true; + + // only if file already exists and we want download it + // do not create new one - because hash of previously created is the same - existing archive is ok + if ( file_exists($zipFilePath) && isset($_POST['download']) && $_POST['download'] == 'true' ){ + $createZip = false; + } + // if we only want to create archive + else + { + if ( file_exists($zipFilePath) && ( !isset($_POST['fileExistsAction']) || !in_array($_POST['fileExistsAction'], array('autorename','overwrite')) ) ){ + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_ALREADY_EXIST); + } + + if ( !$this->_currentFolder->checkAcl( CKFINDER_CONNECTOR_ACL_FILE_UPLOAD )) { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED); + } + // check how to deal with existing file + if ( isset($_POST['fileExistsAction']) && $_POST['fileExistsAction'] == 'autorename' ) + { + if ( !$this->_currentFolder->checkAcl(CKFINDER_CONNECTOR_ACL_FILE_UPLOAD | CKFINDER_CONNECTOR_ACL_FILE_RENAME )) { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED); + } + $zip_filename = CKFinder_Connector_Utils_FileSystem::autoRename($dest_dir, $zip_filename); + $zipFilePath = CKFinder_Connector_Utils_FileSystem::combinePaths($dest_dir, $zip_filename); + } + elseif ( isset($_POST['fileExistsAction']) && $_POST['fileExistsAction'] == 'overwrite' ) + { + if ( !$this->_currentFolder->checkAcl(CKFINDER_CONNECTOR_ACL_FILE_RENAME | CKFINDER_CONNECTOR_ACL_FILE_DELETE)) { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED); + } + if (!CKFinder_Connector_Utils_FileSystem::unlink($zipFilePath)){ + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_ACCESS_DENIED); + } + } + } + + if ( $createZip ){ + $zip = new ZipArchive(); + $result = $zip->open( $zipFilePath, ZIPARCHIVE::CREATE); + if ( $result !== TRUE ) { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_UNKNOWN); + } + foreach ( $files as $pathname => $filename ){ + if ( !empty($filename) ){ + if ( file_exists($pathname) && is_readable($pathname) ){ + $zip->addFile( $pathname, $filename ); + } + } else { + $zip->addEmptyDir( $pathname ); + } + } + $zip->close(); + } + + $file = new CKFinder_Connector_Utils_XmlNode("ZipFile"); + $file->addAttribute("name", $zip_filename); + $this->_connectorNode->addChild($file); + } + + public function onBeforeExecuteCommand( &$command ) + { + if ( $command == 'CreateZip'){ + $this->sendResponse(); + return false; + } + return true ; + } + +} // end of CKFinder_Connector_CommandHandler_DownloadZip class + +class CKFinder_Connector_CommandHandler_DownloadZip extends CKFinder_Connector_CommandHandler_CreateZip +{ + /** + * Sends generated zip file to the user + */ + protected function sendZipFile() + { + if (!function_exists('ob_list_handlers') || ob_list_handlers()) { + @ob_end_clean(); + } + header("Content-Encoding: none"); + + $this->checkConnector(); + $this->checkRequest(); + + // empty wystarczy + if ( empty($_GET['FileName']) ){ + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_FILE_NOT_FOUND); + } + + $resourceTypeInfo = $this->_currentFolder->getResourceTypeConfig(); + $hash = $resourceTypeInfo->getHash(); + if ( $hash !== $_GET['hash'] || $hash !== substr($_GET['FileName'],16,16) ){ + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST); + } + + if (!$this->_currentFolder->checkAcl(CKFINDER_CONNECTOR_ACL_FILE_VIEW)) { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED); + } + + $fileName = CKFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding(trim($_GET['FileName'])); + + if (!CKFinder_Connector_Utils_FileSystem::checkFileName($fileName)) { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST); + } + + if ( strtolower(pathinfo($fileName, PATHINFO_EXTENSION)) !== 'zip'){ + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_EXTENSION); + } + + $dest_dir = CKFinder_Connector_Utils_FileSystem::getTmpDir(); + $filePath = CKFinder_Connector_Utils_FileSystem::combinePaths($dest_dir,$fileName); + if ( !file_exists($filePath) || !is_file($filePath)) { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_FILE_NOT_FOUND); + } + if (!is_readable($filePath)) { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_ACCESS_DENIED); + } + + $zipFileName = CKFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding(trim($_GET['ZipName'])); + if (!CKFinder_Connector_Utils_FileSystem::checkFileName($zipFileName)) { + $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST); + } + $fileFilename = pathinfo($zipFileName,PATHINFO_BASENAME ); + + header("Content-Encoding: none"); + header("Cache-Control: cache, must-revalidate"); + header("Pragma: public"); + header("Expires: 0"); + $user_agent = !empty($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ""; + $encodedName = str_replace("\"", "\\\"", $fileFilename); + if (strpos($user_agent, "MSIE") !== false) { + $encodedName = str_replace(array("+", "%2E"), array(" ", "."), urlencode($encodedName)); + } + header("Content-type: application/octet-stream; name=\"" . $fileFilename . "\""); + header("Content-Disposition: attachment; filename=\"" . $encodedName. "\""); + header("Content-Length: " . filesize($filePath)); + CKFinder_Connector_Utils_FileSystem::sendFile($filePath); + exit; + } + + public function onBeforeExecuteCommand( &$command ) + { + if ( $command == 'DownloadZip'){ + $this->sendZipFile(); + return false; + } + return true ; + } + +} // end of CKFinder_Connector_CommandHandler_DownloadZip + +if (extension_loaded('zip')) +{ + $CommandHandler_UnzipHere = new CKFinder_Connector_CommandHandler_UnzipHere(); + $CommandHandler_UnzipTo = new CKFinder_Connector_CommandHandler_UnzipTo(); + $CommandHandler_CreateZip = new CKFinder_Connector_CommandHandler_CreateZip(); + $CommandHandler_DownloadZip = new CKFinder_Connector_CommandHandler_DownloadZip(); + $config['Hooks']['BeforeExecuteCommand'][] = array($CommandHandler_UnzipHere, "onBeforeExecuteCommand"); + $config['Hooks']['BeforeExecuteCommand'][] = array($CommandHandler_UnzipTo, "onBeforeExecuteCommand"); + $config['Hooks']['BeforeExecuteCommand'][] = array($CommandHandler_CreateZip, "onBeforeExecuteCommand"); + $config['Hooks']['BeforeExecuteCommand'][] = array($CommandHandler_DownloadZip, "onBeforeExecuteCommand"); + $config['Plugins'][] = 'zip'; +}