Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix extraction by sharee #10

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 67 additions & 43 deletions lib/Controller/ExtractionController.php
Original file line number Diff line number Diff line change
@@ -1,31 +1,22 @@
<?php
namespace OCA\Extract\Controller;

use ZipArchive;
use Rar;
namespace OCA\Extract\Controller;

// Only in order to access Filesystem::isFileBlacklisted().
use OC\Files\Filesystem;

use OCP\IRequest;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Controller;
use OCP\Files\NotFoundException;
use OCP\Files\IRootFolder;
use OCP\Files\File;
use OCP\Files\Folder;

use OCP\IL10N;
use OCP\Share\IManager;
use OCP\EventDispatcher\IEventDispatcher;

use \OCP\ILogger;

//use OCP\App\IAppManager;

use OCA\Extract\Service\ExtractionService;

class ExtractionController extends Controller {
class ExtractionController extends Controller
{

/** @var IL10N */
private $l;
Expand All @@ -45,27 +36,26 @@ class ExtractionController extends Controller {
/** @var ExtractionService */
private $extractionService;

public function __construct(
string $AppName
, IRequest $request
, ExtractionService $extractionService
, IRootFolder $rootFolder
, IL10N $l
, ILogger $logger
//, IManager $encryptionManager
, $UserId
){
public function __construct(
string $AppName,
IRequest $request,
ExtractionService $extractionService,
IRootFolder $rootFolder,
IL10N $l,
ILogger $logger,
$UserId
) {
parent::__construct($AppName, $request);
$this->l = $l;
$this->logger = $logger;
//$this->encryptionManager = $encryptionManager;
$this->userId = $UserId;
$this->extractionService = $extractionService;
$this->rootFolder = $rootFolder;
$this->userFolder = $this->rootFolder->getUserFolder($this->userId);
}

private function getFile($directory, $fileName){
private function getFile($directory, $fileName)
{
$fileNode = $this->userFolder->get($directory . '/' . $fileName);
return $fileNode->getStorage()->getLocalFile($fileNode->getInternalPath());
}
Expand All @@ -75,16 +65,16 @@ private function getFile($directory, $fileName){
*
* @param string $fileName The Nextcloud file name.
*
* @param srting $directory The Nextcloud directory name.
* @param string $directory The Nextcloud directory name.
*
* @param string $extractTo The local file-system path of the directory
* with the extracted data, i.e. this is the OS path.
*
* @param null|string $tmpPath The Nextcloud temporary path. This is only
* non-null when extracting from external storage.
*/
private function postExtract(string $fileName, string $directory, string $extractTo, ?string $tmpPath){

private function postExtract(string $fileName, string $directory, string $extractTo, ?string $tmpPath, string $nameOfFile)
{
$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($extractTo));
foreach ($iterator as $file) {
/** @var \SplFileInfo $file */
Expand All @@ -96,21 +86,56 @@ private function postExtract(string $fileName, string $directory, string $extrac
}

$NCDestination = $directory . '/' . $fileName;
if($tmpPath != ""){
if ($tmpPath != "") {
$tmpFolder = $this->rootFolder->get($tmpPath);
$tmpFolder->move($this->userFolder->getFullPath($NCDestination));
}else{
$scanner = new \OC\Files\Utils\Scanner($this->userId, \OC::$server->getDatabaseConnection(), \OC::$server->getLogger());
$scanner->scan($this->userFolder->getFullPath($NCDestination));
} else {
$filePath = "$directory/$fileName";
if($directory == "/") {
$filePath = "$nameOfFile";
}
$info = Filesystem::getView()->getFileInfo("$filePath");
$ownerUID = $info->getOwner()->getUID();
if ($ownerUID != $this->userId) {
$scanner = new \OC\Files\Utils\Scanner($ownerUID, \OC::$server->getDatabaseConnection(), \OC::$server->getLogger());
$matches = preg_split("/^.*\/$ownerUID\//U", $extractTo);
$scanPath = $ownerUID . "/" . $matches[1];
$this->logger->debug("Extracting a shared file, share owner is: $ownerUID, extracted to: $scanPath");
$scanner->scan($scanPath);
} else {
$scanner = new \OC\Files\Utils\Scanner($this->userId, \OC::$server->getDatabaseConnection(), \OC::$server->getLogger());
$scanner->scan($this->userFolder->getFullPath($NCDestination));
}
}
}

/**
* get all storages for $dir
*
* @param string $dir
* @return \OC\Files\Mount\MountPoint[]
*/
protected function getMounts($dir)
{
//TODO: move to the node based fileapi once that's done
\OC_Util::tearDownFS();
\OC_Util::setupFS($this->user);

$mountManager = Filesystem::getMountManager();
$mounts = $mountManager->findIn($dir);
$mounts[] = $mountManager->find($dir);
$mounts = \array_reverse($mounts); //start with the mount of $dir

return $mounts;
}

/**
* The only AJAX callback. This is a hook for ordinary cloud-users, os no admin required.
*
* @NoAdminRequired
*/
public function extract($nameOfFile, $directory, $external, $type){
public function extract($nameOfFile, $directory, $external, $type)
{
$this->logger->warning(\OC::$server->getEncryptionManager()->isEnabled());
if (\OC::$server->getEncryptionManager()->isEnabled()) {
$response = array();
Expand All @@ -124,15 +149,14 @@ public function extract($nameOfFile, $directory, $external, $type){
$extractTo = $dir . '/' . $fileName;

// if the file is un external storage
if($external){

if ($external) {
$appPath = $this->userId . '/' . $this->appName;
try {
$appDirectory = $this->rootFolder->get($appPath);
} catch (\OCP\Files\NotFoundException $e) {
$appDirectory = $this->rootFolder->newFolder($appPath);
}
if(pathinfo($fileName, PATHINFO_EXTENSION) == "tar"){
if (pathinfo($fileName, PATHINFO_EXTENSION) == "tar") {
$archiveDir = pathinfo($fileName, PATHINFO_FILENAME);
} else {
$archiveDir = $fileName;
Expand All @@ -150,33 +174,33 @@ public function extract($nameOfFile, $directory, $external, $type){
} else {
$tmpPath = "";
}

switch ($type) {
case 'zip':
$response = $this->extractionService->extractZip($file, $fileName, $extractTo);
$response = $this->extractionService->extractZip($file, $extractTo);
break;
case 'rar':
$response = $this->extractionService->extractRar($file, $fileName, $extractTo);
$response = $this->extractionService->extractRar($file, $extractTo);
break;
default:
// Check if the file is .tar.gz in order to do the extraction on a single step
if(pathinfo($fileName, PATHINFO_EXTENSION) == "tar"){
if (pathinfo($fileName, PATHINFO_EXTENSION) == "tar") {
$cleanFileName = pathinfo($fileName, PATHINFO_FILENAME);
$extractTo = dirname($extractTo) . '/' . $cleanFileName;
$response = $this->extractionService->extractOther($file, $cleanFileName, $extractTo);
$file = $extractTo . '/' . pathinfo($file, PATHINFO_FILENAME);
$fileName = $cleanFileName;
$response = $this->extractionService->extractOther($file, $fileName, $extractTo);
$response = $this->extractionService->extractOther($file, $extractTo);

// remove .tar file
unlink($file);
}else{
$response = $this->extractionService->extractOther($file, $fileName, $extractTo);
} else {
$response = $this->extractionService->extractOther($file, $extractTo);
}
break;
}

$this->postExtract($fileName, $directory, $extractTo, $tmpPath);
$this->postExtract($fileName, $directory, $extractTo, $tmpPath, $nameOfFile);

return new DataResponse($response);
}
Expand Down
51 changes: 29 additions & 22 deletions lib/Service/ExtractionService.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

/**
* @author Paul Lereverend
* @copyright 2012-2022 Paul Lereverend <[email protected]>
Expand Down Expand Up @@ -26,9 +27,9 @@
use OCP\IL10N;

use ZipArchive;
use Rar;

class ExtractionService {
class ExtractionService
{

/** @var IL10N */
private $l;
Expand All @@ -37,47 +38,51 @@ class ExtractionService {
private $logger;

public function __construct(
IL10N $l
, ILogger $logger
IL10N $l,
ILogger $logger
) {
$this->l = $l;
$this->logger = $logger;
}

public function extractZip($file, $filename, $extractTo){
public function extractZip($file, $extractTo)
{
$response = array();

if (!extension_loaded("zip")){
if (!extension_loaded("zip")) {
$response = array_merge($response, array("code" => 0, "desc" => $this->l->t("Zip extension is not available")));
return $response;
}

$zip = new ZipArchive();

if (!$zip->open($file) === TRUE){
if (!$zip->open($file) === TRUE) {
$response = array_merge($response, array("code" => 0, "desc" => $this->l->t("Cannot open Zip file")));
return $response;
}

$zip->extractTo($extractTo);
$success = $zip->extractTo($extractTo);
$zip->close();
$response = array_merge($response, array("code" => 1));
return $response;
}

public function extractRar($file, $filename, $extractTo){
public function extractRar($file, $extractTo)
{
$response = array();

if (!extension_loaded("rar")){
exec('unrar x ' .escapeshellarg($file). ' -R ' .escapeshellarg($extractTo). '/ -o+',$output,$return);
if(sizeof($output) <= 4){
$response = array_merge($response, array("code" => 0, "desc" => $this->l->t("Oops something went wrong. Check that you have rar extension or unrar installed")));
return $response;
}
}else{
if (!extension_loaded("rar")) {
$output = [];
$return = -1;
exec('unrar x ' . escapeshellarg($file) . ' -R ' . escapeshellarg($extractTo) . '/ -o+', $output, $return);
if (sizeof($output) <= 4) {
$response = array_merge($response, array("code" => 0, "desc" => $this->l->t("Oops something went wrong. Check that you have rar extension or unrar installed")));
return $response;
}
} else {
$rar_file = rar_open($file);
$list = rar_list($rar_file);
foreach($list as $archive_file) {
foreach ($list as $archive_file) {
$entry = rar_entry_get($rar_file, $archive_file->getName());
$entry->extract($extractTo);
}
Expand All @@ -88,14 +93,16 @@ public function extractRar($file, $filename, $extractTo){
return $response;
}

public function extractOther($file, $filename, $extractTo){
public function extractOther($file, $extractTo)
{
$response = array();
$output = [];
$return = -1;
exec('7za -y x ' . escapeshellarg($file) . ' -o' . escapeshellarg($extractTo), $output, $return);

exec('7za -y x ' .escapeshellarg($file). ' -o' .escapeshellarg($extractTo),$output,$return);

if(sizeof($output) <= 5){
if (sizeof($output) <= 5) {
$response = array_merge($response, array("code" => 0, "desc" => $this->l->t("Oops something went wrong. Check that you have p7zip installed")));
$this->logger->error(__METHOD__ . ': ' . $output);
$this->logger->error(__METHOD__ . ': ' . print_r($output, true));
return $response;
}
$response = array_merge($response, array("code" => 1));
Expand Down