From a4b19a5b1e4079752e33d6eb75c72a47ce048bde Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Wed, 6 Apr 2016 10:40:55 +0200 Subject: Rename files to be PSR-4 compliant --- core/Command/App/CheckCode.php | 181 +++++++++++++ core/Command/App/Disable.php | 71 +++++ core/Command/App/Enable.php | 83 ++++++ core/Command/App/GetPath.php | 62 +++++ core/Command/App/ListApps.php | 119 +++++++++ core/Command/Background/Ajax.php | 33 +++ core/Command/Background/Base.php | 77 ++++++ core/Command/Background/Cron.php | 33 +++ core/Command/Background/WebCron.php | 33 +++ core/Command/Base.php | 160 +++++++++++ core/Command/Check.php | 61 +++++ core/Command/Config/App/DeleteConfig.php | 81 ++++++ core/Command/Config/App/GetConfig.php | 93 +++++++ core/Command/Config/App/SetConfig.php | 89 ++++++ core/Command/Config/Import.php | 195 ++++++++++++++ core/Command/Config/ListConfigs.php | 129 +++++++++ core/Command/Config/System/DeleteConfig.php | 117 ++++++++ core/Command/Config/System/GetConfig.php | 100 +++++++ core/Command/Config/System/SetConfig.php | 198 ++++++++++++++ core/Command/Db/ConvertType.php | 311 +++++++++++++++++++++ core/Command/Db/GenerateChangeScript.php | 58 ++++ core/Command/Encryption/ChangeKeyStorageRoot.php | 270 +++++++++++++++++++ core/Command/Encryption/DecryptAll.php | 160 +++++++++++ core/Command/Encryption/Disable.php | 56 ++++ core/Command/Encryption/Enable.php | 78 ++++++ core/Command/Encryption/EncryptAll.php | 134 ++++++++++ core/Command/Encryption/ListModules.php | 80 ++++++ core/Command/Encryption/SetDefaultModule.php | 68 +++++ core/Command/Encryption/ShowKeyStorageRoot.php | 58 ++++ core/Command/Encryption/Status.php | 56 ++++ core/Command/Integrity/CheckApp.php | 69 +++++ core/Command/Integrity/CheckCore.php | 62 +++++ core/Command/Integrity/SignApp.php | 107 ++++++++ core/Command/Integrity/SignCore.php | 100 +++++++ core/Command/L10n/CreateJs.php | 137 ++++++++++ core/Command/Log/Manage.php | 171 ++++++++++++ core/Command/Log/OwnCloud.php | 124 +++++++++ core/Command/Maintenance/Install.php | 178 ++++++++++++ core/Command/Maintenance/Mimetype/UpdateDB.php | 97 +++++++ core/Command/Maintenance/Mimetype/UpdateJS.php | 129 +++++++++ core/Command/Maintenance/Mode.php | 75 ++++++ core/Command/Maintenance/Repair.php | 91 +++++++ core/Command/Maintenance/SingleUser.php | 78 ++++++ core/Command/Security/ImportCertificate.php | 67 +++++ core/Command/Security/ListCertificates.php | 96 +++++++ core/Command/Security/RemoveCertificate.php | 59 ++++ core/Command/Status.php | 49 ++++ core/Command/Upgrade.php | 295 ++++++++++++++++++++ core/Command/User/Add.php | 154 +++++++++++ core/Command/User/Delete.php | 70 +++++ core/Command/User/LastSeen.php | 74 +++++ core/Command/User/Report.php | 86 ++++++ core/Command/User/ResetPassword.php | 121 +++++++++ core/Controller/AvatarController.php | 327 +++++++++++++++++++++++ core/Controller/LostController.php | 257 ++++++++++++++++++ core/Controller/SetupController.php | 126 +++++++++ core/Controller/UserController.php | 79 ++++++ core/Tags/Controller.php | 128 +++++++++ core/command/app/checkcode.php | 181 ------------- core/command/app/disable.php | 71 ----- core/command/app/enable.php | 83 ------ core/command/app/getpath.php | 62 ----- core/command/app/listapps.php | 119 --------- core/command/background/ajax.php | 33 --- core/command/background/base.php | 77 ------ core/command/background/cron.php | 33 --- core/command/background/webcron.php | 33 --- core/command/base.php | 160 ----------- core/command/check.php | 61 ----- core/command/config/app/deleteconfig.php | 81 ------ core/command/config/app/getconfig.php | 93 ------- core/command/config/app/setconfig.php | 89 ------ core/command/config/import.php | 195 -------------- core/command/config/listconfigs.php | 129 --------- core/command/config/system/deleteconfig.php | 117 -------- core/command/config/system/getconfig.php | 100 ------- core/command/config/system/setconfig.php | 198 -------------- core/command/db/converttype.php | 311 --------------------- core/command/db/generatechangescript.php | 58 ---- core/command/encryption/changekeystorageroot.php | 270 ------------------- core/command/encryption/decryptall.php | 160 ----------- core/command/encryption/disable.php | 56 ---- core/command/encryption/enable.php | 78 ------ core/command/encryption/encryptall.php | 134 ---------- core/command/encryption/listmodules.php | 80 ------ core/command/encryption/setdefaultmodule.php | 68 ----- core/command/encryption/showkeystorageroot.php | 58 ---- core/command/encryption/status.php | 56 ---- core/command/integrity/checkapp.php | 69 ----- core/command/integrity/checkcore.php | 62 ----- core/command/integrity/signapp.php | 107 -------- core/command/integrity/signcore.php | 100 ------- core/command/l10n/createjs.php | 137 ---------- core/command/log/manage.php | 171 ------------ core/command/log/owncloud.php | 124 --------- core/command/maintenance/install.php | 178 ------------ core/command/maintenance/mimetype/updatedb.php | 97 ------- core/command/maintenance/mimetype/updatejs.php | 129 --------- core/command/maintenance/mode.php | 75 ------ core/command/maintenance/repair.php | 91 ------- core/command/maintenance/singleuser.php | 78 ------ core/command/security/importcertificate.php | 67 ----- core/command/security/listcertificates.php | 96 ------- core/command/security/removecertificate.php | 59 ---- core/command/status.php | 49 ---- core/command/upgrade.php | 295 -------------------- core/command/user/add.php | 154 ----------- core/command/user/delete.php | 70 ----- core/command/user/lastseen.php | 74 ----- core/command/user/report.php | 86 ------ core/command/user/resetpassword.php | 121 --------- core/controller/avatarcontroller.php | 327 ----------------------- core/controller/lostcontroller.php | 257 ------------------ core/controller/setupcontroller.php | 126 --------- core/controller/usercontroller.php | 79 ------ core/tags/controller.php | 128 --------- 116 files changed, 6650 insertions(+), 6650 deletions(-) create mode 100644 core/Command/App/CheckCode.php create mode 100644 core/Command/App/Disable.php create mode 100644 core/Command/App/Enable.php create mode 100644 core/Command/App/GetPath.php create mode 100644 core/Command/App/ListApps.php create mode 100644 core/Command/Background/Ajax.php create mode 100644 core/Command/Background/Base.php create mode 100644 core/Command/Background/Cron.php create mode 100644 core/Command/Background/WebCron.php create mode 100644 core/Command/Base.php create mode 100644 core/Command/Check.php create mode 100644 core/Command/Config/App/DeleteConfig.php create mode 100644 core/Command/Config/App/GetConfig.php create mode 100644 core/Command/Config/App/SetConfig.php create mode 100644 core/Command/Config/Import.php create mode 100644 core/Command/Config/ListConfigs.php create mode 100644 core/Command/Config/System/DeleteConfig.php create mode 100644 core/Command/Config/System/GetConfig.php create mode 100644 core/Command/Config/System/SetConfig.php create mode 100644 core/Command/Db/ConvertType.php create mode 100644 core/Command/Db/GenerateChangeScript.php create mode 100644 core/Command/Encryption/ChangeKeyStorageRoot.php create mode 100644 core/Command/Encryption/DecryptAll.php create mode 100644 core/Command/Encryption/Disable.php create mode 100644 core/Command/Encryption/Enable.php create mode 100644 core/Command/Encryption/EncryptAll.php create mode 100644 core/Command/Encryption/ListModules.php create mode 100644 core/Command/Encryption/SetDefaultModule.php create mode 100644 core/Command/Encryption/ShowKeyStorageRoot.php create mode 100644 core/Command/Encryption/Status.php create mode 100644 core/Command/Integrity/CheckApp.php create mode 100644 core/Command/Integrity/CheckCore.php create mode 100644 core/Command/Integrity/SignApp.php create mode 100644 core/Command/Integrity/SignCore.php create mode 100644 core/Command/L10n/CreateJs.php create mode 100644 core/Command/Log/Manage.php create mode 100644 core/Command/Log/OwnCloud.php create mode 100644 core/Command/Maintenance/Install.php create mode 100644 core/Command/Maintenance/Mimetype/UpdateDB.php create mode 100644 core/Command/Maintenance/Mimetype/UpdateJS.php create mode 100644 core/Command/Maintenance/Mode.php create mode 100644 core/Command/Maintenance/Repair.php create mode 100644 core/Command/Maintenance/SingleUser.php create mode 100644 core/Command/Security/ImportCertificate.php create mode 100644 core/Command/Security/ListCertificates.php create mode 100644 core/Command/Security/RemoveCertificate.php create mode 100644 core/Command/Status.php create mode 100644 core/Command/Upgrade.php create mode 100644 core/Command/User/Add.php create mode 100644 core/Command/User/Delete.php create mode 100644 core/Command/User/LastSeen.php create mode 100644 core/Command/User/Report.php create mode 100644 core/Command/User/ResetPassword.php create mode 100644 core/Controller/AvatarController.php create mode 100644 core/Controller/LostController.php create mode 100644 core/Controller/SetupController.php create mode 100644 core/Controller/UserController.php create mode 100644 core/Tags/Controller.php delete mode 100644 core/command/app/checkcode.php delete mode 100644 core/command/app/disable.php delete mode 100644 core/command/app/enable.php delete mode 100644 core/command/app/getpath.php delete mode 100644 core/command/app/listapps.php delete mode 100644 core/command/background/ajax.php delete mode 100644 core/command/background/base.php delete mode 100644 core/command/background/cron.php delete mode 100644 core/command/background/webcron.php delete mode 100644 core/command/base.php delete mode 100644 core/command/check.php delete mode 100644 core/command/config/app/deleteconfig.php delete mode 100644 core/command/config/app/getconfig.php delete mode 100644 core/command/config/app/setconfig.php delete mode 100644 core/command/config/import.php delete mode 100644 core/command/config/listconfigs.php delete mode 100644 core/command/config/system/deleteconfig.php delete mode 100644 core/command/config/system/getconfig.php delete mode 100644 core/command/config/system/setconfig.php delete mode 100644 core/command/db/converttype.php delete mode 100644 core/command/db/generatechangescript.php delete mode 100644 core/command/encryption/changekeystorageroot.php delete mode 100644 core/command/encryption/decryptall.php delete mode 100644 core/command/encryption/disable.php delete mode 100644 core/command/encryption/enable.php delete mode 100644 core/command/encryption/encryptall.php delete mode 100644 core/command/encryption/listmodules.php delete mode 100644 core/command/encryption/setdefaultmodule.php delete mode 100644 core/command/encryption/showkeystorageroot.php delete mode 100644 core/command/encryption/status.php delete mode 100644 core/command/integrity/checkapp.php delete mode 100644 core/command/integrity/checkcore.php delete mode 100644 core/command/integrity/signapp.php delete mode 100644 core/command/integrity/signcore.php delete mode 100644 core/command/l10n/createjs.php delete mode 100644 core/command/log/manage.php delete mode 100644 core/command/log/owncloud.php delete mode 100644 core/command/maintenance/install.php delete mode 100644 core/command/maintenance/mimetype/updatedb.php delete mode 100644 core/command/maintenance/mimetype/updatejs.php delete mode 100644 core/command/maintenance/mode.php delete mode 100644 core/command/maintenance/repair.php delete mode 100644 core/command/maintenance/singleuser.php delete mode 100644 core/command/security/importcertificate.php delete mode 100644 core/command/security/listcertificates.php delete mode 100644 core/command/security/removecertificate.php delete mode 100644 core/command/status.php delete mode 100644 core/command/upgrade.php delete mode 100644 core/command/user/add.php delete mode 100644 core/command/user/delete.php delete mode 100644 core/command/user/lastseen.php delete mode 100644 core/command/user/report.php delete mode 100644 core/command/user/resetpassword.php delete mode 100644 core/controller/avatarcontroller.php delete mode 100644 core/controller/lostcontroller.php delete mode 100644 core/controller/setupcontroller.php delete mode 100644 core/controller/usercontroller.php delete mode 100644 core/tags/controller.php (limited to 'core') diff --git a/core/Command/App/CheckCode.php b/core/Command/App/CheckCode.php new file mode 100644 index 00000000000..78f4390e70a --- /dev/null +++ b/core/Command/App/CheckCode.php @@ -0,0 +1,181 @@ + + * @author Morris Jobke + * @author Robin McCorkell + * @author Thomas Müller + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\App; + +use OC\App\CodeChecker\CodeChecker; +use OC\App\CodeChecker\EmptyCheck; +use OC\App\CodeChecker\InfoChecker; +use OC\App\InfoParser; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class CheckCode extends Command { + + /** @var InfoParser */ + private $infoParser; + + protected $checkers = [ + 'private' => '\OC\App\CodeChecker\PrivateCheck', + 'deprecation' => '\OC\App\CodeChecker\DeprecationCheck', + 'strong-comparison' => '\OC\App\CodeChecker\StrongComparisonCheck', + ]; + + public function __construct(InfoParser $infoParser) { + parent::__construct(); + $this->infoParser = $infoParser; + } + + protected function configure() { + $this + ->setName('app:check-code') + ->setDescription('check code to be compliant') + ->addArgument( + 'app-id', + InputArgument::REQUIRED, + 'check the specified app' + ) + ->addOption( + 'checker', + 'c', + InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, + 'enable the specified checker(s)', + [ 'private', 'deprecation', 'strong-comparison' ] + ) + ->addOption( + '--skip-validate-info', + null, + InputOption::VALUE_NONE, + 'skips the info.xml/version check' + ); + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $appId = $input->getArgument('app-id'); + + $checkList = new EmptyCheck(); + foreach ($input->getOption('checker') as $checker) { + if (!isset($this->checkers[$checker])) { + throw new \InvalidArgumentException('Invalid checker: '.$checker); + } + $checkerClass = $this->checkers[$checker]; + $checkList = new $checkerClass($checkList); + } + + $codeChecker = new CodeChecker($checkList); + + $codeChecker->listen('CodeChecker', 'analyseFileBegin', function($params) use ($output) { + if(OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { + $output->writeln("Analysing {$params}"); + } + }); + $codeChecker->listen('CodeChecker', 'analyseFileFinished', function($filename, $errors) use ($output) { + $count = count($errors); + + // show filename if the verbosity is low, but there are errors in a file + if($count > 0 && OutputInterface::VERBOSITY_VERBOSE > $output->getVerbosity()) { + $output->writeln("Analysing {$filename}"); + } + + // show error count if there are errors present or the verbosity is high + if($count > 0 || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { + $output->writeln(" {$count} errors"); + } + usort($errors, function($a, $b) { + return $a['line'] >$b['line']; + }); + + foreach($errors as $p) { + $line = sprintf("%' 4d", $p['line']); + $output->writeln(" line $line: {$p['disallowedToken']} - {$p['reason']}"); + } + }); + $errors = $codeChecker->analyse($appId); + + if(!$input->getOption('skip-validate-info')) { + $infoChecker = new InfoChecker($this->infoParser); + + $infoChecker->listen('InfoChecker', 'mandatoryFieldMissing', function($key) use ($output) { + $output->writeln("Mandatory field missing: $key"); + }); + + $infoChecker->listen('InfoChecker', 'deprecatedFieldFound', function($key, $value) use ($output) { + if($value === [] || is_null($value) || $value === '') { + $output->writeln("Deprecated field available: $key"); + } else { + $output->writeln("Deprecated field available: $key => $value"); + } + }); + + $infoChecker->listen('InfoChecker', 'missingRequirement', function($minMax) use ($output) { + $output->writeln("ownCloud $minMax version requirement missing (will be an error in ownCloud 11 and later)"); + }); + + $infoChecker->listen('InfoChecker', 'duplicateRequirement', function($minMax) use ($output) { + $output->writeln("Duplicate $minMax ownCloud version requirement found"); + }); + + $infoChecker->listen('InfoChecker', 'differentVersions', function($versionFile, $infoXML) use ($output) { + $output->writeln("Different versions provided (appinfo/version: $versionFile - appinfo/info.xml: $infoXML)"); + }); + + $infoChecker->listen('InfoChecker', 'sameVersions', function($path) use ($output) { + $output->writeln("Version file isn't needed anymore and can be safely removed ($path)"); + }); + + $infoChecker->listen('InfoChecker', 'migrateVersion', function($version) use ($output) { + $output->writeln("Migrate the app version to appinfo/info.xml (add $version to appinfo/info.xml and remove appinfo/version)"); + }); + + if(OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { + $infoChecker->listen('InfoChecker', 'mandatoryFieldFound', function($key, $value) use ($output) { + $output->writeln("Mandatory field available: $key => $value"); + }); + + $infoChecker->listen('InfoChecker', 'optionalFieldFound', function($key, $value) use ($output) { + $output->writeln("Optional field available: $key => $value"); + }); + + $infoChecker->listen('InfoChecker', 'unusedFieldFound', function($key, $value) use ($output) { + $output->writeln("Unused field available: $key => $value"); + }); + } + + $infoErrors = $infoChecker->analyse($appId); + + $errors = array_merge($errors, $infoErrors); + } + + if (empty($errors)) { + $output->writeln('App is compliant - awesome job!'); + return 0; + } else { + $output->writeln('App is not compliant'); + return 101; + } + } +} diff --git a/core/Command/App/Disable.php b/core/Command/App/Disable.php new file mode 100644 index 00000000000..743a78cb88d --- /dev/null +++ b/core/Command/App/Disable.php @@ -0,0 +1,71 @@ + + * @author Morris Jobke + * @author Robin Appelman + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\App; + +use OCP\App\IAppManager; +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 Disable extends Command { + + /** @var IAppManager */ + protected $manager; + + /** + * @param IAppManager $manager + */ + public function __construct(IAppManager $manager) { + parent::__construct(); + $this->manager = $manager; + } + + protected function configure() { + $this + ->setName('app:disable') + ->setDescription('disable an app') + ->addArgument( + 'app-id', + InputArgument::REQUIRED, + 'disable the specified app' + ); + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $appId = $input->getArgument('app-id'); + if ($this->manager->isInstalled($appId)) { + try { + $this->manager->disableApp($appId); + $output->writeln($appId . ' disabled'); + } catch(\Exception $e) { + $output->writeln($e->getMessage()); + return 2; + } + } else { + $output->writeln('No such app enabled: ' . $appId); + } + } +} diff --git a/core/Command/App/Enable.php b/core/Command/App/Enable.php new file mode 100644 index 00000000000..0f6ce51fe8f --- /dev/null +++ b/core/Command/App/Enable.php @@ -0,0 +1,83 @@ + + * @author Morris Jobke + * @author Robin Appelman + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\App; + +use OCP\App\IAppManager; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class Enable extends Command { + + /** @var IAppManager */ + protected $manager; + + /** + * @param IAppManager $manager + */ + public function __construct(IAppManager $manager) { + parent::__construct(); + $this->manager = $manager; + } + + protected function configure() { + $this + ->setName('app:enable') + ->setDescription('enable an app') + ->addArgument( + 'app-id', + InputArgument::REQUIRED, + 'enable the specified app' + ) + ->addOption( + 'groups', + 'g', + InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, + 'enable the app only for a list of groups' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $appId = $input->getArgument('app-id'); + + if (!\OC_App::getAppPath($appId)) { + $output->writeln($appId . ' not found'); + return 1; + } + + $groups = $input->getOption('groups'); + if (empty($groups)) { + \OC_App::enable($appId); + $output->writeln($appId . ' enabled'); + } else { + \OC_App::enable($appId, $groups); + $output->writeln($appId . ' enabled for groups: ' . implode(', ', $groups)); + } + return 0; + } +} diff --git a/core/Command/App/GetPath.php b/core/Command/App/GetPath.php new file mode 100644 index 00000000000..33a3f64c53d --- /dev/null +++ b/core/Command/App/GetPath.php @@ -0,0 +1,62 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\App; + +use OC\Core\Command\Base; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class GetPath extends Base { + protected function configure() { + parent::configure(); + + $this + ->setName('app:getpath') + ->setDescription('Get an absolute path to the app directory') + ->addArgument( + 'app', + InputArgument::REQUIRED, + 'Name of the app' + ) + ; + } + + /** + * Executes the current command. + * + * @param InputInterface $input An InputInterface instance + * @param OutputInterface $output An OutputInterface instance + * @return null|int null or 0 if everything went fine, or an error code + */ + protected function execute(InputInterface $input, OutputInterface $output) { + $appName = $input->getArgument('app'); + $path = \OC_App::getAppPath($appName); + if ($path !== false) { + $output->writeln($path); + return 0; + } + + // App not found, exit with non-zero + return 1; + } +} diff --git a/core/Command/App/ListApps.php b/core/Command/App/ListApps.php new file mode 100644 index 00000000000..d7546b3c0c7 --- /dev/null +++ b/core/Command/App/ListApps.php @@ -0,0 +1,119 @@ + + * @author Morris Jobke + * @author Robin Appelman + * @author Victor Dubiniuk + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\App; + +use OC\Core\Command\Base; +use OCP\App\IAppManager; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class ListApps extends Base { + + /** @var IAppManager */ + protected $manager; + + /** + * @param IAppManager $manager + */ + public function __construct(IAppManager $manager) { + parent::__construct(); + $this->manager = $manager; + } + + protected function configure() { + parent::configure(); + + $this + ->setName('app:list') + ->setDescription('List all available apps') + ->addOption( + 'shipped', + null, + InputOption::VALUE_REQUIRED, + 'true - limit to shipped apps only, false - limit to non-shipped apps only' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) { + if ($input->getOption('shipped') === 'true' || $input->getOption('shipped') === 'false'){ + $shippedFilter = $input->getOption('shipped') === 'true'; + } else { + $shippedFilter = null; + } + + $apps = \OC_App::getAllApps(); + $enabledApps = $disabledApps = []; + $versions = \OC_App::getAppVersions(); + + //sort enabled apps above disabled apps + foreach ($apps as $app) { + if ($shippedFilter !== null && \OC_App::isShipped($app) !== $shippedFilter){ + continue; + } + if ($this->manager->isInstalled($app)) { + $enabledApps[] = $app; + } else { + $disabledApps[] = $app; + } + } + + $apps = ['enabled' => [], 'disabled' => []]; + + sort($enabledApps); + foreach ($enabledApps as $app) { + $apps['enabled'][$app] = (isset($versions[$app])) ? $versions[$app] : true; + } + + sort($disabledApps); + foreach ($disabledApps as $app) { + $apps['disabled'][$app] = null; + } + + $this->writeAppList($input, $output, $apps); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @param array $items + */ + protected function writeAppList(InputInterface $input, OutputInterface $output, $items) { + switch ($input->getOption('output')) { + case self::OUTPUT_FORMAT_PLAIN: + $output->writeln('Enabled:'); + parent::writeArrayInOutputFormat($input, $output, $items['enabled']); + + $output->writeln('Disabled:'); + parent::writeArrayInOutputFormat($input, $output, $items['disabled']); + break; + + default: + parent::writeArrayInOutputFormat($input, $output, $items); + break; + } + } +} diff --git a/core/Command/Background/Ajax.php b/core/Command/Background/Ajax.php new file mode 100644 index 00000000000..e9cd1405ebd --- /dev/null +++ b/core/Command/Background/Ajax.php @@ -0,0 +1,33 @@ + +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ + +namespace OC\Core\Command\Background; + +class Ajax extends Base { + + protected function getMode() { + return 'ajax'; + } +} diff --git a/core/Command/Background/Base.php b/core/Command/Background/Base.php new file mode 100644 index 00000000000..48fee818d0a --- /dev/null +++ b/core/Command/Background/Base.php @@ -0,0 +1,77 @@ + +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ + +namespace OC\Core\Command\Background; + +use \OCP\IConfig; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** +* An abstract base class for configuring the background job mode +* from the command line interface. +* Subclasses will override the getMode() function to specify the mode to configure. +*/ +abstract class Base extends Command { + + + abstract protected function getMode(); + + /** + * @var \OCP\IConfig + */ + protected $config; + + /** + * @param \OCP\IConfig $config + */ + public function __construct(IConfig $config) { + $this->config = $config; + parent::__construct(); + } + + protected function configure() { + $mode = $this->getMode(); + $this + ->setName("background:$mode") + ->setDescription("Use $mode to run background jobs"); + } + + /** + * Executing this command will set the background job mode for owncloud. + * The mode to set is specified by the concrete sub class by implementing the + * getMode() function. + * + * @param InputInterface $input + * @param OutputInterface $output + */ + protected function execute(InputInterface $input, OutputInterface $output) { + $mode = $this->getMode(); + $this->config->setAppValue( 'core', 'backgroundjobs_mode', $mode ); + $output->writeln("Set mode for background jobs to '$mode'"); + } +} diff --git a/core/Command/Background/Cron.php b/core/Command/Background/Cron.php new file mode 100644 index 00000000000..434e88893b2 --- /dev/null +++ b/core/Command/Background/Cron.php @@ -0,0 +1,33 @@ + +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ + +namespace OC\Core\Command\Background; + +class Cron extends Base { + + protected function getMode() { + return 'cron'; + } +} diff --git a/core/Command/Background/WebCron.php b/core/Command/Background/WebCron.php new file mode 100644 index 00000000000..23dbe98e635 --- /dev/null +++ b/core/Command/Background/WebCron.php @@ -0,0 +1,33 @@ + +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ + +namespace OC\Core\Command\Background; + +class WebCron extends Base { + + protected function getMode() { + return 'webcron'; + } +} diff --git a/core/Command/Base.php b/core/Command/Base.php new file mode 100644 index 00000000000..7538effd74a --- /dev/null +++ b/core/Command/Base.php @@ -0,0 +1,160 @@ + + * @author Thomas Müller + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class Base extends Command { + const OUTPUT_FORMAT_PLAIN = 'plain'; + const OUTPUT_FORMAT_JSON = 'json'; + const OUTPUT_FORMAT_JSON_PRETTY = 'json_pretty'; + + protected $defaultOutputFormat = self::OUTPUT_FORMAT_PLAIN; + + /** @var boolean */ + private $php_pcntl_signal = false; + + /** @var boolean */ + private $interrupted = false; + + protected function configure() { + $this + ->addOption( + 'output', + null, + InputOption::VALUE_OPTIONAL, + 'Output format (plain, json or json_pretty, default is plain)', + $this->defaultOutputFormat + ) + ; + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @param array $items + * @param string $prefix + */ + protected function writeArrayInOutputFormat(InputInterface $input, OutputInterface $output, $items, $prefix = ' - ') { + switch ($input->getOption('output')) { + case self::OUTPUT_FORMAT_JSON: + $output->writeln(json_encode($items)); + break; + case self::OUTPUT_FORMAT_JSON_PRETTY: + $output->writeln(json_encode($items, JSON_PRETTY_PRINT)); + break; + default: + foreach ($items as $key => $item) { + if (is_array($item)) { + $output->writeln($prefix . $key . ':'); + $this->writeArrayInOutputFormat($input, $output, $item, ' ' . $prefix); + continue; + } + if (!is_int($key)) { + $value = $this->valueToString($item); + if (!is_null($value)) { + $output->writeln($prefix . $key . ': ' . $value); + } else { + $output->writeln($prefix . $key); + } + } else { + $output->writeln($prefix . $this->valueToString($item)); + } + } + break; + } + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @param mixed $item + */ + protected function writeMixedInOutputFormat(InputInterface $input, OutputInterface $output, $item) { + if (is_array($item)) { + $this->writeArrayInOutputFormat($input, $output, $item, ''); + return; + } + + switch ($input->getOption('output')) { + case self::OUTPUT_FORMAT_JSON: + $output->writeln(json_encode($item)); + break; + case self::OUTPUT_FORMAT_JSON_PRETTY: + $output->writeln(json_encode($item, JSON_PRETTY_PRINT)); + break; + default: + $output->writeln($this->valueToString($item, false)); + break; + } + } + + protected function valueToString($value, $returnNull = true) { + if ($value === false) { + return 'false'; + } else if ($value === true) { + return 'true'; + } else if ($value === null) { + return ($returnNull) ? null : 'null'; + } else { + return $value; + } + } + + /** + * @return bool + */ + protected function hasBeenInterrupted() { + // return always false if pcntl_signal functions are not accessible + if ($this->php_pcntl_signal) { + pcntl_signal_dispatch(); + return $this->interrupted; + } else { + return false; + } + } + + /** + * Changes the status of the command to "interrupted" if ctrl-c has been pressed + * + * Gives a chance to the command to properly terminate what it's doing + */ + protected function cancelOperation() { + $this->interrupted = true; + } + + public function run(InputInterface $input, OutputInterface $output) { + // check if the php pcntl_signal functions are accessible + $this->php_pcntl_signal = function_exists('pcntl_signal'); + if ($this->php_pcntl_signal) { + // Collect interrupts and notify the running command + pcntl_signal(SIGTERM, [$this, 'cancelOperation']); + pcntl_signal(SIGINT, [$this, 'cancelOperation']); + } + + return parent::run($input, $output); + } +} diff --git a/core/Command/Check.php b/core/Command/Check.php new file mode 100644 index 00000000000..c2e92f7a8da --- /dev/null +++ b/core/Command/Check.php @@ -0,0 +1,61 @@ + + * @author Morris Jobke + * @author Thomas Müller + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ +namespace OC\Core\Command; + +use OCP\IConfig; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class Check extends Base { + /** + * @var IConfig + */ + private $config; + + public function __construct(IConfig $config) { + parent::__construct(); + $this->config = $config; + } + + protected function configure() { + parent::configure(); + + $this + ->setName('check') + ->setDescription('check dependencies of the server environment') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $errors = \OC_Util::checkServer($this->config); + if (!empty($errors)) { + $errors = array_map(function($item) { + return (string) $item['error']; + }, $errors); + + $this->writeArrayInOutputFormat($input, $output, $errors); + return 1; + } + return 0; + } +} diff --git a/core/Command/Config/App/DeleteConfig.php b/core/Command/Config/App/DeleteConfig.php new file mode 100644 index 00000000000..cccd92ea3d6 --- /dev/null +++ b/core/Command/Config/App/DeleteConfig.php @@ -0,0 +1,81 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Config\App; + +use OC\Core\Command\Base; +use OCP\IConfig; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class DeleteConfig extends Base { + /** * @var IConfig */ + protected $config; + + /** + * @param IConfig $config + */ + public function __construct(IConfig $config) { + parent::__construct(); + $this->config = $config; + } + + protected function configure() { + parent::configure(); + + $this + ->setName('config:app:delete') + ->setDescription('Delete an app config value') + ->addArgument( + 'app', + InputArgument::REQUIRED, + 'Name of the app' + ) + ->addArgument( + 'name', + InputArgument::REQUIRED, + 'Name of the config to delete' + ) + ->addOption( + 'error-if-not-exists', + null, + InputOption::VALUE_NONE, + 'Checks whether the config exists before deleting it' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $appName = $input->getArgument('app'); + $configName = $input->getArgument('name'); + + if ($input->hasParameterOption('--error-if-not-exists') && !in_array($configName, $this->config->getAppKeys($appName))) { + $output->writeln('Config ' . $configName . ' of app ' . $appName . ' could not be deleted because it did not exist'); + return 1; + } + + $this->config->deleteAppValue($appName, $configName); + $output->writeln('Config value ' . $configName . ' of app ' . $appName . ' deleted'); + return 0; + } +} diff --git a/core/Command/Config/App/GetConfig.php b/core/Command/Config/App/GetConfig.php new file mode 100644 index 00000000000..abe71e57d8c --- /dev/null +++ b/core/Command/Config/App/GetConfig.php @@ -0,0 +1,93 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Config\App; + +use OC\Core\Command\Base; +use OCP\IConfig; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class GetConfig extends Base { + /** * @var IConfig */ + protected $config; + + /** + * @param IConfig $config + */ + public function __construct(IConfig $config) { + parent::__construct(); + $this->config = $config; + } + + protected function configure() { + parent::configure(); + + $this + ->setName('config:app:get') + ->setDescription('Get an app config value') + ->addArgument( + 'app', + InputArgument::REQUIRED, + 'Name of the app' + ) + ->addArgument( + 'name', + InputArgument::REQUIRED, + 'Name of the config to get' + ) + ->addOption( + 'default-value', + null, + InputOption::VALUE_OPTIONAL, + 'If no default value is set and the config does not exist, the command will exit with 1' + ) + ; + } + + /** + * Executes the current command. + * + * @param InputInterface $input An InputInterface instance + * @param OutputInterface $output An OutputInterface instance + * @return null|int null or 0 if everything went fine, or an error code + */ + protected function execute(InputInterface $input, OutputInterface $output) { + $appName = $input->getArgument('app'); + $configName = $input->getArgument('name'); + $defaultValue = $input->getOption('default-value'); + + if (!in_array($configName, $this->config->getAppKeys($appName)) && !$input->hasParameterOption('--default-value')) { + return 1; + } + + if (!in_array($configName, $this->config->getAppKeys($appName))) { + $configValue = $defaultValue; + } else { + $configValue = $this->config->getAppValue($appName, $configName); + } + + $this->writeMixedInOutputFormat($input, $output, $configValue); + return 0; + } +} diff --git a/core/Command/Config/App/SetConfig.php b/core/Command/Config/App/SetConfig.php new file mode 100644 index 00000000000..097fde6ba95 --- /dev/null +++ b/core/Command/Config/App/SetConfig.php @@ -0,0 +1,89 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Config\App; + +use OC\Core\Command\Base; +use OCP\IConfig; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class SetConfig extends Base { + /** * @var IConfig */ + protected $config; + + /** + * @param IConfig $config + */ + public function __construct(IConfig $config) { + parent::__construct(); + $this->config = $config; + } + + protected function configure() { + parent::configure(); + + $this + ->setName('config:app:set') + ->setDescription('Set an app config value') + ->addArgument( + 'app', + InputArgument::REQUIRED, + 'Name of the app' + ) + ->addArgument( + 'name', + InputArgument::REQUIRED, + 'Name of the config to set' + ) + ->addOption( + 'value', + null, + InputOption::VALUE_REQUIRED, + 'The new value of the config' + ) + ->addOption( + 'update-only', + null, + InputOption::VALUE_NONE, + 'Only updates the value, if it is not set before, it is not being added' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $appName = $input->getArgument('app'); + $configName = $input->getArgument('name'); + + if (!in_array($configName, $this->config->getAppKeys($appName)) && $input->hasParameterOption('--update-only')) { + $output->writeln('Config value ' . $configName . ' for app ' . $appName . ' not updated, as it has not been set before.'); + return 1; + } + + $configValue = $input->getOption('value'); + $this->config->setAppValue($appName, $configName, $configValue); + + $output->writeln('Config value ' . $configName . ' for app ' . $appName . ' set to ' . $configValue . ''); + return 0; + } +} diff --git a/core/Command/Config/Import.php b/core/Command/Config/Import.php new file mode 100644 index 00000000000..7f1e09d2c95 --- /dev/null +++ b/core/Command/Config/Import.php @@ -0,0 +1,195 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Config; + +use OCP\IConfig; +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 Import extends Command { + protected $validRootKeys = ['system', 'apps']; + + /** @var IConfig */ + protected $config; + + /** + * @param IConfig $config + */ + public function __construct(IConfig $config) { + parent::__construct(); + $this->config = $config; + } + + protected function configure() { + $this + ->setName('config:import') + ->setDescription('Import a list of configs') + ->addArgument( + 'file', + InputArgument::OPTIONAL, + 'File with the json array to import' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $importFile = $input->getArgument('file'); + if ($importFile !== null) { + $content = $this->getArrayFromFile($importFile); + } else { + $content = $this->getArrayFromStdin(); + } + + try { + $configs = $this->validateFileContent($content); + } catch (\UnexpectedValueException $e) { + $output->writeln('' . $e->getMessage(). ''); + return; + } + + if (!empty($configs['system'])) { + $this->config->setSystemValues($configs['system']); + } + + if (!empty($configs['apps'])) { + foreach ($configs['apps'] as $app => $appConfigs) { + foreach ($appConfigs as $key => $value) { + if ($value === null) { + $this->config->deleteAppValue($app, $key); + } else { + $this->config->setAppValue($app, $key, $value); + } + } + } + } + + $output->writeln('Config successfully imported from: ' . $importFile . ''); + } + + /** + * Get the content from stdin ("config:import < file.json") + * + * @return string + */ + protected function getArrayFromStdin() { + // Read from stdin. stream_set_blocking is used to prevent blocking + // when nothing is passed via stdin. + stream_set_blocking(STDIN, 0); + $content = file_get_contents('php://stdin'); + stream_set_blocking(STDIN, 1); + return $content; + } + + /** + * Get the content of the specified file ("config:import file.json") + * + * @param string $importFile + * @return string + */ + protected function getArrayFromFile($importFile) { + $content = file_get_contents($importFile); + return $content; + } + + /** + * @param string $content + * @return array + * @throws \UnexpectedValueException when the array is invalid + */ + protected function validateFileContent($content) { + $decodedContent = json_decode($content, true); + if (!is_array($decodedContent) || empty($decodedContent)) { + throw new \UnexpectedValueException('The file must contain a valid json array'); + } + + $this->validateArray($decodedContent); + + return $decodedContent; + } + + /** + * Validates that the array only contains `system` and `apps` + * + * @param array $array + */ + protected function validateArray($array) { + $arrayKeys = array_keys($array); + $additionalKeys = array_diff($arrayKeys, $this->validRootKeys); + $commonKeys = array_intersect($arrayKeys, $this->validRootKeys); + if (!empty($additionalKeys)) { + throw new \UnexpectedValueException('Found invalid entries in root: ' . implode(', ', $additionalKeys)); + } + if (empty($commonKeys)) { + throw new \UnexpectedValueException('At least one key of the following is expected: ' . implode(', ', $this->validRootKeys)); + } + + if (isset($array['system'])) { + if (is_array($array['system'])) { + foreach ($array['system'] as $name => $value) { + $this->checkTypeRecursively($value, $name); + } + } else { + throw new \UnexpectedValueException('The system config array is not an array'); + } + } + + if (isset($array['apps'])) { + if (is_array($array['apps'])) { + $this->validateAppsArray($array['apps']); + } else { + throw new \UnexpectedValueException('The apps config array is not an array'); + } + } + } + + /** + * @param mixed $configValue + * @param string $configName + */ + protected function checkTypeRecursively($configValue, $configName) { + if (!is_array($configValue) && !is_bool($configValue) && !is_int($configValue) && !is_string($configValue) && !is_null($configValue)) { + throw new \UnexpectedValueException('Invalid system config value for "' . $configName . '". Only arrays, bools, integers, strings and null (delete) are allowed.'); + } + if (is_array($configValue)) { + foreach ($configValue as $key => $value) { + $this->checkTypeRecursively($value, $configName); + } + } + } + + /** + * Validates that app configs are only integers and strings + * + * @param array $array + */ + protected function validateAppsArray($array) { + foreach ($array as $app => $configs) { + foreach ($configs as $name => $value) { + if (!is_int($value) && !is_string($value) && !is_null($value)) { + throw new \UnexpectedValueException('Invalid app config value for "' . $app . '":"' . $name . '". Only integers, strings and null (delete) are allowed.'); + } + } + } + } +} diff --git a/core/Command/Config/ListConfigs.php b/core/Command/Config/ListConfigs.php new file mode 100644 index 00000000000..afebe4c4c07 --- /dev/null +++ b/core/Command/Config/ListConfigs.php @@ -0,0 +1,129 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Config; + +use OC\Core\Command\Base; +use OC\SystemConfig; +use OCP\IAppConfig; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class ListConfigs extends Base { + protected $defaultOutputFormat = self::OUTPUT_FORMAT_JSON_PRETTY; + + /** * @var SystemConfig */ + protected $systemConfig; + + /** @var IAppConfig */ + protected $appConfig; + + /** + * @param SystemConfig $systemConfig + * @param IAppConfig $appConfig + */ + public function __construct(SystemConfig $systemConfig, IAppConfig $appConfig) { + parent::__construct(); + $this->systemConfig = $systemConfig; + $this->appConfig = $appConfig; + } + + protected function configure() { + parent::configure(); + + $this + ->setName('config:list') + ->setDescription('List all configs') + ->addArgument( + 'app', + InputArgument::OPTIONAL, + 'Name of the app ("system" to get the config.php values, "all" for all apps and system)', + 'all' + ) + ->addOption( + 'private', + null, + InputOption::VALUE_NONE, + 'Use this option when you want to include sensitive configs like passwords, salts, ...' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $app = $input->getArgument('app'); + $noSensitiveValues = !$input->getOption('private'); + + switch ($app) { + case 'system': + $configs = [ + 'system' => $this->getSystemConfigs($noSensitiveValues), + ]; + break; + + case 'all': + $apps = $this->appConfig->getApps(); + $configs = [ + 'system' => $this->getSystemConfigs($noSensitiveValues), + 'apps' => [], + ]; + foreach ($apps as $appName) { + $configs['apps'][$appName] = $this->appConfig->getValues($appName, false); + } + break; + + default: + $configs = [ + 'apps' => [ + $app => $this->appConfig->getValues($app, false), + ], + ]; + } + + $this->writeArrayInOutputFormat($input, $output, $configs); + } + + /** + * Get the system configs + * + * @param bool $noSensitiveValues + * @return array + */ + protected function getSystemConfigs($noSensitiveValues) { + $keys = $this->systemConfig->getKeys(); + + $configs = []; + foreach ($keys as $key) { + if ($noSensitiveValues) { + $value = $this->systemConfig->getFilteredValue($key, serialize(null)); + } else { + $value = $this->systemConfig->getValue($key, serialize(null)); + } + + if ($value !== 'N;') { + $configs[$key] = $value; + } + } + + return $configs; + } +} diff --git a/core/Command/Config/System/DeleteConfig.php b/core/Command/Config/System/DeleteConfig.php new file mode 100644 index 00000000000..374f5ac69b7 --- /dev/null +++ b/core/Command/Config/System/DeleteConfig.php @@ -0,0 +1,117 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Config\System; + +use OC\Core\Command\Base; +use OC\SystemConfig; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class DeleteConfig extends Base { + /** * @var SystemConfig */ + protected $systemConfig; + + /** + * @param SystemConfig $systemConfig + */ + public function __construct(SystemConfig $systemConfig) { + parent::__construct(); + $this->systemConfig = $systemConfig; + } + + protected function configure() { + parent::configure(); + + $this + ->setName('config:system:delete') + ->setDescription('Delete a system config value') + ->addArgument( + 'name', + InputArgument::REQUIRED | InputArgument::IS_ARRAY, + 'Name of the config to delete, specify multiple for array parameter' + ) + ->addOption( + 'error-if-not-exists', + null, + InputOption::VALUE_NONE, + 'Checks whether the config exists before deleting it' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $configNames = $input->getArgument('name'); + $configName = $configNames[0]; + + if (sizeof($configNames) > 1) { + if ($input->hasParameterOption('--error-if-not-exists') && !in_array($configName, $this->systemConfig->getKeys())) { + $output->writeln('System config ' . implode(' => ', $configNames) . ' could not be deleted because it did not exist'); + return 1; + } + + $value = $this->systemConfig->getValue($configName); + + try { + $value = $this->removeSubValue(array_slice($configNames, 1), $value, $input->hasParameterOption('--error-if-not-exists')); + } + catch (\UnexpectedValueException $e) { + $output->writeln('System config ' . implode(' => ', $configNames) . ' could not be deleted because it did not exist'); + return 1; + } + + $this->systemConfig->setValue($configName, $value); + $output->writeln('System config value ' . implode(' => ', $configNames) . ' deleted'); + return 0; + } else { + if ($input->hasParameterOption('--error-if-not-exists') && !in_array($configName, $this->systemConfig->getKeys())) { + $output->writeln('System config ' . $configName . ' could not be deleted because it did not exist'); + return 1; + } + + $this->systemConfig->deleteValue($configName); + $output->writeln('System config value ' . $configName . ' deleted'); + return 0; + } + } + + protected function removeSubValue($keys, $currentValue, $throwError) { + $nextKey = array_shift($keys); + + if (is_array($currentValue)) { + if (isset($currentValue[$nextKey])) { + if (empty($keys)) { + unset($currentValue[$nextKey]); + } else { + $currentValue[$nextKey] = $this->removeSubValue($keys, $currentValue[$nextKey], $throwError); + } + } else if ($throwError) { + throw new \UnexpectedValueException('Config parameter does not exist'); + } + } else if ($throwError) { + throw new \UnexpectedValueException('Config parameter does not exist'); + } + + return $currentValue; + } +} diff --git a/core/Command/Config/System/GetConfig.php b/core/Command/Config/System/GetConfig.php new file mode 100644 index 00000000000..b76474112a0 --- /dev/null +++ b/core/Command/Config/System/GetConfig.php @@ -0,0 +1,100 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Config\System; + +use OC\Core\Command\Base; +use OC\SystemConfig; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class GetConfig extends Base { + /** * @var SystemConfig */ + protected $systemConfig; + + /** + * @param SystemConfig $systemConfig + */ + public function __construct(SystemConfig $systemConfig) { + parent::__construct(); + $this->systemConfig = $systemConfig; + } + + protected function configure() { + parent::configure(); + + $this + ->setName('config:system:get') + ->setDescription('Get a system config value') + ->addArgument( + 'name', + InputArgument::REQUIRED | InputArgument::IS_ARRAY, + 'Name of the config to get, specify multiple for array parameter' + ) + ->addOption( + 'default-value', + null, + InputOption::VALUE_OPTIONAL, + 'If no default value is set and the config does not exist, the command will exit with 1' + ) + ; + } + + /** + * Executes the current command. + * + * @param InputInterface $input An InputInterface instance + * @param OutputInterface $output An OutputInterface instance + * @return null|int null or 0 if everything went fine, or an error code + */ + protected function execute(InputInterface $input, OutputInterface $output) { + $configNames = $input->getArgument('name'); + $configName = array_shift($configNames); + $defaultValue = $input->getOption('default-value'); + + if (!in_array($configName, $this->systemConfig->getKeys()) && !$input->hasParameterOption('--default-value')) { + return 1; + } + + if (!in_array($configName, $this->systemConfig->getKeys())) { + $configValue = $defaultValue; + } else { + $configValue = $this->systemConfig->getValue($configName); + if (!empty($configNames)) { + foreach ($configNames as $configName) { + if (isset($configValue[$configName])) { + $configValue = $configValue[$configName]; + } else if (!$input->hasParameterOption('--default-value')) { + return 1; + } else { + $configValue = $defaultValue; + break; + } + } + } + } + + $this->writeMixedInOutputFormat($input, $output, $configValue); + return 0; + } +} diff --git a/core/Command/Config/System/SetConfig.php b/core/Command/Config/System/SetConfig.php new file mode 100644 index 00000000000..c7f206b05d1 --- /dev/null +++ b/core/Command/Config/System/SetConfig.php @@ -0,0 +1,198 @@ + + * @author Robin McCorkell + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Config\System; + +use OC\Core\Command\Base; +use OC\SystemConfig; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class SetConfig extends Base { + /** * @var SystemConfig */ + protected $systemConfig; + + /** + * @param SystemConfig $systemConfig + */ + public function __construct(SystemConfig $systemConfig) { + parent::__construct(); + $this->systemConfig = $systemConfig; + } + + protected function configure() { + parent::configure(); + + $this + ->setName('config:system:set') + ->setDescription('Set a system config value') + ->addArgument( + 'name', + InputArgument::REQUIRED | InputArgument::IS_ARRAY, + 'Name of the config parameter, specify multiple for array parameter' + ) + ->addOption( + 'type', + null, + InputOption::VALUE_REQUIRED, + 'Value type [string, integer, double, boolean]', + 'string' + ) + ->addOption( + 'value', + null, + InputOption::VALUE_REQUIRED, + 'The new value of the config' + ) + ->addOption( + 'update-only', + null, + InputOption::VALUE_NONE, + 'Only updates the value, if it is not set before, it is not being added' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $configNames = $input->getArgument('name'); + $configName = $configNames[0]; + $configValue = $this->castValue($input->getOption('value'), $input->getOption('type')); + $updateOnly = $input->getOption('update-only'); + + if (sizeof($configNames) > 1) { + $existingValue = $this->systemConfig->getValue($configName); + + $newValue = $this->mergeArrayValue( + array_slice($configNames, 1), $existingValue, $configValue['value'], $updateOnly + ); + + $this->systemConfig->setValue($configName, $newValue); + } else { + if ($updateOnly && !in_array($configName, $this->systemConfig->getKeys(), true)) { + throw new \UnexpectedValueException('Config parameter does not exist'); + } + + $this->systemConfig->setValue($configName, $configValue['value']); + } + + $output->writeln('System config value ' . implode(' => ', $configNames) . ' set to ' . $configValue['readable-value'] . ''); + return 0; + } + + /** + * @param string $value + * @param string $type + * @return mixed + * @throws \InvalidArgumentException + */ + protected function castValue($value, $type) { + switch ($type) { + case 'integer': + case 'int': + if (!is_numeric($value)) { + throw new \InvalidArgumentException('Non-numeric value specified'); + } + return [ + 'value' => (int) $value, + 'readable-value' => 'integer ' . (int) $value, + ]; + + case 'double': + case 'float': + if (!is_numeric($value)) { + throw new \InvalidArgumentException('Non-numeric value specified'); + } + return [ + 'value' => (double) $value, + 'readable-value' => 'double ' . (double) $value, + ]; + + case 'boolean': + case 'bool': + $value = strtolower($value); + switch ($value) { + case 'true': + return [ + 'value' => true, + 'readable-value' => 'boolean ' . $value, + ]; + + case 'false': + return [ + 'value' => false, + 'readable-value' => 'boolean ' . $value, + ]; + + default: + throw new \InvalidArgumentException('Unable to parse value as boolean'); + } + + case 'null': + return [ + 'value' => null, + 'readable-value' => 'null', + ]; + + case 'string': + $value = (string) $value; + return [ + 'value' => $value, + 'readable-value' => ($value === '') ? 'empty string' : 'string ' . $value, + ]; + + default: + throw new \InvalidArgumentException('Invalid type'); + } + } + + /** + * @param array $configNames + * @param mixed $existingValues + * @param mixed $value + * @param bool $updateOnly + * @return array merged value + * @throws \UnexpectedValueException + */ + protected function mergeArrayValue(array $configNames, $existingValues, $value, $updateOnly) { + $configName = array_shift($configNames); + if (!is_array($existingValues)) { + $existingValues = []; + } + if (!empty($configNames)) { + if (isset($existingValues[$configName])) { + $existingValue = $existingValues[$configName]; + } else { + $existingValue = []; + } + $existingValues[$configName] = $this->mergeArrayValue($configNames, $existingValue, $value, $updateOnly); + } else { + if (!isset($existingValues[$configName]) && $updateOnly) { + throw new \UnexpectedValueException('Config parameter does not exist'); + } + $existingValues[$configName] = $value; + } + return $existingValues; + } + +} diff --git a/core/Command/Db/ConvertType.php b/core/Command/Db/ConvertType.php new file mode 100644 index 00000000000..864499dcce0 --- /dev/null +++ b/core/Command/Db/ConvertType.php @@ -0,0 +1,311 @@ + + * @author Bart Visscher + * @author Joas Schilling + * @author Morris Jobke + * @author tbelau666 + * @author Thomas Müller + * @author unclejamal3000 + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Db; + +use \OCP\IConfig; +use OC\DB\Connection; +use OC\DB\ConnectionFactory; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class ConvertType extends Command { + /** + * @var \OCP\IConfig + */ + protected $config; + + /** + * @var \OC\DB\ConnectionFactory + */ + protected $connectionFactory; + + /** + * @param \OCP\IConfig $config + * @param \OC\DB\ConnectionFactory $connectionFactory + */ + public function __construct(IConfig $config, ConnectionFactory $connectionFactory) { + $this->config = $config; + $this->connectionFactory = $connectionFactory; + parent::__construct(); + } + + protected function configure() { + $this + ->setName('db:convert-type') + ->setDescription('Convert the ownCloud database to the newly configured one') + ->addArgument( + 'type', + InputArgument::REQUIRED, + 'the type of the database to convert to' + ) + ->addArgument( + 'username', + InputArgument::REQUIRED, + 'the username of the database to convert to' + ) + ->addArgument( + 'hostname', + InputArgument::REQUIRED, + 'the hostname of the database to convert to' + ) + ->addArgument( + 'database', + InputArgument::REQUIRED, + 'the name of the database to convert to' + ) + ->addOption( + 'port', + null, + InputOption::VALUE_REQUIRED, + 'the port of the database to convert to' + ) + ->addOption( + 'password', + null, + InputOption::VALUE_REQUIRED, + 'the password of the database to convert to. Will be asked when not specified. Can also be passed via stdin.' + ) + ->addOption( + 'clear-schema', + null, + InputOption::VALUE_NONE, + 'remove all tables from the destination database' + ) + ->addOption( + 'all-apps', + null, + InputOption::VALUE_NONE, + 'whether to create schema for all apps instead of only installed apps' + ) + ; + } + + protected function validateInput(InputInterface $input, OutputInterface $output) { + $type = $this->connectionFactory->normalizeType($input->getArgument('type')); + if ($type === 'sqlite3') { + throw new \InvalidArgumentException( + 'Converting to SQLite (sqlite3) is currently not supported.' + ); + } + if ($type === $this->config->getSystemValue('dbtype', '')) { + throw new \InvalidArgumentException(sprintf( + 'Can not convert from %1$s to %1$s.', + $type + )); + } + if ($type === 'oci' && $input->getOption('clear-schema')) { + // Doctrine unconditionally tries (at least in version 2.3) + // to drop sequence triggers when dropping a table, even though + // such triggers may not exist. This results in errors like + // "ORA-04080: trigger 'OC_STORAGES_AI_PK' does not exist". + throw new \InvalidArgumentException( + 'The --clear-schema option is not supported when converting to Oracle (oci).' + ); + } + } + + protected function readPassword(InputInterface $input, OutputInterface $output) { + // Explicitly specified password + if ($input->getOption('password')) { + return; + } + + // Read from stdin. stream_set_blocking is used to prevent blocking + // when nothing is passed via stdin. + stream_set_blocking(STDIN, 0); + $password = file_get_contents('php://stdin'); + stream_set_blocking(STDIN, 1); + if (trim($password) !== '') { + $input->setOption('password', $password); + return; + } + + // Read password by interacting + if ($input->isInteractive()) { + /** @var $dialog \Symfony\Component\Console\Helper\DialogHelper */ + $dialog = $this->getHelperSet()->get('dialog'); + $password = $dialog->askHiddenResponse( + $output, + 'What is the database password?', + false + ); + $input->setOption('password', $password); + return; + } + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $this->validateInput($input, $output); + $this->readPassword($input, $output); + + $fromDB = \OC::$server->getDatabaseConnection(); + $toDB = $this->getToDBConnection($input, $output); + + if ($input->getOption('clear-schema')) { + $this->clearSchema($toDB, $input, $output); + } + + $this->createSchema($toDB, $input, $output); + + $toTables = $this->getTables($toDB); + $fromTables = $this->getTables($fromDB); + + // warn/fail if there are more tables in 'from' database + $extraFromTables = array_diff($fromTables, $toTables); + if (!empty($extraFromTables)) { + $output->writeln('The following tables will not be converted:'); + $output->writeln($extraFromTables); + if (!$input->getOption('all-apps')) { + $output->writeln('Please note that tables belonging to available but currently not installed apps'); + $output->writeln('can be included by specifying the --all-apps option.'); + } + /** @var $dialog \Symfony\Component\Console\Helper\DialogHelper */ + $dialog = $this->getHelperSet()->get('dialog'); + if (!$dialog->askConfirmation( + $output, + 'Continue with the conversion (y/n)? [n] ', + false + )) { + return; + } + } + $intersectingTables = array_intersect($toTables, $fromTables); + $this->convertDB($fromDB, $toDB, $intersectingTables, $input, $output); + } + + protected function createSchema(Connection $toDB, InputInterface $input, OutputInterface $output) { + $output->writeln('Creating schema in new database'); + $schemaManager = new \OC\DB\MDB2SchemaManager($toDB); + $schemaManager->createDbFromStructure(\OC::$SERVERROOT.'/db_structure.xml'); + $apps = $input->getOption('all-apps') ? \OC_App::getAllApps() : \OC_App::getEnabledApps(); + foreach($apps as $app) { + if (file_exists(\OC_App::getAppPath($app).'/appinfo/database.xml')) { + $schemaManager->createDbFromStructure(\OC_App::getAppPath($app).'/appinfo/database.xml'); + } + } + } + + protected function getToDBConnection(InputInterface $input, OutputInterface $output) { + $type = $input->getArgument('type'); + $connectionParams = array( + 'host' => $input->getArgument('hostname'), + 'user' => $input->getArgument('username'), + 'password' => $input->getOption('password'), + 'dbname' => $input->getArgument('database'), + 'tablePrefix' => $this->config->getSystemValue('dbtableprefix', 'oc_'), + ); + if ($input->getOption('port')) { + $connectionParams['port'] = $input->getOption('port'); + } + return $this->connectionFactory->getConnection($type, $connectionParams); + } + + protected function clearSchema(Connection $db, InputInterface $input, OutputInterface $output) { + $toTables = $this->getTables($db); + if (!empty($toTables)) { + $output->writeln('Clearing schema in new database'); + } + foreach($toTables as $table) { + $db->getSchemaManager()->dropTable($table); + } + } + + protected function getTables(Connection $db) { + $filterExpression = '/^' . preg_quote($this->config->getSystemValue('dbtableprefix', 'oc_')) . '/'; + $db->getConfiguration()-> + setFilterSchemaAssetsExpression($filterExpression); + return $db->getSchemaManager()->listTableNames(); + } + + protected function copyTable(Connection $fromDB, Connection $toDB, $table, InputInterface $input, OutputInterface $output) { + /** @var $progress \Symfony\Component\Console\Helper\ProgressHelper */ + $progress = $this->getHelperSet()->get('progress'); + $query = 'SELECT COUNT(*) FROM '.$table; + $count = $fromDB->fetchColumn($query); + $query = 'SELECT * FROM '.$table; + $statement = $fromDB->executeQuery($query); + $progress->start($output, $count); + $progress->setRedrawFrequency($count > 100 ? 5 : 1); + while($row = $statement->fetch()) { + $progress->advance(); + if ($input->getArgument('type') === 'oci') { + $data = $row; + } else { + $data = array(); + foreach ($row as $columnName => $value) { + $data[$toDB->quoteIdentifier($columnName)] = $value; + } + } + $toDB->insert($table, $data); + } + $progress->finish(); + } + + protected function convertDB(Connection $fromDB, Connection $toDB, array $tables, InputInterface $input, OutputInterface $output) { + $this->config->setSystemValue('maintenance', true); + try { + // copy table rows + foreach($tables as $table) { + $output->writeln($table); + $this->copyTable($fromDB, $toDB, $table, $input, $output); + } + if ($input->getArgument('type') === 'pgsql') { + $tools = new \OC\DB\PgSqlTools($this->config); + $tools->resynchronizeDatabaseSequences($toDB); + } + // save new database config + $this->saveDBInfo($input); + } catch(\Exception $e) { + $this->config->setSystemValue('maintenance', false); + throw $e; + } + $this->config->setSystemValue('maintenance', false); + } + + protected function saveDBInfo(InputInterface $input) { + $type = $input->getArgument('type'); + $username = $input->getArgument('username'); + $dbHost = $input->getArgument('hostname'); + $dbName = $input->getArgument('database'); + $password = $input->getOption('password'); + if ($input->getOption('port')) { + $dbHost .= ':'.$input->getOption('port'); + } + + $this->config->setSystemValues([ + 'dbtype' => $type, + 'dbname' => $dbName, + 'dbhost' => $dbHost, + 'dbuser' => $username, + 'dbpassword' => $password, + ]); + } +} diff --git a/core/Command/Db/GenerateChangeScript.php b/core/Command/Db/GenerateChangeScript.php new file mode 100644 index 00000000000..85436b02d65 --- /dev/null +++ b/core/Command/Db/GenerateChangeScript.php @@ -0,0 +1,58 @@ + + * @author Thomas Müller + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Db; + +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 GenerateChangeScript extends Command { + protected function configure() { + $this + ->setName('db:generate-change-script') + ->setDescription('generates the change script from the current connected db to db_structure.xml') + ->addArgument( + 'schema-xml', + InputArgument::OPTIONAL, + 'the schema xml to be used as target schema', + \OC::$SERVERROOT . '/db_structure.xml' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) { + + $file = $input->getArgument('schema-xml'); + + $schemaManager = new \OC\DB\MDB2SchemaManager(\OC::$server->getDatabaseConnection()); + + try { + $result = $schemaManager->updateDbFromStructure($file, true); + $output->writeln($result); + } catch (\Exception $e) { + $output->writeln('Failed to update database structure ('.$e.')'); + } + + } +} diff --git a/core/Command/Encryption/ChangeKeyStorageRoot.php b/core/Command/Encryption/ChangeKeyStorageRoot.php new file mode 100644 index 00000000000..801a08b42a8 --- /dev/null +++ b/core/Command/Encryption/ChangeKeyStorageRoot.php @@ -0,0 +1,270 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + + +namespace OC\Core\Command\Encryption; + +use OC\Encryption\Keys\Storage; +use OC\Encryption\Util; +use OC\Files\Filesystem; +use OC\Files\View; +use OCP\IConfig; +use OCP\IUserManager; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\ProgressBar; +use Symfony\Component\Console\Helper\QuestionHelper; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Question\ConfirmationQuestion; + +class ChangeKeyStorageRoot extends Command { + + /** @var View */ + protected $rootView; + + /** @var IUserManager */ + protected $userManager; + + /** @var IConfig */ + protected $config; + + /** @var Util */ + protected $util; + + /** @var QuestionHelper */ + protected $questionHelper; + + /** + * @param View $view + * @param IUserManager $userManager + * @param IConfig $config + * @param Util $util + * @param QuestionHelper $questionHelper + */ + public function __construct(View $view, IUserManager $userManager, IConfig $config, Util $util, QuestionHelper $questionHelper) { + parent::__construct(); + $this->rootView = $view; + $this->userManager = $userManager; + $this->config = $config; + $this->util = $util; + $this->questionHelper = $questionHelper; + } + + protected function configure() { + parent::configure(); + $this + ->setName('encryption:change-key-storage-root') + ->setDescription('Change key storage root') + ->addArgument( + 'newRoot', + InputArgument::OPTIONAL, + 'new root of the key storage relative to the data folder' + ); + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $oldRoot = $this->util->getKeyStorageRoot(); + $newRoot = $input->getArgument('newRoot'); + + if ($newRoot === null) { + $question = new ConfirmationQuestion('No storage root given, do you want to reset the key storage root to the default location? (y/n) ', false); + if (!$this->questionHelper->ask($input, $output, $question)) { + return; + } + $newRoot = ''; + } + + $oldRootDescription = $oldRoot !== '' ? $oldRoot : 'default storage location'; + $newRootDescription = $newRoot !== '' ? $newRoot : 'default storage location'; + $output->writeln("Change key storage root from $oldRootDescription to $newRootDescription"); + $success = $this->moveAllKeys($oldRoot, $newRoot, $output); + if ($success) { + $this->util->setKeyStorageRoot($newRoot); + $output->writeln(''); + $output->writeln("Key storage root successfully changed to $newRootDescription"); + } + } + + /** + * move keys to new key storage root + * + * @param string $oldRoot + * @param string $newRoot + * @param OutputInterface $output + * @return bool + * @throws \Exception + */ + protected function moveAllKeys($oldRoot, $newRoot, OutputInterface $output) { + + $output->writeln("Start to move keys:"); + + if ($this->rootView->is_dir(($oldRoot)) === false) { + $output->writeln("No old keys found: Nothing needs to be moved"); + return false; + } + + $this->prepareNewRoot($newRoot); + $this->moveSystemKeys($oldRoot, $newRoot); + $this->moveUserKeys($oldRoot, $newRoot, $output); + + return true; + } + + /** + * prepare new key storage + * + * @param string $newRoot + * @throws \Exception + */ + protected function prepareNewRoot($newRoot) { + if ($this->rootView->is_dir($newRoot) === false) { + throw new \Exception("New root folder doesn't exist. Please create the folder or check the permissions and try again."); + } + + $result = $this->rootView->file_put_contents( + $newRoot . '/' . Storage::KEY_STORAGE_MARKER, + 'ownCloud will detect this folder as key storage root only if this file exists' + ); + + if ($result === false) { + throw new \Exception("Can't write to new root folder. Please check the permissions and try again"); + } + + } + + + /** + * move system key folder + * + * @param string $oldRoot + * @param string $newRoot + */ + protected function moveSystemKeys($oldRoot, $newRoot) { + if ( + $this->rootView->is_dir($oldRoot . '/files_encryption') && + $this->targetExists($newRoot . '/files_encryption') === false + ) { + $this->rootView->rename($oldRoot . '/files_encryption', $newRoot . '/files_encryption'); + } + } + + + /** + * setup file system for the given user + * + * @param string $uid + */ + protected function setupUserFS($uid) { + \OC_Util::tearDownFS(); + \OC_Util::setupFS($uid); + } + + + /** + * iterate over each user and move the keys to the new storage + * + * @param string $oldRoot + * @param string $newRoot + * @param OutputInterface $output + */ + protected function moveUserKeys($oldRoot, $newRoot, OutputInterface $output) { + + $progress = new ProgressBar($output); + $progress->start(); + + + foreach($this->userManager->getBackends() as $backend) { + $limit = 500; + $offset = 0; + do { + $users = $backend->getUsers('', $limit, $offset); + foreach ($users as $user) { + $progress->advance(); + $this->setupUserFS($user); + $this->moveUserEncryptionFolder($user, $oldRoot, $newRoot); + } + $offset += $limit; + } while(count($users) >= $limit); + } + $progress->finish(); + } + + /** + * move user encryption folder to new root folder + * + * @param string $user + * @param string $oldRoot + * @param string $newRoot + * @throws \Exception + */ + protected function moveUserEncryptionFolder($user, $oldRoot, $newRoot) { + + if ($this->userManager->userExists($user)) { + + $source = $oldRoot . '/' . $user . '/files_encryption'; + $target = $newRoot . '/' . $user . '/files_encryption'; + if ( + $this->rootView->is_dir($source) && + $this->targetExists($target) === false + ) { + $this->prepareParentFolder($newRoot . '/' . $user); + $this->rootView->rename($source, $target); + } + } + } + + /** + * Make preparations to filesystem for saving a key file + * + * @param string $path relative to data/ + */ + protected function prepareParentFolder($path) { + $path = Filesystem::normalizePath($path); + // If the file resides within a subdirectory, create it + if ($this->rootView->file_exists($path) === false) { + $sub_dirs = explode('/', ltrim($path, '/')); + $dir = ''; + foreach ($sub_dirs as $sub_dir) { + $dir .= '/' . $sub_dir; + if ($this->rootView->file_exists($dir) === false) { + $this->rootView->mkdir($dir); + } + } + } + } + + /** + * check if target already exists + * + * @param $path + * @return bool + * @throws \Exception + */ + protected function targetExists($path) { + if ($this->rootView->file_exists($path)) { + throw new \Exception("new folder '$path' already exists"); + } + + return false; + } + +} diff --git a/core/Command/Encryption/DecryptAll.php b/core/Command/Encryption/DecryptAll.php new file mode 100644 index 00000000000..0a126db5b17 --- /dev/null +++ b/core/Command/Encryption/DecryptAll.php @@ -0,0 +1,160 @@ + + * @author Joas Schilling + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Encryption; + +use OCP\App\IAppManager; +use OCP\Encryption\IManager; +use OCP\IConfig; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\QuestionHelper; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Question\ConfirmationQuestion; + +class DecryptAll extends Command { + + /** @var IManager */ + protected $encryptionManager; + + /** @var IAppManager */ + protected $appManager; + + /** @var IConfig */ + protected $config; + + /** @var QuestionHelper */ + protected $questionHelper; + + /** @var bool */ + protected $wasTrashbinEnabled; + + /** @var bool */ + protected $wasSingleUserModeEnabled; + + /** @var \OC\Encryption\DecryptAll */ + protected $decryptAll; + + /** + * @param IManager $encryptionManager + * @param IAppManager $appManager + * @param IConfig $config + * @param \OC\Encryption\DecryptAll $decryptAll + * @param QuestionHelper $questionHelper + */ + public function __construct( + IManager $encryptionManager, + IAppManager $appManager, + IConfig $config, + \OC\Encryption\DecryptAll $decryptAll, + QuestionHelper $questionHelper + ) { + parent::__construct(); + + $this->appManager = $appManager; + $this->encryptionManager = $encryptionManager; + $this->config = $config; + $this->decryptAll = $decryptAll; + $this->questionHelper = $questionHelper; + } + + /** + * Set single user mode and disable the trashbin app + */ + protected function forceSingleUserAndTrashbin() { + $this->wasTrashbinEnabled = $this->appManager->isEnabledForUser('files_trashbin'); + $this->wasSingleUserModeEnabled = $this->config->getSystemValue('singleuser', false); + $this->config->setSystemValue('singleuser', true); + $this->appManager->disableApp('files_trashbin'); + } + + /** + * Reset the single user mode and re-enable the trashbin app + */ + protected function resetSingleUserAndTrashbin() { + $this->config->setSystemValue('singleuser', $this->wasSingleUserModeEnabled); + if ($this->wasTrashbinEnabled) { + $this->appManager->enableApp('files_trashbin'); + } + } + + protected function configure() { + parent::configure(); + + $this->setName('encryption:decrypt-all'); + $this->setDescription('Disable server-side encryption and decrypt all files'); + $this->setHelp( + 'This will disable server-side encryption and decrypt all files for ' + . 'all users if it is supported by your encryption module. ' + . 'Please make sure that no user access his files during this process!' + ); + $this->addArgument( + 'user', + InputArgument::OPTIONAL, + 'user for which you want to decrypt all files (optional)' + ); + } + + protected function execute(InputInterface $input, OutputInterface $output) { + + try { + if ($this->encryptionManager->isEnabled() === true) { + $output->write('Disable server side encryption... '); + $this->config->setAppValue('core', 'encryption_enabled', 'no'); + $output->writeln('done.'); + } else { + $output->writeln('Server side encryption not enabled. Nothing to do.'); + return; + } + + $output->writeln("\n"); + $output->writeln('You are about to start to decrypt all files stored in your ownCloud.'); + $output->writeln('It will depend on the encryption module and your setup if this is possible.'); + $output->writeln('Depending on the number and size of your files this can take some time'); + $output->writeln('Please make sure that no user access his files during this process!'); + $output->writeln(''); + $question = new ConfirmationQuestion('Do you really want to continue? (y/n) ', false); + if ($this->questionHelper->ask($input, $output, $question)) { + $this->forceSingleUserAndTrashbin(); + $user = $input->getArgument('user'); + $result = $this->decryptAll->decryptAll($input, $output, $user); + if ($result === false) { + $output->writeln(' aborted.'); + $this->config->setAppValue('core', 'encryption_enabled', 'yes'); + } + $this->resetSingleUserAndTrashbin(); + } else { + $output->write('Enable server side encryption... '); + $this->config->setAppValue('core', 'encryption_enabled', 'yes'); + $output->writeln('done.'); + $output->writeln('aborted'); + } + } catch (\Exception $e) { + // enable server side encryption again if something went wrong + $this->config->setAppValue('core', 'encryption_enabled', 'yes'); + $this->resetSingleUserAndTrashbin(); + throw $e; + } + + } +} diff --git a/core/Command/Encryption/Disable.php b/core/Command/Encryption/Disable.php new file mode 100644 index 00000000000..0e08a314473 --- /dev/null +++ b/core/Command/Encryption/Disable.php @@ -0,0 +1,56 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Encryption; + +use OCP\IConfig; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class Disable extends Command { + /** @var IConfig */ + protected $config; + + /** + * @param IConfig $config + */ + public function __construct(IConfig $config) { + parent::__construct(); + $this->config = $config; + } + + protected function configure() { + $this + ->setName('encryption:disable') + ->setDescription('Disable encryption') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) { + if ($this->config->getAppValue('core', 'encryption_enabled', 'no') !== 'yes') { + $output->writeln('Encryption is already disabled'); + } else { + $this->config->setAppValue('core', 'encryption_enabled', 'no'); + $output->writeln('Encryption disabled'); + } + } +} diff --git a/core/Command/Encryption/Enable.php b/core/Command/Encryption/Enable.php new file mode 100644 index 00000000000..273320e6155 --- /dev/null +++ b/core/Command/Encryption/Enable.php @@ -0,0 +1,78 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Encryption; + +use OCP\Encryption\IManager; +use OCP\IConfig; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class Enable extends Command { + /** @var IConfig */ + protected $config; + + /** @var IManager */ + protected $encryptionManager; + + /** + * @param IConfig $config + * @param IManager $encryptionManager + */ + public function __construct(IConfig $config, IManager $encryptionManager) { + parent::__construct(); + + $this->encryptionManager = $encryptionManager; + $this->config = $config; + } + + protected function configure() { + $this + ->setName('encryption:enable') + ->setDescription('Enable encryption') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) { + if ($this->config->getAppValue('core', 'encryption_enabled', 'no') === 'yes') { + $output->writeln('Encryption is already enabled'); + } else { + $this->config->setAppValue('core', 'encryption_enabled', 'yes'); + $output->writeln('Encryption enabled'); + } + $output->writeln(''); + + $modules = $this->encryptionManager->getEncryptionModules(); + if (empty($modules)) { + $output->writeln('No encryption module is loaded'); + } else { + $defaultModule = $this->config->getAppValue('core', 'default_encryption_module', null); + if ($defaultModule === null) { + $output->writeln('No default module is set'); + } else if (!isset($modules[$defaultModule])) { + $output->writeln('The current default module does not exist: ' . $defaultModule . ''); + } else { + $output->writeln('Default module: ' . $defaultModule); + } + } + } +} diff --git a/core/Command/Encryption/EncryptAll.php b/core/Command/Encryption/EncryptAll.php new file mode 100644 index 00000000000..02f74a9dea4 --- /dev/null +++ b/core/Command/Encryption/EncryptAll.php @@ -0,0 +1,134 @@ + + * @author Joas Schilling + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Encryption; + +use OCP\App\IAppManager; +use OCP\Encryption\IManager; +use OCP\IConfig; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\QuestionHelper; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Question\ConfirmationQuestion; + +class EncryptAll extends Command { + + /** @var IManager */ + protected $encryptionManager; + + /** @var IAppManager */ + protected $appManager; + + /** @var IConfig */ + protected $config; + + /** @var QuestionHelper */ + protected $questionHelper; + + /** @var bool */ + protected $wasTrashbinEnabled; + + /** @var bool */ + protected $wasSingleUserModeEnabled; + + /** + * @param IManager $encryptionManager + * @param IAppManager $appManager + * @param IConfig $config + * @param QuestionHelper $questionHelper + */ + public function __construct( + IManager $encryptionManager, + IAppManager $appManager, + IConfig $config, + QuestionHelper $questionHelper + ) { + parent::__construct(); + $this->appManager = $appManager; + $this->encryptionManager = $encryptionManager; + $this->config = $config; + $this->questionHelper = $questionHelper; + } + + /** + * Set single user mode and disable the trashbin app + */ + protected function forceSingleUserAndTrashbin() { + $this->wasTrashbinEnabled = $this->appManager->isEnabledForUser('files_trashbin'); + $this->wasSingleUserModeEnabled = $this->config->getSystemValue('singleuser', false); + $this->config->setSystemValue('singleuser', true); + $this->appManager->disableApp('files_trashbin'); + } + + /** + * Reset the single user mode and re-enable the trashbin app + */ + protected function resetSingleUserAndTrashbin() { + $this->config->setSystemValue('singleuser', $this->wasSingleUserModeEnabled); + if ($this->wasTrashbinEnabled) { + $this->appManager->enableApp('files_trashbin'); + } + } + + protected function configure() { + parent::configure(); + + $this->setName('encryption:encrypt-all'); + $this->setDescription('Encrypt all files for all users'); + $this->setHelp( + 'This will encrypt all files for all users. ' + . 'Please make sure that no user access his files during this process!' + ); + } + + protected function execute(InputInterface $input, OutputInterface $output) { + + if ($this->encryptionManager->isEnabled() === false) { + throw new \Exception('Server side encryption is not enabled'); + } + + $output->writeln("\n"); + $output->writeln('You are about to start to encrypt all files stored in your ownCloud.'); + $output->writeln('It will depend on the encryption module you use which files get encrypted.'); + $output->writeln('Depending on the number and size of your files this can take some time'); + $output->writeln('Please make sure that no user access his files during this process!'); + $output->writeln(''); + $question = new ConfirmationQuestion('Do you really want to continue? (y/n) ', false); + if ($this->questionHelper->ask($input, $output, $question)) { + $this->forceSingleUserAndTrashbin(); + + try { + $defaultModule = $this->encryptionManager->getEncryptionModule(); + $defaultModule->encryptAll($input, $output); + } catch (\Exception $ex) { + $this->resetSingleUserAndTrashbin(); + throw $ex; + } + + $this->resetSingleUserAndTrashbin(); + } else { + $output->writeln('aborted'); + } + } + +} diff --git a/core/Command/Encryption/ListModules.php b/core/Command/Encryption/ListModules.php new file mode 100644 index 00000000000..9c061b6e764 --- /dev/null +++ b/core/Command/Encryption/ListModules.php @@ -0,0 +1,80 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Encryption; + +use OC\Core\Command\Base; +use OCP\Encryption\IManager; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class ListModules extends Base { + /** @var IManager */ + protected $encryptionManager; + + /** + * @param IManager $encryptionManager + */ + public function __construct(IManager $encryptionManager) { + parent::__construct(); + $this->encryptionManager = $encryptionManager; + } + + protected function configure() { + parent::configure(); + + $this + ->setName('encryption:list-modules') + ->setDescription('List all available encryption modules') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $encryptionModules = $this->encryptionManager->getEncryptionModules(); + $defaultEncryptionModuleId = $this->encryptionManager->getDefaultEncryptionModuleId(); + + $encModules = array(); + foreach ($encryptionModules as $module) { + $encModules[$module['id']]['displayName'] = $module['displayName']; + $encModules[$module['id']]['default'] = $module['id'] === $defaultEncryptionModuleId; + } + $this->writeModuleList($input, $output, $encModules); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @param array $items + */ + protected function writeModuleList(InputInterface $input, OutputInterface $output, $items) { + if ($input->getOption('output') === self::OUTPUT_FORMAT_PLAIN) { + array_walk($items, function(&$item) { + if (!$item['default']) { + $item = $item['displayName']; + } else { + $item = $item['displayName'] . ' [default*]'; + } + }); + } + + $this->writeArrayInOutputFormat($input, $output, $items); + } +} diff --git a/core/Command/Encryption/SetDefaultModule.php b/core/Command/Encryption/SetDefaultModule.php new file mode 100644 index 00000000000..e9978536201 --- /dev/null +++ b/core/Command/Encryption/SetDefaultModule.php @@ -0,0 +1,68 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Encryption; + + +use OCP\Encryption\IManager; +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 SetDefaultModule extends Command { + /** @var IManager */ + protected $encryptionManager; + + /** + * @param IManager $encryptionManager + */ + public function __construct(IManager $encryptionManager) { + parent::__construct(); + $this->encryptionManager = $encryptionManager; + } + + protected function configure() { + parent::configure(); + + $this + ->setName('encryption:set-default-module') + ->setDescription('Set the encryption default module') + ->addArgument( + 'module', + InputArgument::REQUIRED, + 'ID of the encryption module that should be used' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $moduleId = $input->getArgument('module'); + + if ($moduleId === $this->encryptionManager->getDefaultEncryptionModuleId()) { + $output->writeln('"' . $moduleId . '"" is already the default module'); + } else if ($this->encryptionManager->setDefaultEncryptionModule($moduleId)) { + $output->writeln('Set default module to "' . $moduleId . '"'); + } else { + $output->writeln('The specified module "' . $moduleId . '" does not exist'); + } + } +} diff --git a/core/Command/Encryption/ShowKeyStorageRoot.php b/core/Command/Encryption/ShowKeyStorageRoot.php new file mode 100644 index 00000000000..402352c4bcf --- /dev/null +++ b/core/Command/Encryption/ShowKeyStorageRoot.php @@ -0,0 +1,58 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + + +namespace OC\Core\Command\Encryption; + +use OC\Encryption\Util; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class ShowKeyStorageRoot extends Command{ + + /** @var Util */ + protected $util; + + /** + * @param Util $util + */ + public function __construct(Util $util) { + parent::__construct(); + $this->util = $util; + } + + protected function configure() { + parent::configure(); + $this + ->setName('encryption:show-key-storage-root') + ->setDescription('Show current key storage root'); + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $currentRoot = $this->util->getKeyStorageRoot(); + + $rootDescription = $currentRoot !== '' ? $currentRoot : 'default storage location (data/)'; + + $output->writeln("Current key storage root: $rootDescription"); + } + +} diff --git a/core/Command/Encryption/Status.php b/core/Command/Encryption/Status.php new file mode 100644 index 00000000000..b97ea8833fa --- /dev/null +++ b/core/Command/Encryption/Status.php @@ -0,0 +1,56 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Encryption; + +use OC\Core\Command\Base; +use OCP\Encryption\IManager; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class Status extends Base { + /** @var IManager */ + protected $encryptionManager; + + /** + * @param IManager $encryptionManager + */ + public function __construct(IManager $encryptionManager) { + parent::__construct(); + $this->encryptionManager = $encryptionManager; + } + + protected function configure() { + parent::configure(); + + $this + ->setName('encryption:status') + ->setDescription('Lists the current status of encryption') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $this->writeArrayInOutputFormat($input, $output, [ + 'enabled' => $this->encryptionManager->isEnabled(), + 'defaultModule' => $this->encryptionManager->getDefaultEncryptionModuleId(), + ]); + } +} diff --git a/core/Command/Integrity/CheckApp.php b/core/Command/Integrity/CheckApp.php new file mode 100644 index 00000000000..643af5285b4 --- /dev/null +++ b/core/Command/Integrity/CheckApp.php @@ -0,0 +1,69 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ +namespace OC\Core\Command\Integrity; + +use OC\IntegrityCheck\Checker; +use OC\Core\Command\Base; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Class CheckApp + * + * @package OC\Core\Command\Integrity + */ +class CheckApp extends Base { + + /** + * @var Checker + */ + private $checker; + + public function __construct(Checker $checker) { + parent::__construct(); + $this->checker = $checker; + } + + /** + * {@inheritdoc } + */ + protected function configure() { + parent::configure(); + $this + ->setName('integrity:check-app') + ->setDescription('Check integrity of an app using a signature.') + ->addArgument('appid', null, InputArgument::REQUIRED, 'Application to check') + ->addOption('path', null, InputOption::VALUE_OPTIONAL, 'Path to application. If none is given it will be guessed.'); + } + + /** + * {@inheritdoc } + */ + protected function execute(InputInterface $input, OutputInterface $output) { + $appid = $input->getArgument('appid'); + $path = strval($input->getOption('path')); + $result = $this->checker->verifyAppSignature($appid, $path); + $this->writeArrayInOutputFormat($input, $output, $result); + } + +} diff --git a/core/Command/Integrity/CheckCore.php b/core/Command/Integrity/CheckCore.php new file mode 100644 index 00000000000..460a78e4da7 --- /dev/null +++ b/core/Command/Integrity/CheckCore.php @@ -0,0 +1,62 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Integrity; + +use OC\IntegrityCheck\Checker; +use OC\Core\Command\Base; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Class CheckCore + * + * @package OC\Core\Command\Integrity + */ +class CheckCore extends Base { + /** + * @var Checker + */ + private $checker; + + public function __construct(Checker $checker) { + parent::__construct(); + $this->checker = $checker; + } + + /** + * {@inheritdoc } + */ + protected function configure() { + parent::configure(); + $this + ->setName('integrity:check-core') + ->setDescription('Check integrity of core code using a signature.'); + } + + /** + * {@inheritdoc } + */ + protected function execute(InputInterface $input, OutputInterface $output) { + $result = $this->checker->verifyCoreSignature(); + $this->writeArrayInOutputFormat($input, $output, $result); + } +} diff --git a/core/Command/Integrity/SignApp.php b/core/Command/Integrity/SignApp.php new file mode 100644 index 00000000000..53df9619c6d --- /dev/null +++ b/core/Command/Integrity/SignApp.php @@ -0,0 +1,107 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Integrity; + +use OC\IntegrityCheck\Checker; +use OC\IntegrityCheck\Helpers\FileAccessHelper; +use OCP\IURLGenerator; +use phpseclib\Crypt\RSA; +use phpseclib\File\X509; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Class SignApp + * + * @package OC\Core\Command\Integrity + */ +class SignApp extends Command { + /** @var Checker */ + private $checker; + /** @var FileAccessHelper */ + private $fileAccessHelper; + /** @var IURLGenerator */ + private $urlGenerator; + + /** + * @param Checker $checker + * @param FileAccessHelper $fileAccessHelper + * @param IURLGenerator $urlGenerator + */ + public function __construct(Checker $checker, + FileAccessHelper $fileAccessHelper, + IURLGenerator $urlGenerator) { + parent::__construct(null); + $this->checker = $checker; + $this->fileAccessHelper = $fileAccessHelper; + $this->urlGenerator = $urlGenerator; + } + + protected function configure() { + $this + ->setName('integrity:sign-app') + ->setDescription('Signs an app using a private key.') + ->addOption('path', null, InputOption::VALUE_REQUIRED, 'Application to sign') + ->addOption('privateKey', null, InputOption::VALUE_REQUIRED, 'Path to private key to use for signing') + ->addOption('certificate', null, InputOption::VALUE_REQUIRED, 'Path to certificate to use for signing'); + } + + /** + * {@inheritdoc } + */ + protected function execute(InputInterface $input, OutputInterface $output) { + $path = $input->getOption('path'); + $privateKeyPath = $input->getOption('privateKey'); + $keyBundlePath = $input->getOption('certificate'); + if(is_null($path) || is_null($privateKeyPath) || is_null($keyBundlePath)) { + $documentationUrl = $this->urlGenerator->linkToDocs('developer-code-integrity'); + $output->writeln('This command requires the --path, --privateKey and --certificate.'); + $output->writeln('Example: ./occ integrity:sign-app --path="/Users/lukasreschke/Programming/myapp/" --privateKey="/Users/lukasreschke/private/myapp.key" --certificate="/Users/lukasreschke/public/mycert.crt"'); + $output->writeln('For more information please consult the documentation: '. $documentationUrl); + return null; + } + + $privateKey = $this->fileAccessHelper->file_get_contents($privateKeyPath); + $keyBundle = $this->fileAccessHelper->file_get_contents($keyBundlePath); + + if($privateKey === false) { + $output->writeln(sprintf('Private key "%s" does not exists.', $privateKeyPath)); + return null; + } + + if($keyBundle === false) { + $output->writeln(sprintf('Certificate "%s" does not exists.', $keyBundlePath)); + return null; + } + + $rsa = new RSA(); + $rsa->loadKey($privateKey); + $x509 = new X509(); + $x509->loadX509($keyBundle); + $x509->setPrivateKey($rsa); + $this->checker->writeAppSignature($path, $x509, $rsa); + + $output->writeln('Successfully signed "'.$path.'"'); + } +} diff --git a/core/Command/Integrity/SignCore.php b/core/Command/Integrity/SignCore.php new file mode 100644 index 00000000000..e5c2de73e00 --- /dev/null +++ b/core/Command/Integrity/SignCore.php @@ -0,0 +1,100 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Integrity; + +use OC\IntegrityCheck\Checker; +use OC\IntegrityCheck\Helpers\EnvironmentHelper; +use OC\IntegrityCheck\Helpers\FileAccessHelper; +use phpseclib\Crypt\RSA; +use phpseclib\File\X509; +use Symfony\Component\Console\Command\Command; +use OCP\IConfig; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Class SignCore + * + * @package OC\Core\Command\Integrity + */ +class SignCore extends Command { + /** @var Checker */ + private $checker; + /** @var FileAccessHelper */ + private $fileAccessHelper; + + /** + * @param Checker $checker + * @param FileAccessHelper $fileAccessHelper + */ + public function __construct(Checker $checker, + FileAccessHelper $fileAccessHelper) { + parent::__construct(null); + $this->checker = $checker; + $this->fileAccessHelper = $fileAccessHelper; + } + + protected function configure() { + $this + ->setName('integrity:sign-core') + ->setDescription('Sign core using a private key.') + ->addOption('privateKey', null, InputOption::VALUE_REQUIRED, 'Path to private key to use for signing') + ->addOption('certificate', null, InputOption::VALUE_REQUIRED, 'Path to certificate to use for signing') + ->addOption('path', null, InputOption::VALUE_REQUIRED, 'Path of core to sign'); + } + + /** + * {@inheritdoc } + */ + protected function execute(InputInterface $input, OutputInterface $output) { + $privateKeyPath = $input->getOption('privateKey'); + $keyBundlePath = $input->getOption('certificate'); + $path = $input->getOption('path'); + if(is_null($privateKeyPath) || is_null($keyBundlePath) || is_null($path)) { + $output->writeln('--privateKey, --certificate and --path are required.'); + return null; + } + + $privateKey = $this->fileAccessHelper->file_get_contents($privateKeyPath); + $keyBundle = $this->fileAccessHelper->file_get_contents($keyBundlePath); + + if($privateKey === false) { + $output->writeln(sprintf('Private key "%s" does not exists.', $privateKeyPath)); + return null; + } + + if($keyBundle === false) { + $output->writeln(sprintf('Certificate "%s" does not exists.', $keyBundlePath)); + return null; + } + + $rsa = new RSA(); + $rsa->loadKey($privateKey); + $x509 = new X509(); + $x509->loadX509($keyBundle); + $x509->setPrivateKey($rsa); + $this->checker->writeCoreSignature($x509, $rsa, $path); + + $output->writeln('Successfully signed "core"'); + } +} diff --git a/core/Command/L10n/CreateJs.php b/core/Command/L10n/CreateJs.php new file mode 100644 index 00000000000..c2cfc5d0934 --- /dev/null +++ b/core/Command/L10n/CreateJs.php @@ -0,0 +1,137 @@ + + * @author Thomas Müller + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\L10n; + +use DirectoryIterator; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use UnexpectedValueException; + +class CreateJs extends Command { + + protected function configure() { + $this + ->setName('l10n:createjs') + ->setDescription('Create javascript translation files for a given app') + ->addArgument( + 'app', + InputOption::VALUE_REQUIRED, + 'name of the app' + ) + ->addArgument( + 'lang', + InputOption::VALUE_OPTIONAL, + 'name of the language' + ); + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $app = $input->getArgument('app'); + $lang = $input->getArgument('lang'); + + $path = \OC_App::getAppPath($app); + if ($path === false) { + $output->writeln("The app <$app> is unknown."); + return; + } + $languages = $lang; + if (empty($lang)) { + $languages= $this->getAllLanguages($path); + } + + foreach($languages as $lang) { + $this->writeFiles($app, $path, $lang, $output); + } + } + + private function getAllLanguages($path) { + $result = array(); + foreach (new DirectoryIterator("$path/l10n") as $fileInfo) { + if($fileInfo->isDot()) { + continue; + } + if($fileInfo->isDir()) { + continue; + } + if($fileInfo->getExtension() !== 'php') { + continue; + } + $result[]= substr($fileInfo->getBasename(), 0, -4); + } + + return $result; + } + + private function writeFiles($app, $path, $lang, OutputInterface $output) { + list($translations, $plurals) = $this->loadTranslations($path, $lang); + $this->writeJsFile($app, $path, $lang, $output, $translations, $plurals); + $this->writeJsonFile($path, $lang, $output, $translations, $plurals); + } + + private function writeJsFile($app, $path, $lang, OutputInterface $output, $translations, $plurals) { + $jsFile = "$path/l10n/$lang.js"; + if (file_exists($jsFile)) { + $output->writeln("File already exists: $jsFile"); + return; + } + $content = "OC.L10N.register(\n \"$app\",\n {\n "; + $jsTrans = array(); + foreach ($translations as $id => $val) { + if (is_array($val)) { + $val = '[ ' . join(',', $val) . ']'; + } + $jsTrans[] = "\"$id\" : \"$val\""; + } + $content .= join(",\n ", $jsTrans); + $content .= "\n},\n\"$plurals\");\n"; + + file_put_contents($jsFile, $content); + $output->writeln("Javascript translation file generated: $jsFile"); + } + + private function writeJsonFile($path, $lang, OutputInterface $output, $translations, $plurals) { + $jsFile = "$path/l10n/$lang.json"; + if (file_exists($jsFile)) { + $output->writeln("File already exists: $jsFile"); + return; + } + $content = array('translations' => $translations, 'pluralForm' => $plurals); + file_put_contents($jsFile, json_encode($content)); + $output->writeln("Json translation file generated: $jsFile"); + } + + private function loadTranslations($path, $lang) { + $phpFile = "$path/l10n/$lang.php"; + $TRANSLATIONS = array(); + $PLURAL_FORMS = ''; + if (!file_exists($phpFile)) { + throw new UnexpectedValueException("PHP translation file <$phpFile> does not exist."); + } + require $phpFile; + + return array($TRANSLATIONS, $PLURAL_FORMS); + } +} diff --git a/core/Command/Log/Manage.php b/core/Command/Log/Manage.php new file mode 100644 index 00000000000..1d65d7ed0d8 --- /dev/null +++ b/core/Command/Log/Manage.php @@ -0,0 +1,171 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Log; + +use \OCP\IConfig; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class Manage extends Command { + + const DEFAULT_BACKEND = 'owncloud'; + const DEFAULT_LOG_LEVEL = 2; + const DEFAULT_TIMEZONE = 'UTC'; + + /** @var IConfig */ + protected $config; + + public function __construct(IConfig $config) { + $this->config = $config; + parent::__construct(); + } + + protected function configure() { + $this + ->setName('log:manage') + ->setDescription('manage logging configuration') + ->addOption( + 'backend', + null, + InputOption::VALUE_REQUIRED, + 'set the logging backend [owncloud, syslog, errorlog]' + ) + ->addOption( + 'level', + null, + InputOption::VALUE_REQUIRED, + 'set the log level [debug, info, warning, error]' + ) + ->addOption( + 'timezone', + null, + InputOption::VALUE_REQUIRED, + 'set the logging timezone' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) { + // collate config setting to the end, to avoid partial configuration + $toBeSet = []; + + if ($backend = $input->getOption('backend')) { + $this->validateBackend($backend); + $toBeSet['log_type'] = $backend; + } + + if ($level = $input->getOption('level')) { + if (is_numeric($level)) { + $levelNum = $level; + // sanity check + $this->convertLevelNumber($levelNum); + } else { + $levelNum = $this->convertLevelString($level); + } + $toBeSet['loglevel'] = $levelNum; + } + + if ($timezone = $input->getOption('timezone')) { + $this->validateTimezone($timezone); + $toBeSet['logtimezone'] = $timezone; + } + + // set config + foreach ($toBeSet as $option => $value) { + $this->config->setSystemValue($option, $value); + } + + // display configuration + $backend = $this->config->getSystemValue('log_type', self::DEFAULT_BACKEND); + $output->writeln('Enabled logging backend: '.$backend); + + $levelNum = $this->config->getSystemValue('loglevel', self::DEFAULT_LOG_LEVEL); + $level = $this->convertLevelNumber($levelNum); + $output->writeln('Log level: '.$level.' ('.$levelNum.')'); + + $timezone = $this->config->getSystemValue('logtimezone', self::DEFAULT_TIMEZONE); + $output->writeln('Log timezone: '.$timezone); + } + + /** + * @param string $backend + * @throws \InvalidArgumentException + */ + protected function validateBackend($backend) { + if (!class_exists('OC_Log_'.$backend)) { + throw new \InvalidArgumentException('Invalid backend'); + } + } + + /** + * @param string $timezone + * @throws \Exception + */ + protected function validateTimezone($timezone) { + new \DateTimeZone($timezone); + } + + /** + * @param string $level + * @return int + * @throws \InvalidArgumentException + */ + protected function convertLevelString($level) { + $level = strtolower($level); + switch ($level) { + case 'debug': + return 0; + case 'info': + return 1; + case 'warning': + case 'warn': + return 2; + case 'error': + case 'err': + return 3; + } + throw new \InvalidArgumentException('Invalid log level string'); + } + + /** + * @param int $levelNum + * @return string + * @throws \InvalidArgumentException + */ + protected function convertLevelNumber($levelNum) { + switch ($levelNum) { + case 0: + return 'Debug'; + case 1: + return 'Info'; + case 2: + return 'Warning'; + case 3: + return 'Error'; + } + throw new \InvalidArgumentException('Invalid log level number'); + } +} diff --git a/core/Command/Log/OwnCloud.php b/core/Command/Log/OwnCloud.php new file mode 100644 index 00000000000..7213f6726a2 --- /dev/null +++ b/core/Command/Log/OwnCloud.php @@ -0,0 +1,124 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Log; + +use \OCP\IConfig; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class OwnCloud extends Command { + + /** @var IConfig */ + protected $config; + + public function __construct(IConfig $config) { + $this->config = $config; + parent::__construct(); + } + + protected function configure() { + $this + ->setName('log:owncloud') + ->setDescription('manipulate ownCloud logging backend') + ->addOption( + 'enable', + null, + InputOption::VALUE_NONE, + 'enable this logging backend' + ) + ->addOption( + 'file', + null, + InputOption::VALUE_REQUIRED, + 'set the log file path' + ) + ->addOption( + 'rotate-size', + null, + InputOption::VALUE_REQUIRED, + 'set the file size for log rotation, 0 = disabled' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $toBeSet = []; + + if ($input->getOption('enable')) { + $toBeSet['log_type'] = 'owncloud'; + } + + if ($file = $input->getOption('file')) { + $toBeSet['logfile'] = $file; + } + + if (($rotateSize = $input->getOption('rotate-size')) !== null) { + $rotateSize = \OCP\Util::computerFileSize($rotateSize); + $this->validateRotateSize($rotateSize); + $toBeSet['log_rotate_size'] = $rotateSize; + } + + // set config + foreach ($toBeSet as $option => $value) { + $this->config->setSystemValue($option, $value); + } + + // display config + if ($this->config->getSystemValue('log_type', 'owncloud') === 'owncloud') { + $enabledText = 'enabled'; + } else { + $enabledText = 'disabled'; + } + $output->writeln('Log backend ownCloud: '.$enabledText); + + $dataDir = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT.'/data'); + $defaultLogFile = rtrim($dataDir, '/').'/owncloud.log'; + $output->writeln('Log file: '.$this->config->getSystemValue('logfile', $defaultLogFile)); + + $rotateSize = $this->config->getSystemValue('log_rotate_size', 0); + if ($rotateSize) { + $rotateString = \OCP\Util::humanFileSize($rotateSize); + } else { + $rotateString = 'disabled'; + } + $output->writeln('Rotate at: '.$rotateString); + } + + /** + * @param mixed $rotateSize + * @throws \InvalidArgumentException + */ + protected function validateRotateSize(&$rotateSize) { + if ($rotateSize === false) { + throw new \InvalidArgumentException('Error parsing log rotation file size'); + } + $rotateSize = (int) $rotateSize; + if ($rotateSize < 0) { + throw new \InvalidArgumentException('Log rotation file size must be non-negative'); + } + } + +} diff --git a/core/Command/Maintenance/Install.php b/core/Command/Maintenance/Install.php new file mode 100644 index 00000000000..b1b63b9b3bd --- /dev/null +++ b/core/Command/Maintenance/Install.php @@ -0,0 +1,178 @@ + + * @author Christian Kampka + * @author Morris Jobke + * @author Thomas Müller + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ +namespace OC\Core\Command\Maintenance; + +use InvalidArgumentException; +use OC\Setup; +use OCP\IConfig; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class Install extends Command { + + /** + * @var IConfig + */ + private $config; + + public function __construct(IConfig $config) { + parent::__construct(); + $this->config = $config; + } + + protected function configure() { + $this + ->setName('maintenance:install') + ->setDescription('install ownCloud') + ->addOption('database', null, InputOption::VALUE_REQUIRED, 'Supported database type', 'sqlite') + ->addOption('database-name', null, InputOption::VALUE_REQUIRED, 'Name of the database') + ->addOption('database-host', null, InputOption::VALUE_REQUIRED, 'Hostname of the database', 'localhost') + ->addOption('database-user', null, InputOption::VALUE_REQUIRED, 'User name to connect to the database') + ->addOption('database-pass', null, InputOption::VALUE_OPTIONAL, 'Password of the database user', null) + ->addOption('database-table-prefix', null, InputOption::VALUE_OPTIONAL, 'Prefix for all tables (default: oc_)', null) + ->addOption('admin-user', null, InputOption::VALUE_REQUIRED, 'User name of the admin account', 'admin') + ->addOption('admin-pass', null, InputOption::VALUE_REQUIRED, 'Password of the admin account') + ->addOption('data-dir', null, InputOption::VALUE_REQUIRED, 'Path to data directory', \OC::$SERVERROOT."/data"); + } + + protected function execute(InputInterface $input, OutputInterface $output) { + + // validate the environment + $server = \OC::$server; + $setupHelper = new Setup($this->config, $server->getIniWrapper(), + $server->getL10N('lib'), new \OC_Defaults(), $server->getLogger(), + $server->getSecureRandom()); + $sysInfo = $setupHelper->getSystemInfo(true); + $errors = $sysInfo['errors']; + if (count($errors) > 0) { + $this->printErrors($output, $errors); + + // ignore the OS X setup warning + if(count($errors) !== 1 || + (string)($errors[0]['error']) !== 'Mac OS X is not supported and ownCloud will not work properly on this platform. Use it at your own risk! ') { + return 1; + } + } + + // validate user input + $options = $this->validateInput($input, $output, array_keys($sysInfo['databases'])); + + // perform installation + $errors = $setupHelper->install($options); + if (count($errors) > 0) { + $this->printErrors($output, $errors); + return 1; + } + $output->writeln("ownCloud was successfully installed"); + return 0; + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * @param string[] $supportedDatabases + * @return array + */ + protected function validateInput(InputInterface $input, OutputInterface $output, $supportedDatabases) { + $db = strtolower($input->getOption('database')); + + if (!in_array($db, $supportedDatabases)) { + throw new InvalidArgumentException("Database <$db> is not supported."); + } + + $dbUser = $input->getOption('database-user'); + $dbPass = $input->getOption('database-pass'); + $dbName = $input->getOption('database-name'); + $dbHost = $input->getOption('database-host'); + $dbTablePrefix = 'oc_'; + if ($input->hasParameterOption('--database-table-prefix')) { + $dbTablePrefix = (string) $input->getOption('database-table-prefix'); + $dbTablePrefix = trim($dbTablePrefix); + } + if ($input->hasParameterOption('--database-pass')) { + $dbPass = (string) $input->getOption('database-pass'); + } + $adminLogin = $input->getOption('admin-user'); + $adminPassword = $input->getOption('admin-pass'); + $dataDir = $input->getOption('data-dir'); + + if ($db !== 'sqlite') { + if (is_null($dbUser)) { + throw new InvalidArgumentException("Database user not provided."); + } + if (is_null($dbName)) { + throw new InvalidArgumentException("Database name not provided."); + } + if (is_null($dbPass)) { + /** @var $dialog \Symfony\Component\Console\Helper\DialogHelper */ + $dialog = $this->getHelperSet()->get('dialog'); + $dbPass = $dialog->askHiddenResponse( + $output, + "What is the password to access the database with user <$dbUser>?", + false + ); + } + } + + if (is_null($adminPassword)) { + /** @var $dialog \Symfony\Component\Console\Helper\DialogHelper */ + $dialog = $this->getHelperSet()->get('dialog'); + $adminPassword = $dialog->askHiddenResponse( + $output, + "What is the password you like to use for the admin account <$adminLogin>?", + false + ); + } + + $options = [ + 'dbtype' => $db, + 'dbuser' => $dbUser, + 'dbpass' => $dbPass, + 'dbname' => $dbName, + 'dbhost' => $dbHost, + 'dbtableprefix' => $dbTablePrefix, + 'adminlogin' => $adminLogin, + 'adminpass' => $adminPassword, + 'directory' => $dataDir + ]; + return $options; + } + + /** + * @param OutputInterface $output + * @param $errors + */ + protected function printErrors(OutputInterface $output, $errors) { + foreach ($errors as $error) { + if (is_array($error)) { + $output->writeln('' . (string)$error['error'] . ''); + $output->writeln(' -> ' . (string)$error['hint'] . ''); + } else { + $output->writeln('' . (string)$error . ''); + } + } + } +} diff --git a/core/Command/Maintenance/Mimetype/UpdateDB.php b/core/Command/Maintenance/Mimetype/UpdateDB.php new file mode 100644 index 00000000000..9532f9e1cd9 --- /dev/null +++ b/core/Command/Maintenance/Mimetype/UpdateDB.php @@ -0,0 +1,97 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Maintenance\Mimetype; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Input\InputOption; + +use OCP\Files\IMimeTypeDetector; +use OCP\Files\IMimeTypeLoader; + +class UpdateDB extends Command { + + const DEFAULT_MIMETYPE = 'application/octet-stream'; + + /** @var IMimeTypeDetector */ + protected $mimetypeDetector; + + /** @var IMimeTypeLoader */ + protected $mimetypeLoader; + + public function __construct( + IMimeTypeDetector $mimetypeDetector, + IMimeTypeLoader $mimetypeLoader + ) { + parent::__construct(); + $this->mimetypeDetector = $mimetypeDetector; + $this->mimetypeLoader = $mimetypeLoader; + } + + protected function configure() { + $this + ->setName('maintenance:mimetype:update-db') + ->setDescription('Update database mimetypes and update filecache') + ->addOption( + 'repair-filecache', + null, + InputOption::VALUE_NONE, + 'Repair filecache for all mimetypes, not just new ones' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $mappings = $this->mimetypeDetector->getAllMappings(); + + $totalFilecacheUpdates = 0; + $totalNewMimetypes = 0; + + foreach ($mappings as $ext => $mimetypes) { + if ($ext[0] === '_') { + // comment + continue; + } + $mimetype = $mimetypes[0]; + $existing = $this->mimetypeLoader->exists($mimetype); + // this will add the mimetype if it didn't exist + $mimetypeId = $this->mimetypeLoader->getId($mimetype); + + if (!$existing) { + $output->writeln('Added mimetype "'.$mimetype.'" to database'); + $totalNewMimetypes++; + } + + if (!$existing || $input->getOption('repair-filecache')) { + $touchedFilecacheRows = $this->mimetypeLoader->updateFilecache($ext, $mimetypeId); + if ($touchedFilecacheRows > 0) { + $output->writeln('Updated '.$touchedFilecacheRows.' filecache rows for mimetype "'.$mimetype.'"'); + } + $totalFilecacheUpdates += $touchedFilecacheRows; + } + } + + $output->writeln('Added '.$totalNewMimetypes.' new mimetypes'); + $output->writeln('Updated '.$totalFilecacheUpdates.' filecache rows'); + } +} diff --git a/core/Command/Maintenance/Mimetype/UpdateJS.php b/core/Command/Maintenance/Mimetype/UpdateJS.php new file mode 100644 index 00000000000..a87f50e32de --- /dev/null +++ b/core/Command/Maintenance/Mimetype/UpdateJS.php @@ -0,0 +1,129 @@ + + * @author Robin McCorkell + * @author Roeland Jago Douma + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Maintenance\Mimetype; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +use OCP\Files\IMimeTypeDetector; + +class UpdateJS extends Command { + + /** @var IMimeTypeDetector */ + protected $mimetypeDetector; + + public function __construct( + IMimeTypeDetector $mimetypeDetector + ) { + parent::__construct(); + $this->mimetypeDetector = $mimetypeDetector; + } + + protected function configure() { + $this + ->setName('maintenance:mimetype:update-js') + ->setDescription('Update mimetypelist.js'); + } + + protected function execute(InputInterface $input, OutputInterface $output) { + // Fetch all the aliases + $aliases = $this->mimetypeDetector->getAllAliases(); + + // Remove comments + $keys = array_filter(array_keys($aliases), function($k) { + return $k[0] === '_'; + }); + foreach($keys as $key) { + unset($aliases[$key]); + } + + // Fetch all files + $dir = new \DirectoryIterator(\OC::$SERVERROOT.'/core/img/filetypes'); + + $files = []; + foreach($dir as $fileInfo) { + if ($fileInfo->isFile()) { + $file = preg_replace('/.[^.]*$/', '', $fileInfo->getFilename()); + $files[] = $file; + } + } + + //Remove duplicates + $files = array_values(array_unique($files)); + sort($files); + + // Fetch all themes! + $themes = []; + $dirs = new \DirectoryIterator(\OC::$SERVERROOT.'/themes/'); + foreach($dirs as $dir) { + //Valid theme dir + if ($dir->isFile() || $dir->isDot()) { + continue; + } + + $theme = $dir->getFilename(); + $themeDir = $dir->getPath() . '/' . $theme . '/core/img/filetypes/'; + // Check if this theme has its own filetype icons + if (!file_exists($themeDir)) { + continue; + } + + $themes[$theme] = []; + // Fetch all the theme icons! + $themeIt = new \DirectoryIterator($themeDir); + foreach ($themeIt as $fileInfo) { + if ($fileInfo->isFile()) { + $file = preg_replace('/.[^.]*$/', '', $fileInfo->getFilename()); + $themes[$theme][] = $file; + } + } + + //Remove Duplicates + $themes[$theme] = array_values(array_unique($themes[$theme])); + sort($themes[$theme]); + } + + //Generate the JS + $js = '/** +* This file is automatically generated +* DO NOT EDIT MANUALLY! +* +* You can update the list of MimeType Aliases in config/mimetypealiases.json +* The list of files is fetched from core/img/filetypes +* To regenerate this file run ./occ maintenance:mimetypesjs +*/ +OC.MimeTypeList={ + aliases: ' . json_encode($aliases, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . ', + files: ' . json_encode($files, JSON_PRETTY_PRINT) . ', + themes: ' . json_encode($themes, JSON_PRETTY_PRINT) . ' +}; +'; + + //Output the JS + file_put_contents(\OC::$SERVERROOT.'/core/js/mimetypelist.js', $js); + + $output->writeln('mimetypelist.js is updated'); + } +} diff --git a/core/Command/Maintenance/Mode.php b/core/Command/Maintenance/Mode.php new file mode 100644 index 00000000000..28f4fb2f7f1 --- /dev/null +++ b/core/Command/Maintenance/Mode.php @@ -0,0 +1,75 @@ + + * @author scolebrook + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Maintenance; + +use \OCP\IConfig; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class Mode extends Command { + + /** @var IConfig */ + protected $config; + + public function __construct(IConfig $config) { + $this->config = $config; + parent::__construct(); + } + + protected function configure() { + $this + ->setName('maintenance:mode') + ->setDescription('set maintenance mode') + ->addOption( + 'on', + null, + InputOption::VALUE_NONE, + 'enable maintenance mode' + ) + ->addOption( + 'off', + null, + InputOption::VALUE_NONE, + 'disable maintenance mode' + ); + } + + protected function execute(InputInterface $input, OutputInterface $output) { + if ($input->getOption('on')) { + $this->config->setSystemValue('maintenance', true); + $output->writeln('Maintenance mode enabled'); + } elseif ($input->getOption('off')) { + $this->config->setSystemValue('maintenance', false); + $output->writeln('Maintenance mode disabled'); + } else { + if ($this->config->getSystemValue('maintenance', false)) { + $output->writeln('Maintenance mode is currently enabled'); + } else { + $output->writeln('Maintenance mode is currently disabled'); + } + } + } +} diff --git a/core/Command/Maintenance/Repair.php b/core/Command/Maintenance/Repair.php new file mode 100644 index 00000000000..95e2b872227 --- /dev/null +++ b/core/Command/Maintenance/Repair.php @@ -0,0 +1,91 @@ + + * @author Morris Jobke + * @author Robin Appelman + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Maintenance; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class Repair extends Command { + /** + * @var \OC\Repair $repair + */ + protected $repair; + /** @var \OCP\IConfig */ + protected $config; + + /** + * @param \OC\Repair $repair + * @param \OCP\IConfig $config + */ + public function __construct(\OC\Repair $repair, \OCP\IConfig $config) { + $this->repair = $repair; + $this->config = $config; + parent::__construct(); + } + + protected function configure() { + $this + ->setName('maintenance:repair') + ->setDescription('repair this installation') + ->addOption( + 'include-expensive', + null, + InputOption::VALUE_NONE, + 'Use this option when you want to include resource and load expensive tasks' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $includeExpensive = $input->getOption('include-expensive'); + if ($includeExpensive) { + foreach ($this->repair->getExpensiveRepairSteps() as $step) { + $this->repair->addStep($step); + } + } + + $maintenanceMode = $this->config->getSystemValue('maintenance', false); + $this->config->setSystemValue('maintenance', true); + + $this->repair->listen('\OC\Repair', 'step', function ($description) use ($output) { + $output->writeln(' - ' . $description); + }); + $this->repair->listen('\OC\Repair', 'info', function ($description) use ($output) { + $output->writeln(' - ' . $description); + }); + $this->repair->listen('\OC\Repair', 'warning', function ($description) use ($output) { + $output->writeln(' - WARNING: ' . $description); + }); + $this->repair->listen('\OC\Repair', 'error', function ($description) use ($output) { + $output->writeln(' - ERROR: ' . $description); + }); + + $this->repair->run(); + + $this->config->setSystemValue('maintenance', $maintenanceMode); + } +} diff --git a/core/Command/Maintenance/SingleUser.php b/core/Command/Maintenance/SingleUser.php new file mode 100644 index 00000000000..2e6f1f136e7 --- /dev/null +++ b/core/Command/Maintenance/SingleUser.php @@ -0,0 +1,78 @@ + + * @author Robin Appelman + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Maintenance; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +use OCP\IConfig; + +class SingleUser extends Command { + + /** @var IConfig */ + protected $config; + + /** + * @param IConfig $config + */ + public function __construct(IConfig $config) { + $this->config = $config; + parent::__construct(); + } + + protected function configure() { + $this + ->setName('maintenance:singleuser') + ->setDescription('set single user mode') + ->addOption( + 'on', + null, + InputOption::VALUE_NONE, + 'enable single user mode' + ) + ->addOption( + 'off', + null, + InputOption::VALUE_NONE, + 'disable single user mode' + ); + } + + protected function execute(InputInterface $input, OutputInterface $output) { + if ($input->getOption('on')) { + $this->config->setSystemValue('singleuser', true); + $output->writeln('Single user mode enabled'); + } elseif ($input->getOption('off')) { + $this->config->setSystemValue('singleuser', false); + $output->writeln('Single user mode disabled'); + } else { + if ($this->config->getSystemValue('singleuser', false)) { + $output->writeln('Single user mode is currently enabled'); + } else { + $output->writeln('Single user mode is currently disabled'); + } + } + } +} diff --git a/core/Command/Security/ImportCertificate.php b/core/Command/Security/ImportCertificate.php new file mode 100644 index 00000000000..6aae7ad1d9f --- /dev/null +++ b/core/Command/Security/ImportCertificate.php @@ -0,0 +1,67 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Security; + +use OC\Core\Command\Base; +use OCP\ICertificateManager; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class ImportCertificate extends Base { + + /** @var ICertificateManager */ + protected $certificateManager; + + public function __construct(ICertificateManager $certificateManager) { + $this->certificateManager = $certificateManager; + parent::__construct(); + } + + protected function configure() { + $this + ->setName('security:certificates:import') + ->setDescription('import trusted certificate') + ->addArgument( + 'path', + InputArgument::REQUIRED, + 'path to the certificate to import' + ); + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $path = $input->getArgument('path'); + + if (!file_exists($path)) { + $output->writeln('certificate not found'); + return; + } + + $certData = file_get_contents($path); + $name = basename($path); + + $this->certificateManager->addCertificate($certData, $name); + } +} diff --git a/core/Command/Security/ListCertificates.php b/core/Command/Security/ListCertificates.php new file mode 100644 index 00000000000..91deb2d340a --- /dev/null +++ b/core/Command/Security/ListCertificates.php @@ -0,0 +1,96 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Security; + +use OC\Core\Command\Base; +use OCP\ICertificate; +use OCP\ICertificateManager; +use OCP\IL10N; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class ListCertificates extends Base { + + /** @var ICertificateManager */ + protected $certificateManager; + /** @var IL10N */ + protected $l; + + public function __construct(ICertificateManager $certificateManager, IL10N $l) { + $this->certificateManager = $certificateManager; + $this->l = $l; + parent::__construct(); + } + + protected function configure() { + $this + ->setName('security:certificates') + ->setDescription('list trusted certificates'); + parent::configure(); + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $outputType = $input->getOption('output'); + if ($outputType === self::OUTPUT_FORMAT_JSON || $outputType === self::OUTPUT_FORMAT_JSON_PRETTY) { + $certificates = array_map(function (ICertificate $certificate) { + return [ + 'name' => $certificate->getName(), + 'common_name' => $certificate->getCommonName(), + 'organization' => $certificate->getOrganization(), + 'expire' => $certificate->getExpireDate()->format(\DateTime::ATOM), + 'issuer' => $certificate->getIssuerName(), + 'issuer_organization' => $certificate->getIssuerOrganization(), + 'issue_date' => $certificate->getIssueDate()->format(\DateTime::ATOM) + ]; + }, $this->certificateManager->listCertificates()); + if ($outputType === self::OUTPUT_FORMAT_JSON) { + $output->writeln(json_encode(array_values($certificates))); + } else { + $output->writeln(json_encode(array_values($certificates), JSON_PRETTY_PRINT)); + } + } else { + $table = new Table($output); + $table->setHeaders([ + 'File Name', + 'Common Name', + 'Organization', + 'Valid Until', + 'Issued By' + ]); + + $rows = array_map(function (ICertificate $certificate) { + return [ + $certificate->getName(), + $certificate->getCommonName(), + $certificate->getOrganization(), + $this->l->l('date', $certificate->getExpireDate()), + $certificate->getIssuerName() + ]; + }, $this->certificateManager->listCertificates()); + $table->setRows($rows); + $table->render(); + } + } +} diff --git a/core/Command/Security/RemoveCertificate.php b/core/Command/Security/RemoveCertificate.php new file mode 100644 index 00000000000..68e409aee1c --- /dev/null +++ b/core/Command/Security/RemoveCertificate.php @@ -0,0 +1,59 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\Security; + +use OC\Core\Command\Base; +use OCP\ICertificateManager; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class RemoveCertificate extends Base { + + /** @var ICertificateManager */ + protected $certificateManager; + + public function __construct(ICertificateManager $certificateManager) { + $this->certificateManager = $certificateManager; + parent::__construct(); + } + + protected function configure() { + $this + ->setName('security:certificates:remove') + ->setDescription('remove trusted certificate') + ->addArgument( + 'name', + InputArgument::REQUIRED, + 'the file name of the certificate to remove' + ); + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $name = $input->getArgument('name'); + + $this->certificateManager->removeCertificate($name); + } +} diff --git a/core/Command/Status.php b/core/Command/Status.php new file mode 100644 index 00000000000..6bc9c28d4d1 --- /dev/null +++ b/core/Command/Status.php @@ -0,0 +1,49 @@ + + * @author Joas Schilling + * @author Morris Jobke + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command; + +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class Status extends Base { + protected function configure() { + parent::configure(); + + $this + ->setName('status') + ->setDescription('show some status information') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $values = array( + 'installed' => (bool) \OC::$server->getConfig()->getSystemValue('installed', false), + 'version' => implode('.', \OCP\Util::getVersion()), + 'versionstring' => \OC_Util::getVersionString(), + 'edition' => \OC_Util::getEditionString(), + ); + + $this->writeArrayInOutputFormat($input, $output, $values); + } +} diff --git a/core/Command/Upgrade.php b/core/Command/Upgrade.php new file mode 100644 index 00000000000..cbb1f26f938 --- /dev/null +++ b/core/Command/Upgrade.php @@ -0,0 +1,295 @@ + + * @author Björn Schießle + * @author Joas Schilling + * @author Lukas Reschke + * @author Morris Jobke + * @author Owen Winkler + * @author Steffen Lindner + * @author Thomas Müller + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command; + +use OC\Console\TimestampFormatter; +use OC\Updater; +use OCP\IConfig; +use OCP\ILogger; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\ProgressBar; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\EventDispatcher\GenericEvent; + +class Upgrade extends Command { + + const ERROR_SUCCESS = 0; + const ERROR_NOT_INSTALLED = 1; + const ERROR_MAINTENANCE_MODE = 2; + const ERROR_UP_TO_DATE = 3; + const ERROR_INVALID_ARGUMENTS = 4; + const ERROR_FAILURE = 5; + + /** @var IConfig */ + private $config; + + /** @var ILogger */ + private $logger; + + /** + * @param IConfig $config + * @param ILogger $logger + */ + public function __construct(IConfig $config, ILogger $logger) { + parent::__construct(); + $this->config = $config; + $this->logger = $logger; + } + + protected function configure() { + $this + ->setName('upgrade') + ->setDescription('run upgrade routines after installation of a new release. The release has to be installed before.') + ->addOption( + '--skip-migration-test', + null, + InputOption::VALUE_NONE, + 'skips the database schema migration simulation and update directly' + ) + ->addOption( + '--dry-run', + null, + InputOption::VALUE_NONE, + 'only runs the database schema migration simulation, do not actually update' + ) + ->addOption( + '--no-app-disable', + null, + InputOption::VALUE_NONE, + 'skips the disable of third party apps' + ); + } + + /** + * Execute the upgrade command + * + * @param InputInterface $input input interface + * @param OutputInterface $output output interface + */ + protected function execute(InputInterface $input, OutputInterface $output) { + + $simulateStepEnabled = true; + $updateStepEnabled = true; + $skip3rdPartyAppsDisable = false; + + if ($input->getOption('skip-migration-test')) { + $simulateStepEnabled = false; + } + if ($input->getOption('dry-run')) { + $updateStepEnabled = false; + } + if ($input->getOption('no-app-disable')) { + $skip3rdPartyAppsDisable = true; + } + + if (!$simulateStepEnabled && !$updateStepEnabled) { + $output->writeln( + 'Only one of "--skip-migration-test" or "--dry-run" ' . + 'can be specified at a time.' + ); + return self::ERROR_INVALID_ARGUMENTS; + } + + if(\OC::checkUpgrade(false)) { + if (OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) { + // Prepend each line with a little timestamp + $timestampFormatter = new TimestampFormatter($this->config, $output->getFormatter()); + $output->setFormatter($timestampFormatter); + } + + $self = $this; + $updater = new Updater( + \OC::$server->getHTTPHelper(), + $this->config, + \OC::$server->getIntegrityCodeChecker(), + $this->logger + ); + + $updater->setSimulateStepEnabled($simulateStepEnabled); + $updater->setUpdateStepEnabled($updateStepEnabled); + $updater->setSkip3rdPartyAppsDisable($skip3rdPartyAppsDisable); + $dispatcher = \OC::$server->getEventDispatcher(); + $progress = new ProgressBar($output); + $progress->setFormat(" %message%\n %current%/%max% [%bar%] %percent:3s%%"); + $listener = function($event) use ($progress, $output) { + if ($event instanceof GenericEvent) { + $message = $event->getSubject(); + if (OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) { + $output->writeln(' Checking table ' . $message); + } else { + if (strlen($message) > 60) { + $message = substr($message, 0, 57) . '...'; + } + $progress->setMessage($message); + if ($event[0] === 1) { + $output->writeln(''); + $progress->start($event[1]); + } + $progress->setProgress($event[0]); + if ($event[0] === $event[1]) { + $progress->setMessage('Done'); + $progress->finish(); + $output->writeln(''); + } + } + } + }; + $dispatcher->addListener('\OC\DB\Migrator::executeSql', $listener); + $dispatcher->addListener('\OC\DB\Migrator::checkTable', $listener); + + $updater->listen('\OC\Updater', 'maintenanceEnabled', function () use($output) { + $output->writeln('Turned on maintenance mode'); + }); + $updater->listen('\OC\Updater', 'maintenanceDisabled', function () use($output) { + $output->writeln('Turned off maintenance mode'); + }); + $updater->listen('\OC\Updater', 'maintenanceActive', function () use($output) { + $output->writeln('Maintenance mode is kept active'); + }); + $updater->listen('\OC\Updater', 'updateEnd', + function ($success) use($output, $updateStepEnabled, $self) { + $mode = $updateStepEnabled ? 'Update' : 'Update simulation'; + if ($success) { + $message = "$mode successful"; + } else { + $message = "$mode failed"; + } + $output->writeln($message); + }); + $updater->listen('\OC\Updater', 'dbUpgradeBefore', function () use($output) { + $output->writeln('Updating database schema'); + }); + $updater->listen('\OC\Updater', 'dbUpgrade', function () use($output) { + $output->writeln('Updated database'); + }); + $updater->listen('\OC\Updater', 'dbSimulateUpgradeBefore', function () use($output) { + $output->writeln('Checking whether the database schema can be updated (this can take a long time depending on the database size)'); + }); + $updater->listen('\OC\Updater', 'dbSimulateUpgrade', function () use($output) { + $output->writeln('Checked database schema update'); + }); + $updater->listen('\OC\Updater', 'incompatibleAppDisabled', function ($app) use($output) { + $output->writeln('Disabled incompatible app: ' . $app . ''); + }); + $updater->listen('\OC\Updater', 'thirdPartyAppDisabled', function ($app) use ($output) { + $output->writeln('Disabled 3rd-party app: ' . $app . ''); + }); + $updater->listen('\OC\Updater', 'upgradeAppStoreApp', function ($app) use($output) { + $output->writeln('Update 3rd-party app: ' . $app . ''); + }); + $updater->listen('\OC\Updater', 'repairWarning', function ($app) use($output) { + $output->writeln('Repair warning: ' . $app . ''); + }); + $updater->listen('\OC\Updater', 'repairError', function ($app) use($output) { + $output->writeln('Repair error: ' . $app . ''); + }); + $updater->listen('\OC\Updater', 'appUpgradeCheckBefore', function () use ($output) { + $output->writeln('Checking updates of apps'); + }); + $updater->listen('\OC\Updater', 'appSimulateUpdate', function ($app) use ($output) { + $output->writeln("Checking whether the database schema for <$app> can be updated (this can take a long time depending on the database size)"); + }); + $updater->listen('\OC\Updater', 'appUpgradeCheck', function () use ($output) { + $output->writeln('Checked database schema update for apps'); + }); + $updater->listen('\OC\Updater', 'appUpgradeStarted', function ($app, $version) use ($output) { + $output->writeln("Updating <$app> ..."); + }); + $updater->listen('\OC\Updater', 'appUpgrade', function ($app, $version) use ($output) { + $output->writeln("Updated <$app> to $version"); + }); + $updater->listen('\OC\Updater', 'failure', function ($message) use($output, $self) { + $output->writeln("$message"); + }); + $updater->listen('\OC\Updater', 'setDebugLogLevel', function ($logLevel, $logLevelName) use($output) { + $output->writeln("Set log level to debug"); + }); + $updater->listen('\OC\Updater', 'resetLogLevel', function ($logLevel, $logLevelName) use($output) { + $output->writeln("Reset log level"); + }); + $updater->listen('\OC\Updater', 'startCheckCodeIntegrity', function () use($output) { + $output->writeln("Starting code integrity check..."); + }); + $updater->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function () use($output) { + $output->writeln("Finished code integrity check"); + }); + + if(OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) { + $updater->listen('\OC\Updater', 'repairInfo', function ($message) use($output) { + $output->writeln('Repair info: ' . $message . ''); + }); + $updater->listen('\OC\Updater', 'repairStep', function ($message) use($output) { + $output->writeln('Repair step: ' . $message . ''); + }); + } + + $success = $updater->upgrade(); + + $this->postUpgradeCheck($input, $output); + + if(!$success) { + return self::ERROR_FAILURE; + } + + return self::ERROR_SUCCESS; + } else if($this->config->getSystemValue('maintenance', false)) { + //Possible scenario: ownCloud core is updated but an app failed + $output->writeln('ownCloud is in maintenance mode'); + $output->write('Maybe an upgrade is already in process. Please check the ' + . 'logfile (data/owncloud.log). If you want to re-run the ' + . 'upgrade procedure, remove the "maintenance mode" from ' + . 'config.php and call this script again.' + , true); + return self::ERROR_MAINTENANCE_MODE; + } else { + $output->writeln('ownCloud is already latest version'); + return self::ERROR_UP_TO_DATE; + } + } + + /** + * Perform a post upgrade check (specific to the command line tool) + * + * @param InputInterface $input input interface + * @param OutputInterface $output output interface + */ + protected function postUpgradeCheck(InputInterface $input, OutputInterface $output) { + $trustedDomains = $this->config->getSystemValue('trusted_domains', array()); + if (empty($trustedDomains)) { + $output->write( + 'The setting "trusted_domains" could not be ' . + 'set automatically by the upgrade script, ' . + 'please set it manually' + ); + } + } +} diff --git a/core/Command/User/Add.php b/core/Command/User/Add.php new file mode 100644 index 00000000000..6c7e3a47231 --- /dev/null +++ b/core/Command/User/Add.php @@ -0,0 +1,154 @@ + + * @author Laurens Post + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\User; + +use OC\Files\Filesystem; +use OCP\IGroupManager; +use OCP\IUser; +use OCP\IUserManager; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Question\Question; + +class Add extends Command { + /** @var \OCP\IUserManager */ + protected $userManager; + + /** @var \OCP\IGroupManager */ + protected $groupManager; + + /** + * @param IUserManager $userManager + * @param IGroupManager $groupManager + */ + public function __construct(IUserManager $userManager, IGroupManager $groupManager) { + parent::__construct(); + $this->userManager = $userManager; + $this->groupManager = $groupManager; + } + + protected function configure() { + $this + ->setName('user:add') + ->setDescription('adds a user') + ->addArgument( + 'uid', + InputArgument::REQUIRED, + 'User ID used to login (must only contain a-z, A-Z, 0-9, -, _ and @)' + ) + ->addOption( + 'password-from-env', + null, + InputOption::VALUE_NONE, + 'read password from environment variable OC_PASS' + ) + ->addOption( + 'display-name', + null, + InputOption::VALUE_OPTIONAL, + 'User name used in the web UI (can contain any characters)' + ) + ->addOption( + 'group', + 'g', + InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, + 'groups the user should be added to (The group will be created if it does not exist)' + ); + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $uid = $input->getArgument('uid'); + if ($this->userManager->userExists($uid)) { + $output->writeln('The user "' . $uid . '" already exists.'); + return 1; + } + + if ($input->getOption('password-from-env')) { + $password = getenv('OC_PASS'); + if (!$password) { + $output->writeln('--password-from-env given, but OC_PASS is empty!'); + return 1; + } + } elseif ($input->isInteractive()) { + /** @var $dialog \Symfony\Component\Console\Helper\DialogHelper */ + $dialog = $this->getHelperSet()->get('dialog'); + $password = $dialog->askHiddenResponse( + $output, + 'Enter password: ', + false + ); + $confirm = $dialog->askHiddenResponse( + $output, + 'Confirm password: ', + false + ); + + if ($password !== $confirm) { + $output->writeln("Passwords did not match!"); + return 1; + } + } else { + $output->writeln("Interactive input or --password-from-env is needed for entering a password!"); + return 1; + } + + $user = $this->userManager->createUser( + $input->getArgument('uid'), + $password + ); + + if ($user instanceof IUser) { + $output->writeln('The user "' . $user->getUID() . '" was created successfully'); + } else { + $output->writeln('An error occurred while creating the user'); + return 1; + } + + if ($input->getOption('display-name')) { + $user->setDisplayName($input->getOption('display-name')); + $output->writeln('Display name set to "' . $user->getDisplayName() . '"'); + } + + $groups = $input->getOption('group'); + + if (!empty($groups)) { + // Make sure we init the Filesystem for the user, in case we need to + // init some group shares. + Filesystem::init($user->getUID(), ''); + } + + foreach ($groups as $groupName) { + $group = $this->groupManager->get($groupName); + if (!$group) { + $this->groupManager->createGroup($groupName); + $group = $this->groupManager->get($groupName); + $output->writeln('Created group "' . $group->getGID() . '"'); + } + $group->addUser($user); + $output->writeln('User "' . $user->getUID() . '" added to group "' . $group->getGID() . '"'); + } + } +} diff --git a/core/Command/User/Delete.php b/core/Command/User/Delete.php new file mode 100644 index 00000000000..b9a0a0e3950 --- /dev/null +++ b/core/Command/User/Delete.php @@ -0,0 +1,70 @@ + + * @author Jens-Christian Fischer + * @author Joas Schilling + * @author Morris Jobke + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\User; + +use OCP\IUserManager; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Input\InputArgument; + +class Delete extends Command { + /** @var IUserManager */ + protected $userManager; + + /** + * @param IUserManager $userManager + */ + public function __construct(IUserManager $userManager) { + $this->userManager = $userManager; + parent::__construct(); + } + + protected function configure() { + $this + ->setName('user:delete') + ->setDescription('deletes the specified user') + ->addArgument( + 'uid', + InputArgument::REQUIRED, + 'the username' + ); + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $user = $this->userManager->get($input->getArgument('uid')); + if (is_null($user)) { + $output->writeln('User does not exist'); + return; + } + + if ($user->delete()) { + $output->writeln('The specified user was deleted'); + return; + } + + $output->writeln('The specified user could not be deleted. Please check the logs.'); + } +} diff --git a/core/Command/User/LastSeen.php b/core/Command/User/LastSeen.php new file mode 100644 index 00000000000..6bb45a87875 --- /dev/null +++ b/core/Command/User/LastSeen.php @@ -0,0 +1,74 @@ + + * @author Joas Schilling + * @author Morris Jobke + * @author Pierre Ozoux + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\User; + +use OCP\IUserManager; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Input\InputArgument; + +class LastSeen extends Command { + /** @var IUserManager */ + protected $userManager; + + /** + * @param IUserManager $userManager + */ + public function __construct(IUserManager $userManager) { + $this->userManager = $userManager; + parent::__construct(); + } + + protected function configure() { + $this + ->setName('user:lastseen') + ->setDescription('shows when the user was logged in last time') + ->addArgument( + 'uid', + InputArgument::REQUIRED, + 'the username' + ); + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $user = $this->userManager->get($input->getArgument('uid')); + if(is_null($user)) { + $output->writeln('User does not exist'); + return; + } + + $lastLogin = $user->getLastLogin(); + if($lastLogin === 0) { + $output->writeln('User ' . $user->getUID() . + ' has never logged in, yet.'); + } else { + $date = new \DateTime(); + $date->setTimestamp($lastLogin); + $output->writeln($user->getUID() . + '`s last login: ' . $date->format('d.m.Y H:i')); + } + } +} diff --git a/core/Command/User/Report.php b/core/Command/User/Report.php new file mode 100644 index 00000000000..df9f7e41620 --- /dev/null +++ b/core/Command/User/Report.php @@ -0,0 +1,86 @@ + + * @author Joas Schilling + * @author Morris Jobke + * @author Thomas Müller + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\User; + +use OCP\IUserManager; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class Report extends Command { + /** @var IUserManager */ + protected $userManager; + + /** + * @param IUserManager $userManager + */ + public function __construct(IUserManager $userManager) { + $this->userManager = $userManager; + parent::__construct(); + } + + protected function configure() { + $this + ->setName('user:report') + ->setDescription('shows how many users have access'); + } + + protected function execute(InputInterface $input, OutputInterface $output) { + /** @var \Symfony\Component\Console\Helper\TableHelper $table */ + $table = $this->getHelperSet()->get('table'); + $table->setHeaders(array('User Report', '')); + $userCountArray = $this->countUsers(); + if(!empty($userCountArray)) { + $total = 0; + $rows = array(); + foreach($userCountArray as $classname => $users) { + $total += $users; + $rows[] = array($classname, $users); + } + + $rows[] = array(' '); + $rows[] = array('total users', $total); + } else { + $rows[] = array('No backend enabled that supports user counting', ''); + } + + $userDirectoryCount = $this->countUserDirectories(); + $rows[] = array(' '); + $rows[] = array('user directories', $userDirectoryCount); + + $table->setRows($rows); + $table->render($output); + } + + private function countUsers() { + return $this->userManager->countUsers(); + } + + private function countUserDirectories() { + $dataview = new \OC\Files\View('/'); + $userDirectories = $dataview->getDirectoryContent('/', 'httpd/unix-directory'); + return count($userDirectories); + } +} diff --git a/core/Command/User/ResetPassword.php b/core/Command/User/ResetPassword.php new file mode 100644 index 00000000000..f3f2d5b0630 --- /dev/null +++ b/core/Command/User/ResetPassword.php @@ -0,0 +1,121 @@ + + * @author Christopher Schäpers + * @author Clark Tomlinson + * @author Joas Schilling + * @author Laurens Post + * @author Morris Jobke + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Command\User; + +use OCP\IUserManager; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class ResetPassword extends Command { + + /** @var IUserManager */ + protected $userManager; + + public function __construct(IUserManager $userManager) { + $this->userManager = $userManager; + parent::__construct(); + } + + protected function configure() { + $this + ->setName('user:resetpassword') + ->setDescription('Resets the password of the named user') + ->addArgument( + 'user', + InputArgument::REQUIRED, + 'Username to reset password' + ) + ->addOption( + 'password-from-env', + null, + InputOption::VALUE_NONE, + 'read password from environment variable OC_PASS' + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) { + $username = $input->getArgument('user'); + + /** @var $user \OCP\IUser */ + $user = $this->userManager->get($username); + if (is_null($user)) { + $output->writeln('User does not exist'); + return 1; + } + + if ($input->getOption('password-from-env')) { + $password = getenv('OC_PASS'); + if (!$password) { + $output->writeln('--password-from-env given, but OC_PASS is empty!'); + return 1; + } + } elseif ($input->isInteractive()) { + /** @var $dialog \Symfony\Component\Console\Helper\DialogHelper */ + $dialog = $this->getHelperSet()->get('dialog'); + + if (\OCP\App::isEnabled('encryption')) { + $output->writeln( + 'Warning: Resetting the password when using encryption will result in data loss!' + ); + if (!$dialog->askConfirmation($output, 'Do you want to continue?', true)) { + return 1; + } + } + + $password = $dialog->askHiddenResponse( + $output, + 'Enter a new password: ', + false + ); + $confirm = $dialog->askHiddenResponse( + $output, + 'Confirm the new password: ', + false + ); + + if ($password !== $confirm) { + $output->writeln("Passwords did not match!"); + return 1; + } + } else { + $output->writeln("Interactive input or --password-from-env is needed for entering a new password!"); + return 1; + } + + $success = $user->setPassword($password); + if ($success) { + $output->writeln("Successfully reset password for " . $username . ""); + } else { + $output->writeln("Error while resetting password!"); + return 1; + } + } +} diff --git a/core/Controller/AvatarController.php b/core/Controller/AvatarController.php new file mode 100644 index 00000000000..adfe38ab2db --- /dev/null +++ b/core/Controller/AvatarController.php @@ -0,0 +1,327 @@ + + * @author Lukas Reschke + * @author Morris Jobke + * @author Robin Appelman + * @author Roeland Jago Douma + * @author Thomas Müller + * @author Vincent Petry + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ +namespace OC\Core\Controller; + +use OCP\AppFramework\Controller; +use OCP\AppFramework\Http; +use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\Http\DataDisplayResponse; +use OCP\Files\NotFoundException; +use OCP\IAvatarManager; +use OCP\ILogger; +use OCP\IL10N; +use OCP\IRequest; +use OCP\IUserManager; +use OCP\IUserSession; +use OCP\Files\Folder; + +/** + * Class AvatarController + * + * @package OC\Core\Controller + */ +class AvatarController extends Controller { + + /** @var IAvatarManager */ + protected $avatarManager; + + /** @var \OC\Cache\File */ + protected $cache; + + /** @var IL10N */ + protected $l; + + /** @var IUserManager */ + protected $userManager; + + /** @var IUserSession */ + protected $userSession; + + /** @var Folder */ + protected $userFolder; + + /** @var ILogger */ + protected $logger; + + /** + * @param string $appName + * @param IRequest $request + * @param IAvatarManager $avatarManager + * @param \OC\Cache\File $cache + * @param IL10N $l10n + * @param IUserManager $userManager + * @param IUserSession $userSession + * @param Folder $userFolder + * @param ILogger $logger + */ + public function __construct($appName, + IRequest $request, + IAvatarManager $avatarManager, + \OC\Cache\File $cache, + IL10N $l10n, + IUserManager $userManager, + IUserSession $userSession, + Folder $userFolder, + ILogger $logger) { + parent::__construct($appName, $request); + + $this->avatarManager = $avatarManager; + $this->cache = $cache; + $this->l = $l10n; + $this->userManager = $userManager; + $this->userSession = $userSession; + $this->userFolder = $userFolder; + $this->logger = $logger; + } + + /** + * @NoAdminRequired + * @NoCSRFRequired + * + * @param string $userId + * @param int $size + * @return DataResponse|DataDisplayResponse + */ + public function getAvatar($userId, $size) { + if ($size > 2048) { + $size = 2048; + } elseif ($size <= 0) { + $size = 64; + } + + try { + $avatar = $this->avatarManager->getAvatar($userId)->getFile($size); + $resp = new DataDisplayResponse($avatar->getContent(), + Http::STATUS_OK, + ['Content-Type' => $avatar->getMimeType()]); + $resp->setETag($avatar->getEtag()); + } catch (NotFoundException $e) { + $user = $this->userManager->get($userId); + $resp = new DataResponse([ + 'data' => [ + 'displayname' => $user->getDisplayName(), + ], + ]); + } catch (\Exception $e) { + $resp = new DataResponse([ + 'data' => [ + 'displayname' => '', + ], + ]); + } + + $resp->addHeader('Pragma', 'public'); + $resp->cacheFor(0); + $resp->setLastModified(new \DateTime('now', new \DateTimeZone('GMT'))); + + return $resp; + } + + /** + * @NoAdminRequired + * + * @param string $path + * @return DataResponse + */ + public function postAvatar($path) { + $userId = $this->userSession->getUser()->getUID(); + $files = $this->request->getUploadedFile('files'); + + $headers = []; + if ($this->request->isUserAgent([\OC\AppFramework\Http\Request::USER_AGENT_IE_8])) { + // due to upload iframe workaround, need to set content-type to text/plain + $headers['Content-Type'] = 'text/plain'; + } + + if (isset($path)) { + $path = stripslashes($path); + $node = $this->userFolder->get($path); + if (!($node instanceof \OCP\Files\File)) { + return new DataResponse(['data' => ['message' => $this->l->t('Please select a file.')]], Http::STATUS_OK, $headers); + } + if ($node->getSize() > 20*1024*1024) { + return new DataResponse( + ['data' => ['message' => $this->l->t('File is too big')]], + Http::STATUS_BAD_REQUEST, + $headers + ); + } + $content = $node->getContent(); + } elseif (!is_null($files)) { + if ( + $files['error'][0] === 0 && + is_uploaded_file($files['tmp_name'][0]) && + !\OC\Files\Filesystem::isFileBlacklisted($files['tmp_name'][0]) + ) { + if ($files['size'][0] > 20*1024*1024) { + return new DataResponse( + ['data' => ['message' => $this->l->t('File is too big')]], + Http::STATUS_BAD_REQUEST, + $headers + ); + } + $this->cache->set('avatar_upload', file_get_contents($files['tmp_name'][0]), 7200); + $content = $this->cache->get('avatar_upload'); + unlink($files['tmp_name'][0]); + } else { + return new DataResponse( + ['data' => ['message' => $this->l->t('Invalid file provided')]], + Http::STATUS_BAD_REQUEST, + $headers + ); + } + } else { + //Add imgfile + return new DataResponse( + ['data' => ['message' => $this->l->t('No image or file provided')]], + Http::STATUS_BAD_REQUEST, + $headers + ); + } + + try { + $image = new \OC_Image(); + $image->loadFromData($content); + $image->fixOrientation(); + + if ($image->valid()) { + $mimeType = $image->mimeType(); + if ($mimeType !== 'image/jpeg' && $mimeType !== 'image/png') { + return new DataResponse( + ['data' => ['message' => $this->l->t('Unknown filetype')]], + Http::STATUS_OK, + $headers + ); + } + + $this->cache->set('tmpAvatar', $image->data(), 7200); + return new DataResponse( + ['data' => 'notsquare'], + Http::STATUS_OK, + $headers + ); + } else { + return new DataResponse( + ['data' => ['message' => $this->l->t('Invalid image')]], + Http::STATUS_OK, + $headers + ); + } + } catch (\Exception $e) { + $this->logger->logException($e, ['app' => 'core']); + return new DataResponse(['data' => ['message' => $this->l->t('An error occurred. Please contact your admin.')]], Http::STATUS_OK, $headers); + } + } + + /** + * @NoAdminRequired + * + * @return DataResponse + */ + public function deleteAvatar() { + $userId = $this->userSession->getUser()->getUID(); + + try { + $avatar = $this->avatarManager->getAvatar($userId); + $avatar->remove(); + return new DataResponse(); + } catch (\Exception $e) { + $this->logger->logException($e, ['app' => 'core']); + return new DataResponse(['data' => ['message' => $this->l->t('An error occurred. Please contact your admin.')]], Http::STATUS_BAD_REQUEST); + } + } + + /** + * @NoAdminRequired + * + * @return DataResponse|DataDisplayResponse + */ + public function getTmpAvatar() { + $tmpAvatar = $this->cache->get('tmpAvatar'); + if (is_null($tmpAvatar)) { + return new DataResponse(['data' => [ + 'message' => $this->l->t("No temporary profile picture available, try again") + ]], + Http::STATUS_NOT_FOUND); + } + + $image = new \OC_Image($tmpAvatar); + + $resp = new DataDisplayResponse($image->data(), + Http::STATUS_OK, + ['Content-Type' => $image->mimeType()]); + + $resp->setETag(crc32($image->data())); + $resp->cacheFor(0); + $resp->setLastModified(new \DateTime('now', new \DateTimeZone('GMT'))); + return $resp; + } + + /** + * @NoAdminRequired + * + * @param array $crop + * @return DataResponse + */ + public function postCroppedAvatar($crop) { + $userId = $this->userSession->getUser()->getUID(); + + if (is_null($crop)) { + return new DataResponse(['data' => ['message' => $this->l->t("No crop data provided")]], + Http::STATUS_BAD_REQUEST); + } + + if (!isset($crop['x'], $crop['y'], $crop['w'], $crop['h'])) { + return new DataResponse(['data' => ['message' => $this->l->t("No valid crop data provided")]], + Http::STATUS_BAD_REQUEST); + } + + $tmpAvatar = $this->cache->get('tmpAvatar'); + if (is_null($tmpAvatar)) { + return new DataResponse(['data' => [ + 'message' => $this->l->t("No temporary profile picture available, try again") + ]], + Http::STATUS_BAD_REQUEST); + } + + $image = new \OC_Image($tmpAvatar); + $image->crop($crop['x'], $crop['y'], round($crop['w']), round($crop['h'])); + try { + $avatar = $this->avatarManager->getAvatar($userId); + $avatar->set($image); + // Clean up + $this->cache->remove('tmpAvatar'); + return new DataResponse(['status' => 'success']); + } catch (\OC\NotSquareException $e) { + return new DataResponse(['data' => ['message' => $this->l->t('Crop is not square')]], + Http::STATUS_BAD_REQUEST); + } catch (\Exception $e) { + $this->logger->logException($e, ['app' => 'core']); + return new DataResponse(['data' => ['message' => $this->l->t('An error occurred. Please contact your admin.')]], Http::STATUS_BAD_REQUEST); + } + } +} diff --git a/core/Controller/LostController.php b/core/Controller/LostController.php new file mode 100644 index 00000000000..0e0932b288b --- /dev/null +++ b/core/Controller/LostController.php @@ -0,0 +1,257 @@ + + * @author Björn Schießle + * @author Lukas Reschke + * @author Morris Jobke + * @author Roeland Jago Douma + * @author Thomas Müller + * @author Victor Dubiniuk + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Controller; + +use \OCP\AppFramework\Controller; +use \OCP\AppFramework\Http\TemplateResponse; +use OCP\AppFramework\Utility\ITimeFactory; +use \OCP\IURLGenerator; +use \OCP\IRequest; +use \OCP\IL10N; +use \OCP\IConfig; +use OCP\IUserManager; +use OCP\Mail\IMailer; +use OCP\Security\ISecureRandom; +use \OC_Defaults; +use OCP\Security\StringUtils; + +/** + * Class LostController + * + * Successfully changing a password will emit the post_passwordReset hook. + * + * @package OC\Core\Controller + */ +class LostController extends Controller { + + /** @var IURLGenerator */ + protected $urlGenerator; + /** @var IUserManager */ + protected $userManager; + // FIXME: Inject a non-static factory of OC_Defaults for better unit-testing + /** @var OC_Defaults */ + protected $defaults; + /** @var IL10N */ + protected $l10n; + /** @var string */ + protected $from; + /** @var bool */ + protected $isDataEncrypted; + /** @var IConfig */ + protected $config; + /** @var ISecureRandom */ + protected $secureRandom; + /** @var IMailer */ + protected $mailer; + /** @var ITimeFactory */ + protected $timeFactory; + + /** + * @param string $appName + * @param IRequest $request + * @param IURLGenerator $urlGenerator + * @param IUserManager $userManager + * @param OC_Defaults $defaults + * @param IL10N $l10n + * @param IConfig $config + * @param ISecureRandom $secureRandom + * @param string $from + * @param string $isDataEncrypted + * @param IMailer $mailer + * @param ITimeFactory $timeFactory + */ + public function __construct($appName, + IRequest $request, + IURLGenerator $urlGenerator, + IUserManager $userManager, + OC_Defaults $defaults, + IL10N $l10n, + IConfig $config, + ISecureRandom $secureRandom, + $from, + $isDataEncrypted, + IMailer $mailer, + ITimeFactory $timeFactory) { + parent::__construct($appName, $request); + $this->urlGenerator = $urlGenerator; + $this->userManager = $userManager; + $this->defaults = $defaults; + $this->l10n = $l10n; + $this->secureRandom = $secureRandom; + $this->from = $from; + $this->isDataEncrypted = $isDataEncrypted; + $this->config = $config; + $this->mailer = $mailer; + $this->timeFactory = $timeFactory; + } + + /** + * Someone wants to reset their password: + * + * @PublicPage + * @NoCSRFRequired + * + * @param string $token + * @param string $userId + * @return TemplateResponse + */ + public function resetform($token, $userId) { + return new TemplateResponse( + 'core', + 'lostpassword/resetpassword', + array( + 'link' => $this->urlGenerator->linkToRouteAbsolute('core.lost.setPassword', array('userId' => $userId, 'token' => $token)), + ), + 'guest' + ); + } + + /** + * @param $message + * @param array $additional + * @return array + */ + private function error($message, array $additional=array()) { + return array_merge(array('status' => 'error', 'msg' => $message), $additional); + } + + /** + * @return array + */ + private function success() { + return array('status'=>'success'); + } + + /** + * @PublicPage + * + * @param string $user + * @return array + */ + public function email($user){ + // FIXME: use HTTP error codes + try { + $this->sendEmail($user); + } catch (\Exception $e){ + return $this->error($e->getMessage()); + } + + return $this->success(); + } + + /** + * @PublicPage + * @param string $token + * @param string $userId + * @param string $password + * @param boolean $proceed + * @return array + */ + public function setPassword($token, $userId, $password, $proceed) { + if ($this->isDataEncrypted && !$proceed) { + return $this->error('', array('encryption' => true)); + } + + try { + $user = $this->userManager->get($userId); + + $splittedToken = explode(':', $this->config->getUserValue($userId, 'owncloud', 'lostpassword', null)); + if(count($splittedToken) !== 2) { + throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid')); + } + + if ($splittedToken[0] < ($this->timeFactory->getTime() - 60*60*12) || + $user->getLastLogin() > $splittedToken[0]) { + throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is expired')); + } + + if (!StringUtils::equals($splittedToken[1], $token)) { + throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid')); + } + + if (!$user->setPassword($password)) { + throw new \Exception(); + } + + \OC_Hook::emit('\OC\Core\LostPassword\Controller\LostController', 'post_passwordReset', array('uid' => $userId, 'password' => $password)); + + $this->config->deleteUserValue($userId, 'owncloud', 'lostpassword'); + @\OC_User::unsetMagicInCookie(); + + } catch (\Exception $e){ + return $this->error($e->getMessage()); + } + + return $this->success(); + } + + /** + * @param string $user + * @throws \Exception + */ + protected function sendEmail($user) { + if (!$this->userManager->userExists($user)) { + throw new \Exception($this->l10n->t('Couldn\'t send reset email. Please make sure your username is correct.')); + } + + $userObject = $this->userManager->get($user); + $email = $userObject->getEMailAddress(); + + if (empty($email)) { + throw new \Exception( + $this->l10n->t('Could not send reset email because there is no email address for this username. Please contact your administrator.') + ); + } + + $token = $this->secureRandom->generate(21, + ISecureRandom::CHAR_DIGITS. + ISecureRandom::CHAR_LOWER. + ISecureRandom::CHAR_UPPER); + $this->config->setUserValue($user, 'owncloud', 'lostpassword', $this->timeFactory->getTime() .':'. $token); + + $link = $this->urlGenerator->linkToRouteAbsolute('core.lost.resetform', array('userId' => $user, 'token' => $token)); + + $tmpl = new \OC_Template('core', 'lostpassword/email'); + $tmpl->assign('link', $link); + $msg = $tmpl->fetchPage(); + + try { + $message = $this->mailer->createMessage(); + $message->setTo([$email => $user]); + $message->setSubject($this->l10n->t('%s password reset', [$this->defaults->getName()])); + $message->setPlainBody($msg); + $message->setFrom([$this->from => $this->defaults->getName()]); + $this->mailer->send($message); + } catch (\Exception $e) { + throw new \Exception($this->l10n->t( + 'Couldn\'t send reset email. Please contact your administrator.' + )); + } + } + +} diff --git a/core/Controller/SetupController.php b/core/Controller/SetupController.php new file mode 100644 index 00000000000..f25c6f39a0b --- /dev/null +++ b/core/Controller/SetupController.php @@ -0,0 +1,126 @@ + + * @author ideaship + * @author Lukas Reschke + * @author Morris Jobke + * @author Robin Appelman + * @author Robin McCorkell + * @author Thomas Müller + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Controller; + +use OC\Setup; + +class SetupController { + /** @var Setup */ + protected $setupHelper; + /** @var string */ + private $autoConfigFile; + + /** + * @param Setup $setupHelper + */ + function __construct(Setup $setupHelper) { + $this->autoConfigFile = \OC::$SERVERROOT.'/config/autoconfig.php'; + $this->setupHelper = $setupHelper; + } + + /** + * @param $post + */ + public function run($post) { + // Check for autosetup: + $post = $this->loadAutoConfig($post); + $opts = $this->setupHelper->getSystemInfo(); + + // convert 'abcpassword' to 'abcpass' + if (isset($post['adminpassword'])) { + $post['adminpass'] = $post['adminpassword']; + } + if (isset($post['dbpassword'])) { + $post['dbpass'] = $post['dbpassword']; + } + + if(isset($post['install']) AND $post['install']=='true') { + // We have to launch the installation process : + $e = $this->setupHelper->install($post); + $errors = array('errors' => $e); + + if(count($e) > 0) { + $options = array_merge($opts, $post, $errors); + $this->display($options); + } else { + $this->finishSetup(); + } + } else { + $options = array_merge($opts, $post); + $this->display($options); + } + } + + public function display($post) { + $defaults = array( + 'adminlogin' => '', + 'adminpass' => '', + 'dbuser' => '', + 'dbpass' => '', + 'dbname' => '', + 'dbtablespace' => '', + 'dbhost' => 'localhost', + 'dbtype' => '', + ); + $parameters = array_merge($defaults, $post); + + \OC_Util::addVendorScript('strengthify/jquery.strengthify'); + \OC_Util::addVendorStyle('strengthify/strengthify'); + \OC_Util::addScript('setup'); + \OC_Template::printGuestPage('', 'installation', $parameters); + } + + public function finishSetup() { + if( file_exists( $this->autoConfigFile )) { + unlink($this->autoConfigFile); + } + \OC::$server->getIntegrityCodeChecker()->runInstanceVerification(); + \OC_Util::redirectToDefaultPage(); + } + + public function loadAutoConfig($post) { + if( file_exists($this->autoConfigFile)) { + \OCP\Util::writeLog('core', 'Autoconfig file found, setting up ownCloud…', \OCP\Util::INFO); + $AUTOCONFIG = array(); + include $this->autoConfigFile; + $post = array_merge ($post, $AUTOCONFIG); + } + + $dbIsSet = isset($post['dbtype']); + $directoryIsSet = isset($post['directory']); + $adminAccountIsSet = isset($post['adminlogin']); + + if ($dbIsSet AND $directoryIsSet AND $adminAccountIsSet) { + $post['install'] = 'true'; + } + $post['dbIsSet'] = $dbIsSet; + $post['directoryIsSet'] = $directoryIsSet; + + return $post; + } +} diff --git a/core/Controller/UserController.php b/core/Controller/UserController.php new file mode 100644 index 00000000000..72193761022 --- /dev/null +++ b/core/Controller/UserController.php @@ -0,0 +1,79 @@ + + * @author Morris Jobke + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Controller; + +use \OCP\AppFramework\Controller; +use \OCP\AppFramework\Http\JSONResponse; +use \OCP\IRequest; + +class UserController extends Controller { + /** + * @var \OCP\IUserManager + */ + protected $userManager; + + /** + * @var \OC_Defaults + */ + protected $defaults; + + public function __construct($appName, + IRequest $request, + $userManager, + $defaults + ) { + parent::__construct($appName, $request); + $this->userManager = $userManager; + $this->defaults = $defaults; + } + + /** + * Lookup user display names + * + * @NoAdminRequired + * + * @param array $users + * + * @return JSONResponse + */ + public function getDisplayNames($users) { + $result = array(); + + foreach ($users as $user) { + $userObject = $this->userManager->get($user); + if (is_object($userObject)) { + $result[$user] = $userObject->getDisplayName(); + } else { + $result[$user] = $user; + } + } + + $json = array( + 'users' => $result, + 'status' => 'success' + ); + + return new JSONResponse($json); + + } +} diff --git a/core/Tags/Controller.php b/core/Tags/Controller.php new file mode 100644 index 00000000000..9798a59d56f --- /dev/null +++ b/core/Tags/Controller.php @@ -0,0 +1,128 @@ + + * @author Thomas Tanghus + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Core\Tags; + +class Controller { + protected static function getTagger($type) { + \OC_JSON::checkLoggedIn(); + \OC_JSON::callCheck(); + + try { + $tagger = \OC::$server->getTagManager()->load($type); + return $tagger; + } catch(\Exception $e) { + \OCP\Util::writeLog('core', __METHOD__ . ' Exception: ' . $e->getMessage(), \OCP\Util::ERROR); + $l = new \OC_L10n('core'); + \OC_JSON::error(array('message'=> $l->t('Error loading tags'))); + exit; + } + } + + public static function getTags($args) { + $tagger = self::getTagger($args['type']); + \OC_JSON::success(array('tags'=> $tagger->getTags())); + } + + public static function getFavorites($args) { + $tagger = self::getTagger($args['type']); + \OC_JSON::success(array('ids'=> $tagger->getFavorites())); + } + + public static function getIdsForTag($args) { + $tagger = self::getTagger($args['type']); + \OC_JSON::success(array('ids'=> $tagger->getIdsForTag($_GET['tag']))); + } + + public static function addTag($args) { + $tagger = self::getTagger($args['type']); + + $id = $tagger->add(strip_tags($_POST['tag'])); + if($id === false) { + $l = new \OC_L10n('core'); + \OC_JSON::error(array('message'=> $l->t('Tag already exists'))); + } else { + \OC_JSON::success(array('id'=> $id)); + } + } + + public static function deleteTags($args) { + $tags = $_POST['tags']; + if(!is_array($tags)) { + $tags = array($tags); + } + + $tagger = self::getTagger($args['type']); + + if(!$tagger->delete($tags)) { + $l = new \OC_L10n('core'); + \OC_JSON::error(array('message'=> $l->t('Error deleting tag(s)'))); + } else { + \OC_JSON::success(); + } + } + + public static function tagAs($args) { + $tagger = self::getTagger($args['type']); + + if(!$tagger->tagAs($args['id'], $_POST['tag'])) { + $l = new \OC_L10n('core'); + \OC_JSON::error(array('message'=> $l->t('Error tagging'))); + } else { + \OC_JSON::success(); + } + } + + public static function unTag($args) { + $tagger = self::getTagger($args['type']); + + if(!$tagger->unTag($args['id'], $_POST['tag'])) { + $l = new \OC_L10n('core'); + \OC_JSON::error(array('message'=> $l->t('Error untagging'))); + } else { + \OC_JSON::success(); + } + } + + public static function favorite($args) { + $tagger = self::getTagger($args['type']); + + if(!$tagger->addToFavorites($args['id'])) { + $l = new \OC_L10n('core'); + \OC_JSON::error(array('message'=> $l->t('Error favoriting'))); + } else { + \OC_JSON::success(); + } + } + + public static function unFavorite($args) { + $tagger = self::getTagger($args['type']); + + if(!$tagger->removeFromFavorites($args['id'])) { + $l = new \OC_L10n('core'); + \OC_JSON::error(array('message'=> $l->t('Error unfavoriting'))); + } else { + \OC_JSON::success(); + } + } + +} diff --git a/core/command/app/checkcode.php b/core/command/app/checkcode.php deleted file mode 100644 index 78f4390e70a..00000000000 --- a/core/command/app/checkcode.php +++ /dev/null @@ -1,181 +0,0 @@ - - * @author Morris Jobke - * @author Robin McCorkell - * @author Thomas Müller - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\App; - -use OC\App\CodeChecker\CodeChecker; -use OC\App\CodeChecker\EmptyCheck; -use OC\App\CodeChecker\InfoChecker; -use OC\App\InfoParser; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -class CheckCode extends Command { - - /** @var InfoParser */ - private $infoParser; - - protected $checkers = [ - 'private' => '\OC\App\CodeChecker\PrivateCheck', - 'deprecation' => '\OC\App\CodeChecker\DeprecationCheck', - 'strong-comparison' => '\OC\App\CodeChecker\StrongComparisonCheck', - ]; - - public function __construct(InfoParser $infoParser) { - parent::__construct(); - $this->infoParser = $infoParser; - } - - protected function configure() { - $this - ->setName('app:check-code') - ->setDescription('check code to be compliant') - ->addArgument( - 'app-id', - InputArgument::REQUIRED, - 'check the specified app' - ) - ->addOption( - 'checker', - 'c', - InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, - 'enable the specified checker(s)', - [ 'private', 'deprecation', 'strong-comparison' ] - ) - ->addOption( - '--skip-validate-info', - null, - InputOption::VALUE_NONE, - 'skips the info.xml/version check' - ); - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $appId = $input->getArgument('app-id'); - - $checkList = new EmptyCheck(); - foreach ($input->getOption('checker') as $checker) { - if (!isset($this->checkers[$checker])) { - throw new \InvalidArgumentException('Invalid checker: '.$checker); - } - $checkerClass = $this->checkers[$checker]; - $checkList = new $checkerClass($checkList); - } - - $codeChecker = new CodeChecker($checkList); - - $codeChecker->listen('CodeChecker', 'analyseFileBegin', function($params) use ($output) { - if(OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { - $output->writeln("Analysing {$params}"); - } - }); - $codeChecker->listen('CodeChecker', 'analyseFileFinished', function($filename, $errors) use ($output) { - $count = count($errors); - - // show filename if the verbosity is low, but there are errors in a file - if($count > 0 && OutputInterface::VERBOSITY_VERBOSE > $output->getVerbosity()) { - $output->writeln("Analysing {$filename}"); - } - - // show error count if there are errors present or the verbosity is high - if($count > 0 || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { - $output->writeln(" {$count} errors"); - } - usort($errors, function($a, $b) { - return $a['line'] >$b['line']; - }); - - foreach($errors as $p) { - $line = sprintf("%' 4d", $p['line']); - $output->writeln(" line $line: {$p['disallowedToken']} - {$p['reason']}"); - } - }); - $errors = $codeChecker->analyse($appId); - - if(!$input->getOption('skip-validate-info')) { - $infoChecker = new InfoChecker($this->infoParser); - - $infoChecker->listen('InfoChecker', 'mandatoryFieldMissing', function($key) use ($output) { - $output->writeln("Mandatory field missing: $key"); - }); - - $infoChecker->listen('InfoChecker', 'deprecatedFieldFound', function($key, $value) use ($output) { - if($value === [] || is_null($value) || $value === '') { - $output->writeln("Deprecated field available: $key"); - } else { - $output->writeln("Deprecated field available: $key => $value"); - } - }); - - $infoChecker->listen('InfoChecker', 'missingRequirement', function($minMax) use ($output) { - $output->writeln("ownCloud $minMax version requirement missing (will be an error in ownCloud 11 and later)"); - }); - - $infoChecker->listen('InfoChecker', 'duplicateRequirement', function($minMax) use ($output) { - $output->writeln("Duplicate $minMax ownCloud version requirement found"); - }); - - $infoChecker->listen('InfoChecker', 'differentVersions', function($versionFile, $infoXML) use ($output) { - $output->writeln("Different versions provided (appinfo/version: $versionFile - appinfo/info.xml: $infoXML)"); - }); - - $infoChecker->listen('InfoChecker', 'sameVersions', function($path) use ($output) { - $output->writeln("Version file isn't needed anymore and can be safely removed ($path)"); - }); - - $infoChecker->listen('InfoChecker', 'migrateVersion', function($version) use ($output) { - $output->writeln("Migrate the app version to appinfo/info.xml (add $version to appinfo/info.xml and remove appinfo/version)"); - }); - - if(OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { - $infoChecker->listen('InfoChecker', 'mandatoryFieldFound', function($key, $value) use ($output) { - $output->writeln("Mandatory field available: $key => $value"); - }); - - $infoChecker->listen('InfoChecker', 'optionalFieldFound', function($key, $value) use ($output) { - $output->writeln("Optional field available: $key => $value"); - }); - - $infoChecker->listen('InfoChecker', 'unusedFieldFound', function($key, $value) use ($output) { - $output->writeln("Unused field available: $key => $value"); - }); - } - - $infoErrors = $infoChecker->analyse($appId); - - $errors = array_merge($errors, $infoErrors); - } - - if (empty($errors)) { - $output->writeln('App is compliant - awesome job!'); - return 0; - } else { - $output->writeln('App is not compliant'); - return 101; - } - } -} diff --git a/core/command/app/disable.php b/core/command/app/disable.php deleted file mode 100644 index 743a78cb88d..00000000000 --- a/core/command/app/disable.php +++ /dev/null @@ -1,71 +0,0 @@ - - * @author Morris Jobke - * @author Robin Appelman - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\App; - -use OCP\App\IAppManager; -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 Disable extends Command { - - /** @var IAppManager */ - protected $manager; - - /** - * @param IAppManager $manager - */ - public function __construct(IAppManager $manager) { - parent::__construct(); - $this->manager = $manager; - } - - protected function configure() { - $this - ->setName('app:disable') - ->setDescription('disable an app') - ->addArgument( - 'app-id', - InputArgument::REQUIRED, - 'disable the specified app' - ); - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $appId = $input->getArgument('app-id'); - if ($this->manager->isInstalled($appId)) { - try { - $this->manager->disableApp($appId); - $output->writeln($appId . ' disabled'); - } catch(\Exception $e) { - $output->writeln($e->getMessage()); - return 2; - } - } else { - $output->writeln('No such app enabled: ' . $appId); - } - } -} diff --git a/core/command/app/enable.php b/core/command/app/enable.php deleted file mode 100644 index 0f6ce51fe8f..00000000000 --- a/core/command/app/enable.php +++ /dev/null @@ -1,83 +0,0 @@ - - * @author Morris Jobke - * @author Robin Appelman - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\App; - -use OCP\App\IAppManager; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -class Enable extends Command { - - /** @var IAppManager */ - protected $manager; - - /** - * @param IAppManager $manager - */ - public function __construct(IAppManager $manager) { - parent::__construct(); - $this->manager = $manager; - } - - protected function configure() { - $this - ->setName('app:enable') - ->setDescription('enable an app') - ->addArgument( - 'app-id', - InputArgument::REQUIRED, - 'enable the specified app' - ) - ->addOption( - 'groups', - 'g', - InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, - 'enable the app only for a list of groups' - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $appId = $input->getArgument('app-id'); - - if (!\OC_App::getAppPath($appId)) { - $output->writeln($appId . ' not found'); - return 1; - } - - $groups = $input->getOption('groups'); - if (empty($groups)) { - \OC_App::enable($appId); - $output->writeln($appId . ' enabled'); - } else { - \OC_App::enable($appId, $groups); - $output->writeln($appId . ' enabled for groups: ' . implode(', ', $groups)); - } - return 0; - } -} diff --git a/core/command/app/getpath.php b/core/command/app/getpath.php deleted file mode 100644 index 33a3f64c53d..00000000000 --- a/core/command/app/getpath.php +++ /dev/null @@ -1,62 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\App; - -use OC\Core\Command\Base; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -class GetPath extends Base { - protected function configure() { - parent::configure(); - - $this - ->setName('app:getpath') - ->setDescription('Get an absolute path to the app directory') - ->addArgument( - 'app', - InputArgument::REQUIRED, - 'Name of the app' - ) - ; - } - - /** - * Executes the current command. - * - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance - * @return null|int null or 0 if everything went fine, or an error code - */ - protected function execute(InputInterface $input, OutputInterface $output) { - $appName = $input->getArgument('app'); - $path = \OC_App::getAppPath($appName); - if ($path !== false) { - $output->writeln($path); - return 0; - } - - // App not found, exit with non-zero - return 1; - } -} diff --git a/core/command/app/listapps.php b/core/command/app/listapps.php deleted file mode 100644 index d7546b3c0c7..00000000000 --- a/core/command/app/listapps.php +++ /dev/null @@ -1,119 +0,0 @@ - - * @author Morris Jobke - * @author Robin Appelman - * @author Victor Dubiniuk - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\App; - -use OC\Core\Command\Base; -use OCP\App\IAppManager; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -class ListApps extends Base { - - /** @var IAppManager */ - protected $manager; - - /** - * @param IAppManager $manager - */ - public function __construct(IAppManager $manager) { - parent::__construct(); - $this->manager = $manager; - } - - protected function configure() { - parent::configure(); - - $this - ->setName('app:list') - ->setDescription('List all available apps') - ->addOption( - 'shipped', - null, - InputOption::VALUE_REQUIRED, - 'true - limit to shipped apps only, false - limit to non-shipped apps only' - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) { - if ($input->getOption('shipped') === 'true' || $input->getOption('shipped') === 'false'){ - $shippedFilter = $input->getOption('shipped') === 'true'; - } else { - $shippedFilter = null; - } - - $apps = \OC_App::getAllApps(); - $enabledApps = $disabledApps = []; - $versions = \OC_App::getAppVersions(); - - //sort enabled apps above disabled apps - foreach ($apps as $app) { - if ($shippedFilter !== null && \OC_App::isShipped($app) !== $shippedFilter){ - continue; - } - if ($this->manager->isInstalled($app)) { - $enabledApps[] = $app; - } else { - $disabledApps[] = $app; - } - } - - $apps = ['enabled' => [], 'disabled' => []]; - - sort($enabledApps); - foreach ($enabledApps as $app) { - $apps['enabled'][$app] = (isset($versions[$app])) ? $versions[$app] : true; - } - - sort($disabledApps); - foreach ($disabledApps as $app) { - $apps['disabled'][$app] = null; - } - - $this->writeAppList($input, $output, $apps); - } - - /** - * @param InputInterface $input - * @param OutputInterface $output - * @param array $items - */ - protected function writeAppList(InputInterface $input, OutputInterface $output, $items) { - switch ($input->getOption('output')) { - case self::OUTPUT_FORMAT_PLAIN: - $output->writeln('Enabled:'); - parent::writeArrayInOutputFormat($input, $output, $items['enabled']); - - $output->writeln('Disabled:'); - parent::writeArrayInOutputFormat($input, $output, $items['disabled']); - break; - - default: - parent::writeArrayInOutputFormat($input, $output, $items); - break; - } - } -} diff --git a/core/command/background/ajax.php b/core/command/background/ajax.php deleted file mode 100644 index e9cd1405ebd..00000000000 --- a/core/command/background/ajax.php +++ /dev/null @@ -1,33 +0,0 @@ - -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -*/ - -namespace OC\Core\Command\Background; - -class Ajax extends Base { - - protected function getMode() { - return 'ajax'; - } -} diff --git a/core/command/background/base.php b/core/command/background/base.php deleted file mode 100644 index 48fee818d0a..00000000000 --- a/core/command/background/base.php +++ /dev/null @@ -1,77 +0,0 @@ - -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -*/ - -namespace OC\Core\Command\Background; - -use \OCP\IConfig; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -/** -* An abstract base class for configuring the background job mode -* from the command line interface. -* Subclasses will override the getMode() function to specify the mode to configure. -*/ -abstract class Base extends Command { - - - abstract protected function getMode(); - - /** - * @var \OCP\IConfig - */ - protected $config; - - /** - * @param \OCP\IConfig $config - */ - public function __construct(IConfig $config) { - $this->config = $config; - parent::__construct(); - } - - protected function configure() { - $mode = $this->getMode(); - $this - ->setName("background:$mode") - ->setDescription("Use $mode to run background jobs"); - } - - /** - * Executing this command will set the background job mode for owncloud. - * The mode to set is specified by the concrete sub class by implementing the - * getMode() function. - * - * @param InputInterface $input - * @param OutputInterface $output - */ - protected function execute(InputInterface $input, OutputInterface $output) { - $mode = $this->getMode(); - $this->config->setAppValue( 'core', 'backgroundjobs_mode', $mode ); - $output->writeln("Set mode for background jobs to '$mode'"); - } -} diff --git a/core/command/background/cron.php b/core/command/background/cron.php deleted file mode 100644 index 434e88893b2..00000000000 --- a/core/command/background/cron.php +++ /dev/null @@ -1,33 +0,0 @@ - -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -*/ - -namespace OC\Core\Command\Background; - -class Cron extends Base { - - protected function getMode() { - return 'cron'; - } -} diff --git a/core/command/background/webcron.php b/core/command/background/webcron.php deleted file mode 100644 index 23dbe98e635..00000000000 --- a/core/command/background/webcron.php +++ /dev/null @@ -1,33 +0,0 @@ - -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -* THE SOFTWARE. -*/ - -namespace OC\Core\Command\Background; - -class WebCron extends Base { - - protected function getMode() { - return 'webcron'; - } -} diff --git a/core/command/base.php b/core/command/base.php deleted file mode 100644 index 7538effd74a..00000000000 --- a/core/command/base.php +++ /dev/null @@ -1,160 +0,0 @@ - - * @author Thomas Müller - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -class Base extends Command { - const OUTPUT_FORMAT_PLAIN = 'plain'; - const OUTPUT_FORMAT_JSON = 'json'; - const OUTPUT_FORMAT_JSON_PRETTY = 'json_pretty'; - - protected $defaultOutputFormat = self::OUTPUT_FORMAT_PLAIN; - - /** @var boolean */ - private $php_pcntl_signal = false; - - /** @var boolean */ - private $interrupted = false; - - protected function configure() { - $this - ->addOption( - 'output', - null, - InputOption::VALUE_OPTIONAL, - 'Output format (plain, json or json_pretty, default is plain)', - $this->defaultOutputFormat - ) - ; - } - - /** - * @param InputInterface $input - * @param OutputInterface $output - * @param array $items - * @param string $prefix - */ - protected function writeArrayInOutputFormat(InputInterface $input, OutputInterface $output, $items, $prefix = ' - ') { - switch ($input->getOption('output')) { - case self::OUTPUT_FORMAT_JSON: - $output->writeln(json_encode($items)); - break; - case self::OUTPUT_FORMAT_JSON_PRETTY: - $output->writeln(json_encode($items, JSON_PRETTY_PRINT)); - break; - default: - foreach ($items as $key => $item) { - if (is_array($item)) { - $output->writeln($prefix . $key . ':'); - $this->writeArrayInOutputFormat($input, $output, $item, ' ' . $prefix); - continue; - } - if (!is_int($key)) { - $value = $this->valueToString($item); - if (!is_null($value)) { - $output->writeln($prefix . $key . ': ' . $value); - } else { - $output->writeln($prefix . $key); - } - } else { - $output->writeln($prefix . $this->valueToString($item)); - } - } - break; - } - } - - /** - * @param InputInterface $input - * @param OutputInterface $output - * @param mixed $item - */ - protected function writeMixedInOutputFormat(InputInterface $input, OutputInterface $output, $item) { - if (is_array($item)) { - $this->writeArrayInOutputFormat($input, $output, $item, ''); - return; - } - - switch ($input->getOption('output')) { - case self::OUTPUT_FORMAT_JSON: - $output->writeln(json_encode($item)); - break; - case self::OUTPUT_FORMAT_JSON_PRETTY: - $output->writeln(json_encode($item, JSON_PRETTY_PRINT)); - break; - default: - $output->writeln($this->valueToString($item, false)); - break; - } - } - - protected function valueToString($value, $returnNull = true) { - if ($value === false) { - return 'false'; - } else if ($value === true) { - return 'true'; - } else if ($value === null) { - return ($returnNull) ? null : 'null'; - } else { - return $value; - } - } - - /** - * @return bool - */ - protected function hasBeenInterrupted() { - // return always false if pcntl_signal functions are not accessible - if ($this->php_pcntl_signal) { - pcntl_signal_dispatch(); - return $this->interrupted; - } else { - return false; - } - } - - /** - * Changes the status of the command to "interrupted" if ctrl-c has been pressed - * - * Gives a chance to the command to properly terminate what it's doing - */ - protected function cancelOperation() { - $this->interrupted = true; - } - - public function run(InputInterface $input, OutputInterface $output) { - // check if the php pcntl_signal functions are accessible - $this->php_pcntl_signal = function_exists('pcntl_signal'); - if ($this->php_pcntl_signal) { - // Collect interrupts and notify the running command - pcntl_signal(SIGTERM, [$this, 'cancelOperation']); - pcntl_signal(SIGINT, [$this, 'cancelOperation']); - } - - return parent::run($input, $output); - } -} diff --git a/core/command/check.php b/core/command/check.php deleted file mode 100644 index c2e92f7a8da..00000000000 --- a/core/command/check.php +++ /dev/null @@ -1,61 +0,0 @@ - - * @author Morris Jobke - * @author Thomas Müller - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ -namespace OC\Core\Command; - -use OCP\IConfig; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -class Check extends Base { - /** - * @var IConfig - */ - private $config; - - public function __construct(IConfig $config) { - parent::__construct(); - $this->config = $config; - } - - protected function configure() { - parent::configure(); - - $this - ->setName('check') - ->setDescription('check dependencies of the server environment') - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $errors = \OC_Util::checkServer($this->config); - if (!empty($errors)) { - $errors = array_map(function($item) { - return (string) $item['error']; - }, $errors); - - $this->writeArrayInOutputFormat($input, $output, $errors); - return 1; - } - return 0; - } -} diff --git a/core/command/config/app/deleteconfig.php b/core/command/config/app/deleteconfig.php deleted file mode 100644 index cccd92ea3d6..00000000000 --- a/core/command/config/app/deleteconfig.php +++ /dev/null @@ -1,81 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Config\App; - -use OC\Core\Command\Base; -use OCP\IConfig; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -class DeleteConfig extends Base { - /** * @var IConfig */ - protected $config; - - /** - * @param IConfig $config - */ - public function __construct(IConfig $config) { - parent::__construct(); - $this->config = $config; - } - - protected function configure() { - parent::configure(); - - $this - ->setName('config:app:delete') - ->setDescription('Delete an app config value') - ->addArgument( - 'app', - InputArgument::REQUIRED, - 'Name of the app' - ) - ->addArgument( - 'name', - InputArgument::REQUIRED, - 'Name of the config to delete' - ) - ->addOption( - 'error-if-not-exists', - null, - InputOption::VALUE_NONE, - 'Checks whether the config exists before deleting it' - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $appName = $input->getArgument('app'); - $configName = $input->getArgument('name'); - - if ($input->hasParameterOption('--error-if-not-exists') && !in_array($configName, $this->config->getAppKeys($appName))) { - $output->writeln('Config ' . $configName . ' of app ' . $appName . ' could not be deleted because it did not exist'); - return 1; - } - - $this->config->deleteAppValue($appName, $configName); - $output->writeln('Config value ' . $configName . ' of app ' . $appName . ' deleted'); - return 0; - } -} diff --git a/core/command/config/app/getconfig.php b/core/command/config/app/getconfig.php deleted file mode 100644 index abe71e57d8c..00000000000 --- a/core/command/config/app/getconfig.php +++ /dev/null @@ -1,93 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Config\App; - -use OC\Core\Command\Base; -use OCP\IConfig; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -class GetConfig extends Base { - /** * @var IConfig */ - protected $config; - - /** - * @param IConfig $config - */ - public function __construct(IConfig $config) { - parent::__construct(); - $this->config = $config; - } - - protected function configure() { - parent::configure(); - - $this - ->setName('config:app:get') - ->setDescription('Get an app config value') - ->addArgument( - 'app', - InputArgument::REQUIRED, - 'Name of the app' - ) - ->addArgument( - 'name', - InputArgument::REQUIRED, - 'Name of the config to get' - ) - ->addOption( - 'default-value', - null, - InputOption::VALUE_OPTIONAL, - 'If no default value is set and the config does not exist, the command will exit with 1' - ) - ; - } - - /** - * Executes the current command. - * - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance - * @return null|int null or 0 if everything went fine, or an error code - */ - protected function execute(InputInterface $input, OutputInterface $output) { - $appName = $input->getArgument('app'); - $configName = $input->getArgument('name'); - $defaultValue = $input->getOption('default-value'); - - if (!in_array($configName, $this->config->getAppKeys($appName)) && !$input->hasParameterOption('--default-value')) { - return 1; - } - - if (!in_array($configName, $this->config->getAppKeys($appName))) { - $configValue = $defaultValue; - } else { - $configValue = $this->config->getAppValue($appName, $configName); - } - - $this->writeMixedInOutputFormat($input, $output, $configValue); - return 0; - } -} diff --git a/core/command/config/app/setconfig.php b/core/command/config/app/setconfig.php deleted file mode 100644 index 097fde6ba95..00000000000 --- a/core/command/config/app/setconfig.php +++ /dev/null @@ -1,89 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Config\App; - -use OC\Core\Command\Base; -use OCP\IConfig; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -class SetConfig extends Base { - /** * @var IConfig */ - protected $config; - - /** - * @param IConfig $config - */ - public function __construct(IConfig $config) { - parent::__construct(); - $this->config = $config; - } - - protected function configure() { - parent::configure(); - - $this - ->setName('config:app:set') - ->setDescription('Set an app config value') - ->addArgument( - 'app', - InputArgument::REQUIRED, - 'Name of the app' - ) - ->addArgument( - 'name', - InputArgument::REQUIRED, - 'Name of the config to set' - ) - ->addOption( - 'value', - null, - InputOption::VALUE_REQUIRED, - 'The new value of the config' - ) - ->addOption( - 'update-only', - null, - InputOption::VALUE_NONE, - 'Only updates the value, if it is not set before, it is not being added' - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $appName = $input->getArgument('app'); - $configName = $input->getArgument('name'); - - if (!in_array($configName, $this->config->getAppKeys($appName)) && $input->hasParameterOption('--update-only')) { - $output->writeln('Config value ' . $configName . ' for app ' . $appName . ' not updated, as it has not been set before.'); - return 1; - } - - $configValue = $input->getOption('value'); - $this->config->setAppValue($appName, $configName, $configValue); - - $output->writeln('Config value ' . $configName . ' for app ' . $appName . ' set to ' . $configValue . ''); - return 0; - } -} diff --git a/core/command/config/import.php b/core/command/config/import.php deleted file mode 100644 index 7f1e09d2c95..00000000000 --- a/core/command/config/import.php +++ /dev/null @@ -1,195 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Config; - -use OCP\IConfig; -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 Import extends Command { - protected $validRootKeys = ['system', 'apps']; - - /** @var IConfig */ - protected $config; - - /** - * @param IConfig $config - */ - public function __construct(IConfig $config) { - parent::__construct(); - $this->config = $config; - } - - protected function configure() { - $this - ->setName('config:import') - ->setDescription('Import a list of configs') - ->addArgument( - 'file', - InputArgument::OPTIONAL, - 'File with the json array to import' - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $importFile = $input->getArgument('file'); - if ($importFile !== null) { - $content = $this->getArrayFromFile($importFile); - } else { - $content = $this->getArrayFromStdin(); - } - - try { - $configs = $this->validateFileContent($content); - } catch (\UnexpectedValueException $e) { - $output->writeln('' . $e->getMessage(). ''); - return; - } - - if (!empty($configs['system'])) { - $this->config->setSystemValues($configs['system']); - } - - if (!empty($configs['apps'])) { - foreach ($configs['apps'] as $app => $appConfigs) { - foreach ($appConfigs as $key => $value) { - if ($value === null) { - $this->config->deleteAppValue($app, $key); - } else { - $this->config->setAppValue($app, $key, $value); - } - } - } - } - - $output->writeln('Config successfully imported from: ' . $importFile . ''); - } - - /** - * Get the content from stdin ("config:import < file.json") - * - * @return string - */ - protected function getArrayFromStdin() { - // Read from stdin. stream_set_blocking is used to prevent blocking - // when nothing is passed via stdin. - stream_set_blocking(STDIN, 0); - $content = file_get_contents('php://stdin'); - stream_set_blocking(STDIN, 1); - return $content; - } - - /** - * Get the content of the specified file ("config:import file.json") - * - * @param string $importFile - * @return string - */ - protected function getArrayFromFile($importFile) { - $content = file_get_contents($importFile); - return $content; - } - - /** - * @param string $content - * @return array - * @throws \UnexpectedValueException when the array is invalid - */ - protected function validateFileContent($content) { - $decodedContent = json_decode($content, true); - if (!is_array($decodedContent) || empty($decodedContent)) { - throw new \UnexpectedValueException('The file must contain a valid json array'); - } - - $this->validateArray($decodedContent); - - return $decodedContent; - } - - /** - * Validates that the array only contains `system` and `apps` - * - * @param array $array - */ - protected function validateArray($array) { - $arrayKeys = array_keys($array); - $additionalKeys = array_diff($arrayKeys, $this->validRootKeys); - $commonKeys = array_intersect($arrayKeys, $this->validRootKeys); - if (!empty($additionalKeys)) { - throw new \UnexpectedValueException('Found invalid entries in root: ' . implode(', ', $additionalKeys)); - } - if (empty($commonKeys)) { - throw new \UnexpectedValueException('At least one key of the following is expected: ' . implode(', ', $this->validRootKeys)); - } - - if (isset($array['system'])) { - if (is_array($array['system'])) { - foreach ($array['system'] as $name => $value) { - $this->checkTypeRecursively($value, $name); - } - } else { - throw new \UnexpectedValueException('The system config array is not an array'); - } - } - - if (isset($array['apps'])) { - if (is_array($array['apps'])) { - $this->validateAppsArray($array['apps']); - } else { - throw new \UnexpectedValueException('The apps config array is not an array'); - } - } - } - - /** - * @param mixed $configValue - * @param string $configName - */ - protected function checkTypeRecursively($configValue, $configName) { - if (!is_array($configValue) && !is_bool($configValue) && !is_int($configValue) && !is_string($configValue) && !is_null($configValue)) { - throw new \UnexpectedValueException('Invalid system config value for "' . $configName . '". Only arrays, bools, integers, strings and null (delete) are allowed.'); - } - if (is_array($configValue)) { - foreach ($configValue as $key => $value) { - $this->checkTypeRecursively($value, $configName); - } - } - } - - /** - * Validates that app configs are only integers and strings - * - * @param array $array - */ - protected function validateAppsArray($array) { - foreach ($array as $app => $configs) { - foreach ($configs as $name => $value) { - if (!is_int($value) && !is_string($value) && !is_null($value)) { - throw new \UnexpectedValueException('Invalid app config value for "' . $app . '":"' . $name . '". Only integers, strings and null (delete) are allowed.'); - } - } - } - } -} diff --git a/core/command/config/listconfigs.php b/core/command/config/listconfigs.php deleted file mode 100644 index afebe4c4c07..00000000000 --- a/core/command/config/listconfigs.php +++ /dev/null @@ -1,129 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Config; - -use OC\Core\Command\Base; -use OC\SystemConfig; -use OCP\IAppConfig; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -class ListConfigs extends Base { - protected $defaultOutputFormat = self::OUTPUT_FORMAT_JSON_PRETTY; - - /** * @var SystemConfig */ - protected $systemConfig; - - /** @var IAppConfig */ - protected $appConfig; - - /** - * @param SystemConfig $systemConfig - * @param IAppConfig $appConfig - */ - public function __construct(SystemConfig $systemConfig, IAppConfig $appConfig) { - parent::__construct(); - $this->systemConfig = $systemConfig; - $this->appConfig = $appConfig; - } - - protected function configure() { - parent::configure(); - - $this - ->setName('config:list') - ->setDescription('List all configs') - ->addArgument( - 'app', - InputArgument::OPTIONAL, - 'Name of the app ("system" to get the config.php values, "all" for all apps and system)', - 'all' - ) - ->addOption( - 'private', - null, - InputOption::VALUE_NONE, - 'Use this option when you want to include sensitive configs like passwords, salts, ...' - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $app = $input->getArgument('app'); - $noSensitiveValues = !$input->getOption('private'); - - switch ($app) { - case 'system': - $configs = [ - 'system' => $this->getSystemConfigs($noSensitiveValues), - ]; - break; - - case 'all': - $apps = $this->appConfig->getApps(); - $configs = [ - 'system' => $this->getSystemConfigs($noSensitiveValues), - 'apps' => [], - ]; - foreach ($apps as $appName) { - $configs['apps'][$appName] = $this->appConfig->getValues($appName, false); - } - break; - - default: - $configs = [ - 'apps' => [ - $app => $this->appConfig->getValues($app, false), - ], - ]; - } - - $this->writeArrayInOutputFormat($input, $output, $configs); - } - - /** - * Get the system configs - * - * @param bool $noSensitiveValues - * @return array - */ - protected function getSystemConfigs($noSensitiveValues) { - $keys = $this->systemConfig->getKeys(); - - $configs = []; - foreach ($keys as $key) { - if ($noSensitiveValues) { - $value = $this->systemConfig->getFilteredValue($key, serialize(null)); - } else { - $value = $this->systemConfig->getValue($key, serialize(null)); - } - - if ($value !== 'N;') { - $configs[$key] = $value; - } - } - - return $configs; - } -} diff --git a/core/command/config/system/deleteconfig.php b/core/command/config/system/deleteconfig.php deleted file mode 100644 index 374f5ac69b7..00000000000 --- a/core/command/config/system/deleteconfig.php +++ /dev/null @@ -1,117 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Config\System; - -use OC\Core\Command\Base; -use OC\SystemConfig; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -class DeleteConfig extends Base { - /** * @var SystemConfig */ - protected $systemConfig; - - /** - * @param SystemConfig $systemConfig - */ - public function __construct(SystemConfig $systemConfig) { - parent::__construct(); - $this->systemConfig = $systemConfig; - } - - protected function configure() { - parent::configure(); - - $this - ->setName('config:system:delete') - ->setDescription('Delete a system config value') - ->addArgument( - 'name', - InputArgument::REQUIRED | InputArgument::IS_ARRAY, - 'Name of the config to delete, specify multiple for array parameter' - ) - ->addOption( - 'error-if-not-exists', - null, - InputOption::VALUE_NONE, - 'Checks whether the config exists before deleting it' - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $configNames = $input->getArgument('name'); - $configName = $configNames[0]; - - if (sizeof($configNames) > 1) { - if ($input->hasParameterOption('--error-if-not-exists') && !in_array($configName, $this->systemConfig->getKeys())) { - $output->writeln('System config ' . implode(' => ', $configNames) . ' could not be deleted because it did not exist'); - return 1; - } - - $value = $this->systemConfig->getValue($configName); - - try { - $value = $this->removeSubValue(array_slice($configNames, 1), $value, $input->hasParameterOption('--error-if-not-exists')); - } - catch (\UnexpectedValueException $e) { - $output->writeln('System config ' . implode(' => ', $configNames) . ' could not be deleted because it did not exist'); - return 1; - } - - $this->systemConfig->setValue($configName, $value); - $output->writeln('System config value ' . implode(' => ', $configNames) . ' deleted'); - return 0; - } else { - if ($input->hasParameterOption('--error-if-not-exists') && !in_array($configName, $this->systemConfig->getKeys())) { - $output->writeln('System config ' . $configName . ' could not be deleted because it did not exist'); - return 1; - } - - $this->systemConfig->deleteValue($configName); - $output->writeln('System config value ' . $configName . ' deleted'); - return 0; - } - } - - protected function removeSubValue($keys, $currentValue, $throwError) { - $nextKey = array_shift($keys); - - if (is_array($currentValue)) { - if (isset($currentValue[$nextKey])) { - if (empty($keys)) { - unset($currentValue[$nextKey]); - } else { - $currentValue[$nextKey] = $this->removeSubValue($keys, $currentValue[$nextKey], $throwError); - } - } else if ($throwError) { - throw new \UnexpectedValueException('Config parameter does not exist'); - } - } else if ($throwError) { - throw new \UnexpectedValueException('Config parameter does not exist'); - } - - return $currentValue; - } -} diff --git a/core/command/config/system/getconfig.php b/core/command/config/system/getconfig.php deleted file mode 100644 index b76474112a0..00000000000 --- a/core/command/config/system/getconfig.php +++ /dev/null @@ -1,100 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Config\System; - -use OC\Core\Command\Base; -use OC\SystemConfig; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -class GetConfig extends Base { - /** * @var SystemConfig */ - protected $systemConfig; - - /** - * @param SystemConfig $systemConfig - */ - public function __construct(SystemConfig $systemConfig) { - parent::__construct(); - $this->systemConfig = $systemConfig; - } - - protected function configure() { - parent::configure(); - - $this - ->setName('config:system:get') - ->setDescription('Get a system config value') - ->addArgument( - 'name', - InputArgument::REQUIRED | InputArgument::IS_ARRAY, - 'Name of the config to get, specify multiple for array parameter' - ) - ->addOption( - 'default-value', - null, - InputOption::VALUE_OPTIONAL, - 'If no default value is set and the config does not exist, the command will exit with 1' - ) - ; - } - - /** - * Executes the current command. - * - * @param InputInterface $input An InputInterface instance - * @param OutputInterface $output An OutputInterface instance - * @return null|int null or 0 if everything went fine, or an error code - */ - protected function execute(InputInterface $input, OutputInterface $output) { - $configNames = $input->getArgument('name'); - $configName = array_shift($configNames); - $defaultValue = $input->getOption('default-value'); - - if (!in_array($configName, $this->systemConfig->getKeys()) && !$input->hasParameterOption('--default-value')) { - return 1; - } - - if (!in_array($configName, $this->systemConfig->getKeys())) { - $configValue = $defaultValue; - } else { - $configValue = $this->systemConfig->getValue($configName); - if (!empty($configNames)) { - foreach ($configNames as $configName) { - if (isset($configValue[$configName])) { - $configValue = $configValue[$configName]; - } else if (!$input->hasParameterOption('--default-value')) { - return 1; - } else { - $configValue = $defaultValue; - break; - } - } - } - } - - $this->writeMixedInOutputFormat($input, $output, $configValue); - return 0; - } -} diff --git a/core/command/config/system/setconfig.php b/core/command/config/system/setconfig.php deleted file mode 100644 index c7f206b05d1..00000000000 --- a/core/command/config/system/setconfig.php +++ /dev/null @@ -1,198 +0,0 @@ - - * @author Robin McCorkell - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Config\System; - -use OC\Core\Command\Base; -use OC\SystemConfig; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -class SetConfig extends Base { - /** * @var SystemConfig */ - protected $systemConfig; - - /** - * @param SystemConfig $systemConfig - */ - public function __construct(SystemConfig $systemConfig) { - parent::__construct(); - $this->systemConfig = $systemConfig; - } - - protected function configure() { - parent::configure(); - - $this - ->setName('config:system:set') - ->setDescription('Set a system config value') - ->addArgument( - 'name', - InputArgument::REQUIRED | InputArgument::IS_ARRAY, - 'Name of the config parameter, specify multiple for array parameter' - ) - ->addOption( - 'type', - null, - InputOption::VALUE_REQUIRED, - 'Value type [string, integer, double, boolean]', - 'string' - ) - ->addOption( - 'value', - null, - InputOption::VALUE_REQUIRED, - 'The new value of the config' - ) - ->addOption( - 'update-only', - null, - InputOption::VALUE_NONE, - 'Only updates the value, if it is not set before, it is not being added' - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $configNames = $input->getArgument('name'); - $configName = $configNames[0]; - $configValue = $this->castValue($input->getOption('value'), $input->getOption('type')); - $updateOnly = $input->getOption('update-only'); - - if (sizeof($configNames) > 1) { - $existingValue = $this->systemConfig->getValue($configName); - - $newValue = $this->mergeArrayValue( - array_slice($configNames, 1), $existingValue, $configValue['value'], $updateOnly - ); - - $this->systemConfig->setValue($configName, $newValue); - } else { - if ($updateOnly && !in_array($configName, $this->systemConfig->getKeys(), true)) { - throw new \UnexpectedValueException('Config parameter does not exist'); - } - - $this->systemConfig->setValue($configName, $configValue['value']); - } - - $output->writeln('System config value ' . implode(' => ', $configNames) . ' set to ' . $configValue['readable-value'] . ''); - return 0; - } - - /** - * @param string $value - * @param string $type - * @return mixed - * @throws \InvalidArgumentException - */ - protected function castValue($value, $type) { - switch ($type) { - case 'integer': - case 'int': - if (!is_numeric($value)) { - throw new \InvalidArgumentException('Non-numeric value specified'); - } - return [ - 'value' => (int) $value, - 'readable-value' => 'integer ' . (int) $value, - ]; - - case 'double': - case 'float': - if (!is_numeric($value)) { - throw new \InvalidArgumentException('Non-numeric value specified'); - } - return [ - 'value' => (double) $value, - 'readable-value' => 'double ' . (double) $value, - ]; - - case 'boolean': - case 'bool': - $value = strtolower($value); - switch ($value) { - case 'true': - return [ - 'value' => true, - 'readable-value' => 'boolean ' . $value, - ]; - - case 'false': - return [ - 'value' => false, - 'readable-value' => 'boolean ' . $value, - ]; - - default: - throw new \InvalidArgumentException('Unable to parse value as boolean'); - } - - case 'null': - return [ - 'value' => null, - 'readable-value' => 'null', - ]; - - case 'string': - $value = (string) $value; - return [ - 'value' => $value, - 'readable-value' => ($value === '') ? 'empty string' : 'string ' . $value, - ]; - - default: - throw new \InvalidArgumentException('Invalid type'); - } - } - - /** - * @param array $configNames - * @param mixed $existingValues - * @param mixed $value - * @param bool $updateOnly - * @return array merged value - * @throws \UnexpectedValueException - */ - protected function mergeArrayValue(array $configNames, $existingValues, $value, $updateOnly) { - $configName = array_shift($configNames); - if (!is_array($existingValues)) { - $existingValues = []; - } - if (!empty($configNames)) { - if (isset($existingValues[$configName])) { - $existingValue = $existingValues[$configName]; - } else { - $existingValue = []; - } - $existingValues[$configName] = $this->mergeArrayValue($configNames, $existingValue, $value, $updateOnly); - } else { - if (!isset($existingValues[$configName]) && $updateOnly) { - throw new \UnexpectedValueException('Config parameter does not exist'); - } - $existingValues[$configName] = $value; - } - return $existingValues; - } - -} diff --git a/core/command/db/converttype.php b/core/command/db/converttype.php deleted file mode 100644 index 864499dcce0..00000000000 --- a/core/command/db/converttype.php +++ /dev/null @@ -1,311 +0,0 @@ - - * @author Bart Visscher - * @author Joas Schilling - * @author Morris Jobke - * @author tbelau666 - * @author Thomas Müller - * @author unclejamal3000 - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Db; - -use \OCP\IConfig; -use OC\DB\Connection; -use OC\DB\ConnectionFactory; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -class ConvertType extends Command { - /** - * @var \OCP\IConfig - */ - protected $config; - - /** - * @var \OC\DB\ConnectionFactory - */ - protected $connectionFactory; - - /** - * @param \OCP\IConfig $config - * @param \OC\DB\ConnectionFactory $connectionFactory - */ - public function __construct(IConfig $config, ConnectionFactory $connectionFactory) { - $this->config = $config; - $this->connectionFactory = $connectionFactory; - parent::__construct(); - } - - protected function configure() { - $this - ->setName('db:convert-type') - ->setDescription('Convert the ownCloud database to the newly configured one') - ->addArgument( - 'type', - InputArgument::REQUIRED, - 'the type of the database to convert to' - ) - ->addArgument( - 'username', - InputArgument::REQUIRED, - 'the username of the database to convert to' - ) - ->addArgument( - 'hostname', - InputArgument::REQUIRED, - 'the hostname of the database to convert to' - ) - ->addArgument( - 'database', - InputArgument::REQUIRED, - 'the name of the database to convert to' - ) - ->addOption( - 'port', - null, - InputOption::VALUE_REQUIRED, - 'the port of the database to convert to' - ) - ->addOption( - 'password', - null, - InputOption::VALUE_REQUIRED, - 'the password of the database to convert to. Will be asked when not specified. Can also be passed via stdin.' - ) - ->addOption( - 'clear-schema', - null, - InputOption::VALUE_NONE, - 'remove all tables from the destination database' - ) - ->addOption( - 'all-apps', - null, - InputOption::VALUE_NONE, - 'whether to create schema for all apps instead of only installed apps' - ) - ; - } - - protected function validateInput(InputInterface $input, OutputInterface $output) { - $type = $this->connectionFactory->normalizeType($input->getArgument('type')); - if ($type === 'sqlite3') { - throw new \InvalidArgumentException( - 'Converting to SQLite (sqlite3) is currently not supported.' - ); - } - if ($type === $this->config->getSystemValue('dbtype', '')) { - throw new \InvalidArgumentException(sprintf( - 'Can not convert from %1$s to %1$s.', - $type - )); - } - if ($type === 'oci' && $input->getOption('clear-schema')) { - // Doctrine unconditionally tries (at least in version 2.3) - // to drop sequence triggers when dropping a table, even though - // such triggers may not exist. This results in errors like - // "ORA-04080: trigger 'OC_STORAGES_AI_PK' does not exist". - throw new \InvalidArgumentException( - 'The --clear-schema option is not supported when converting to Oracle (oci).' - ); - } - } - - protected function readPassword(InputInterface $input, OutputInterface $output) { - // Explicitly specified password - if ($input->getOption('password')) { - return; - } - - // Read from stdin. stream_set_blocking is used to prevent blocking - // when nothing is passed via stdin. - stream_set_blocking(STDIN, 0); - $password = file_get_contents('php://stdin'); - stream_set_blocking(STDIN, 1); - if (trim($password) !== '') { - $input->setOption('password', $password); - return; - } - - // Read password by interacting - if ($input->isInteractive()) { - /** @var $dialog \Symfony\Component\Console\Helper\DialogHelper */ - $dialog = $this->getHelperSet()->get('dialog'); - $password = $dialog->askHiddenResponse( - $output, - 'What is the database password?', - false - ); - $input->setOption('password', $password); - return; - } - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $this->validateInput($input, $output); - $this->readPassword($input, $output); - - $fromDB = \OC::$server->getDatabaseConnection(); - $toDB = $this->getToDBConnection($input, $output); - - if ($input->getOption('clear-schema')) { - $this->clearSchema($toDB, $input, $output); - } - - $this->createSchema($toDB, $input, $output); - - $toTables = $this->getTables($toDB); - $fromTables = $this->getTables($fromDB); - - // warn/fail if there are more tables in 'from' database - $extraFromTables = array_diff($fromTables, $toTables); - if (!empty($extraFromTables)) { - $output->writeln('The following tables will not be converted:'); - $output->writeln($extraFromTables); - if (!$input->getOption('all-apps')) { - $output->writeln('Please note that tables belonging to available but currently not installed apps'); - $output->writeln('can be included by specifying the --all-apps option.'); - } - /** @var $dialog \Symfony\Component\Console\Helper\DialogHelper */ - $dialog = $this->getHelperSet()->get('dialog'); - if (!$dialog->askConfirmation( - $output, - 'Continue with the conversion (y/n)? [n] ', - false - )) { - return; - } - } - $intersectingTables = array_intersect($toTables, $fromTables); - $this->convertDB($fromDB, $toDB, $intersectingTables, $input, $output); - } - - protected function createSchema(Connection $toDB, InputInterface $input, OutputInterface $output) { - $output->writeln('Creating schema in new database'); - $schemaManager = new \OC\DB\MDB2SchemaManager($toDB); - $schemaManager->createDbFromStructure(\OC::$SERVERROOT.'/db_structure.xml'); - $apps = $input->getOption('all-apps') ? \OC_App::getAllApps() : \OC_App::getEnabledApps(); - foreach($apps as $app) { - if (file_exists(\OC_App::getAppPath($app).'/appinfo/database.xml')) { - $schemaManager->createDbFromStructure(\OC_App::getAppPath($app).'/appinfo/database.xml'); - } - } - } - - protected function getToDBConnection(InputInterface $input, OutputInterface $output) { - $type = $input->getArgument('type'); - $connectionParams = array( - 'host' => $input->getArgument('hostname'), - 'user' => $input->getArgument('username'), - 'password' => $input->getOption('password'), - 'dbname' => $input->getArgument('database'), - 'tablePrefix' => $this->config->getSystemValue('dbtableprefix', 'oc_'), - ); - if ($input->getOption('port')) { - $connectionParams['port'] = $input->getOption('port'); - } - return $this->connectionFactory->getConnection($type, $connectionParams); - } - - protected function clearSchema(Connection $db, InputInterface $input, OutputInterface $output) { - $toTables = $this->getTables($db); - if (!empty($toTables)) { - $output->writeln('Clearing schema in new database'); - } - foreach($toTables as $table) { - $db->getSchemaManager()->dropTable($table); - } - } - - protected function getTables(Connection $db) { - $filterExpression = '/^' . preg_quote($this->config->getSystemValue('dbtableprefix', 'oc_')) . '/'; - $db->getConfiguration()-> - setFilterSchemaAssetsExpression($filterExpression); - return $db->getSchemaManager()->listTableNames(); - } - - protected function copyTable(Connection $fromDB, Connection $toDB, $table, InputInterface $input, OutputInterface $output) { - /** @var $progress \Symfony\Component\Console\Helper\ProgressHelper */ - $progress = $this->getHelperSet()->get('progress'); - $query = 'SELECT COUNT(*) FROM '.$table; - $count = $fromDB->fetchColumn($query); - $query = 'SELECT * FROM '.$table; - $statement = $fromDB->executeQuery($query); - $progress->start($output, $count); - $progress->setRedrawFrequency($count > 100 ? 5 : 1); - while($row = $statement->fetch()) { - $progress->advance(); - if ($input->getArgument('type') === 'oci') { - $data = $row; - } else { - $data = array(); - foreach ($row as $columnName => $value) { - $data[$toDB->quoteIdentifier($columnName)] = $value; - } - } - $toDB->insert($table, $data); - } - $progress->finish(); - } - - protected function convertDB(Connection $fromDB, Connection $toDB, array $tables, InputInterface $input, OutputInterface $output) { - $this->config->setSystemValue('maintenance', true); - try { - // copy table rows - foreach($tables as $table) { - $output->writeln($table); - $this->copyTable($fromDB, $toDB, $table, $input, $output); - } - if ($input->getArgument('type') === 'pgsql') { - $tools = new \OC\DB\PgSqlTools($this->config); - $tools->resynchronizeDatabaseSequences($toDB); - } - // save new database config - $this->saveDBInfo($input); - } catch(\Exception $e) { - $this->config->setSystemValue('maintenance', false); - throw $e; - } - $this->config->setSystemValue('maintenance', false); - } - - protected function saveDBInfo(InputInterface $input) { - $type = $input->getArgument('type'); - $username = $input->getArgument('username'); - $dbHost = $input->getArgument('hostname'); - $dbName = $input->getArgument('database'); - $password = $input->getOption('password'); - if ($input->getOption('port')) { - $dbHost .= ':'.$input->getOption('port'); - } - - $this->config->setSystemValues([ - 'dbtype' => $type, - 'dbname' => $dbName, - 'dbhost' => $dbHost, - 'dbuser' => $username, - 'dbpassword' => $password, - ]); - } -} diff --git a/core/command/db/generatechangescript.php b/core/command/db/generatechangescript.php deleted file mode 100644 index 85436b02d65..00000000000 --- a/core/command/db/generatechangescript.php +++ /dev/null @@ -1,58 +0,0 @@ - - * @author Thomas Müller - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Db; - -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 GenerateChangeScript extends Command { - protected function configure() { - $this - ->setName('db:generate-change-script') - ->setDescription('generates the change script from the current connected db to db_structure.xml') - ->addArgument( - 'schema-xml', - InputArgument::OPTIONAL, - 'the schema xml to be used as target schema', - \OC::$SERVERROOT . '/db_structure.xml' - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) { - - $file = $input->getArgument('schema-xml'); - - $schemaManager = new \OC\DB\MDB2SchemaManager(\OC::$server->getDatabaseConnection()); - - try { - $result = $schemaManager->updateDbFromStructure($file, true); - $output->writeln($result); - } catch (\Exception $e) { - $output->writeln('Failed to update database structure ('.$e.')'); - } - - } -} diff --git a/core/command/encryption/changekeystorageroot.php b/core/command/encryption/changekeystorageroot.php deleted file mode 100644 index 801a08b42a8..00000000000 --- a/core/command/encryption/changekeystorageroot.php +++ /dev/null @@ -1,270 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - - -namespace OC\Core\Command\Encryption; - -use OC\Encryption\Keys\Storage; -use OC\Encryption\Util; -use OC\Files\Filesystem; -use OC\Files\View; -use OCP\IConfig; -use OCP\IUserManager; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Helper\ProgressBar; -use Symfony\Component\Console\Helper\QuestionHelper; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Question\ConfirmationQuestion; - -class ChangeKeyStorageRoot extends Command { - - /** @var View */ - protected $rootView; - - /** @var IUserManager */ - protected $userManager; - - /** @var IConfig */ - protected $config; - - /** @var Util */ - protected $util; - - /** @var QuestionHelper */ - protected $questionHelper; - - /** - * @param View $view - * @param IUserManager $userManager - * @param IConfig $config - * @param Util $util - * @param QuestionHelper $questionHelper - */ - public function __construct(View $view, IUserManager $userManager, IConfig $config, Util $util, QuestionHelper $questionHelper) { - parent::__construct(); - $this->rootView = $view; - $this->userManager = $userManager; - $this->config = $config; - $this->util = $util; - $this->questionHelper = $questionHelper; - } - - protected function configure() { - parent::configure(); - $this - ->setName('encryption:change-key-storage-root') - ->setDescription('Change key storage root') - ->addArgument( - 'newRoot', - InputArgument::OPTIONAL, - 'new root of the key storage relative to the data folder' - ); - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $oldRoot = $this->util->getKeyStorageRoot(); - $newRoot = $input->getArgument('newRoot'); - - if ($newRoot === null) { - $question = new ConfirmationQuestion('No storage root given, do you want to reset the key storage root to the default location? (y/n) ', false); - if (!$this->questionHelper->ask($input, $output, $question)) { - return; - } - $newRoot = ''; - } - - $oldRootDescription = $oldRoot !== '' ? $oldRoot : 'default storage location'; - $newRootDescription = $newRoot !== '' ? $newRoot : 'default storage location'; - $output->writeln("Change key storage root from $oldRootDescription to $newRootDescription"); - $success = $this->moveAllKeys($oldRoot, $newRoot, $output); - if ($success) { - $this->util->setKeyStorageRoot($newRoot); - $output->writeln(''); - $output->writeln("Key storage root successfully changed to $newRootDescription"); - } - } - - /** - * move keys to new key storage root - * - * @param string $oldRoot - * @param string $newRoot - * @param OutputInterface $output - * @return bool - * @throws \Exception - */ - protected function moveAllKeys($oldRoot, $newRoot, OutputInterface $output) { - - $output->writeln("Start to move keys:"); - - if ($this->rootView->is_dir(($oldRoot)) === false) { - $output->writeln("No old keys found: Nothing needs to be moved"); - return false; - } - - $this->prepareNewRoot($newRoot); - $this->moveSystemKeys($oldRoot, $newRoot); - $this->moveUserKeys($oldRoot, $newRoot, $output); - - return true; - } - - /** - * prepare new key storage - * - * @param string $newRoot - * @throws \Exception - */ - protected function prepareNewRoot($newRoot) { - if ($this->rootView->is_dir($newRoot) === false) { - throw new \Exception("New root folder doesn't exist. Please create the folder or check the permissions and try again."); - } - - $result = $this->rootView->file_put_contents( - $newRoot . '/' . Storage::KEY_STORAGE_MARKER, - 'ownCloud will detect this folder as key storage root only if this file exists' - ); - - if ($result === false) { - throw new \Exception("Can't write to new root folder. Please check the permissions and try again"); - } - - } - - - /** - * move system key folder - * - * @param string $oldRoot - * @param string $newRoot - */ - protected function moveSystemKeys($oldRoot, $newRoot) { - if ( - $this->rootView->is_dir($oldRoot . '/files_encryption') && - $this->targetExists($newRoot . '/files_encryption') === false - ) { - $this->rootView->rename($oldRoot . '/files_encryption', $newRoot . '/files_encryption'); - } - } - - - /** - * setup file system for the given user - * - * @param string $uid - */ - protected function setupUserFS($uid) { - \OC_Util::tearDownFS(); - \OC_Util::setupFS($uid); - } - - - /** - * iterate over each user and move the keys to the new storage - * - * @param string $oldRoot - * @param string $newRoot - * @param OutputInterface $output - */ - protected function moveUserKeys($oldRoot, $newRoot, OutputInterface $output) { - - $progress = new ProgressBar($output); - $progress->start(); - - - foreach($this->userManager->getBackends() as $backend) { - $limit = 500; - $offset = 0; - do { - $users = $backend->getUsers('', $limit, $offset); - foreach ($users as $user) { - $progress->advance(); - $this->setupUserFS($user); - $this->moveUserEncryptionFolder($user, $oldRoot, $newRoot); - } - $offset += $limit; - } while(count($users) >= $limit); - } - $progress->finish(); - } - - /** - * move user encryption folder to new root folder - * - * @param string $user - * @param string $oldRoot - * @param string $newRoot - * @throws \Exception - */ - protected function moveUserEncryptionFolder($user, $oldRoot, $newRoot) { - - if ($this->userManager->userExists($user)) { - - $source = $oldRoot . '/' . $user . '/files_encryption'; - $target = $newRoot . '/' . $user . '/files_encryption'; - if ( - $this->rootView->is_dir($source) && - $this->targetExists($target) === false - ) { - $this->prepareParentFolder($newRoot . '/' . $user); - $this->rootView->rename($source, $target); - } - } - } - - /** - * Make preparations to filesystem for saving a key file - * - * @param string $path relative to data/ - */ - protected function prepareParentFolder($path) { - $path = Filesystem::normalizePath($path); - // If the file resides within a subdirectory, create it - if ($this->rootView->file_exists($path) === false) { - $sub_dirs = explode('/', ltrim($path, '/')); - $dir = ''; - foreach ($sub_dirs as $sub_dir) { - $dir .= '/' . $sub_dir; - if ($this->rootView->file_exists($dir) === false) { - $this->rootView->mkdir($dir); - } - } - } - } - - /** - * check if target already exists - * - * @param $path - * @return bool - * @throws \Exception - */ - protected function targetExists($path) { - if ($this->rootView->file_exists($path)) { - throw new \Exception("new folder '$path' already exists"); - } - - return false; - } - -} diff --git a/core/command/encryption/decryptall.php b/core/command/encryption/decryptall.php deleted file mode 100644 index 0a126db5b17..00000000000 --- a/core/command/encryption/decryptall.php +++ /dev/null @@ -1,160 +0,0 @@ - - * @author Joas Schilling - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Encryption; - -use OCP\App\IAppManager; -use OCP\Encryption\IManager; -use OCP\IConfig; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Helper\QuestionHelper; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Question\ConfirmationQuestion; - -class DecryptAll extends Command { - - /** @var IManager */ - protected $encryptionManager; - - /** @var IAppManager */ - protected $appManager; - - /** @var IConfig */ - protected $config; - - /** @var QuestionHelper */ - protected $questionHelper; - - /** @var bool */ - protected $wasTrashbinEnabled; - - /** @var bool */ - protected $wasSingleUserModeEnabled; - - /** @var \OC\Encryption\DecryptAll */ - protected $decryptAll; - - /** - * @param IManager $encryptionManager - * @param IAppManager $appManager - * @param IConfig $config - * @param \OC\Encryption\DecryptAll $decryptAll - * @param QuestionHelper $questionHelper - */ - public function __construct( - IManager $encryptionManager, - IAppManager $appManager, - IConfig $config, - \OC\Encryption\DecryptAll $decryptAll, - QuestionHelper $questionHelper - ) { - parent::__construct(); - - $this->appManager = $appManager; - $this->encryptionManager = $encryptionManager; - $this->config = $config; - $this->decryptAll = $decryptAll; - $this->questionHelper = $questionHelper; - } - - /** - * Set single user mode and disable the trashbin app - */ - protected function forceSingleUserAndTrashbin() { - $this->wasTrashbinEnabled = $this->appManager->isEnabledForUser('files_trashbin'); - $this->wasSingleUserModeEnabled = $this->config->getSystemValue('singleuser', false); - $this->config->setSystemValue('singleuser', true); - $this->appManager->disableApp('files_trashbin'); - } - - /** - * Reset the single user mode and re-enable the trashbin app - */ - protected function resetSingleUserAndTrashbin() { - $this->config->setSystemValue('singleuser', $this->wasSingleUserModeEnabled); - if ($this->wasTrashbinEnabled) { - $this->appManager->enableApp('files_trashbin'); - } - } - - protected function configure() { - parent::configure(); - - $this->setName('encryption:decrypt-all'); - $this->setDescription('Disable server-side encryption and decrypt all files'); - $this->setHelp( - 'This will disable server-side encryption and decrypt all files for ' - . 'all users if it is supported by your encryption module. ' - . 'Please make sure that no user access his files during this process!' - ); - $this->addArgument( - 'user', - InputArgument::OPTIONAL, - 'user for which you want to decrypt all files (optional)' - ); - } - - protected function execute(InputInterface $input, OutputInterface $output) { - - try { - if ($this->encryptionManager->isEnabled() === true) { - $output->write('Disable server side encryption... '); - $this->config->setAppValue('core', 'encryption_enabled', 'no'); - $output->writeln('done.'); - } else { - $output->writeln('Server side encryption not enabled. Nothing to do.'); - return; - } - - $output->writeln("\n"); - $output->writeln('You are about to start to decrypt all files stored in your ownCloud.'); - $output->writeln('It will depend on the encryption module and your setup if this is possible.'); - $output->writeln('Depending on the number and size of your files this can take some time'); - $output->writeln('Please make sure that no user access his files during this process!'); - $output->writeln(''); - $question = new ConfirmationQuestion('Do you really want to continue? (y/n) ', false); - if ($this->questionHelper->ask($input, $output, $question)) { - $this->forceSingleUserAndTrashbin(); - $user = $input->getArgument('user'); - $result = $this->decryptAll->decryptAll($input, $output, $user); - if ($result === false) { - $output->writeln(' aborted.'); - $this->config->setAppValue('core', 'encryption_enabled', 'yes'); - } - $this->resetSingleUserAndTrashbin(); - } else { - $output->write('Enable server side encryption... '); - $this->config->setAppValue('core', 'encryption_enabled', 'yes'); - $output->writeln('done.'); - $output->writeln('aborted'); - } - } catch (\Exception $e) { - // enable server side encryption again if something went wrong - $this->config->setAppValue('core', 'encryption_enabled', 'yes'); - $this->resetSingleUserAndTrashbin(); - throw $e; - } - - } -} diff --git a/core/command/encryption/disable.php b/core/command/encryption/disable.php deleted file mode 100644 index 0e08a314473..00000000000 --- a/core/command/encryption/disable.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Encryption; - -use OCP\IConfig; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -class Disable extends Command { - /** @var IConfig */ - protected $config; - - /** - * @param IConfig $config - */ - public function __construct(IConfig $config) { - parent::__construct(); - $this->config = $config; - } - - protected function configure() { - $this - ->setName('encryption:disable') - ->setDescription('Disable encryption') - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) { - if ($this->config->getAppValue('core', 'encryption_enabled', 'no') !== 'yes') { - $output->writeln('Encryption is already disabled'); - } else { - $this->config->setAppValue('core', 'encryption_enabled', 'no'); - $output->writeln('Encryption disabled'); - } - } -} diff --git a/core/command/encryption/enable.php b/core/command/encryption/enable.php deleted file mode 100644 index 273320e6155..00000000000 --- a/core/command/encryption/enable.php +++ /dev/null @@ -1,78 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Encryption; - -use OCP\Encryption\IManager; -use OCP\IConfig; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -class Enable extends Command { - /** @var IConfig */ - protected $config; - - /** @var IManager */ - protected $encryptionManager; - - /** - * @param IConfig $config - * @param IManager $encryptionManager - */ - public function __construct(IConfig $config, IManager $encryptionManager) { - parent::__construct(); - - $this->encryptionManager = $encryptionManager; - $this->config = $config; - } - - protected function configure() { - $this - ->setName('encryption:enable') - ->setDescription('Enable encryption') - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) { - if ($this->config->getAppValue('core', 'encryption_enabled', 'no') === 'yes') { - $output->writeln('Encryption is already enabled'); - } else { - $this->config->setAppValue('core', 'encryption_enabled', 'yes'); - $output->writeln('Encryption enabled'); - } - $output->writeln(''); - - $modules = $this->encryptionManager->getEncryptionModules(); - if (empty($modules)) { - $output->writeln('No encryption module is loaded'); - } else { - $defaultModule = $this->config->getAppValue('core', 'default_encryption_module', null); - if ($defaultModule === null) { - $output->writeln('No default module is set'); - } else if (!isset($modules[$defaultModule])) { - $output->writeln('The current default module does not exist: ' . $defaultModule . ''); - } else { - $output->writeln('Default module: ' . $defaultModule); - } - } - } -} diff --git a/core/command/encryption/encryptall.php b/core/command/encryption/encryptall.php deleted file mode 100644 index 02f74a9dea4..00000000000 --- a/core/command/encryption/encryptall.php +++ /dev/null @@ -1,134 +0,0 @@ - - * @author Joas Schilling - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Encryption; - -use OCP\App\IAppManager; -use OCP\Encryption\IManager; -use OCP\IConfig; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Helper\QuestionHelper; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Question\ConfirmationQuestion; - -class EncryptAll extends Command { - - /** @var IManager */ - protected $encryptionManager; - - /** @var IAppManager */ - protected $appManager; - - /** @var IConfig */ - protected $config; - - /** @var QuestionHelper */ - protected $questionHelper; - - /** @var bool */ - protected $wasTrashbinEnabled; - - /** @var bool */ - protected $wasSingleUserModeEnabled; - - /** - * @param IManager $encryptionManager - * @param IAppManager $appManager - * @param IConfig $config - * @param QuestionHelper $questionHelper - */ - public function __construct( - IManager $encryptionManager, - IAppManager $appManager, - IConfig $config, - QuestionHelper $questionHelper - ) { - parent::__construct(); - $this->appManager = $appManager; - $this->encryptionManager = $encryptionManager; - $this->config = $config; - $this->questionHelper = $questionHelper; - } - - /** - * Set single user mode and disable the trashbin app - */ - protected function forceSingleUserAndTrashbin() { - $this->wasTrashbinEnabled = $this->appManager->isEnabledForUser('files_trashbin'); - $this->wasSingleUserModeEnabled = $this->config->getSystemValue('singleuser', false); - $this->config->setSystemValue('singleuser', true); - $this->appManager->disableApp('files_trashbin'); - } - - /** - * Reset the single user mode and re-enable the trashbin app - */ - protected function resetSingleUserAndTrashbin() { - $this->config->setSystemValue('singleuser', $this->wasSingleUserModeEnabled); - if ($this->wasTrashbinEnabled) { - $this->appManager->enableApp('files_trashbin'); - } - } - - protected function configure() { - parent::configure(); - - $this->setName('encryption:encrypt-all'); - $this->setDescription('Encrypt all files for all users'); - $this->setHelp( - 'This will encrypt all files for all users. ' - . 'Please make sure that no user access his files during this process!' - ); - } - - protected function execute(InputInterface $input, OutputInterface $output) { - - if ($this->encryptionManager->isEnabled() === false) { - throw new \Exception('Server side encryption is not enabled'); - } - - $output->writeln("\n"); - $output->writeln('You are about to start to encrypt all files stored in your ownCloud.'); - $output->writeln('It will depend on the encryption module you use which files get encrypted.'); - $output->writeln('Depending on the number and size of your files this can take some time'); - $output->writeln('Please make sure that no user access his files during this process!'); - $output->writeln(''); - $question = new ConfirmationQuestion('Do you really want to continue? (y/n) ', false); - if ($this->questionHelper->ask($input, $output, $question)) { - $this->forceSingleUserAndTrashbin(); - - try { - $defaultModule = $this->encryptionManager->getEncryptionModule(); - $defaultModule->encryptAll($input, $output); - } catch (\Exception $ex) { - $this->resetSingleUserAndTrashbin(); - throw $ex; - } - - $this->resetSingleUserAndTrashbin(); - } else { - $output->writeln('aborted'); - } - } - -} diff --git a/core/command/encryption/listmodules.php b/core/command/encryption/listmodules.php deleted file mode 100644 index 9c061b6e764..00000000000 --- a/core/command/encryption/listmodules.php +++ /dev/null @@ -1,80 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Encryption; - -use OC\Core\Command\Base; -use OCP\Encryption\IManager; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -class ListModules extends Base { - /** @var IManager */ - protected $encryptionManager; - - /** - * @param IManager $encryptionManager - */ - public function __construct(IManager $encryptionManager) { - parent::__construct(); - $this->encryptionManager = $encryptionManager; - } - - protected function configure() { - parent::configure(); - - $this - ->setName('encryption:list-modules') - ->setDescription('List all available encryption modules') - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $encryptionModules = $this->encryptionManager->getEncryptionModules(); - $defaultEncryptionModuleId = $this->encryptionManager->getDefaultEncryptionModuleId(); - - $encModules = array(); - foreach ($encryptionModules as $module) { - $encModules[$module['id']]['displayName'] = $module['displayName']; - $encModules[$module['id']]['default'] = $module['id'] === $defaultEncryptionModuleId; - } - $this->writeModuleList($input, $output, $encModules); - } - - /** - * @param InputInterface $input - * @param OutputInterface $output - * @param array $items - */ - protected function writeModuleList(InputInterface $input, OutputInterface $output, $items) { - if ($input->getOption('output') === self::OUTPUT_FORMAT_PLAIN) { - array_walk($items, function(&$item) { - if (!$item['default']) { - $item = $item['displayName']; - } else { - $item = $item['displayName'] . ' [default*]'; - } - }); - } - - $this->writeArrayInOutputFormat($input, $output, $items); - } -} diff --git a/core/command/encryption/setdefaultmodule.php b/core/command/encryption/setdefaultmodule.php deleted file mode 100644 index e9978536201..00000000000 --- a/core/command/encryption/setdefaultmodule.php +++ /dev/null @@ -1,68 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Encryption; - - -use OCP\Encryption\IManager; -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 SetDefaultModule extends Command { - /** @var IManager */ - protected $encryptionManager; - - /** - * @param IManager $encryptionManager - */ - public function __construct(IManager $encryptionManager) { - parent::__construct(); - $this->encryptionManager = $encryptionManager; - } - - protected function configure() { - parent::configure(); - - $this - ->setName('encryption:set-default-module') - ->setDescription('Set the encryption default module') - ->addArgument( - 'module', - InputArgument::REQUIRED, - 'ID of the encryption module that should be used' - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $moduleId = $input->getArgument('module'); - - if ($moduleId === $this->encryptionManager->getDefaultEncryptionModuleId()) { - $output->writeln('"' . $moduleId . '"" is already the default module'); - } else if ($this->encryptionManager->setDefaultEncryptionModule($moduleId)) { - $output->writeln('Set default module to "' . $moduleId . '"'); - } else { - $output->writeln('The specified module "' . $moduleId . '" does not exist'); - } - } -} diff --git a/core/command/encryption/showkeystorageroot.php b/core/command/encryption/showkeystorageroot.php deleted file mode 100644 index 402352c4bcf..00000000000 --- a/core/command/encryption/showkeystorageroot.php +++ /dev/null @@ -1,58 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - - -namespace OC\Core\Command\Encryption; - -use OC\Encryption\Util; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -class ShowKeyStorageRoot extends Command{ - - /** @var Util */ - protected $util; - - /** - * @param Util $util - */ - public function __construct(Util $util) { - parent::__construct(); - $this->util = $util; - } - - protected function configure() { - parent::configure(); - $this - ->setName('encryption:show-key-storage-root') - ->setDescription('Show current key storage root'); - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $currentRoot = $this->util->getKeyStorageRoot(); - - $rootDescription = $currentRoot !== '' ? $currentRoot : 'default storage location (data/)'; - - $output->writeln("Current key storage root: $rootDescription"); - } - -} diff --git a/core/command/encryption/status.php b/core/command/encryption/status.php deleted file mode 100644 index b97ea8833fa..00000000000 --- a/core/command/encryption/status.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Encryption; - -use OC\Core\Command\Base; -use OCP\Encryption\IManager; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -class Status extends Base { - /** @var IManager */ - protected $encryptionManager; - - /** - * @param IManager $encryptionManager - */ - public function __construct(IManager $encryptionManager) { - parent::__construct(); - $this->encryptionManager = $encryptionManager; - } - - protected function configure() { - parent::configure(); - - $this - ->setName('encryption:status') - ->setDescription('Lists the current status of encryption') - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $this->writeArrayInOutputFormat($input, $output, [ - 'enabled' => $this->encryptionManager->isEnabled(), - 'defaultModule' => $this->encryptionManager->getDefaultEncryptionModuleId(), - ]); - } -} diff --git a/core/command/integrity/checkapp.php b/core/command/integrity/checkapp.php deleted file mode 100644 index 643af5285b4..00000000000 --- a/core/command/integrity/checkapp.php +++ /dev/null @@ -1,69 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ -namespace OC\Core\Command\Integrity; - -use OC\IntegrityCheck\Checker; -use OC\Core\Command\Base; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * Class CheckApp - * - * @package OC\Core\Command\Integrity - */ -class CheckApp extends Base { - - /** - * @var Checker - */ - private $checker; - - public function __construct(Checker $checker) { - parent::__construct(); - $this->checker = $checker; - } - - /** - * {@inheritdoc } - */ - protected function configure() { - parent::configure(); - $this - ->setName('integrity:check-app') - ->setDescription('Check integrity of an app using a signature.') - ->addArgument('appid', null, InputArgument::REQUIRED, 'Application to check') - ->addOption('path', null, InputOption::VALUE_OPTIONAL, 'Path to application. If none is given it will be guessed.'); - } - - /** - * {@inheritdoc } - */ - protected function execute(InputInterface $input, OutputInterface $output) { - $appid = $input->getArgument('appid'); - $path = strval($input->getOption('path')); - $result = $this->checker->verifyAppSignature($appid, $path); - $this->writeArrayInOutputFormat($input, $output, $result); - } - -} diff --git a/core/command/integrity/checkcore.php b/core/command/integrity/checkcore.php deleted file mode 100644 index 460a78e4da7..00000000000 --- a/core/command/integrity/checkcore.php +++ /dev/null @@ -1,62 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Integrity; - -use OC\IntegrityCheck\Checker; -use OC\Core\Command\Base; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * Class CheckCore - * - * @package OC\Core\Command\Integrity - */ -class CheckCore extends Base { - /** - * @var Checker - */ - private $checker; - - public function __construct(Checker $checker) { - parent::__construct(); - $this->checker = $checker; - } - - /** - * {@inheritdoc } - */ - protected function configure() { - parent::configure(); - $this - ->setName('integrity:check-core') - ->setDescription('Check integrity of core code using a signature.'); - } - - /** - * {@inheritdoc } - */ - protected function execute(InputInterface $input, OutputInterface $output) { - $result = $this->checker->verifyCoreSignature(); - $this->writeArrayInOutputFormat($input, $output, $result); - } -} diff --git a/core/command/integrity/signapp.php b/core/command/integrity/signapp.php deleted file mode 100644 index 53df9619c6d..00000000000 --- a/core/command/integrity/signapp.php +++ /dev/null @@ -1,107 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Integrity; - -use OC\IntegrityCheck\Checker; -use OC\IntegrityCheck\Helpers\FileAccessHelper; -use OCP\IURLGenerator; -use phpseclib\Crypt\RSA; -use phpseclib\File\X509; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * Class SignApp - * - * @package OC\Core\Command\Integrity - */ -class SignApp extends Command { - /** @var Checker */ - private $checker; - /** @var FileAccessHelper */ - private $fileAccessHelper; - /** @var IURLGenerator */ - private $urlGenerator; - - /** - * @param Checker $checker - * @param FileAccessHelper $fileAccessHelper - * @param IURLGenerator $urlGenerator - */ - public function __construct(Checker $checker, - FileAccessHelper $fileAccessHelper, - IURLGenerator $urlGenerator) { - parent::__construct(null); - $this->checker = $checker; - $this->fileAccessHelper = $fileAccessHelper; - $this->urlGenerator = $urlGenerator; - } - - protected function configure() { - $this - ->setName('integrity:sign-app') - ->setDescription('Signs an app using a private key.') - ->addOption('path', null, InputOption::VALUE_REQUIRED, 'Application to sign') - ->addOption('privateKey', null, InputOption::VALUE_REQUIRED, 'Path to private key to use for signing') - ->addOption('certificate', null, InputOption::VALUE_REQUIRED, 'Path to certificate to use for signing'); - } - - /** - * {@inheritdoc } - */ - protected function execute(InputInterface $input, OutputInterface $output) { - $path = $input->getOption('path'); - $privateKeyPath = $input->getOption('privateKey'); - $keyBundlePath = $input->getOption('certificate'); - if(is_null($path) || is_null($privateKeyPath) || is_null($keyBundlePath)) { - $documentationUrl = $this->urlGenerator->linkToDocs('developer-code-integrity'); - $output->writeln('This command requires the --path, --privateKey and --certificate.'); - $output->writeln('Example: ./occ integrity:sign-app --path="/Users/lukasreschke/Programming/myapp/" --privateKey="/Users/lukasreschke/private/myapp.key" --certificate="/Users/lukasreschke/public/mycert.crt"'); - $output->writeln('For more information please consult the documentation: '. $documentationUrl); - return null; - } - - $privateKey = $this->fileAccessHelper->file_get_contents($privateKeyPath); - $keyBundle = $this->fileAccessHelper->file_get_contents($keyBundlePath); - - if($privateKey === false) { - $output->writeln(sprintf('Private key "%s" does not exists.', $privateKeyPath)); - return null; - } - - if($keyBundle === false) { - $output->writeln(sprintf('Certificate "%s" does not exists.', $keyBundlePath)); - return null; - } - - $rsa = new RSA(); - $rsa->loadKey($privateKey); - $x509 = new X509(); - $x509->loadX509($keyBundle); - $x509->setPrivateKey($rsa); - $this->checker->writeAppSignature($path, $x509, $rsa); - - $output->writeln('Successfully signed "'.$path.'"'); - } -} diff --git a/core/command/integrity/signcore.php b/core/command/integrity/signcore.php deleted file mode 100644 index e5c2de73e00..00000000000 --- a/core/command/integrity/signcore.php +++ /dev/null @@ -1,100 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Integrity; - -use OC\IntegrityCheck\Checker; -use OC\IntegrityCheck\Helpers\EnvironmentHelper; -use OC\IntegrityCheck\Helpers\FileAccessHelper; -use phpseclib\Crypt\RSA; -use phpseclib\File\X509; -use Symfony\Component\Console\Command\Command; -use OCP\IConfig; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * Class SignCore - * - * @package OC\Core\Command\Integrity - */ -class SignCore extends Command { - /** @var Checker */ - private $checker; - /** @var FileAccessHelper */ - private $fileAccessHelper; - - /** - * @param Checker $checker - * @param FileAccessHelper $fileAccessHelper - */ - public function __construct(Checker $checker, - FileAccessHelper $fileAccessHelper) { - parent::__construct(null); - $this->checker = $checker; - $this->fileAccessHelper = $fileAccessHelper; - } - - protected function configure() { - $this - ->setName('integrity:sign-core') - ->setDescription('Sign core using a private key.') - ->addOption('privateKey', null, InputOption::VALUE_REQUIRED, 'Path to private key to use for signing') - ->addOption('certificate', null, InputOption::VALUE_REQUIRED, 'Path to certificate to use for signing') - ->addOption('path', null, InputOption::VALUE_REQUIRED, 'Path of core to sign'); - } - - /** - * {@inheritdoc } - */ - protected function execute(InputInterface $input, OutputInterface $output) { - $privateKeyPath = $input->getOption('privateKey'); - $keyBundlePath = $input->getOption('certificate'); - $path = $input->getOption('path'); - if(is_null($privateKeyPath) || is_null($keyBundlePath) || is_null($path)) { - $output->writeln('--privateKey, --certificate and --path are required.'); - return null; - } - - $privateKey = $this->fileAccessHelper->file_get_contents($privateKeyPath); - $keyBundle = $this->fileAccessHelper->file_get_contents($keyBundlePath); - - if($privateKey === false) { - $output->writeln(sprintf('Private key "%s" does not exists.', $privateKeyPath)); - return null; - } - - if($keyBundle === false) { - $output->writeln(sprintf('Certificate "%s" does not exists.', $keyBundlePath)); - return null; - } - - $rsa = new RSA(); - $rsa->loadKey($privateKey); - $x509 = new X509(); - $x509->loadX509($keyBundle); - $x509->setPrivateKey($rsa); - $this->checker->writeCoreSignature($x509, $rsa, $path); - - $output->writeln('Successfully signed "core"'); - } -} diff --git a/core/command/l10n/createjs.php b/core/command/l10n/createjs.php deleted file mode 100644 index c2cfc5d0934..00000000000 --- a/core/command/l10n/createjs.php +++ /dev/null @@ -1,137 +0,0 @@ - - * @author Thomas Müller - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\L10n; - -use DirectoryIterator; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use UnexpectedValueException; - -class CreateJs extends Command { - - protected function configure() { - $this - ->setName('l10n:createjs') - ->setDescription('Create javascript translation files for a given app') - ->addArgument( - 'app', - InputOption::VALUE_REQUIRED, - 'name of the app' - ) - ->addArgument( - 'lang', - InputOption::VALUE_OPTIONAL, - 'name of the language' - ); - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $app = $input->getArgument('app'); - $lang = $input->getArgument('lang'); - - $path = \OC_App::getAppPath($app); - if ($path === false) { - $output->writeln("The app <$app> is unknown."); - return; - } - $languages = $lang; - if (empty($lang)) { - $languages= $this->getAllLanguages($path); - } - - foreach($languages as $lang) { - $this->writeFiles($app, $path, $lang, $output); - } - } - - private function getAllLanguages($path) { - $result = array(); - foreach (new DirectoryIterator("$path/l10n") as $fileInfo) { - if($fileInfo->isDot()) { - continue; - } - if($fileInfo->isDir()) { - continue; - } - if($fileInfo->getExtension() !== 'php') { - continue; - } - $result[]= substr($fileInfo->getBasename(), 0, -4); - } - - return $result; - } - - private function writeFiles($app, $path, $lang, OutputInterface $output) { - list($translations, $plurals) = $this->loadTranslations($path, $lang); - $this->writeJsFile($app, $path, $lang, $output, $translations, $plurals); - $this->writeJsonFile($path, $lang, $output, $translations, $plurals); - } - - private function writeJsFile($app, $path, $lang, OutputInterface $output, $translations, $plurals) { - $jsFile = "$path/l10n/$lang.js"; - if (file_exists($jsFile)) { - $output->writeln("File already exists: $jsFile"); - return; - } - $content = "OC.L10N.register(\n \"$app\",\n {\n "; - $jsTrans = array(); - foreach ($translations as $id => $val) { - if (is_array($val)) { - $val = '[ ' . join(',', $val) . ']'; - } - $jsTrans[] = "\"$id\" : \"$val\""; - } - $content .= join(",\n ", $jsTrans); - $content .= "\n},\n\"$plurals\");\n"; - - file_put_contents($jsFile, $content); - $output->writeln("Javascript translation file generated: $jsFile"); - } - - private function writeJsonFile($path, $lang, OutputInterface $output, $translations, $plurals) { - $jsFile = "$path/l10n/$lang.json"; - if (file_exists($jsFile)) { - $output->writeln("File already exists: $jsFile"); - return; - } - $content = array('translations' => $translations, 'pluralForm' => $plurals); - file_put_contents($jsFile, json_encode($content)); - $output->writeln("Json translation file generated: $jsFile"); - } - - private function loadTranslations($path, $lang) { - $phpFile = "$path/l10n/$lang.php"; - $TRANSLATIONS = array(); - $PLURAL_FORMS = ''; - if (!file_exists($phpFile)) { - throw new UnexpectedValueException("PHP translation file <$phpFile> does not exist."); - } - require $phpFile; - - return array($TRANSLATIONS, $PLURAL_FORMS); - } -} diff --git a/core/command/log/manage.php b/core/command/log/manage.php deleted file mode 100644 index 1d65d7ed0d8..00000000000 --- a/core/command/log/manage.php +++ /dev/null @@ -1,171 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Log; - -use \OCP\IConfig; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -class Manage extends Command { - - const DEFAULT_BACKEND = 'owncloud'; - const DEFAULT_LOG_LEVEL = 2; - const DEFAULT_TIMEZONE = 'UTC'; - - /** @var IConfig */ - protected $config; - - public function __construct(IConfig $config) { - $this->config = $config; - parent::__construct(); - } - - protected function configure() { - $this - ->setName('log:manage') - ->setDescription('manage logging configuration') - ->addOption( - 'backend', - null, - InputOption::VALUE_REQUIRED, - 'set the logging backend [owncloud, syslog, errorlog]' - ) - ->addOption( - 'level', - null, - InputOption::VALUE_REQUIRED, - 'set the log level [debug, info, warning, error]' - ) - ->addOption( - 'timezone', - null, - InputOption::VALUE_REQUIRED, - 'set the logging timezone' - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) { - // collate config setting to the end, to avoid partial configuration - $toBeSet = []; - - if ($backend = $input->getOption('backend')) { - $this->validateBackend($backend); - $toBeSet['log_type'] = $backend; - } - - if ($level = $input->getOption('level')) { - if (is_numeric($level)) { - $levelNum = $level; - // sanity check - $this->convertLevelNumber($levelNum); - } else { - $levelNum = $this->convertLevelString($level); - } - $toBeSet['loglevel'] = $levelNum; - } - - if ($timezone = $input->getOption('timezone')) { - $this->validateTimezone($timezone); - $toBeSet['logtimezone'] = $timezone; - } - - // set config - foreach ($toBeSet as $option => $value) { - $this->config->setSystemValue($option, $value); - } - - // display configuration - $backend = $this->config->getSystemValue('log_type', self::DEFAULT_BACKEND); - $output->writeln('Enabled logging backend: '.$backend); - - $levelNum = $this->config->getSystemValue('loglevel', self::DEFAULT_LOG_LEVEL); - $level = $this->convertLevelNumber($levelNum); - $output->writeln('Log level: '.$level.' ('.$levelNum.')'); - - $timezone = $this->config->getSystemValue('logtimezone', self::DEFAULT_TIMEZONE); - $output->writeln('Log timezone: '.$timezone); - } - - /** - * @param string $backend - * @throws \InvalidArgumentException - */ - protected function validateBackend($backend) { - if (!class_exists('OC_Log_'.$backend)) { - throw new \InvalidArgumentException('Invalid backend'); - } - } - - /** - * @param string $timezone - * @throws \Exception - */ - protected function validateTimezone($timezone) { - new \DateTimeZone($timezone); - } - - /** - * @param string $level - * @return int - * @throws \InvalidArgumentException - */ - protected function convertLevelString($level) { - $level = strtolower($level); - switch ($level) { - case 'debug': - return 0; - case 'info': - return 1; - case 'warning': - case 'warn': - return 2; - case 'error': - case 'err': - return 3; - } - throw new \InvalidArgumentException('Invalid log level string'); - } - - /** - * @param int $levelNum - * @return string - * @throws \InvalidArgumentException - */ - protected function convertLevelNumber($levelNum) { - switch ($levelNum) { - case 0: - return 'Debug'; - case 1: - return 'Info'; - case 2: - return 'Warning'; - case 3: - return 'Error'; - } - throw new \InvalidArgumentException('Invalid log level number'); - } -} diff --git a/core/command/log/owncloud.php b/core/command/log/owncloud.php deleted file mode 100644 index 7213f6726a2..00000000000 --- a/core/command/log/owncloud.php +++ /dev/null @@ -1,124 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Log; - -use \OCP\IConfig; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -class OwnCloud extends Command { - - /** @var IConfig */ - protected $config; - - public function __construct(IConfig $config) { - $this->config = $config; - parent::__construct(); - } - - protected function configure() { - $this - ->setName('log:owncloud') - ->setDescription('manipulate ownCloud logging backend') - ->addOption( - 'enable', - null, - InputOption::VALUE_NONE, - 'enable this logging backend' - ) - ->addOption( - 'file', - null, - InputOption::VALUE_REQUIRED, - 'set the log file path' - ) - ->addOption( - 'rotate-size', - null, - InputOption::VALUE_REQUIRED, - 'set the file size for log rotation, 0 = disabled' - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $toBeSet = []; - - if ($input->getOption('enable')) { - $toBeSet['log_type'] = 'owncloud'; - } - - if ($file = $input->getOption('file')) { - $toBeSet['logfile'] = $file; - } - - if (($rotateSize = $input->getOption('rotate-size')) !== null) { - $rotateSize = \OCP\Util::computerFileSize($rotateSize); - $this->validateRotateSize($rotateSize); - $toBeSet['log_rotate_size'] = $rotateSize; - } - - // set config - foreach ($toBeSet as $option => $value) { - $this->config->setSystemValue($option, $value); - } - - // display config - if ($this->config->getSystemValue('log_type', 'owncloud') === 'owncloud') { - $enabledText = 'enabled'; - } else { - $enabledText = 'disabled'; - } - $output->writeln('Log backend ownCloud: '.$enabledText); - - $dataDir = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT.'/data'); - $defaultLogFile = rtrim($dataDir, '/').'/owncloud.log'; - $output->writeln('Log file: '.$this->config->getSystemValue('logfile', $defaultLogFile)); - - $rotateSize = $this->config->getSystemValue('log_rotate_size', 0); - if ($rotateSize) { - $rotateString = \OCP\Util::humanFileSize($rotateSize); - } else { - $rotateString = 'disabled'; - } - $output->writeln('Rotate at: '.$rotateString); - } - - /** - * @param mixed $rotateSize - * @throws \InvalidArgumentException - */ - protected function validateRotateSize(&$rotateSize) { - if ($rotateSize === false) { - throw new \InvalidArgumentException('Error parsing log rotation file size'); - } - $rotateSize = (int) $rotateSize; - if ($rotateSize < 0) { - throw new \InvalidArgumentException('Log rotation file size must be non-negative'); - } - } - -} diff --git a/core/command/maintenance/install.php b/core/command/maintenance/install.php deleted file mode 100644 index b1b63b9b3bd..00000000000 --- a/core/command/maintenance/install.php +++ /dev/null @@ -1,178 +0,0 @@ - - * @author Christian Kampka - * @author Morris Jobke - * @author Thomas Müller - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ -namespace OC\Core\Command\Maintenance; - -use InvalidArgumentException; -use OC\Setup; -use OCP\IConfig; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -class Install extends Command { - - /** - * @var IConfig - */ - private $config; - - public function __construct(IConfig $config) { - parent::__construct(); - $this->config = $config; - } - - protected function configure() { - $this - ->setName('maintenance:install') - ->setDescription('install ownCloud') - ->addOption('database', null, InputOption::VALUE_REQUIRED, 'Supported database type', 'sqlite') - ->addOption('database-name', null, InputOption::VALUE_REQUIRED, 'Name of the database') - ->addOption('database-host', null, InputOption::VALUE_REQUIRED, 'Hostname of the database', 'localhost') - ->addOption('database-user', null, InputOption::VALUE_REQUIRED, 'User name to connect to the database') - ->addOption('database-pass', null, InputOption::VALUE_OPTIONAL, 'Password of the database user', null) - ->addOption('database-table-prefix', null, InputOption::VALUE_OPTIONAL, 'Prefix for all tables (default: oc_)', null) - ->addOption('admin-user', null, InputOption::VALUE_REQUIRED, 'User name of the admin account', 'admin') - ->addOption('admin-pass', null, InputOption::VALUE_REQUIRED, 'Password of the admin account') - ->addOption('data-dir', null, InputOption::VALUE_REQUIRED, 'Path to data directory', \OC::$SERVERROOT."/data"); - } - - protected function execute(InputInterface $input, OutputInterface $output) { - - // validate the environment - $server = \OC::$server; - $setupHelper = new Setup($this->config, $server->getIniWrapper(), - $server->getL10N('lib'), new \OC_Defaults(), $server->getLogger(), - $server->getSecureRandom()); - $sysInfo = $setupHelper->getSystemInfo(true); - $errors = $sysInfo['errors']; - if (count($errors) > 0) { - $this->printErrors($output, $errors); - - // ignore the OS X setup warning - if(count($errors) !== 1 || - (string)($errors[0]['error']) !== 'Mac OS X is not supported and ownCloud will not work properly on this platform. Use it at your own risk! ') { - return 1; - } - } - - // validate user input - $options = $this->validateInput($input, $output, array_keys($sysInfo['databases'])); - - // perform installation - $errors = $setupHelper->install($options); - if (count($errors) > 0) { - $this->printErrors($output, $errors); - return 1; - } - $output->writeln("ownCloud was successfully installed"); - return 0; - } - - /** - * @param InputInterface $input - * @param OutputInterface $output - * @param string[] $supportedDatabases - * @return array - */ - protected function validateInput(InputInterface $input, OutputInterface $output, $supportedDatabases) { - $db = strtolower($input->getOption('database')); - - if (!in_array($db, $supportedDatabases)) { - throw new InvalidArgumentException("Database <$db> is not supported."); - } - - $dbUser = $input->getOption('database-user'); - $dbPass = $input->getOption('database-pass'); - $dbName = $input->getOption('database-name'); - $dbHost = $input->getOption('database-host'); - $dbTablePrefix = 'oc_'; - if ($input->hasParameterOption('--database-table-prefix')) { - $dbTablePrefix = (string) $input->getOption('database-table-prefix'); - $dbTablePrefix = trim($dbTablePrefix); - } - if ($input->hasParameterOption('--database-pass')) { - $dbPass = (string) $input->getOption('database-pass'); - } - $adminLogin = $input->getOption('admin-user'); - $adminPassword = $input->getOption('admin-pass'); - $dataDir = $input->getOption('data-dir'); - - if ($db !== 'sqlite') { - if (is_null($dbUser)) { - throw new InvalidArgumentException("Database user not provided."); - } - if (is_null($dbName)) { - throw new InvalidArgumentException("Database name not provided."); - } - if (is_null($dbPass)) { - /** @var $dialog \Symfony\Component\Console\Helper\DialogHelper */ - $dialog = $this->getHelperSet()->get('dialog'); - $dbPass = $dialog->askHiddenResponse( - $output, - "What is the password to access the database with user <$dbUser>?", - false - ); - } - } - - if (is_null($adminPassword)) { - /** @var $dialog \Symfony\Component\Console\Helper\DialogHelper */ - $dialog = $this->getHelperSet()->get('dialog'); - $adminPassword = $dialog->askHiddenResponse( - $output, - "What is the password you like to use for the admin account <$adminLogin>?", - false - ); - } - - $options = [ - 'dbtype' => $db, - 'dbuser' => $dbUser, - 'dbpass' => $dbPass, - 'dbname' => $dbName, - 'dbhost' => $dbHost, - 'dbtableprefix' => $dbTablePrefix, - 'adminlogin' => $adminLogin, - 'adminpass' => $adminPassword, - 'directory' => $dataDir - ]; - return $options; - } - - /** - * @param OutputInterface $output - * @param $errors - */ - protected function printErrors(OutputInterface $output, $errors) { - foreach ($errors as $error) { - if (is_array($error)) { - $output->writeln('' . (string)$error['error'] . ''); - $output->writeln(' -> ' . (string)$error['hint'] . ''); - } else { - $output->writeln('' . (string)$error . ''); - } - } - } -} diff --git a/core/command/maintenance/mimetype/updatedb.php b/core/command/maintenance/mimetype/updatedb.php deleted file mode 100644 index 9532f9e1cd9..00000000000 --- a/core/command/maintenance/mimetype/updatedb.php +++ /dev/null @@ -1,97 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Maintenance\Mimetype; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Input\InputOption; - -use OCP\Files\IMimeTypeDetector; -use OCP\Files\IMimeTypeLoader; - -class UpdateDB extends Command { - - const DEFAULT_MIMETYPE = 'application/octet-stream'; - - /** @var IMimeTypeDetector */ - protected $mimetypeDetector; - - /** @var IMimeTypeLoader */ - protected $mimetypeLoader; - - public function __construct( - IMimeTypeDetector $mimetypeDetector, - IMimeTypeLoader $mimetypeLoader - ) { - parent::__construct(); - $this->mimetypeDetector = $mimetypeDetector; - $this->mimetypeLoader = $mimetypeLoader; - } - - protected function configure() { - $this - ->setName('maintenance:mimetype:update-db') - ->setDescription('Update database mimetypes and update filecache') - ->addOption( - 'repair-filecache', - null, - InputOption::VALUE_NONE, - 'Repair filecache for all mimetypes, not just new ones' - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $mappings = $this->mimetypeDetector->getAllMappings(); - - $totalFilecacheUpdates = 0; - $totalNewMimetypes = 0; - - foreach ($mappings as $ext => $mimetypes) { - if ($ext[0] === '_') { - // comment - continue; - } - $mimetype = $mimetypes[0]; - $existing = $this->mimetypeLoader->exists($mimetype); - // this will add the mimetype if it didn't exist - $mimetypeId = $this->mimetypeLoader->getId($mimetype); - - if (!$existing) { - $output->writeln('Added mimetype "'.$mimetype.'" to database'); - $totalNewMimetypes++; - } - - if (!$existing || $input->getOption('repair-filecache')) { - $touchedFilecacheRows = $this->mimetypeLoader->updateFilecache($ext, $mimetypeId); - if ($touchedFilecacheRows > 0) { - $output->writeln('Updated '.$touchedFilecacheRows.' filecache rows for mimetype "'.$mimetype.'"'); - } - $totalFilecacheUpdates += $touchedFilecacheRows; - } - } - - $output->writeln('Added '.$totalNewMimetypes.' new mimetypes'); - $output->writeln('Updated '.$totalFilecacheUpdates.' filecache rows'); - } -} diff --git a/core/command/maintenance/mimetype/updatejs.php b/core/command/maintenance/mimetype/updatejs.php deleted file mode 100644 index a87f50e32de..00000000000 --- a/core/command/maintenance/mimetype/updatejs.php +++ /dev/null @@ -1,129 +0,0 @@ - - * @author Robin McCorkell - * @author Roeland Jago Douma - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Maintenance\Mimetype; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -use OCP\Files\IMimeTypeDetector; - -class UpdateJS extends Command { - - /** @var IMimeTypeDetector */ - protected $mimetypeDetector; - - public function __construct( - IMimeTypeDetector $mimetypeDetector - ) { - parent::__construct(); - $this->mimetypeDetector = $mimetypeDetector; - } - - protected function configure() { - $this - ->setName('maintenance:mimetype:update-js') - ->setDescription('Update mimetypelist.js'); - } - - protected function execute(InputInterface $input, OutputInterface $output) { - // Fetch all the aliases - $aliases = $this->mimetypeDetector->getAllAliases(); - - // Remove comments - $keys = array_filter(array_keys($aliases), function($k) { - return $k[0] === '_'; - }); - foreach($keys as $key) { - unset($aliases[$key]); - } - - // Fetch all files - $dir = new \DirectoryIterator(\OC::$SERVERROOT.'/core/img/filetypes'); - - $files = []; - foreach($dir as $fileInfo) { - if ($fileInfo->isFile()) { - $file = preg_replace('/.[^.]*$/', '', $fileInfo->getFilename()); - $files[] = $file; - } - } - - //Remove duplicates - $files = array_values(array_unique($files)); - sort($files); - - // Fetch all themes! - $themes = []; - $dirs = new \DirectoryIterator(\OC::$SERVERROOT.'/themes/'); - foreach($dirs as $dir) { - //Valid theme dir - if ($dir->isFile() || $dir->isDot()) { - continue; - } - - $theme = $dir->getFilename(); - $themeDir = $dir->getPath() . '/' . $theme . '/core/img/filetypes/'; - // Check if this theme has its own filetype icons - if (!file_exists($themeDir)) { - continue; - } - - $themes[$theme] = []; - // Fetch all the theme icons! - $themeIt = new \DirectoryIterator($themeDir); - foreach ($themeIt as $fileInfo) { - if ($fileInfo->isFile()) { - $file = preg_replace('/.[^.]*$/', '', $fileInfo->getFilename()); - $themes[$theme][] = $file; - } - } - - //Remove Duplicates - $themes[$theme] = array_values(array_unique($themes[$theme])); - sort($themes[$theme]); - } - - //Generate the JS - $js = '/** -* This file is automatically generated -* DO NOT EDIT MANUALLY! -* -* You can update the list of MimeType Aliases in config/mimetypealiases.json -* The list of files is fetched from core/img/filetypes -* To regenerate this file run ./occ maintenance:mimetypesjs -*/ -OC.MimeTypeList={ - aliases: ' . json_encode($aliases, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . ', - files: ' . json_encode($files, JSON_PRETTY_PRINT) . ', - themes: ' . json_encode($themes, JSON_PRETTY_PRINT) . ' -}; -'; - - //Output the JS - file_put_contents(\OC::$SERVERROOT.'/core/js/mimetypelist.js', $js); - - $output->writeln('mimetypelist.js is updated'); - } -} diff --git a/core/command/maintenance/mode.php b/core/command/maintenance/mode.php deleted file mode 100644 index 28f4fb2f7f1..00000000000 --- a/core/command/maintenance/mode.php +++ /dev/null @@ -1,75 +0,0 @@ - - * @author scolebrook - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Maintenance; - -use \OCP\IConfig; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -class Mode extends Command { - - /** @var IConfig */ - protected $config; - - public function __construct(IConfig $config) { - $this->config = $config; - parent::__construct(); - } - - protected function configure() { - $this - ->setName('maintenance:mode') - ->setDescription('set maintenance mode') - ->addOption( - 'on', - null, - InputOption::VALUE_NONE, - 'enable maintenance mode' - ) - ->addOption( - 'off', - null, - InputOption::VALUE_NONE, - 'disable maintenance mode' - ); - } - - protected function execute(InputInterface $input, OutputInterface $output) { - if ($input->getOption('on')) { - $this->config->setSystemValue('maintenance', true); - $output->writeln('Maintenance mode enabled'); - } elseif ($input->getOption('off')) { - $this->config->setSystemValue('maintenance', false); - $output->writeln('Maintenance mode disabled'); - } else { - if ($this->config->getSystemValue('maintenance', false)) { - $output->writeln('Maintenance mode is currently enabled'); - } else { - $output->writeln('Maintenance mode is currently disabled'); - } - } - } -} diff --git a/core/command/maintenance/repair.php b/core/command/maintenance/repair.php deleted file mode 100644 index 95e2b872227..00000000000 --- a/core/command/maintenance/repair.php +++ /dev/null @@ -1,91 +0,0 @@ - - * @author Morris Jobke - * @author Robin Appelman - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Maintenance; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -class Repair extends Command { - /** - * @var \OC\Repair $repair - */ - protected $repair; - /** @var \OCP\IConfig */ - protected $config; - - /** - * @param \OC\Repair $repair - * @param \OCP\IConfig $config - */ - public function __construct(\OC\Repair $repair, \OCP\IConfig $config) { - $this->repair = $repair; - $this->config = $config; - parent::__construct(); - } - - protected function configure() { - $this - ->setName('maintenance:repair') - ->setDescription('repair this installation') - ->addOption( - 'include-expensive', - null, - InputOption::VALUE_NONE, - 'Use this option when you want to include resource and load expensive tasks' - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $includeExpensive = $input->getOption('include-expensive'); - if ($includeExpensive) { - foreach ($this->repair->getExpensiveRepairSteps() as $step) { - $this->repair->addStep($step); - } - } - - $maintenanceMode = $this->config->getSystemValue('maintenance', false); - $this->config->setSystemValue('maintenance', true); - - $this->repair->listen('\OC\Repair', 'step', function ($description) use ($output) { - $output->writeln(' - ' . $description); - }); - $this->repair->listen('\OC\Repair', 'info', function ($description) use ($output) { - $output->writeln(' - ' . $description); - }); - $this->repair->listen('\OC\Repair', 'warning', function ($description) use ($output) { - $output->writeln(' - WARNING: ' . $description); - }); - $this->repair->listen('\OC\Repair', 'error', function ($description) use ($output) { - $output->writeln(' - ERROR: ' . $description); - }); - - $this->repair->run(); - - $this->config->setSystemValue('maintenance', $maintenanceMode); - } -} diff --git a/core/command/maintenance/singleuser.php b/core/command/maintenance/singleuser.php deleted file mode 100644 index 2e6f1f136e7..00000000000 --- a/core/command/maintenance/singleuser.php +++ /dev/null @@ -1,78 +0,0 @@ - - * @author Robin Appelman - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Maintenance; - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -use OCP\IConfig; - -class SingleUser extends Command { - - /** @var IConfig */ - protected $config; - - /** - * @param IConfig $config - */ - public function __construct(IConfig $config) { - $this->config = $config; - parent::__construct(); - } - - protected function configure() { - $this - ->setName('maintenance:singleuser') - ->setDescription('set single user mode') - ->addOption( - 'on', - null, - InputOption::VALUE_NONE, - 'enable single user mode' - ) - ->addOption( - 'off', - null, - InputOption::VALUE_NONE, - 'disable single user mode' - ); - } - - protected function execute(InputInterface $input, OutputInterface $output) { - if ($input->getOption('on')) { - $this->config->setSystemValue('singleuser', true); - $output->writeln('Single user mode enabled'); - } elseif ($input->getOption('off')) { - $this->config->setSystemValue('singleuser', false); - $output->writeln('Single user mode disabled'); - } else { - if ($this->config->getSystemValue('singleuser', false)) { - $output->writeln('Single user mode is currently enabled'); - } else { - $output->writeln('Single user mode is currently disabled'); - } - } - } -} diff --git a/core/command/security/importcertificate.php b/core/command/security/importcertificate.php deleted file mode 100644 index 6aae7ad1d9f..00000000000 --- a/core/command/security/importcertificate.php +++ /dev/null @@ -1,67 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Security; - -use OC\Core\Command\Base; -use OCP\ICertificateManager; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Helper\Table; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -class ImportCertificate extends Base { - - /** @var ICertificateManager */ - protected $certificateManager; - - public function __construct(ICertificateManager $certificateManager) { - $this->certificateManager = $certificateManager; - parent::__construct(); - } - - protected function configure() { - $this - ->setName('security:certificates:import') - ->setDescription('import trusted certificate') - ->addArgument( - 'path', - InputArgument::REQUIRED, - 'path to the certificate to import' - ); - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $path = $input->getArgument('path'); - - if (!file_exists($path)) { - $output->writeln('certificate not found'); - return; - } - - $certData = file_get_contents($path); - $name = basename($path); - - $this->certificateManager->addCertificate($certData, $name); - } -} diff --git a/core/command/security/listcertificates.php b/core/command/security/listcertificates.php deleted file mode 100644 index 91deb2d340a..00000000000 --- a/core/command/security/listcertificates.php +++ /dev/null @@ -1,96 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Security; - -use OC\Core\Command\Base; -use OCP\ICertificate; -use OCP\ICertificateManager; -use OCP\IL10N; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Helper\Table; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -class ListCertificates extends Base { - - /** @var ICertificateManager */ - protected $certificateManager; - /** @var IL10N */ - protected $l; - - public function __construct(ICertificateManager $certificateManager, IL10N $l) { - $this->certificateManager = $certificateManager; - $this->l = $l; - parent::__construct(); - } - - protected function configure() { - $this - ->setName('security:certificates') - ->setDescription('list trusted certificates'); - parent::configure(); - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $outputType = $input->getOption('output'); - if ($outputType === self::OUTPUT_FORMAT_JSON || $outputType === self::OUTPUT_FORMAT_JSON_PRETTY) { - $certificates = array_map(function (ICertificate $certificate) { - return [ - 'name' => $certificate->getName(), - 'common_name' => $certificate->getCommonName(), - 'organization' => $certificate->getOrganization(), - 'expire' => $certificate->getExpireDate()->format(\DateTime::ATOM), - 'issuer' => $certificate->getIssuerName(), - 'issuer_organization' => $certificate->getIssuerOrganization(), - 'issue_date' => $certificate->getIssueDate()->format(\DateTime::ATOM) - ]; - }, $this->certificateManager->listCertificates()); - if ($outputType === self::OUTPUT_FORMAT_JSON) { - $output->writeln(json_encode(array_values($certificates))); - } else { - $output->writeln(json_encode(array_values($certificates), JSON_PRETTY_PRINT)); - } - } else { - $table = new Table($output); - $table->setHeaders([ - 'File Name', - 'Common Name', - 'Organization', - 'Valid Until', - 'Issued By' - ]); - - $rows = array_map(function (ICertificate $certificate) { - return [ - $certificate->getName(), - $certificate->getCommonName(), - $certificate->getOrganization(), - $this->l->l('date', $certificate->getExpireDate()), - $certificate->getIssuerName() - ]; - }, $this->certificateManager->listCertificates()); - $table->setRows($rows); - $table->render(); - } - } -} diff --git a/core/command/security/removecertificate.php b/core/command/security/removecertificate.php deleted file mode 100644 index 68e409aee1c..00000000000 --- a/core/command/security/removecertificate.php +++ /dev/null @@ -1,59 +0,0 @@ - - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\Security; - -use OC\Core\Command\Base; -use OCP\ICertificateManager; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Helper\Table; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -class RemoveCertificate extends Base { - - /** @var ICertificateManager */ - protected $certificateManager; - - public function __construct(ICertificateManager $certificateManager) { - $this->certificateManager = $certificateManager; - parent::__construct(); - } - - protected function configure() { - $this - ->setName('security:certificates:remove') - ->setDescription('remove trusted certificate') - ->addArgument( - 'name', - InputArgument::REQUIRED, - 'the file name of the certificate to remove' - ); - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $name = $input->getArgument('name'); - - $this->certificateManager->removeCertificate($name); - } -} diff --git a/core/command/status.php b/core/command/status.php deleted file mode 100644 index 6bc9c28d4d1..00000000000 --- a/core/command/status.php +++ /dev/null @@ -1,49 +0,0 @@ - - * @author Joas Schilling - * @author Morris Jobke - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command; - -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -class Status extends Base { - protected function configure() { - parent::configure(); - - $this - ->setName('status') - ->setDescription('show some status information') - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $values = array( - 'installed' => (bool) \OC::$server->getConfig()->getSystemValue('installed', false), - 'version' => implode('.', \OCP\Util::getVersion()), - 'versionstring' => \OC_Util::getVersionString(), - 'edition' => \OC_Util::getEditionString(), - ); - - $this->writeArrayInOutputFormat($input, $output, $values); - } -} diff --git a/core/command/upgrade.php b/core/command/upgrade.php deleted file mode 100644 index cbb1f26f938..00000000000 --- a/core/command/upgrade.php +++ /dev/null @@ -1,295 +0,0 @@ - - * @author Björn Schießle - * @author Joas Schilling - * @author Lukas Reschke - * @author Morris Jobke - * @author Owen Winkler - * @author Steffen Lindner - * @author Thomas Müller - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command; - -use OC\Console\TimestampFormatter; -use OC\Updater; -use OCP\IConfig; -use OCP\ILogger; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Helper\ProgressBar; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\EventDispatcher\GenericEvent; - -class Upgrade extends Command { - - const ERROR_SUCCESS = 0; - const ERROR_NOT_INSTALLED = 1; - const ERROR_MAINTENANCE_MODE = 2; - const ERROR_UP_TO_DATE = 3; - const ERROR_INVALID_ARGUMENTS = 4; - const ERROR_FAILURE = 5; - - /** @var IConfig */ - private $config; - - /** @var ILogger */ - private $logger; - - /** - * @param IConfig $config - * @param ILogger $logger - */ - public function __construct(IConfig $config, ILogger $logger) { - parent::__construct(); - $this->config = $config; - $this->logger = $logger; - } - - protected function configure() { - $this - ->setName('upgrade') - ->setDescription('run upgrade routines after installation of a new release. The release has to be installed before.') - ->addOption( - '--skip-migration-test', - null, - InputOption::VALUE_NONE, - 'skips the database schema migration simulation and update directly' - ) - ->addOption( - '--dry-run', - null, - InputOption::VALUE_NONE, - 'only runs the database schema migration simulation, do not actually update' - ) - ->addOption( - '--no-app-disable', - null, - InputOption::VALUE_NONE, - 'skips the disable of third party apps' - ); - } - - /** - * Execute the upgrade command - * - * @param InputInterface $input input interface - * @param OutputInterface $output output interface - */ - protected function execute(InputInterface $input, OutputInterface $output) { - - $simulateStepEnabled = true; - $updateStepEnabled = true; - $skip3rdPartyAppsDisable = false; - - if ($input->getOption('skip-migration-test')) { - $simulateStepEnabled = false; - } - if ($input->getOption('dry-run')) { - $updateStepEnabled = false; - } - if ($input->getOption('no-app-disable')) { - $skip3rdPartyAppsDisable = true; - } - - if (!$simulateStepEnabled && !$updateStepEnabled) { - $output->writeln( - 'Only one of "--skip-migration-test" or "--dry-run" ' . - 'can be specified at a time.' - ); - return self::ERROR_INVALID_ARGUMENTS; - } - - if(\OC::checkUpgrade(false)) { - if (OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) { - // Prepend each line with a little timestamp - $timestampFormatter = new TimestampFormatter($this->config, $output->getFormatter()); - $output->setFormatter($timestampFormatter); - } - - $self = $this; - $updater = new Updater( - \OC::$server->getHTTPHelper(), - $this->config, - \OC::$server->getIntegrityCodeChecker(), - $this->logger - ); - - $updater->setSimulateStepEnabled($simulateStepEnabled); - $updater->setUpdateStepEnabled($updateStepEnabled); - $updater->setSkip3rdPartyAppsDisable($skip3rdPartyAppsDisable); - $dispatcher = \OC::$server->getEventDispatcher(); - $progress = new ProgressBar($output); - $progress->setFormat(" %message%\n %current%/%max% [%bar%] %percent:3s%%"); - $listener = function($event) use ($progress, $output) { - if ($event instanceof GenericEvent) { - $message = $event->getSubject(); - if (OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) { - $output->writeln(' Checking table ' . $message); - } else { - if (strlen($message) > 60) { - $message = substr($message, 0, 57) . '...'; - } - $progress->setMessage($message); - if ($event[0] === 1) { - $output->writeln(''); - $progress->start($event[1]); - } - $progress->setProgress($event[0]); - if ($event[0] === $event[1]) { - $progress->setMessage('Done'); - $progress->finish(); - $output->writeln(''); - } - } - } - }; - $dispatcher->addListener('\OC\DB\Migrator::executeSql', $listener); - $dispatcher->addListener('\OC\DB\Migrator::checkTable', $listener); - - $updater->listen('\OC\Updater', 'maintenanceEnabled', function () use($output) { - $output->writeln('Turned on maintenance mode'); - }); - $updater->listen('\OC\Updater', 'maintenanceDisabled', function () use($output) { - $output->writeln('Turned off maintenance mode'); - }); - $updater->listen('\OC\Updater', 'maintenanceActive', function () use($output) { - $output->writeln('Maintenance mode is kept active'); - }); - $updater->listen('\OC\Updater', 'updateEnd', - function ($success) use($output, $updateStepEnabled, $self) { - $mode = $updateStepEnabled ? 'Update' : 'Update simulation'; - if ($success) { - $message = "$mode successful"; - } else { - $message = "$mode failed"; - } - $output->writeln($message); - }); - $updater->listen('\OC\Updater', 'dbUpgradeBefore', function () use($output) { - $output->writeln('Updating database schema'); - }); - $updater->listen('\OC\Updater', 'dbUpgrade', function () use($output) { - $output->writeln('Updated database'); - }); - $updater->listen('\OC\Updater', 'dbSimulateUpgradeBefore', function () use($output) { - $output->writeln('Checking whether the database schema can be updated (this can take a long time depending on the database size)'); - }); - $updater->listen('\OC\Updater', 'dbSimulateUpgrade', function () use($output) { - $output->writeln('Checked database schema update'); - }); - $updater->listen('\OC\Updater', 'incompatibleAppDisabled', function ($app) use($output) { - $output->writeln('Disabled incompatible app: ' . $app . ''); - }); - $updater->listen('\OC\Updater', 'thirdPartyAppDisabled', function ($app) use ($output) { - $output->writeln('Disabled 3rd-party app: ' . $app . ''); - }); - $updater->listen('\OC\Updater', 'upgradeAppStoreApp', function ($app) use($output) { - $output->writeln('Update 3rd-party app: ' . $app . ''); - }); - $updater->listen('\OC\Updater', 'repairWarning', function ($app) use($output) { - $output->writeln('Repair warning: ' . $app . ''); - }); - $updater->listen('\OC\Updater', 'repairError', function ($app) use($output) { - $output->writeln('Repair error: ' . $app . ''); - }); - $updater->listen('\OC\Updater', 'appUpgradeCheckBefore', function () use ($output) { - $output->writeln('Checking updates of apps'); - }); - $updater->listen('\OC\Updater', 'appSimulateUpdate', function ($app) use ($output) { - $output->writeln("Checking whether the database schema for <$app> can be updated (this can take a long time depending on the database size)"); - }); - $updater->listen('\OC\Updater', 'appUpgradeCheck', function () use ($output) { - $output->writeln('Checked database schema update for apps'); - }); - $updater->listen('\OC\Updater', 'appUpgradeStarted', function ($app, $version) use ($output) { - $output->writeln("Updating <$app> ..."); - }); - $updater->listen('\OC\Updater', 'appUpgrade', function ($app, $version) use ($output) { - $output->writeln("Updated <$app> to $version"); - }); - $updater->listen('\OC\Updater', 'failure', function ($message) use($output, $self) { - $output->writeln("$message"); - }); - $updater->listen('\OC\Updater', 'setDebugLogLevel', function ($logLevel, $logLevelName) use($output) { - $output->writeln("Set log level to debug"); - }); - $updater->listen('\OC\Updater', 'resetLogLevel', function ($logLevel, $logLevelName) use($output) { - $output->writeln("Reset log level"); - }); - $updater->listen('\OC\Updater', 'startCheckCodeIntegrity', function () use($output) { - $output->writeln("Starting code integrity check..."); - }); - $updater->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function () use($output) { - $output->writeln("Finished code integrity check"); - }); - - if(OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) { - $updater->listen('\OC\Updater', 'repairInfo', function ($message) use($output) { - $output->writeln('Repair info: ' . $message . ''); - }); - $updater->listen('\OC\Updater', 'repairStep', function ($message) use($output) { - $output->writeln('Repair step: ' . $message . ''); - }); - } - - $success = $updater->upgrade(); - - $this->postUpgradeCheck($input, $output); - - if(!$success) { - return self::ERROR_FAILURE; - } - - return self::ERROR_SUCCESS; - } else if($this->config->getSystemValue('maintenance', false)) { - //Possible scenario: ownCloud core is updated but an app failed - $output->writeln('ownCloud is in maintenance mode'); - $output->write('Maybe an upgrade is already in process. Please check the ' - . 'logfile (data/owncloud.log). If you want to re-run the ' - . 'upgrade procedure, remove the "maintenance mode" from ' - . 'config.php and call this script again.' - , true); - return self::ERROR_MAINTENANCE_MODE; - } else { - $output->writeln('ownCloud is already latest version'); - return self::ERROR_UP_TO_DATE; - } - } - - /** - * Perform a post upgrade check (specific to the command line tool) - * - * @param InputInterface $input input interface - * @param OutputInterface $output output interface - */ - protected function postUpgradeCheck(InputInterface $input, OutputInterface $output) { - $trustedDomains = $this->config->getSystemValue('trusted_domains', array()); - if (empty($trustedDomains)) { - $output->write( - 'The setting "trusted_domains" could not be ' . - 'set automatically by the upgrade script, ' . - 'please set it manually' - ); - } - } -} diff --git a/core/command/user/add.php b/core/command/user/add.php deleted file mode 100644 index 6c7e3a47231..00000000000 --- a/core/command/user/add.php +++ /dev/null @@ -1,154 +0,0 @@ - - * @author Laurens Post - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\User; - -use OC\Files\Filesystem; -use OCP\IGroupManager; -use OCP\IUser; -use OCP\IUserManager; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Question\Question; - -class Add extends Command { - /** @var \OCP\IUserManager */ - protected $userManager; - - /** @var \OCP\IGroupManager */ - protected $groupManager; - - /** - * @param IUserManager $userManager - * @param IGroupManager $groupManager - */ - public function __construct(IUserManager $userManager, IGroupManager $groupManager) { - parent::__construct(); - $this->userManager = $userManager; - $this->groupManager = $groupManager; - } - - protected function configure() { - $this - ->setName('user:add') - ->setDescription('adds a user') - ->addArgument( - 'uid', - InputArgument::REQUIRED, - 'User ID used to login (must only contain a-z, A-Z, 0-9, -, _ and @)' - ) - ->addOption( - 'password-from-env', - null, - InputOption::VALUE_NONE, - 'read password from environment variable OC_PASS' - ) - ->addOption( - 'display-name', - null, - InputOption::VALUE_OPTIONAL, - 'User name used in the web UI (can contain any characters)' - ) - ->addOption( - 'group', - 'g', - InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, - 'groups the user should be added to (The group will be created if it does not exist)' - ); - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $uid = $input->getArgument('uid'); - if ($this->userManager->userExists($uid)) { - $output->writeln('The user "' . $uid . '" already exists.'); - return 1; - } - - if ($input->getOption('password-from-env')) { - $password = getenv('OC_PASS'); - if (!$password) { - $output->writeln('--password-from-env given, but OC_PASS is empty!'); - return 1; - } - } elseif ($input->isInteractive()) { - /** @var $dialog \Symfony\Component\Console\Helper\DialogHelper */ - $dialog = $this->getHelperSet()->get('dialog'); - $password = $dialog->askHiddenResponse( - $output, - 'Enter password: ', - false - ); - $confirm = $dialog->askHiddenResponse( - $output, - 'Confirm password: ', - false - ); - - if ($password !== $confirm) { - $output->writeln("Passwords did not match!"); - return 1; - } - } else { - $output->writeln("Interactive input or --password-from-env is needed for entering a password!"); - return 1; - } - - $user = $this->userManager->createUser( - $input->getArgument('uid'), - $password - ); - - if ($user instanceof IUser) { - $output->writeln('The user "' . $user->getUID() . '" was created successfully'); - } else { - $output->writeln('An error occurred while creating the user'); - return 1; - } - - if ($input->getOption('display-name')) { - $user->setDisplayName($input->getOption('display-name')); - $output->writeln('Display name set to "' . $user->getDisplayName() . '"'); - } - - $groups = $input->getOption('group'); - - if (!empty($groups)) { - // Make sure we init the Filesystem for the user, in case we need to - // init some group shares. - Filesystem::init($user->getUID(), ''); - } - - foreach ($groups as $groupName) { - $group = $this->groupManager->get($groupName); - if (!$group) { - $this->groupManager->createGroup($groupName); - $group = $this->groupManager->get($groupName); - $output->writeln('Created group "' . $group->getGID() . '"'); - } - $group->addUser($user); - $output->writeln('User "' . $user->getUID() . '" added to group "' . $group->getGID() . '"'); - } - } -} diff --git a/core/command/user/delete.php b/core/command/user/delete.php deleted file mode 100644 index b9a0a0e3950..00000000000 --- a/core/command/user/delete.php +++ /dev/null @@ -1,70 +0,0 @@ - - * @author Jens-Christian Fischer - * @author Joas Schilling - * @author Morris Jobke - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\User; - -use OCP\IUserManager; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Input\InputArgument; - -class Delete extends Command { - /** @var IUserManager */ - protected $userManager; - - /** - * @param IUserManager $userManager - */ - public function __construct(IUserManager $userManager) { - $this->userManager = $userManager; - parent::__construct(); - } - - protected function configure() { - $this - ->setName('user:delete') - ->setDescription('deletes the specified user') - ->addArgument( - 'uid', - InputArgument::REQUIRED, - 'the username' - ); - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $user = $this->userManager->get($input->getArgument('uid')); - if (is_null($user)) { - $output->writeln('User does not exist'); - return; - } - - if ($user->delete()) { - $output->writeln('The specified user was deleted'); - return; - } - - $output->writeln('The specified user could not be deleted. Please check the logs.'); - } -} diff --git a/core/command/user/lastseen.php b/core/command/user/lastseen.php deleted file mode 100644 index 6bb45a87875..00000000000 --- a/core/command/user/lastseen.php +++ /dev/null @@ -1,74 +0,0 @@ - - * @author Joas Schilling - * @author Morris Jobke - * @author Pierre Ozoux - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\User; - -use OCP\IUserManager; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Input\InputArgument; - -class LastSeen extends Command { - /** @var IUserManager */ - protected $userManager; - - /** - * @param IUserManager $userManager - */ - public function __construct(IUserManager $userManager) { - $this->userManager = $userManager; - parent::__construct(); - } - - protected function configure() { - $this - ->setName('user:lastseen') - ->setDescription('shows when the user was logged in last time') - ->addArgument( - 'uid', - InputArgument::REQUIRED, - 'the username' - ); - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $user = $this->userManager->get($input->getArgument('uid')); - if(is_null($user)) { - $output->writeln('User does not exist'); - return; - } - - $lastLogin = $user->getLastLogin(); - if($lastLogin === 0) { - $output->writeln('User ' . $user->getUID() . - ' has never logged in, yet.'); - } else { - $date = new \DateTime(); - $date->setTimestamp($lastLogin); - $output->writeln($user->getUID() . - '`s last login: ' . $date->format('d.m.Y H:i')); - } - } -} diff --git a/core/command/user/report.php b/core/command/user/report.php deleted file mode 100644 index df9f7e41620..00000000000 --- a/core/command/user/report.php +++ /dev/null @@ -1,86 +0,0 @@ - - * @author Joas Schilling - * @author Morris Jobke - * @author Thomas Müller - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\User; - -use OCP\IUserManager; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -class Report extends Command { - /** @var IUserManager */ - protected $userManager; - - /** - * @param IUserManager $userManager - */ - public function __construct(IUserManager $userManager) { - $this->userManager = $userManager; - parent::__construct(); - } - - protected function configure() { - $this - ->setName('user:report') - ->setDescription('shows how many users have access'); - } - - protected function execute(InputInterface $input, OutputInterface $output) { - /** @var \Symfony\Component\Console\Helper\TableHelper $table */ - $table = $this->getHelperSet()->get('table'); - $table->setHeaders(array('User Report', '')); - $userCountArray = $this->countUsers(); - if(!empty($userCountArray)) { - $total = 0; - $rows = array(); - foreach($userCountArray as $classname => $users) { - $total += $users; - $rows[] = array($classname, $users); - } - - $rows[] = array(' '); - $rows[] = array('total users', $total); - } else { - $rows[] = array('No backend enabled that supports user counting', ''); - } - - $userDirectoryCount = $this->countUserDirectories(); - $rows[] = array(' '); - $rows[] = array('user directories', $userDirectoryCount); - - $table->setRows($rows); - $table->render($output); - } - - private function countUsers() { - return $this->userManager->countUsers(); - } - - private function countUserDirectories() { - $dataview = new \OC\Files\View('/'); - $userDirectories = $dataview->getDirectoryContent('/', 'httpd/unix-directory'); - return count($userDirectories); - } -} diff --git a/core/command/user/resetpassword.php b/core/command/user/resetpassword.php deleted file mode 100644 index f3f2d5b0630..00000000000 --- a/core/command/user/resetpassword.php +++ /dev/null @@ -1,121 +0,0 @@ - - * @author Christopher Schäpers - * @author Clark Tomlinson - * @author Joas Schilling - * @author Laurens Post - * @author Morris Jobke - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Command\User; - -use OCP\IUserManager; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -class ResetPassword extends Command { - - /** @var IUserManager */ - protected $userManager; - - public function __construct(IUserManager $userManager) { - $this->userManager = $userManager; - parent::__construct(); - } - - protected function configure() { - $this - ->setName('user:resetpassword') - ->setDescription('Resets the password of the named user') - ->addArgument( - 'user', - InputArgument::REQUIRED, - 'Username to reset password' - ) - ->addOption( - 'password-from-env', - null, - InputOption::VALUE_NONE, - 'read password from environment variable OC_PASS' - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) { - $username = $input->getArgument('user'); - - /** @var $user \OCP\IUser */ - $user = $this->userManager->get($username); - if (is_null($user)) { - $output->writeln('User does not exist'); - return 1; - } - - if ($input->getOption('password-from-env')) { - $password = getenv('OC_PASS'); - if (!$password) { - $output->writeln('--password-from-env given, but OC_PASS is empty!'); - return 1; - } - } elseif ($input->isInteractive()) { - /** @var $dialog \Symfony\Component\Console\Helper\DialogHelper */ - $dialog = $this->getHelperSet()->get('dialog'); - - if (\OCP\App::isEnabled('encryption')) { - $output->writeln( - 'Warning: Resetting the password when using encryption will result in data loss!' - ); - if (!$dialog->askConfirmation($output, 'Do you want to continue?', true)) { - return 1; - } - } - - $password = $dialog->askHiddenResponse( - $output, - 'Enter a new password: ', - false - ); - $confirm = $dialog->askHiddenResponse( - $output, - 'Confirm the new password: ', - false - ); - - if ($password !== $confirm) { - $output->writeln("Passwords did not match!"); - return 1; - } - } else { - $output->writeln("Interactive input or --password-from-env is needed for entering a new password!"); - return 1; - } - - $success = $user->setPassword($password); - if ($success) { - $output->writeln("Successfully reset password for " . $username . ""); - } else { - $output->writeln("Error while resetting password!"); - return 1; - } - } -} diff --git a/core/controller/avatarcontroller.php b/core/controller/avatarcontroller.php deleted file mode 100644 index adfe38ab2db..00000000000 --- a/core/controller/avatarcontroller.php +++ /dev/null @@ -1,327 +0,0 @@ - - * @author Lukas Reschke - * @author Morris Jobke - * @author Robin Appelman - * @author Roeland Jago Douma - * @author Thomas Müller - * @author Vincent Petry - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ -namespace OC\Core\Controller; - -use OCP\AppFramework\Controller; -use OCP\AppFramework\Http; -use OCP\AppFramework\Http\DataResponse; -use OCP\AppFramework\Http\DataDisplayResponse; -use OCP\Files\NotFoundException; -use OCP\IAvatarManager; -use OCP\ILogger; -use OCP\IL10N; -use OCP\IRequest; -use OCP\IUserManager; -use OCP\IUserSession; -use OCP\Files\Folder; - -/** - * Class AvatarController - * - * @package OC\Core\Controller - */ -class AvatarController extends Controller { - - /** @var IAvatarManager */ - protected $avatarManager; - - /** @var \OC\Cache\File */ - protected $cache; - - /** @var IL10N */ - protected $l; - - /** @var IUserManager */ - protected $userManager; - - /** @var IUserSession */ - protected $userSession; - - /** @var Folder */ - protected $userFolder; - - /** @var ILogger */ - protected $logger; - - /** - * @param string $appName - * @param IRequest $request - * @param IAvatarManager $avatarManager - * @param \OC\Cache\File $cache - * @param IL10N $l10n - * @param IUserManager $userManager - * @param IUserSession $userSession - * @param Folder $userFolder - * @param ILogger $logger - */ - public function __construct($appName, - IRequest $request, - IAvatarManager $avatarManager, - \OC\Cache\File $cache, - IL10N $l10n, - IUserManager $userManager, - IUserSession $userSession, - Folder $userFolder, - ILogger $logger) { - parent::__construct($appName, $request); - - $this->avatarManager = $avatarManager; - $this->cache = $cache; - $this->l = $l10n; - $this->userManager = $userManager; - $this->userSession = $userSession; - $this->userFolder = $userFolder; - $this->logger = $logger; - } - - /** - * @NoAdminRequired - * @NoCSRFRequired - * - * @param string $userId - * @param int $size - * @return DataResponse|DataDisplayResponse - */ - public function getAvatar($userId, $size) { - if ($size > 2048) { - $size = 2048; - } elseif ($size <= 0) { - $size = 64; - } - - try { - $avatar = $this->avatarManager->getAvatar($userId)->getFile($size); - $resp = new DataDisplayResponse($avatar->getContent(), - Http::STATUS_OK, - ['Content-Type' => $avatar->getMimeType()]); - $resp->setETag($avatar->getEtag()); - } catch (NotFoundException $e) { - $user = $this->userManager->get($userId); - $resp = new DataResponse([ - 'data' => [ - 'displayname' => $user->getDisplayName(), - ], - ]); - } catch (\Exception $e) { - $resp = new DataResponse([ - 'data' => [ - 'displayname' => '', - ], - ]); - } - - $resp->addHeader('Pragma', 'public'); - $resp->cacheFor(0); - $resp->setLastModified(new \DateTime('now', new \DateTimeZone('GMT'))); - - return $resp; - } - - /** - * @NoAdminRequired - * - * @param string $path - * @return DataResponse - */ - public function postAvatar($path) { - $userId = $this->userSession->getUser()->getUID(); - $files = $this->request->getUploadedFile('files'); - - $headers = []; - if ($this->request->isUserAgent([\OC\AppFramework\Http\Request::USER_AGENT_IE_8])) { - // due to upload iframe workaround, need to set content-type to text/plain - $headers['Content-Type'] = 'text/plain'; - } - - if (isset($path)) { - $path = stripslashes($path); - $node = $this->userFolder->get($path); - if (!($node instanceof \OCP\Files\File)) { - return new DataResponse(['data' => ['message' => $this->l->t('Please select a file.')]], Http::STATUS_OK, $headers); - } - if ($node->getSize() > 20*1024*1024) { - return new DataResponse( - ['data' => ['message' => $this->l->t('File is too big')]], - Http::STATUS_BAD_REQUEST, - $headers - ); - } - $content = $node->getContent(); - } elseif (!is_null($files)) { - if ( - $files['error'][0] === 0 && - is_uploaded_file($files['tmp_name'][0]) && - !\OC\Files\Filesystem::isFileBlacklisted($files['tmp_name'][0]) - ) { - if ($files['size'][0] > 20*1024*1024) { - return new DataResponse( - ['data' => ['message' => $this->l->t('File is too big')]], - Http::STATUS_BAD_REQUEST, - $headers - ); - } - $this->cache->set('avatar_upload', file_get_contents($files['tmp_name'][0]), 7200); - $content = $this->cache->get('avatar_upload'); - unlink($files['tmp_name'][0]); - } else { - return new DataResponse( - ['data' => ['message' => $this->l->t('Invalid file provided')]], - Http::STATUS_BAD_REQUEST, - $headers - ); - } - } else { - //Add imgfile - return new DataResponse( - ['data' => ['message' => $this->l->t('No image or file provided')]], - Http::STATUS_BAD_REQUEST, - $headers - ); - } - - try { - $image = new \OC_Image(); - $image->loadFromData($content); - $image->fixOrientation(); - - if ($image->valid()) { - $mimeType = $image->mimeType(); - if ($mimeType !== 'image/jpeg' && $mimeType !== 'image/png') { - return new DataResponse( - ['data' => ['message' => $this->l->t('Unknown filetype')]], - Http::STATUS_OK, - $headers - ); - } - - $this->cache->set('tmpAvatar', $image->data(), 7200); - return new DataResponse( - ['data' => 'notsquare'], - Http::STATUS_OK, - $headers - ); - } else { - return new DataResponse( - ['data' => ['message' => $this->l->t('Invalid image')]], - Http::STATUS_OK, - $headers - ); - } - } catch (\Exception $e) { - $this->logger->logException($e, ['app' => 'core']); - return new DataResponse(['data' => ['message' => $this->l->t('An error occurred. Please contact your admin.')]], Http::STATUS_OK, $headers); - } - } - - /** - * @NoAdminRequired - * - * @return DataResponse - */ - public function deleteAvatar() { - $userId = $this->userSession->getUser()->getUID(); - - try { - $avatar = $this->avatarManager->getAvatar($userId); - $avatar->remove(); - return new DataResponse(); - } catch (\Exception $e) { - $this->logger->logException($e, ['app' => 'core']); - return new DataResponse(['data' => ['message' => $this->l->t('An error occurred. Please contact your admin.')]], Http::STATUS_BAD_REQUEST); - } - } - - /** - * @NoAdminRequired - * - * @return DataResponse|DataDisplayResponse - */ - public function getTmpAvatar() { - $tmpAvatar = $this->cache->get('tmpAvatar'); - if (is_null($tmpAvatar)) { - return new DataResponse(['data' => [ - 'message' => $this->l->t("No temporary profile picture available, try again") - ]], - Http::STATUS_NOT_FOUND); - } - - $image = new \OC_Image($tmpAvatar); - - $resp = new DataDisplayResponse($image->data(), - Http::STATUS_OK, - ['Content-Type' => $image->mimeType()]); - - $resp->setETag(crc32($image->data())); - $resp->cacheFor(0); - $resp->setLastModified(new \DateTime('now', new \DateTimeZone('GMT'))); - return $resp; - } - - /** - * @NoAdminRequired - * - * @param array $crop - * @return DataResponse - */ - public function postCroppedAvatar($crop) { - $userId = $this->userSession->getUser()->getUID(); - - if (is_null($crop)) { - return new DataResponse(['data' => ['message' => $this->l->t("No crop data provided")]], - Http::STATUS_BAD_REQUEST); - } - - if (!isset($crop['x'], $crop['y'], $crop['w'], $crop['h'])) { - return new DataResponse(['data' => ['message' => $this->l->t("No valid crop data provided")]], - Http::STATUS_BAD_REQUEST); - } - - $tmpAvatar = $this->cache->get('tmpAvatar'); - if (is_null($tmpAvatar)) { - return new DataResponse(['data' => [ - 'message' => $this->l->t("No temporary profile picture available, try again") - ]], - Http::STATUS_BAD_REQUEST); - } - - $image = new \OC_Image($tmpAvatar); - $image->crop($crop['x'], $crop['y'], round($crop['w']), round($crop['h'])); - try { - $avatar = $this->avatarManager->getAvatar($userId); - $avatar->set($image); - // Clean up - $this->cache->remove('tmpAvatar'); - return new DataResponse(['status' => 'success']); - } catch (\OC\NotSquareException $e) { - return new DataResponse(['data' => ['message' => $this->l->t('Crop is not square')]], - Http::STATUS_BAD_REQUEST); - } catch (\Exception $e) { - $this->logger->logException($e, ['app' => 'core']); - return new DataResponse(['data' => ['message' => $this->l->t('An error occurred. Please contact your admin.')]], Http::STATUS_BAD_REQUEST); - } - } -} diff --git a/core/controller/lostcontroller.php b/core/controller/lostcontroller.php deleted file mode 100644 index 0e0932b288b..00000000000 --- a/core/controller/lostcontroller.php +++ /dev/null @@ -1,257 +0,0 @@ - - * @author Björn Schießle - * @author Lukas Reschke - * @author Morris Jobke - * @author Roeland Jago Douma - * @author Thomas Müller - * @author Victor Dubiniuk - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Controller; - -use \OCP\AppFramework\Controller; -use \OCP\AppFramework\Http\TemplateResponse; -use OCP\AppFramework\Utility\ITimeFactory; -use \OCP\IURLGenerator; -use \OCP\IRequest; -use \OCP\IL10N; -use \OCP\IConfig; -use OCP\IUserManager; -use OCP\Mail\IMailer; -use OCP\Security\ISecureRandom; -use \OC_Defaults; -use OCP\Security\StringUtils; - -/** - * Class LostController - * - * Successfully changing a password will emit the post_passwordReset hook. - * - * @package OC\Core\Controller - */ -class LostController extends Controller { - - /** @var IURLGenerator */ - protected $urlGenerator; - /** @var IUserManager */ - protected $userManager; - // FIXME: Inject a non-static factory of OC_Defaults for better unit-testing - /** @var OC_Defaults */ - protected $defaults; - /** @var IL10N */ - protected $l10n; - /** @var string */ - protected $from; - /** @var bool */ - protected $isDataEncrypted; - /** @var IConfig */ - protected $config; - /** @var ISecureRandom */ - protected $secureRandom; - /** @var IMailer */ - protected $mailer; - /** @var ITimeFactory */ - protected $timeFactory; - - /** - * @param string $appName - * @param IRequest $request - * @param IURLGenerator $urlGenerator - * @param IUserManager $userManager - * @param OC_Defaults $defaults - * @param IL10N $l10n - * @param IConfig $config - * @param ISecureRandom $secureRandom - * @param string $from - * @param string $isDataEncrypted - * @param IMailer $mailer - * @param ITimeFactory $timeFactory - */ - public function __construct($appName, - IRequest $request, - IURLGenerator $urlGenerator, - IUserManager $userManager, - OC_Defaults $defaults, - IL10N $l10n, - IConfig $config, - ISecureRandom $secureRandom, - $from, - $isDataEncrypted, - IMailer $mailer, - ITimeFactory $timeFactory) { - parent::__construct($appName, $request); - $this->urlGenerator = $urlGenerator; - $this->userManager = $userManager; - $this->defaults = $defaults; - $this->l10n = $l10n; - $this->secureRandom = $secureRandom; - $this->from = $from; - $this->isDataEncrypted = $isDataEncrypted; - $this->config = $config; - $this->mailer = $mailer; - $this->timeFactory = $timeFactory; - } - - /** - * Someone wants to reset their password: - * - * @PublicPage - * @NoCSRFRequired - * - * @param string $token - * @param string $userId - * @return TemplateResponse - */ - public function resetform($token, $userId) { - return new TemplateResponse( - 'core', - 'lostpassword/resetpassword', - array( - 'link' => $this->urlGenerator->linkToRouteAbsolute('core.lost.setPassword', array('userId' => $userId, 'token' => $token)), - ), - 'guest' - ); - } - - /** - * @param $message - * @param array $additional - * @return array - */ - private function error($message, array $additional=array()) { - return array_merge(array('status' => 'error', 'msg' => $message), $additional); - } - - /** - * @return array - */ - private function success() { - return array('status'=>'success'); - } - - /** - * @PublicPage - * - * @param string $user - * @return array - */ - public function email($user){ - // FIXME: use HTTP error codes - try { - $this->sendEmail($user); - } catch (\Exception $e){ - return $this->error($e->getMessage()); - } - - return $this->success(); - } - - /** - * @PublicPage - * @param string $token - * @param string $userId - * @param string $password - * @param boolean $proceed - * @return array - */ - public function setPassword($token, $userId, $password, $proceed) { - if ($this->isDataEncrypted && !$proceed) { - return $this->error('', array('encryption' => true)); - } - - try { - $user = $this->userManager->get($userId); - - $splittedToken = explode(':', $this->config->getUserValue($userId, 'owncloud', 'lostpassword', null)); - if(count($splittedToken) !== 2) { - throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid')); - } - - if ($splittedToken[0] < ($this->timeFactory->getTime() - 60*60*12) || - $user->getLastLogin() > $splittedToken[0]) { - throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is expired')); - } - - if (!StringUtils::equals($splittedToken[1], $token)) { - throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid')); - } - - if (!$user->setPassword($password)) { - throw new \Exception(); - } - - \OC_Hook::emit('\OC\Core\LostPassword\Controller\LostController', 'post_passwordReset', array('uid' => $userId, 'password' => $password)); - - $this->config->deleteUserValue($userId, 'owncloud', 'lostpassword'); - @\OC_User::unsetMagicInCookie(); - - } catch (\Exception $e){ - return $this->error($e->getMessage()); - } - - return $this->success(); - } - - /** - * @param string $user - * @throws \Exception - */ - protected function sendEmail($user) { - if (!$this->userManager->userExists($user)) { - throw new \Exception($this->l10n->t('Couldn\'t send reset email. Please make sure your username is correct.')); - } - - $userObject = $this->userManager->get($user); - $email = $userObject->getEMailAddress(); - - if (empty($email)) { - throw new \Exception( - $this->l10n->t('Could not send reset email because there is no email address for this username. Please contact your administrator.') - ); - } - - $token = $this->secureRandom->generate(21, - ISecureRandom::CHAR_DIGITS. - ISecureRandom::CHAR_LOWER. - ISecureRandom::CHAR_UPPER); - $this->config->setUserValue($user, 'owncloud', 'lostpassword', $this->timeFactory->getTime() .':'. $token); - - $link = $this->urlGenerator->linkToRouteAbsolute('core.lost.resetform', array('userId' => $user, 'token' => $token)); - - $tmpl = new \OC_Template('core', 'lostpassword/email'); - $tmpl->assign('link', $link); - $msg = $tmpl->fetchPage(); - - try { - $message = $this->mailer->createMessage(); - $message->setTo([$email => $user]); - $message->setSubject($this->l10n->t('%s password reset', [$this->defaults->getName()])); - $message->setPlainBody($msg); - $message->setFrom([$this->from => $this->defaults->getName()]); - $this->mailer->send($message); - } catch (\Exception $e) { - throw new \Exception($this->l10n->t( - 'Couldn\'t send reset email. Please contact your administrator.' - )); - } - } - -} diff --git a/core/controller/setupcontroller.php b/core/controller/setupcontroller.php deleted file mode 100644 index f25c6f39a0b..00000000000 --- a/core/controller/setupcontroller.php +++ /dev/null @@ -1,126 +0,0 @@ - - * @author ideaship - * @author Lukas Reschke - * @author Morris Jobke - * @author Robin Appelman - * @author Robin McCorkell - * @author Thomas Müller - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Controller; - -use OC\Setup; - -class SetupController { - /** @var Setup */ - protected $setupHelper; - /** @var string */ - private $autoConfigFile; - - /** - * @param Setup $setupHelper - */ - function __construct(Setup $setupHelper) { - $this->autoConfigFile = \OC::$SERVERROOT.'/config/autoconfig.php'; - $this->setupHelper = $setupHelper; - } - - /** - * @param $post - */ - public function run($post) { - // Check for autosetup: - $post = $this->loadAutoConfig($post); - $opts = $this->setupHelper->getSystemInfo(); - - // convert 'abcpassword' to 'abcpass' - if (isset($post['adminpassword'])) { - $post['adminpass'] = $post['adminpassword']; - } - if (isset($post['dbpassword'])) { - $post['dbpass'] = $post['dbpassword']; - } - - if(isset($post['install']) AND $post['install']=='true') { - // We have to launch the installation process : - $e = $this->setupHelper->install($post); - $errors = array('errors' => $e); - - if(count($e) > 0) { - $options = array_merge($opts, $post, $errors); - $this->display($options); - } else { - $this->finishSetup(); - } - } else { - $options = array_merge($opts, $post); - $this->display($options); - } - } - - public function display($post) { - $defaults = array( - 'adminlogin' => '', - 'adminpass' => '', - 'dbuser' => '', - 'dbpass' => '', - 'dbname' => '', - 'dbtablespace' => '', - 'dbhost' => 'localhost', - 'dbtype' => '', - ); - $parameters = array_merge($defaults, $post); - - \OC_Util::addVendorScript('strengthify/jquery.strengthify'); - \OC_Util::addVendorStyle('strengthify/strengthify'); - \OC_Util::addScript('setup'); - \OC_Template::printGuestPage('', 'installation', $parameters); - } - - public function finishSetup() { - if( file_exists( $this->autoConfigFile )) { - unlink($this->autoConfigFile); - } - \OC::$server->getIntegrityCodeChecker()->runInstanceVerification(); - \OC_Util::redirectToDefaultPage(); - } - - public function loadAutoConfig($post) { - if( file_exists($this->autoConfigFile)) { - \OCP\Util::writeLog('core', 'Autoconfig file found, setting up ownCloud…', \OCP\Util::INFO); - $AUTOCONFIG = array(); - include $this->autoConfigFile; - $post = array_merge ($post, $AUTOCONFIG); - } - - $dbIsSet = isset($post['dbtype']); - $directoryIsSet = isset($post['directory']); - $adminAccountIsSet = isset($post['adminlogin']); - - if ($dbIsSet AND $directoryIsSet AND $adminAccountIsSet) { - $post['install'] = 'true'; - } - $post['dbIsSet'] = $dbIsSet; - $post['directoryIsSet'] = $directoryIsSet; - - return $post; - } -} diff --git a/core/controller/usercontroller.php b/core/controller/usercontroller.php deleted file mode 100644 index 72193761022..00000000000 --- a/core/controller/usercontroller.php +++ /dev/null @@ -1,79 +0,0 @@ - - * @author Morris Jobke - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Controller; - -use \OCP\AppFramework\Controller; -use \OCP\AppFramework\Http\JSONResponse; -use \OCP\IRequest; - -class UserController extends Controller { - /** - * @var \OCP\IUserManager - */ - protected $userManager; - - /** - * @var \OC_Defaults - */ - protected $defaults; - - public function __construct($appName, - IRequest $request, - $userManager, - $defaults - ) { - parent::__construct($appName, $request); - $this->userManager = $userManager; - $this->defaults = $defaults; - } - - /** - * Lookup user display names - * - * @NoAdminRequired - * - * @param array $users - * - * @return JSONResponse - */ - public function getDisplayNames($users) { - $result = array(); - - foreach ($users as $user) { - $userObject = $this->userManager->get($user); - if (is_object($userObject)) { - $result[$user] = $userObject->getDisplayName(); - } else { - $result[$user] = $user; - } - } - - $json = array( - 'users' => $result, - 'status' => 'success' - ); - - return new JSONResponse($json); - - } -} diff --git a/core/tags/controller.php b/core/tags/controller.php deleted file mode 100644 index 9798a59d56f..00000000000 --- a/core/tags/controller.php +++ /dev/null @@ -1,128 +0,0 @@ - - * @author Thomas Tanghus - * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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, version 3, - * along with this program. If not, see - * - */ - -namespace OC\Core\Tags; - -class Controller { - protected static function getTagger($type) { - \OC_JSON::checkLoggedIn(); - \OC_JSON::callCheck(); - - try { - $tagger = \OC::$server->getTagManager()->load($type); - return $tagger; - } catch(\Exception $e) { - \OCP\Util::writeLog('core', __METHOD__ . ' Exception: ' . $e->getMessage(), \OCP\Util::ERROR); - $l = new \OC_L10n('core'); - \OC_JSON::error(array('message'=> $l->t('Error loading tags'))); - exit; - } - } - - public static function getTags($args) { - $tagger = self::getTagger($args['type']); - \OC_JSON::success(array('tags'=> $tagger->getTags())); - } - - public static function getFavorites($args) { - $tagger = self::getTagger($args['type']); - \OC_JSON::success(array('ids'=> $tagger->getFavorites())); - } - - public static function getIdsForTag($args) { - $tagger = self::getTagger($args['type']); - \OC_JSON::success(array('ids'=> $tagger->getIdsForTag($_GET['tag']))); - } - - public static function addTag($args) { - $tagger = self::getTagger($args['type']); - - $id = $tagger->add(strip_tags($_POST['tag'])); - if($id === false) { - $l = new \OC_L10n('core'); - \OC_JSON::error(array('message'=> $l->t('Tag already exists'))); - } else { - \OC_JSON::success(array('id'=> $id)); - } - } - - public static function deleteTags($args) { - $tags = $_POST['tags']; - if(!is_array($tags)) { - $tags = array($tags); - } - - $tagger = self::getTagger($args['type']); - - if(!$tagger->delete($tags)) { - $l = new \OC_L10n('core'); - \OC_JSON::error(array('message'=> $l->t('Error deleting tag(s)'))); - } else { - \OC_JSON::success(); - } - } - - public static function tagAs($args) { - $tagger = self::getTagger($args['type']); - - if(!$tagger->tagAs($args['id'], $_POST['tag'])) { - $l = new \OC_L10n('core'); - \OC_JSON::error(array('message'=> $l->t('Error tagging'))); - } else { - \OC_JSON::success(); - } - } - - public static function unTag($args) { - $tagger = self::getTagger($args['type']); - - if(!$tagger->unTag($args['id'], $_POST['tag'])) { - $l = new \OC_L10n('core'); - \OC_JSON::error(array('message'=> $l->t('Error untagging'))); - } else { - \OC_JSON::success(); - } - } - - public static function favorite($args) { - $tagger = self::getTagger($args['type']); - - if(!$tagger->addToFavorites($args['id'])) { - $l = new \OC_L10n('core'); - \OC_JSON::error(array('message'=> $l->t('Error favoriting'))); - } else { - \OC_JSON::success(); - } - } - - public static function unFavorite($args) { - $tagger = self::getTagger($args['type']); - - if(!$tagger->removeFromFavorites($args['id'])) { - $l = new \OC_L10n('core'); - \OC_JSON::error(array('message'=> $l->t('Error unfavoriting'))); - } else { - \OC_JSON::success(); - } - } - -} -- cgit v1.2.3