diff --git a/appinfo/info.xml b/appinfo/info.xml
index 5fa0c22..ad05434 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -5,7 +5,7 @@
OCC Web
OCC Commands in a web terminal
- 0.0.2
+ 0.0.3
agpl
Adphi
OCCWeb
diff --git a/lib/Controller/OCCApplication.php b/lib/Controller/OCCApplication.php
new file mode 100644
index 0000000..7acca97
--- /dev/null
+++ b/lib/Controller/OCCApplication.php
@@ -0,0 +1,225 @@
+
+ * @author Jörn Friedrich Dreyer
+ * @author Lukas Reschke
+ * @author Miha Frangez
+ * @author Morris Jobke
+ * @author noveens
+ * @author Robin Appelman
+ * @author Thomas Müller
+ * @author Victor Dubiniuk
+ *
+ * @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 OCA\OCCWeb\Controller;
+
+use OC\MemoryInfo;
+use OC\NeedsUpdateException;
+use OC_App;
+use OCP\AppFramework\QueryException;
+use OCP\Console\ConsoleEvent;
+use OCP\IConfig;
+use OCP\ILogger;
+use Symfony\Component\Console\Application as SymfonyApplication;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\ConsoleOutputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+
+class OCCApplication {
+ /** @var IConfig */
+ private $config;
+ /** @var EventDispatcherInterface */
+ private $dispatcher;
+ /** @var ILogger */
+ private $logger;
+ /** @var MemoryInfo */
+ private $memoryInfo;
+
+ /**
+ * @param IConfig $config
+ * @param EventDispatcherInterface $dispatcher
+ * @param ILogger $logger
+ * @param MemoryInfo $memoryInfo
+ */
+ public function __construct(IConfig $config,
+ EventDispatcherInterface $dispatcher,
+ ILogger $logger,
+ MemoryInfo $memoryInfo) {
+ $defaults = \OC::$server->getThemingDefaults();
+ $this->config = $config;
+ $this->application = new SymfonyApplication($defaults->getName(), \OC_Util::getVersionString());
+ $this->dispatcher = $dispatcher;
+ $this->logger = $logger;
+ $this->memoryInfo = $memoryInfo;
+ }
+
+ /**
+ * @param InputInterface $input
+ * @param ConsoleOutputInterface $output
+ * @throws \Exception
+ */
+ public function loadCommands(
+ InputInterface $input,
+ ConsoleOutputInterface $output
+ ) {
+ // $application is required to be defined in the register_command scripts
+ $application = $this->application;
+ $inputDefinition = $application->getDefinition();
+ $inputDefinition->addOption(
+ new InputOption(
+ 'no-warnings',
+ null,
+ InputOption::VALUE_NONE,
+ 'Skip global warnings, show command output only',
+ null
+ )
+ );
+ try {
+ $input->bind($inputDefinition);
+ } catch (\RuntimeException $e) {
+ //expected if there are extra options
+ }
+ if ($input->getOption('no-warnings')) {
+ $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
+ }
+
+ if ($this->memoryInfo->isMemoryLimitSufficient() === false) {
+ $output->getErrorOutput()->writeln(
+ 'The current PHP memory limit ' .
+ 'is below the recommended value of 512MB.'
+ );
+ }
+
+ try {
+ require_once __DIR__ . '/../../../../core/register_command.php';
+ if ($this->config->getSystemValue('installed', false)) {
+ if (\OCP\Util::needUpgrade()) {
+ throw new NeedsUpdateException();
+ } elseif ($this->config->getSystemValue('maintenance', false)) {
+ $this->writeMaintenanceModeInfo($input, $output);
+ } else {
+ OC_App::loadApps();
+ foreach (\OC::$server->getAppManager()->getInstalledApps() as $app) {
+ $appPath = \OC_App::getAppPath($app);
+ if ($appPath === false) {
+ continue;
+ }
+ // load commands using info.xml
+ $info = \OC_App::getAppInfo($app);
+ if (isset($info['commands'])) {
+ $this->loadCommandsFromInfoXml($info['commands']);
+ }
+ // load from register_command.php
+ \OC_App::registerAutoloading($app, $appPath);
+ $file = $appPath . '/appinfo/register_command.php';
+ if (file_exists($file)) {
+ try {
+ require $file;
+ } catch (\Exception $e) {
+ $this->logger->logException($e);
+ }
+ }
+ }
+ }
+ } else if ($input->getArgument('command') !== '_completion' && $input->getArgument('command') !== 'maintenance:install') {
+ $output->writeln("Nextcloud is not installed - only a limited number of commands are available");
+ }
+ } catch(NeedsUpdateException $e) {
+ if ($input->getArgument('command') !== '_completion') {
+ $output->writeln("Nextcloud or one of the apps require upgrade - only a limited number of commands are available");
+ $output->writeln("You may use your browser or the occ upgrade command to do the upgrade");
+ }
+ }
+
+ if ($input->getFirstArgument() !== 'check') {
+ $errors = \OC_Util::checkServer(\OC::$server->getSystemConfig());
+ if (!empty($errors)) {
+ foreach ($errors as $error) {
+ $output->writeln((string)$error['error']);
+ $output->writeln((string)$error['hint']);
+ $output->writeln('');
+ }
+ throw new \Exception("Environment not properly prepared.");
+ }
+ }
+ }
+
+ /**
+ * Write a maintenance mode info.
+ * The commands "_completion" and "maintenance:mode" are excluded.
+ *
+ * @param InputInterface $input The input implementation for reading inputs.
+ * @param ConsoleOutputInterface $output The output implementation
+ * for writing outputs.
+ * @return void
+ */
+ private function writeMaintenanceModeInfo(
+ InputInterface $input, ConsoleOutputInterface $output
+ ) {
+ if ($input->getArgument('command') !== '_completion'
+ && $input->getArgument('command') !== 'maintenance:mode') {
+ $errOutput = $output->getErrorOutput();
+ $errOutput->writeln(
+ 'Nextcloud is in maintenance mode - ' .
+ 'no apps have been loaded' . PHP_EOL
+ );
+ }
+ }
+
+ /**
+ * Sets whether to automatically exit after a command execution or not.
+ *
+ * @param bool $boolean Whether to automatically exit after a command execution or not
+ */
+ public function setAutoExit($boolean) {
+ $this->application->setAutoExit($boolean);
+ }
+
+ /**
+ * @param InputInterface $input
+ * @param OutputInterface $output
+ * @return int
+ * @throws \Exception
+ */
+ public function run(InputInterface $input = null, OutputInterface $output = null) {
+ $this->dispatcher->dispatch(ConsoleEvent::EVENT_RUN, new ConsoleEvent(
+ ConsoleEvent::EVENT_RUN,
+ ['occ']
+ ));
+ return $this->application->run($input, $output);
+ }
+
+ private function loadCommandsFromInfoXml($commands) {
+ foreach ($commands as $command) {
+ try {
+ $c = \OC::$server->query($command);
+ } catch (QueryException $e) {
+ if (class_exists($command)) {
+ $c = new $command();
+ } else {
+ throw new \Exception("Console command '$command' is unknown and could not be loaded");
+ }
+ }
+
+ $this->application->add($c);
+ }
+ }
+}
diff --git a/lib/Controller/OCCController.php b/lib/Controller/OCCController.php
index 8dbc800..3a51589 100644
--- a/lib/Controller/OCCController.php
+++ b/lib/Controller/OCCController.php
@@ -2,7 +2,6 @@
namespace OCA\OCCWeb\Controller;
-use OC\Console\Application;
use OCP\IRequest;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Http\DataResponse;
@@ -11,7 +10,7 @@ use OCP\ILogger;
use Symfony\Component\Console\Input\StringInput;
use Symfony\Component\Console\Output\OutputInterface;
-class OccController extends Controller implements IRequest
+class OccController extends Controller
{
private $logger;
private $userId;
@@ -30,10 +29,9 @@ class OccController extends Controller implements IRequest
$this->server = array(
'argv' => ["occ"],
);
- $this->application = new Application(
+ $this->application = new OCCApplication(
\OC::$server->getConfig(),
\OC::$server->getEventDispatcher(),
- $this,
\OC::$server->getLogger(),
\OC::$server->query(\OC\MemoryInfo::class)
);
@@ -95,264 +93,6 @@ class OccController extends Controller implements IRequest
}
return new DataResponse($cmds);
}
-
- /**
- * Lets you access post and get parameters by the index
- * In case of json requests the encoded json body is accessed
- *
- * @param string $key the key which you want to access in the URL Parameter
- * placeholder, $_POST or $_GET array.
- * The priority how they're returned is the following:
- * 1. URL parameters
- * 2. POST parameters
- * 3. GET parameters
- * @param mixed $default If the key is not found, this value will be returned
- * @return mixed the content of the array
- * @since 6.0.0
- */
- public function getParam(string $key, $default = null)
- {
- // TODO: Implement getParam() method.
- }
-
- /**
- * Returns all params that were received, be it from the request
- *
- * (as GET or POST) or through the URL by the route
- *
- * @return array the array with all parameters
- * @since 6.0.0
- */
- public function getParams(): array
- {
- // TODO: Implement getParams() method.
- }
-
- /**
- * Returns the method of the request
- *
- * @return string the method of the request (POST, GET, etc)
- * @since 6.0.0
- */
- public function getMethod(): string
- {
- // TODO: Implement getMethod() method.
- }
-
- /**
- * Shortcut for accessing an uploaded file through the $_FILES array
- *
- * @param string $key the key that will be taken from the $_FILES array
- * @return array the file in the $_FILES element
- * @since 6.0.0
- */
- public function getUploadedFile(string $key)
- {
- // TODO: Implement getUploadedFile() method.
- }
-
- /**
- * Shortcut for getting env variables
- *
- * @param string $key the key that will be taken from the $_ENV array
- * @return array the value in the $_ENV element
- * @since 6.0.0
- */
- public function getEnv(string $key)
- {
- // TODO: Implement getEnv() method.
- }
-
- /**
- * Shortcut for getting cookie variables
- *
- * @param string $key the key that will be taken from the $_COOKIE array
- * @return string|null the value in the $_COOKIE element
- * @since 6.0.0
- */
- public function getCookie(string $key)
- {
- // TODO: Implement getCookie() method.
- }
-
- /**
- * Checks if the CSRF check was correct
- *
- * @return bool true if CSRF check passed
- * @since 6.0.0
- */
- public function passesCSRFCheck(): bool
- {
- // TODO: Implement passesCSRFCheck() method.
- }
-
- /**
- * Checks if the strict cookie has been sent with the request if the request
- * is including any cookies.
- *
- * @return bool
- * @since 9.0.0
- */
- public function passesStrictCookieCheck(): bool
- {
- // TODO: Implement passesStrictCookieCheck() method.
- }
-
- /**
- * Checks if the lax cookie has been sent with the request if the request
- * is including any cookies.
- *
- * @return bool
- * @since 9.0.0
- */
- public function passesLaxCookieCheck(): bool
- {
- // TODO: Implement passesLaxCookieCheck() method.
- }
-
- /**
- * Returns an ID for the request, value is not guaranteed to be unique and is mostly meant for logging
- * If `mod_unique_id` is installed this value will be taken.
- *
- * @return string
- * @since 8.1.0
- */
- public function getId(): string
- {
- // TODO: Implement getId() method.
- }
-
- /**
- * Returns the remote address, if the connection came from a trusted proxy
- * and `forwarded_for_headers` has been configured then the IP address
- * specified in this header will be returned instead.
- * Do always use this instead of $_SERVER['REMOTE_ADDR']
- *
- * @return string IP address
- * @since 8.1.0
- */
- public function getRemoteAddress(): string
- {
- // TODO: Implement getRemoteAddress() method.
- }
-
- /**
- * Returns the server protocol. It respects reverse proxy servers and load
- * balancers.
- *
- * @return string Server protocol (http or https)
- * @since 8.1.0
- */
- public function getServerProtocol(): string
- {
- // TODO: Implement getServerProtocol() method.
- }
-
- /**
- * Returns the used HTTP protocol.
- *
- * @return string HTTP protocol. HTTP/2, HTTP/1.1 or HTTP/1.0.
- * @since 8.2.0
- */
- public function getHttpProtocol(): string
- {
- // TODO: Implement getHttpProtocol() method.
- }
-
- /**
- * Returns the request uri, even if the website uses one or more
- * reverse proxies
- *
- * @return string
- * @since 8.1.0
- */
- public function getRequestUri(): string
- {
- // TODO: Implement getRequestUri() method.
- }
-
- /**
- * Get raw PathInfo from request (not urldecoded)
- *
- * @throws \Exception
- * @return string Path info
- * @since 8.1.0
- */
- public function getRawPathInfo(): string
- {
- // TODO: Implement getRawPathInfo() method.
- }
-
- /**
- * Get PathInfo from request
- *
- * @throws \Exception
- * @return string|false Path info or false when not found
- * @since 8.1.0
- */
- public function getPathInfo()
- {
- // TODO: Implement getPathInfo() method.
- }
-
- /**
- * Returns the script name, even if the website uses one or more
- * reverse proxies
- *
- * @return string the script name
- * @since 8.1.0
- */
- public function getScriptName(): string
- {
- // TODO: Implement getScriptName() method.
- }
-
- /**
- * Checks whether the user agent matches a given regex
- *
- * @param array $agent array of agent names
- * @return bool true if at least one of the given agent matches, false otherwise
- * @since 8.1.0
- */
- public function isUserAgent(array $agent): bool
- {
- // TODO: Implement isUserAgent() method.
- }
-
- /**
- * Returns the unverified server host from the headers without checking
- * whether it is a trusted domain
- *
- * @return string Server host
- * @since 8.1.0
- */
- public function getInsecureServerHost(): string
- {
- // TODO: Implement getInsecureServerHost() method.
- }
-
- /**
- * Returns the server host from the headers, or the first configured
- * trusted domain if the host isn't in the trusted list
- *
- * @return string Server host
- * @since 8.1.0
- */
- public function getServerHost(): string
- {
- // TODO: Implement getServerHost() method.
- }
-
- /**
- * @param string $name
- *
- * @return string
- * @since 6.0.0
- */
- public function getHeader(string $name): string
- {
- // TODO: Implement getHeader() method.
- }
}
function exceptionHandler($exception)