Skip to content
This repository has been archived by the owner on Nov 25, 2020. It is now read-only.

Commit

Permalink
New compression plugin to support TAR, TAR.GZ and TAR.BZ2 archive format
Browse files Browse the repository at this point in the history
  • Loading branch information
isma91 committed Oct 13, 2015
1 parent 6d8db1a commit 190b849
Show file tree
Hide file tree
Showing 6 changed files with 531 additions and 0 deletions.
277 changes: 277 additions & 0 deletions core/src/plugins/action.compression/class.PluginCompression.php
@@ -0,0 +1,277 @@
<?php
/*
* Copyright 2007-2013 Charles du Jeu - Abstrium SAS <team (at) pyd.io>
* This file is part of Pydio.
*
* Pydio is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Pydio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Pydio. If not, see <http://www.gnu.org/licenses/>.
*
* The latest code can be found at <http://pyd.io/>.
*/

defined('AJXP_EXEC') or die('Access not allowed');

/**
* Plugin to compress to TAR or TAR.GZ or TAR.BZ2... He can also extract your archives
* @package AjaXplorer_Plugins
* @subpackage Action
*/
class PluginCompression extends AJXP_Plugin
{
/**
* @param String $action
* @param Array $httpVars
* @param Array $fileVars
* @throws Exception
*/
public function receiveAction($action, $httpVars, $fileVars)
{
//TODO : DESTROY THE PROGRESS FILE AT THE END OF THE PROCESS + POSSIBILITY TO CANCEL COMPRESS TO HAVE JUST THE TAR FILE
//VAR CREATION OUTSIDE OF ALL CONDITIONS, THEY ARE MUST HAVE VAR !!
$messages = ConfService::getMessages();
$repository = ConfService::getRepository();
$userSelection = new UserSelection($repository, $httpVars);
$nodes = $userSelection->buildNodes();
$currentDirPath = AJXP_Utils::safeDirname($userSelection->getUniqueNode()->getPath());
$currentDirPath = rtrim($currentDirPath, "/") . "/";
$currentDirUrl = $userSelection->currentBaseUrl().$currentDirPath;
if (empty($httpVars["compression_id"])) {
$compressionId = sha1(rand());
$httpVars["compression_id"] = $compressionId;
} else {
$compressionId = $httpVars["compression_id"];
}
$progressCompressionFileName = $this->getPluginCacheDir(false, true) . DIRECTORY_SEPARATOR . "progressCompressionID-" . $compressionId . ".txt";
if (empty($httpVars["extraction_id"])) {
$extractId = sha1(rand());
$httpVars["extraction_id"] = $extractId;
} else {
$extractId = $httpVars["extraction_id"];
}
$progressExtractFileName = $this->getPluginCacheDir(false, true) . DIRECTORY_SEPARATOR . "progressExtractID-" . $extractId . ".txt";
if ($action == "compression") {
$archiveName = AJXP_Utils::sanitize(AJXP_Utils::decodeSecureMagic($httpVars["archiveName"]), AJXP_SANITIZE_FILENAME);
$archiveFormat = $httpVars["type_archive"];
$tabTypeArchive = [".tar", ".tar.gz", ".tar.bz2"];
$acceptedExtension = false;
foreach ($tabTypeArchive as $extensionArchive) {
if ($extensionArchive == $archiveFormat) {
$acceptedExtension = true;
break;
}
}
if ($acceptedExtension == false) {
throw new AJXP_Exception($messages["compression.16"]);
}
$typeArchive = $httpVars["type_archive"];
//if we can run in background we do it
if (ConfService::backgroundActionsSupported() && !ConfService::currentContextIsCommandLine()) {
$archivePath = $currentDirPath.$archiveName;
file_put_contents($progressCompressionFileName, $messages["compression.5"]);
AJXP_Controller::applyActionInBackground($repository->getId(), "compression", $httpVars);
AJXP_XMLWriter::header();
AJXP_XMLWriter::triggerBgAction("check_compression_status", array(
"repository_id" => $repository->getId(),
"compression_id" => $compressionId,
"archive_path" => SystemTextEncoding::toUTF8($archivePath)
), $messages["compression.5"], true, 4);
AJXP_XMLWriter::close();
return null;
} else {
$maxAuthorizedSize = 4294967296;
$currentDirUrlLength = strlen($currentDirUrl);
$tabFolders = [];
$tabAllRecursiveFiles = [];
$tabFilesNames = [];
foreach ($nodes as $node) {
$nodeUrl = $node->getUrl();
if (is_file($nodeUrl) && filesize($nodeUrl) < $maxAuthorizedSize) {
array_push($tabAllRecursiveFiles, $nodeUrl);
array_push($tabFilesNames, substr($nodeUrl, $currentDirUrlLength));
}
if (is_dir($nodeUrl)) {
array_push($tabFolders, $nodeUrl);
}
}
//DO A FOREACH OR IT'S GONNA HAVE SOME SAMES FILES NAMES
foreach ($tabFolders as $value) {
$dossiers = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($value));
foreach ($dossiers as $file) {
if ($file->isDir()) {
continue;
}
array_push($tabAllRecursiveFiles, $file->getPathname());
array_push($tabFilesNames, substr($file->getPathname(), $currentDirUrlLength));
}
}
try {
$tmpArchiveName = tempnam(AJXP_Utils::getAjxpTmpDir(), "tar-compression") . ".tar";
$archive = new PharData($tmpArchiveName);
} catch (Exception $e) {
throw $e;
}
$counterCompression = 0;
//THE TWO ARRAY ARE MERGED FOR THE FOREACH LOOP
$tabAllFiles = array_combine($tabAllRecursiveFiles, $tabFilesNames);
foreach ($tabAllFiles as $fullPath => $fileName) {
try {
$archive->addFile(AJXP_MetaStreamWrapper::getRealFSReference($fullPath), $fileName);
$counterCompression++;
file_put_contents($progressCompressionFileName, sprintf($messages["compression.6"], ($counterCompression / count($tabAllFiles)) * 100 . " %"));
} catch (Exception $e) {
unlink($tmpArchiveName);
throw $e;
}
}
$finalArchive = $tmpArchiveName;
if ($typeArchive != ".tar") {
$archiveTypeCompress = substr(strrchr($typeArchive, "."), 1);
file_put_contents($progressCompressionFileName, sprintf($messages["compression.7"], strtoupper($archiveTypeCompress)));
if ($archiveTypeCompress == "gz") {
$archive->compress(Phar::GZ);
} elseif ($archiveTypeCompress == "bz2") {
$archive->compress(Phar::BZ2);
}
$finalArchive = $tmpArchiveName . "." . $archiveTypeCompress;
}
$destArchive = AJXP_MetaStreamWrapper::getRealFSReference($currentDirUrl . $archiveName);
rename($finalArchive, $destArchive);
AJXP_Controller::applyHook("node.before_create", array($destArchive, filesize($destArchive)));
if (file_exists($tmpArchiveName)) {
unlink($tmpArchiveName);
unlink(substr($tmpArchiveName, 0, -4));
}
$newNode = new AJXP_Node($currentDirUrl . $archiveName);
AJXP_Controller::applyHook("node.change", array(null, $newNode, false));
file_put_contents($progressCompressionFileName, "SUCCESS");
}
}
elseif ($action == "check_compression_status") {
$archivePath = AJXP_Utils::decodeSecureMagic($httpVars["archive_path"]);
$progressCompression = file_get_contents($progressCompressionFileName);
if ($progressCompression != "SUCCESS") {
AJXP_XMLWriter::header();
AJXP_XMLWriter::triggerBgAction("check_compression_status", array(
"repository_id" => $repository->getId(),
"compression_id" => $compressionId,
"archive_path" => SystemTextEncoding::toUTF8($archivePath)
), $progressCompression, true, 3);
AJXP_XMLWriter::close();
} else {
$newNode = new AJXP_Node($userSelection->currentBaseUrl() . $archivePath);
$nodesDiffs = array("ADD" => array($newNode), "REMOVE" => array(), "UPDATE" => array());
AJXP_Controller::applyHook("node.change", array(null, $newNode, false));
AJXP_XMLWriter::header();
AJXP_XMLWriter::sendMessage($messages["compression.8"], null);
AJXP_XMLWriter::writeNodesDiff($nodesDiffs, false);
AJXP_XMLWriter::close();
unlink($progressCompressionFileName);
}
}
elseif ($action == "extraction") {
$fileArchive = AJXP_Utils::sanitize(AJXP_Utils::decodeSecureMagic($httpVars["file"]), AJXP_SANITIZE_DIRNAME);
$fileArchive = substr(strrchr($fileArchive, DIRECTORY_SEPARATOR), 1);
$authorizedExtension = ["tar" => 4, "gz" => 7, "bz2" => 8];
$acceptedArchive = false;
$extensionLength = 0;
$counterExtract = 0;
$currentAllPydioPath = $currentDirUrl . $fileArchive;
$pharCurrentAllPydioPath = "phar://" . AJXP_MetaStreamWrapper::getRealFSReference($currentAllPydioPath);
$pathInfoCurrentAllPydioPath = pathinfo($currentAllPydioPath)["extension"];
//WE TAKE ONLY TAR, TAR.GZ AND TAR.BZ2 ARCHIVES
foreach ($authorizedExtension as $extension => $strlenExtension) {
if ($pathInfoCurrentAllPydioPath == $extension) {
$acceptedArchive = true;
$extensionLength = $strlenExtension;
break;
}
}
if ($acceptedArchive == false) {
throw new AJXP_Exception($messages["compression.15"]);
}
$onlyFileName = substr($fileArchive, 0, -$extensionLength);
$lastPosOnlyFileName = strrpos($onlyFileName, "-");
$tmpOnlyFileName = substr($onlyFileName, 0, $lastPosOnlyFileName);
$counterDuplicate = substr($onlyFileName, $lastPosOnlyFileName + 1);
if ($lastPosOnlyFileName == false) {
$tmpOnlyFileName = $onlyFileName;
$counterDuplicate = 1;
}
while (file_exists($currentDirUrl . $onlyFileName)) {
$onlyFileName = $tmpOnlyFileName . "-" . $counterDuplicate;
$counterDuplicate++;
}
if (ConfService::backgroundActionsSupported() && !ConfService::currentContextIsCommandLine()) {
file_put_contents($progressExtractFileName, $messages["compression.12"]);
AJXP_Controller::applyActionInBackground($repository->getId(), "extraction", $httpVars);
AJXP_XMLWriter::header();
AJXP_XMLWriter::triggerBgAction("check_extraction_status", array(
"repository_id" => $repository->getId(),
"extraction_id" => $extractId,
"currentDirUrl" => $currentDirUrl,
"onlyFileName" => $onlyFileName
), $messages["compression.12"], true, 3);
AJXP_XMLWriter::close();
return null;
}
mkdir($currentDirUrl . $onlyFileName, 0777, true);
chmod(AJXP_MetaStreamWrapper::getRealFSReference($currentDirUrl . $onlyFileName), 0777);
try {
$archive = new PharData(AJXP_MetaStreamWrapper::getRealFSReference($currentAllPydioPath));
$fichiersArchive = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($pharCurrentAllPydioPath));
foreach ($fichiersArchive as $file) {
$fileGetPathName = $file->getPathname();
if($file->isDir()) {
continue;
}
$fileNameInArchive = substr(strstr($fileGetPathName, $fileArchive), strlen($fileArchive) + 1);
var_dump($currentDirUrl . $onlyFileName . DIRECTORY_SEPARATOR . $fileNameInArchive);
$archive->extractTo(AJXP_MetaStreamWrapper::getRealFSReference($currentDirUrl . $onlyFileName), $fileNameInArchive, false);
$newNode = new AJXP_Node($currentDirUrl . $onlyFileName . DIRECTORY_SEPARATOR . $fileNameInArchive);
AJXP_Controller::applyHook("node.change", array(null, $newNode, false));
$counterExtract++;
file_put_contents($progressExtractFileName, sprintf($messages["compression.12"], ($counterExtract / $archive->count()) * 100 . " %"));
}
} catch (Exception $e) {
throw new AJXP_Exception($e);
}
file_put_contents($progressExtractFileName, "SUCCESS");
}
elseif ($action == "check_extraction_status") {
$currentDirUrl = $httpVars["currentDirUrl"];
$onlyFileName = $httpVars["onlyFileName"];
$progressExtract = file_get_contents($progressExtractFileName);
if ($progressExtract != "SUCCESS") {
AJXP_XMLWriter::header();
AJXP_XMLWriter::triggerBgAction("check_extraction_status", array(
"repository_id" => $repository->getId(),
"extraction_id" => $extractId,
"currentDirUrl" => $currentDirUrl,
"onlyFileName" => $onlyFileName
), $progressExtract, true, 3);
AJXP_XMLWriter::close();
} else {
$newNode = new AJXP_Node($currentDirUrl . $onlyFileName);
$nodesDiffs = array("ADD" => array($newNode), "REMOVE" => array(), "UPDATE" => array());
AJXP_Controller::applyHook("node.change", array(null, $newNode, false));
AJXP_XMLWriter::header();
AJXP_XMLWriter::sendMessage(sprintf($messages["compression.14"], $onlyFileName), null);
AJXP_XMLWriter::writeNodesDiff($nodesDiffs, false);
AJXP_XMLWriter::close();
if (file_exists($progressExtractFileName)) {
unlink($progressExtractFileName);
}
}
}
}
}

0 comments on commit 190b849

Please sign in to comment.