%PDF- %PDF-
| Direktori : /www/varak.net/nextcloud.varak.net/apps_old/apps/passwords/lib/Command/ |
| Current File : /www/varak.net/nextcloud.varak.net/apps_old/apps/passwords/lib/Command/BackupImportCommand.php |
<?php
/**
* This file is part of the Passwords App
* created by Marius David Wieschollek
* and licensed under the AGPL.
*/
namespace OCA\Passwords\Command;
use Exception;
use OCA\Passwords\Helper\Backup\BackupMigrationHelper;
use OCA\Passwords\Services\BackupService;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\Files\SimpleFS\ISimpleFile;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Class BackupImportCommand
*
* @package OCA\Passwords\Command
*/
class BackupImportCommand extends Command {
/**
* @var BackupService
*/
protected BackupService $backupService;
/**
* @var BackupMigrationHelper
*/
protected BackupMigrationHelper $migrationHelper;
/**
* BackupImportCommand constructor.
*
* @param BackupService $backupService
* @param BackupMigrationHelper $migrationHelper
*/
public function __construct(BackupService $backupService, BackupMigrationHelper $migrationHelper) {
$this->backupService = $backupService;
$this->migrationHelper = $migrationHelper;
parent::__construct();
}
/**
*
*/
protected function configure(): void {
$this->setName('passwords:backup:import')
->addArgument('file', InputArgument::REQUIRED, 'The location of the backup file')
->setDescription('Import a backup from a file');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
*
* @return int
* @throws NotPermittedException
* @throws Exception
*/
protected function execute(InputInterface $input, OutputInterface $output): int {
$file = realpath($input->getArgument('file'));
[$importFile, $isCompressed] = $this->checkIfFileCanBeRead($file);
$json = $this->readFile($file, $isCompressed);
$json = $this->validateData($json);
[$name, $data] = $this->encodeData($importFile, $json);
$backup = $this->createBackup($name, $data);
$info = $this->backupService->getBackupInfo($backup);
$output->writeln(sprintf('Imported backup: %s, %s %s', $info['label'], $info['size'], $info['format']));
return 0;
}
/**
* @param string $file
*
* @return array
* @throws NotFoundException
* @throws Exception
*/
protected function checkIfFileCanBeRead(string $file): array {
if(!$file || !is_file($file) || !is_readable($file)) throw new NotFoundException();
$importFile = basename($file);
if(!preg_match('/[\w+\-.](\.json(\.gz)?)$/', $importFile, $matches)) {
throw new Exception('Invalid file type');
}
$isCompressed = isset($matches[2]);
if($isCompressed && !extension_loaded('zlib')) {
throw new Exception('PHP extension zlib is required to import compressed backups.');
}
return [$importFile, $isCompressed];
}
/**
* @param $file
* @param $isCompressed
*
* @return array
*/
protected function readFile(string $file, bool $isCompressed): array {
$data = file_get_contents($file);
if($isCompressed) {
$data = gzdecode($data);
}
return json_decode($data, true);
}
/**
* @param array $json
*
* @return array
* @throws Exception
*/
protected function validateData(array $json): array {
if(!isset($json['version']) || $json['version'] < 100 || !isset($json['keys'])) {
throw new Exception('The file does not contain a valid server backup');
}
return $this->migrationHelper->convert($json);
}
/**
* @param $importFile
* @param array $json
*
* @return array
*/
protected function encodeData($importFile, array $json): array {
$label = substr($importFile, 0, strrpos($importFile, '.json'));
if(strlen($label) > 20) $label = substr($label, 0, 20);
$name = $label.'.json';
$data = json_encode($json);
if(extension_loaded('zlib')) {
$name .= '.gz';
$data = gzencode($data);
}
return [$name, $data];
}
/**
* @param $name
* @param $data
*
* @return ISimpleFile
* @throws NotFoundException
* @throws NotPermittedException
*/
protected function createBackup($name, $data): ISimpleFile {
$folder = $this->backupService->getBackupFolder();
if($folder->fileExists($name)) {
$oldFile = $folder->getFile($name);
$oldFile->delete();
}
$file = $folder->newFile($name);
$file->putContent($data);
return $file;
}
}