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

Commit

Permalink
Add tar binary support to compression plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
snw35 committed Oct 6, 2016
1 parent 35b87fd commit 66bd0ac
Showing 1 changed file with 173 additions and 54 deletions.
227 changes: 173 additions & 54 deletions core/src/plugins/action.compression/PluginCompression.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,33 @@ class PluginCompression extends Plugin
* @throws \Pydio\Core\Exception\ActionNotFoundException
* @throws \Pydio\Core\Exception\AuthRequiredException
*/

// Multi-platform function taken from stackoverflow
// http://stackoverflow.com/questions/12424787/how-to-check-if-a-shell-command-exists-from-php
// Check that a command exists on the system for use with exec
public function command_exists ($command)
{
$whereIsCommand = (PHP_OS == 'WINNT') ? 'where' : 'which';
$process = proc_open(
"$whereIsCommand $command",
array(
0 => array("pipe", "r"), //STDIN
1 => array("pipe", "w"), //STDOUT
2 => array("pipe", "w"), //STDERR
),
$pipes
);
if ($process !== false) {
$stdout = stream_get_contents($pipes[1]);
$stderr = stream_get_contents($pipes[2]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);
return $stdout != '';
}
return false;
}

public function receiveAction(\Psr\Http\Message\ServerRequestInterface &$requestInterface, \Psr\Http\Message\ResponseInterface &$responseInterface)
{
/** @var \Pydio\Core\Model\ContextInterface $ctx */
Expand All @@ -78,9 +105,9 @@ public function receiveAction(\Psr\Http\Message\ServerRequestInterface &$request
$responseInterface = $responseInterface->withBody($serializableStream);

switch ($requestInterface->getAttribute("action")) {

case "compression":

$archiveName = InputFilter::decodeSecureMagic($httpVars["archive_name"], InputFilter::SANITIZE_FILENAME);
$archiveFormat = $httpVars["type_archive"];
$tabTypeArchive = array(".tar", ".tar.gz", ".tar.bz2");
Expand Down Expand Up @@ -140,51 +167,107 @@ public function receiveAction(\Psr\Http\Message\ServerRequestInterface &$request
$postMessageStatus($messages["compression.17"], Task::STATUS_FAILED);
throw new PydioException($messages["compression.17"]);
}
try {
$tmpArchiveName = tempnam(ApplicationState::getTemporaryFolder(), "tar-compression") . ".tar";
$archive = new PharData($tmpArchiveName);
} catch (Exception $e) {
$postMessageStatus($e->getMessage(), Task::STATUS_FAILED);
throw $e;
}
$counterCompression = 0;
//THE TWO ARRAY ARE MERGED FOR THE FOREACH LOOP
$tabAllFiles = array_combine($tabAllRecursiveFiles, $tabFilesNames);
foreach ($tabAllFiles as $fullPath => $fileName) {
// Builds a shell command that changes to the workspace location in the filesystem, and then
// compresses with tar and any parallel compression utilities that are installed.
if ($this->command_exists("tar")) {
$FileNames = array();
$FolderNames = array();
foreach ($nodes as $node) {
$nodeUrl = $node->getUrl();
if (is_file($nodeUrl) && filesize($nodeUrl) < $maxAuthorizedSize) {
array_push($FileNames, escapeshellarg(substr($nodeUrl, $currentDirUrlLength)));
}
if (is_dir($nodeUrl)) {
array_push($FolderNames, escapeshellarg(substr($nodeUrl, $currentDirUrlLength)));
}
}
if ($archiveFormat == ".tar.gz") {
if ($this->command_exists("pigz")) {
$tarCommand = "tar -I pigz -cf ";
} else {
$tarCommand = "tar -czf ";
}
} elseif ($archiveFormat == ".tar.bz2") {
if ($this->command_exists("lbzip2")) {
$tarCommand = "tar -I lbzip2 -cf ";
} elseif ($this->command_exists("pbzip2")) {
$tarCommand = "tar -I pbzip2 -cf ";
} else {
$tarCommand = "tar -cjf ";
}
} elseif ($archiveFormat == ".tar") {
$tarCommand = "tar -cf ";
} else {
file_put_contents($progressCompressionFileName, "Error : " . $messages["compression.15"]);
throw new PydioException($messages["compression.15"]);
}
$changeDirCommand = "cd " . MetaStreamWrapper::getRealFSReference($currentDirUrl) . " && ";
$compressCommand = $changeDirCommand . $tarCommand . escapeshellarg($archiveName) . " " . implode(" ", $FolderNames) . " " . implode(" ", $FileNames);
$cmdExitCode = 0;
$cmdOutput = '';
exec($compressCommand, $cmdOutput, $cmdExitCode);
if ($cmdExitCode > 0) {
file_put_contents($progressCompressionFileName, "Error : " . $messages["compression.15"]);
throw new PydioException($messages["compression.15"]);
}
} else {
// If tar command is not found, compress with PHP Phar instead
try {
$archive->addFile(MetaStreamWrapper::getRealFSReference($fullPath), $fileName);
$counterCompression++;
$percent = round(($counterCompression / count($tabAllFiles)) * 100, 0, PHP_ROUND_HALF_DOWN);
$postMessageStatus(sprintf($messages["compression.6"], $percent . " %"), Task::STATUS_RUNNING, $percent);
$tmpArchiveName = tempnam(ApplicationState::getAjxpTmpDir(), "tar-compression") . ".tar";
$archive = new PharData($tmpArchiveName);
} catch (Exception $e) {
unlink($tmpArchiveName);
$postMessageStatus($e->getMessage(), Task::STATUS_FAILED);
throw $e;
}
}
$finalArchive = $tmpArchiveName;
if ($typeArchive != ".tar") {
$archiveTypeCompress = substr(strrchr($typeArchive, "."), 1);
$postMessageStatus(sprintf($messages["compression.7"], strtoupper($archiveTypeCompress)), Task::STATUS_RUNNING);
if ($archiveTypeCompress == "gz") {
$archive->compress(Phar::GZ);
} elseif ($archiveTypeCompress == "bz2") {
$archive->compress(Phar::BZ2);
$counterCompression = 0;
//THE TWO ARRAY ARE MERGED FOR THE FOREACH LOOP
$tabAllFiles = array_combine($tabAllRecursiveFiles, $tabFilesNames);
foreach ($tabAllFiles as $fullPath => $fileName) {
try {
$archive->addFile(MetaStreamWrapper::getRealFSReference($fullPath), $fileName);
$counterCompression++;
$percent = round(($counterCompression / count($tabAllFiles)) * 100, 0, PHP_ROUND_HALF_DOWN);
$postMessageStatus(sprintf($messages["compression.6"], $percent . " %"), Task::STATUS_RUNNING, $percent);
} catch (Exception $e) {
unlink($tmpArchiveName);
$postMessageStatus($e->getMessage(), Task::STATUS_FAILED);
throw $e;
}
}
$finalArchive = $tmpArchiveName;
if ($typeArchive != ".tar") {
$archiveTypeCompress = substr(strrchr($typeArchive, "."), 1);
$postMessageStatus(sprintf($messages["compression.7"], strtoupper($archiveTypeCompress)), Task::STATUS_RUNNING);
if ($archiveTypeCompress == "gz") {
$archive->compress(Phar::GZ);
} elseif ($archiveTypeCompress == "bz2") {
$archive->compress(Phar::BZ2);
}
$finalArchive = $tmpArchiveName . "." . $archiveTypeCompress;
}
$finalArchive = $tmpArchiveName . "." . $archiveTypeCompress;
}

$newNode = new AJXP_Node($currentDirUrl . $archiveName);
$destArchive = $newNode->getRealFile();
rename($finalArchive, $destArchive);
Controller::applyHook("node.before_create", array($newNode, filesize($destArchive)));

if (file_exists($tmpArchiveName)) {
unlink($tmpArchiveName);
unlink(substr($tmpArchiveName, 0, -4));
}
Controller::applyHook("node.change", array(null, $newNode, false), true);
$postMessageStatus("Finished", Task::STATUS_COMPLETE);
break;

// End of Phar compression section
}

$newNode = new AJXP_Node($currentDirUrl . $archiveName);
$destArchive = $newNode->getRealFile();
rename($finalArchive, $destArchive);
Controller::applyHook("node.before_create", array($newNode, filesize($destArchive)));
if (file_exists($tmpArchiveName)) {
unlink($tmpArchiveName);
unlink(substr($tmpArchiveName, 0, -4));
}
Controller::applyHook("node.change", array(null, $newNode, false), true);
$postMessageStatus("Finished", Task::STATUS_COMPLETE);

break;

case "extraction":
Expand Down Expand Up @@ -238,29 +321,65 @@ public function receiveAction(\Psr\Http\Message\ServerRequestInterface &$request

mkdir($currentDirUrl . $onlyFileName, 0777, true);
chmod(MetaStreamWrapper::getRealFSReference($currentDirUrl . $onlyFileName), 0777);
try {
$archive = new PharData(MetaStreamWrapper::getRealFSReference($currentAllPydioPath));
$fichiersArchive = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($pharCurrentAllPydioPath));
foreach ($fichiersArchive as $file) {
$fileGetPathName = $file->getPathname();
if ($file->isDir()) {
continue;

// Builds a command that will use any parallel extraction utilities installed to extract an archive file though tar.
if ($this->command_exists("tar")) {
if ($pathInfoCurrentAllPydioPath == "gz") {
if ($this->command_exists("pigz")) {
$tarCommand = "tar -I pigz -xf ";
} else {
$tarCommand = "tar -xzf ";
}
$fileNameInArchive = substr(strstr($fileGetPathName, $fileArchive), strlen($fileArchive) + 1);
try {
$archive->extractTo(MetaStreamWrapper::getRealFSReference($currentDirUrl . $onlyFileName), $fileNameInArchive, false);
} catch (Exception $e) {
$postMessageStatus($e->getMessage(), Task::STATUS_FAILED);
throw new PydioException($e);
} elseif ($pathInfoCurrentAllPydioPath == "bz2") {
if ($this->command_exists("lbzip2")) {
$tarCommand = "tar -I lbzip2 -xf ";
} elseif ($this->command_exists("pbzip2")) {
$tarCommand = "tar -I pbzip2 -xf ";
} else {
$tarCommand = "tar -xjf ";
}
} elseif ($pathInfoCurrentAllPydioPath == "tar") {
$tarCommand = "tar -xf ";
} else {
file_put_contents($progressExtractFileName, "Error : " . $messages["compression.15"]);
throw new PydioException($messages["compression.15"]);
}
$extractCommand = $tarCommand . escapeshellarg(MetaStreamWrapper::getRealFSReference($currentDirUrl . $fileArchive)) . " -C " . escapeshellarg(MetaStreamWrapper::getRealFSReference($currentDirUrl . $onlyFileName));
$cmdExitCode = 0;
$cmdOutput = '';
exec($extractCommand, $cmdOutput, $cmdExitCode);
if ($cmdExitCode > 0) {
file_put_contents($progressExtractFileName, "Error : " . $messages["compression.15"]);
throw new PydioException($messages["compression.15"]);
}
} else {
// If tar command is not found, extract using PHP Phar instead
try {
$archive = new PharData(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);
try {
$archive->extractTo(MetaStreamWrapper::getRealFSReference($currentDirUrl . $onlyFileName), $fileNameInArchive, false);
} catch (Exception $e) {
$postMessageStatus($e->getMessage(), Task::STATUS_FAILED);
throw new PydioException($e);
}
$counterExtract++;
$progress = round(($counterExtract / $archive->count()) * 100, 0, PHP_ROUND_HALF_DOWN);
$postMessageStatus(sprintf($messages["compression.13"], $progress . "%"), Task::STATUS_RUNNING, $progress);
}
$counterExtract++;
$progress = round(($counterExtract / $archive->count()) * 100, 0, PHP_ROUND_HALF_DOWN);
$postMessageStatus(sprintf($messages["compression.13"], $progress . "%"), Task::STATUS_RUNNING, $progress);
} catch (Exception $e) {
$postMessageStatus($e->getMessage(), Task::STATUS_FAILED);
throw new PydioException($e);
}
} catch (Exception $e) {
$postMessageStatus($e->getMessage(), Task::STATUS_FAILED);
throw new PydioException($e);
// End of Phar extraction section
}

$postMessageStatus("Done", Task::STATUS_COMPLETE, 100);
$newNode = new AJXP_Node($currentDirUrl . $onlyFileName);
$nodesDiff = new NodesDiff();
Expand Down

0 comments on commit 66bd0ac

Please sign in to comment.