308 строки
7.1 KiB
PHP
308 строки
7.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
/**
|
|
* Nextcloud - Backup now. Restore later.
|
|
*
|
|
* This file is licensed under the Affero General Public License version 3 or
|
|
* later. See the COPYING file.
|
|
*
|
|
* @author Maxence Lange <maxence@artificial-owl.com>
|
|
* @copyright 2021, Maxence Lange <maxence@artificial-owl.com>
|
|
* @license GNU AGPL version 3 or any later version
|
|
*
|
|
* This program 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.
|
|
*
|
|
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
|
|
namespace OCA\Backup;
|
|
|
|
use Composer\Autoload\ClassLoader;
|
|
use Exception;
|
|
use OC\Config;
|
|
use OC\Logger;
|
|
use OCA\Backup\Service\PointService;
|
|
use OCP\IConfig;
|
|
use OCP\ILogger;
|
|
use Symfony\Component\Console\Input\ArgvInput;
|
|
use Symfony\Component\Console\Input\InputArgument;
|
|
use Symfony\Component\Console\Input\InputDefinition;
|
|
use Symfony\Component\Console\Input\InputOption;
|
|
use Symfony\Component\Console\Output\ConsoleOutput;
|
|
use ZipArchive;
|
|
|
|
echo "\n" . 'At this moment, this script will not works. Sorry.' . "\n";
|
|
echo 'Please follow online documentation to restore your backup.'. "\n\n";
|
|
|
|
exit();
|
|
|
|
/**
|
|
* extracting app files
|
|
*/
|
|
if (!extractAppFiles()) {
|
|
exit();
|
|
}
|
|
|
|
|
|
/**
|
|
* init few stuff.
|
|
*/
|
|
$verbose = false;
|
|
if (in_array('-v', $argv) || in_array('--verbose', $argv)) {
|
|
$verbose = true;
|
|
}
|
|
|
|
|
|
/**
|
|
* loading libs.
|
|
*/
|
|
if ($verbose) {
|
|
echo 'Loading libraries.' . "\n";
|
|
}
|
|
|
|
$classes = [
|
|
'Service\ChunkService',
|
|
'Service\CliService',
|
|
'Service\ConfigService',
|
|
'Service\EncryptService',
|
|
'Service\FilesService',
|
|
|
|
'Model\ArchiveFile',
|
|
'Model\Backup',
|
|
'Model\BackupArchive',
|
|
'Model\BackupChunk',
|
|
'Model\BackupOptions',
|
|
'Model\Error',
|
|
'Model\RemoteStorage',
|
|
|
|
'ISqlDump',
|
|
'SqlDump\SqlDumpMySQL',
|
|
|
|
'Exceptions\ArchiveCreateException',
|
|
'Exceptions\ArchiveNotFoundException',
|
|
'Exceptions\BackupFolderException',
|
|
'Exceptions\BackupScriptNotFoundException',
|
|
'Exceptions\VersionException',
|
|
'Exceptions\EncryptionKeyException',
|
|
'Exceptions\ArchiveDeleteException',
|
|
'Exceptions\BackupAppCopyException',
|
|
'Exceptions\BackupNotFoundException',
|
|
];
|
|
|
|
$mockup = [
|
|
'OCP\IConfig',
|
|
'OC\Config',
|
|
'OCP\ILogger',
|
|
'OC\Logger'
|
|
];
|
|
|
|
loadClasses($classes, $mockup);
|
|
|
|
|
|
/**
|
|
* generate Container.
|
|
*/
|
|
if ($verbose) {
|
|
echo 'Generating Container.' . "\n";
|
|
}
|
|
$container = new DIContainer();
|
|
|
|
$container->registerInterface(IConfig::class, Config::class);
|
|
$container->registerInterface(ILogger::class, Logger::class);
|
|
|
|
|
|
/**
|
|
* init Services.
|
|
*/
|
|
if ($verbose) {
|
|
echo 'Loading Services.' . "\n";
|
|
}
|
|
|
|
try {
|
|
/**
|
|
* @var CliService $cliService
|
|
*/
|
|
$cliService = $container->query(CliService::class);
|
|
} catch (DependencyInjectionException $e) {
|
|
echo $e->getMessage() . "\n";
|
|
exit();
|
|
}
|
|
|
|
|
|
if ($verbose) {
|
|
echo 'App is ready.' . "\n";
|
|
}
|
|
|
|
|
|
/**
|
|
* init input/output
|
|
*/
|
|
$inputDefinition = generateInputDefinition();
|
|
|
|
$input = new ArgvInput($argv, $inputDefinition);
|
|
$output = new ConsoleOutput();
|
|
$output = $output->section();
|
|
$cliService->init($input, $output);
|
|
|
|
if ($verbose) {
|
|
$output->writeln('Switching to <info>better</info> console output!');
|
|
$output->writeln('');
|
|
}
|
|
|
|
|
|
/**
|
|
* parsing backup.json
|
|
*/
|
|
if ($verbose) {
|
|
echo 'Parsing backup.json.' . "\n";
|
|
}
|
|
$json = file_get_contents(PointService::METADATA_FILE);
|
|
|
|
$backup = new Backup();
|
|
$backup->import(json_decode($json, true));
|
|
$backup->setLocal(true);
|
|
|
|
$backup->setEncryptionKey($input->getOption('key'));
|
|
$options = $backup->getOptions();
|
|
$options->setNewRoot($input->getOption('root'));
|
|
$options->setPath($input->getOption('path'));
|
|
$options->setSearch($input->getOption('search'));
|
|
$options->setConfigRaw($input->getOption('config'));
|
|
$options->setChunk($input->getOption('chunk'));
|
|
$options->setAll($input->getOption('all'));
|
|
$options->setArchive($input->getOption('archive'));
|
|
$options->setFixDataDir($input->getOption('fix-datadirectory'));
|
|
|
|
$cliService->displayBackupResume($backup);
|
|
|
|
|
|
/**
|
|
* let's start based on Options
|
|
*/
|
|
try {
|
|
switch ($input->getArgument('action')) {
|
|
|
|
case 'details':
|
|
$cliService->displayBackupDetails($backup);
|
|
break;
|
|
|
|
case 'restore':
|
|
$cliService->displayBackupRestore($backup);
|
|
break;
|
|
|
|
case 'files':
|
|
$cliService->displayFilesList($backup);
|
|
break;
|
|
|
|
default:
|
|
$output->writeln('details/restore/files');
|
|
break;
|
|
}
|
|
} catch (Exception $e) {
|
|
echo "\n" . $e->getMessage() . "\n\n";
|
|
exit();
|
|
}
|
|
|
|
|
|
/**
|
|
* The End.
|
|
*/
|
|
|
|
|
|
/**
|
|
* @return bool
|
|
*/
|
|
function extractAppFiles(): bool {
|
|
if (is_dir(__DIR__ . '/app/')) {
|
|
return true;
|
|
}
|
|
|
|
echo 'Extracting Backup App files (using PHP/ZipArchive) ' . "\n";
|
|
|
|
try {
|
|
$zip = new ZipArchive();
|
|
if (($err = $zip->open('app.zip')) !== true) {
|
|
throw new Exception('failed with error ' . $err);
|
|
}
|
|
|
|
$zip->extractTo('./');
|
|
$zip->close();
|
|
|
|
return true;
|
|
} catch (Exception $e) {
|
|
echo $e->getMessage() . "\n";
|
|
echo 'Extracting Backup App files (using unzip command) ' . "\n";
|
|
system('unzip app.zip');
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* @param array $classes
|
|
* @param array $mockups
|
|
*
|
|
* @return ClassLoader
|
|
*/
|
|
function loadClasses(array $classes, array $mockups): ClassLoader {
|
|
$r = 'OCA\Backup\\';
|
|
$p = __DIR__ . '/app/lib/';
|
|
$map = [];
|
|
foreach ($classes as $class) {
|
|
$classPath = str_replace('\\', '/', $class);
|
|
$map[$r . $class] = $p . $classPath . '.php';
|
|
}
|
|
|
|
foreach ($mockups as $class) {
|
|
$classPath = str_replace('\\', '/', $class);
|
|
$map[$class] = $p . 'Mockup/' . $classPath . '.php';
|
|
}
|
|
|
|
$loader = require 'app/vendor/autoload.php';
|
|
$loader->addClassMap($map);
|
|
$loader->register();
|
|
|
|
return $loader;
|
|
}
|
|
|
|
|
|
/**
|
|
* @return InputDefinition
|
|
*/
|
|
function generateInputDefinition(): InputDefinition {
|
|
$input = new InputDefinition();
|
|
|
|
$input->addOption(new InputOption('verbose', 'v'));
|
|
$input->addOption(new InputOption('full-install'));
|
|
$input->addOption(new InputOption('check'));
|
|
$input->addOption(new InputOption('key', 'k', InputOption::VALUE_REQUIRED, '', ''));
|
|
$input->addOption(new InputOption('root', '', InputOption::VALUE_REQUIRED, '', ''));
|
|
$input->addOption(new InputOption('search', '', InputOption::VALUE_REQUIRED, '', ''));
|
|
$input->addOption(new InputOption('config', '', InputOption::VALUE_REQUIRED, '', '{}'));
|
|
$input->addOption(new InputOption('path', '', InputOption::VALUE_REQUIRED, '', ''));
|
|
$input->addOption(new InputOption('chunk', '', InputOption::VALUE_REQUIRED, '', ''));
|
|
$input->addOption(new InputOption('archive', '', InputOption::VALUE_REQUIRED, '', ''));
|
|
$input->addOption(new InputOption('dir', '', InputOption::VALUE_REQUIRED, '', ''));
|
|
$input->addOption(new InputOption('fix-datadirectory'));
|
|
$input->addOption(new InputOption('all'));
|
|
$input->addArgument(new InputArgument('action'));
|
|
$input->addArgument(new InputArgument('search'));
|
|
|
|
return $input;
|
|
}
|