Passed
Push — master ( 7c68e0...2cc411 )
by Joas
11:56
created
cron.php 1 patch
Indentation   +117 added lines, -117 removed lines patch added patch discarded remove patch
@@ -38,124 +38,124 @@
 block discarded – undo
38 38
 
39 39
 try {
40 40
 
41
-	require_once __DIR__ . '/lib/base.php';
42
-
43
-	if (\OCP\Util::needUpgrade()) {
44
-		\OC::$server->getLogger()->debug('Update required, skipping cron', ['app' => 'cron']);
45
-		exit;
46
-	}
47
-	if ((bool) \OC::$server->getSystemConfig()->getValue('maintenance', false)) {
48
-		\OC::$server->getLogger()->debug('We are in maintenance mode, skipping cron', ['app' => 'cron']);
49
-		exit;
50
-	}
51
-
52
-	// load all apps to get all api routes properly setup
53
-	OC_App::loadApps();
54
-
55
-	\OC::$server->getSession()->close();
56
-
57
-	// initialize a dummy memory session
58
-	$session = new \OC\Session\Memory('');
59
-	$cryptoWrapper = \OC::$server->getSessionCryptoWrapper();
60
-	$session = $cryptoWrapper->wrapSession($session);
61
-	\OC::$server->setSession($session);
62
-
63
-	$logger = \OC::$server->getLogger();
64
-	$config = \OC::$server->getConfig();
65
-
66
-	// Don't do anything if Nextcloud has not been installed
67
-	if (!$config->getSystemValue('installed', false)) {
68
-		exit(0);
69
-	}
70
-
71
-	\OC::$server->getTempManager()->cleanOld();
72
-
73
-	// Exit if background jobs are disabled!
74
-	$appMode = $config->getAppValue('core', 'backgroundjobs_mode', 'ajax');
75
-	if ($appMode === 'none') {
76
-		if (OC::$CLI) {
77
-			echo 'Background Jobs are disabled!' . PHP_EOL;
78
-		} else {
79
-			OC_JSON::error(array('data' => array('message' => 'Background jobs disabled!')));
80
-		}
81
-		exit(1);
82
-	}
83
-
84
-	if (OC::$CLI) {
85
-		// set to run indefinitely if needed
86
-		if (strpos(@ini_get('disable_functions'), 'set_time_limit') === false) {
87
-			@set_time_limit(0);
88
-		}
89
-
90
-		// the cron job must be executed with the right user
91
-		if (!function_exists('posix_getuid')) {
92
-			echo "The posix extensions are required - see http://php.net/manual/en/book.posix.php" . PHP_EOL;
93
-			exit(1);
94
-		}
95
-		$user = posix_getpwuid(posix_getuid());
96
-		$configUser = posix_getpwuid(fileowner(OC::$configDir . 'config.php'));
97
-		if ($user['name'] !== $configUser['name']) {
98
-			echo "Console has to be executed with the same user as the web server is operated" . PHP_EOL;
99
-			echo "Current user: " . $user['name'] . PHP_EOL;
100
-			echo "Web server user: " . $configUser['name'] . PHP_EOL;
101
-			exit(1);
102
-		}
103
-
104
-		// We call Nextcloud from the CLI (aka cron)
105
-		if ($appMode !== 'cron') {
106
-			$config->setAppValue('core', 'backgroundjobs_mode', 'cron');
107
-		}
108
-
109
-		// Work
110
-		$jobList = \OC::$server->getJobList();
111
-
112
-		// We only ask for jobs for 14 minutes, because after 15 minutes the next
113
-		// system cron task should spawn.
114
-		$endTime = time() + 14 * 60;
115
-
116
-		$executedJobs = [];
117
-		while ($job = $jobList->getNext()) {
118
-			if (isset($executedJobs[$job->getId()])) {
119
-				$jobList->unlockJob($job);
120
-				break;
121
-			}
122
-
123
-			$job->execute($jobList, $logger);
124
-			// clean up after unclean jobs
125
-			\OC_Util::tearDownFS();
126
-
127
-			$jobList->setLastJob($job);
128
-			$executedJobs[$job->getId()] = true;
129
-			unset($job);
130
-
131
-			if (time() > $endTime) {
132
-				break;
133
-			}
134
-		}
135
-
136
-	} else {
137
-		// We call cron.php from some website
138
-		if ($appMode === 'cron') {
139
-			// Cron is cron :-P
140
-			OC_JSON::error(array('data' => array('message' => 'Backgroundjobs are using system cron!')));
141
-		} else {
142
-			// Work and success :-)
143
-			$jobList = \OC::$server->getJobList();
144
-			$job = $jobList->getNext();
145
-			if ($job != null) {
146
-				$job->execute($jobList, $logger);
147
-				$jobList->setLastJob($job);
148
-			}
149
-			OC_JSON::success();
150
-		}
151
-	}
152
-
153
-	// Log the successful cron execution
154
-	$config->setAppValue('core', 'lastcron', time());
155
-	exit();
41
+    require_once __DIR__ . '/lib/base.php';
42
+
43
+    if (\OCP\Util::needUpgrade()) {
44
+        \OC::$server->getLogger()->debug('Update required, skipping cron', ['app' => 'cron']);
45
+        exit;
46
+    }
47
+    if ((bool) \OC::$server->getSystemConfig()->getValue('maintenance', false)) {
48
+        \OC::$server->getLogger()->debug('We are in maintenance mode, skipping cron', ['app' => 'cron']);
49
+        exit;
50
+    }
51
+
52
+    // load all apps to get all api routes properly setup
53
+    OC_App::loadApps();
54
+
55
+    \OC::$server->getSession()->close();
56
+
57
+    // initialize a dummy memory session
58
+    $session = new \OC\Session\Memory('');
59
+    $cryptoWrapper = \OC::$server->getSessionCryptoWrapper();
60
+    $session = $cryptoWrapper->wrapSession($session);
61
+    \OC::$server->setSession($session);
62
+
63
+    $logger = \OC::$server->getLogger();
64
+    $config = \OC::$server->getConfig();
65
+
66
+    // Don't do anything if Nextcloud has not been installed
67
+    if (!$config->getSystemValue('installed', false)) {
68
+        exit(0);
69
+    }
70
+
71
+    \OC::$server->getTempManager()->cleanOld();
72
+
73
+    // Exit if background jobs are disabled!
74
+    $appMode = $config->getAppValue('core', 'backgroundjobs_mode', 'ajax');
75
+    if ($appMode === 'none') {
76
+        if (OC::$CLI) {
77
+            echo 'Background Jobs are disabled!' . PHP_EOL;
78
+        } else {
79
+            OC_JSON::error(array('data' => array('message' => 'Background jobs disabled!')));
80
+        }
81
+        exit(1);
82
+    }
83
+
84
+    if (OC::$CLI) {
85
+        // set to run indefinitely if needed
86
+        if (strpos(@ini_get('disable_functions'), 'set_time_limit') === false) {
87
+            @set_time_limit(0);
88
+        }
89
+
90
+        // the cron job must be executed with the right user
91
+        if (!function_exists('posix_getuid')) {
92
+            echo "The posix extensions are required - see http://php.net/manual/en/book.posix.php" . PHP_EOL;
93
+            exit(1);
94
+        }
95
+        $user = posix_getpwuid(posix_getuid());
96
+        $configUser = posix_getpwuid(fileowner(OC::$configDir . 'config.php'));
97
+        if ($user['name'] !== $configUser['name']) {
98
+            echo "Console has to be executed with the same user as the web server is operated" . PHP_EOL;
99
+            echo "Current user: " . $user['name'] . PHP_EOL;
100
+            echo "Web server user: " . $configUser['name'] . PHP_EOL;
101
+            exit(1);
102
+        }
103
+
104
+        // We call Nextcloud from the CLI (aka cron)
105
+        if ($appMode !== 'cron') {
106
+            $config->setAppValue('core', 'backgroundjobs_mode', 'cron');
107
+        }
108
+
109
+        // Work
110
+        $jobList = \OC::$server->getJobList();
111
+
112
+        // We only ask for jobs for 14 minutes, because after 15 minutes the next
113
+        // system cron task should spawn.
114
+        $endTime = time() + 14 * 60;
115
+
116
+        $executedJobs = [];
117
+        while ($job = $jobList->getNext()) {
118
+            if (isset($executedJobs[$job->getId()])) {
119
+                $jobList->unlockJob($job);
120
+                break;
121
+            }
122
+
123
+            $job->execute($jobList, $logger);
124
+            // clean up after unclean jobs
125
+            \OC_Util::tearDownFS();
126
+
127
+            $jobList->setLastJob($job);
128
+            $executedJobs[$job->getId()] = true;
129
+            unset($job);
130
+
131
+            if (time() > $endTime) {
132
+                break;
133
+            }
134
+        }
135
+
136
+    } else {
137
+        // We call cron.php from some website
138
+        if ($appMode === 'cron') {
139
+            // Cron is cron :-P
140
+            OC_JSON::error(array('data' => array('message' => 'Backgroundjobs are using system cron!')));
141
+        } else {
142
+            // Work and success :-)
143
+            $jobList = \OC::$server->getJobList();
144
+            $job = $jobList->getNext();
145
+            if ($job != null) {
146
+                $job->execute($jobList, $logger);
147
+                $jobList->setLastJob($job);
148
+            }
149
+            OC_JSON::success();
150
+        }
151
+    }
152
+
153
+    // Log the successful cron execution
154
+    $config->setAppValue('core', 'lastcron', time());
155
+    exit();
156 156
 
157 157
 } catch (Exception $ex) {
158
-	\OC::$server->getLogger()->logException($ex, ['app' => 'cron']);
158
+    \OC::$server->getLogger()->logException($ex, ['app' => 'cron']);
159 159
 } catch (Error $ex) {
160
-	\OC::$server->getLogger()->logException($ex, ['app' => 'cron']);
160
+    \OC::$server->getLogger()->logException($ex, ['app' => 'cron']);
161 161
 }
Please login to merge, or discard this patch.
ocs/v1.php 2 patches
Indentation   +40 added lines, -40 removed lines patch added patch discarded remove patch
@@ -33,13 +33,13 @@  discard block
 block discarded – undo
33 33
 require_once __DIR__ . '/../lib/base.php';
34 34
 
35 35
 if (\OCP\Util::needUpgrade()
36
-	|| \OC::$server->getConfig()->getSystemValueBool('maintenance')) {
37
-	// since the behavior of apps or remotes are unpredictable during
38
-	// an upgrade, return a 503 directly
39
-	http_response_code(503);
40
-	$response = new \OC\OCS\Result(null, 503, 'Service unavailable');
41
-	OC_API::respond($response, OC_API::requestedFormat());
42
-	exit;
36
+    || \OC::$server->getConfig()->getSystemValueBool('maintenance')) {
37
+    // since the behavior of apps or remotes are unpredictable during
38
+    // an upgrade, return a 503 directly
39
+    http_response_code(503);
40
+    $response = new \OC\OCS\Result(null, 503, 'Service unavailable');
41
+    OC_API::respond($response, OC_API::requestedFormat());
42
+    exit;
43 43
 }
44 44
 
45 45
 use Symfony\Component\Routing\Exception\ResourceNotFoundException;
@@ -50,56 +50,56 @@  discard block
 block discarded – undo
50 50
  * We first try the old routes since the appframework triggers more login stuff.
51 51
  */
52 52
 try {
53
-	OC_App::loadApps(['session']);
54
-	OC_App::loadApps(['authentication']);
55
-	// load all apps to get all api routes properly setup
56
-	OC_App::loadApps();
53
+    OC_App::loadApps(['session']);
54
+    OC_App::loadApps(['authentication']);
55
+    // load all apps to get all api routes properly setup
56
+    OC_App::loadApps();
57 57
 
58
-	OC::$server->getRouter()->match('/ocs'.\OC::$server->getRequest()->getRawPathInfo());
58
+    OC::$server->getRouter()->match('/ocs'.\OC::$server->getRequest()->getRawPathInfo());
59 59
 
60
-	sleep(1);
61
-	OC::$server->getLogger()->info('This uses an old OCP\API::register construct. This will be removed in a future version of Nextcloud. Please migrate to the OCSController');
60
+    sleep(1);
61
+    OC::$server->getLogger()->info('This uses an old OCP\API::register construct. This will be removed in a future version of Nextcloud. Please migrate to the OCSController');
62 62
 
63
-	return;
63
+    return;
64 64
 } catch (ResourceNotFoundException $e) {
65
-	// Fall through the not found
65
+    // Fall through the not found
66 66
 } catch (MethodNotAllowedException $e) {
67
-	OC_API::setContentType();
68
-	http_response_code(405);
69
-	exit();
67
+    OC_API::setContentType();
68
+    http_response_code(405);
69
+    exit();
70 70
 } catch (Exception $ex) {
71
-	OC_API::respond($ex->getResult(), OC_API::requestedFormat());
72
-	exit();
71
+    OC_API::respond($ex->getResult(), OC_API::requestedFormat());
72
+    exit();
73 73
 }
74 74
 
75 75
 /*
76 76
  * Try the appframework routes
77 77
  */
78 78
 try {
79
-	if(!\OC::$server->getUserSession()->isLoggedIn()) {
80
-		OC::handleLogin(\OC::$server->getRequest());
81
-	}
82
-	OC::$server->getRouter()->match('/ocsapp'.\OC::$server->getRequest()->getRawPathInfo());
79
+    if(!\OC::$server->getUserSession()->isLoggedIn()) {
80
+        OC::handleLogin(\OC::$server->getRequest());
81
+    }
82
+    OC::$server->getRouter()->match('/ocsapp'.\OC::$server->getRequest()->getRawPathInfo());
83 83
 } catch (ResourceNotFoundException $e) {
84
-	OC_API::setContentType();
84
+    OC_API::setContentType();
85 85
 
86
-	$format = \OC::$server->getRequest()->getParam('format', 'xml');
87
-	$txt='Invalid query, please check the syntax. API specifications are here:'
88
-		.' http://www.freedesktop.org/wiki/Specifications/open-collaboration-services.'."\n";
89
-	OC_API::respond(new \OC\OCS\Result(null, \OCP\API::RESPOND_NOT_FOUND, $txt), $format);
86
+    $format = \OC::$server->getRequest()->getParam('format', 'xml');
87
+    $txt='Invalid query, please check the syntax. API specifications are here:'
88
+        .' http://www.freedesktop.org/wiki/Specifications/open-collaboration-services.'."\n";
89
+    OC_API::respond(new \OC\OCS\Result(null, \OCP\API::RESPOND_NOT_FOUND, $txt), $format);
90 90
 } catch (MethodNotAllowedException $e) {
91
-	OC_API::setContentType();
92
-	http_response_code(405);
91
+    OC_API::setContentType();
92
+    http_response_code(405);
93 93
 } catch (\OC\OCS\Exception $ex) {
94
-	OC_API::respond($ex->getResult(), OC_API::requestedFormat());
94
+    OC_API::respond($ex->getResult(), OC_API::requestedFormat());
95 95
 } catch (\OC\User\LoginException $e) {
96
-	OC_API::respond(new \OC\OCS\Result(null, \OCP\API::RESPOND_UNAUTHORISED, 'Unauthorised'));
96
+    OC_API::respond(new \OC\OCS\Result(null, \OCP\API::RESPOND_UNAUTHORISED, 'Unauthorised'));
97 97
 } catch (\Exception $e) {
98
-	\OC::$server->getLogger()->logException($e);
99
-	OC_API::setContentType();
98
+    \OC::$server->getLogger()->logException($e);
99
+    OC_API::setContentType();
100 100
 
101
-	$format = \OC::$server->getRequest()->getParam('format', 'xml');
102
-	$txt='Invalid query, please check the syntax. API specifications are here:'
103
-		.' http://www.freedesktop.org/wiki/Specifications/open-collaboration-services.'."\n";
104
-	OC_API::respond(new \OC\OCS\Result(null, \OCP\API::RESPOND_NOT_FOUND, $txt), $format);
101
+    $format = \OC::$server->getRequest()->getParam('format', 'xml');
102
+    $txt='Invalid query, please check the syntax. API specifications are here:'
103
+        .' http://www.freedesktop.org/wiki/Specifications/open-collaboration-services.'."\n";
104
+    OC_API::respond(new \OC\OCS\Result(null, \OCP\API::RESPOND_NOT_FOUND, $txt), $format);
105 105
 }
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -29,8 +29,8 @@  discard block
 block discarded – undo
29 29
  *
30 30
  */
31 31
 
32
-require_once __DIR__ . '/../lib/versioncheck.php';
33
-require_once __DIR__ . '/../lib/base.php';
32
+require_once __DIR__.'/../lib/versioncheck.php';
33
+require_once __DIR__.'/../lib/base.php';
34 34
 
35 35
 if (\OCP\Util::needUpgrade()
36 36
 	|| \OC::$server->getConfig()->getSystemValueBool('maintenance')) {
@@ -76,7 +76,7 @@  discard block
 block discarded – undo
76 76
  * Try the appframework routes
77 77
  */
78 78
 try {
79
-	if(!\OC::$server->getUserSession()->isLoggedIn()) {
79
+	if (!\OC::$server->getUserSession()->isLoggedIn()) {
80 80
 		OC::handleLogin(\OC::$server->getRequest());
81 81
 	}
82 82
 	OC::$server->getRouter()->match('/ocsapp'.\OC::$server->getRequest()->getRawPathInfo());
@@ -84,7 +84,7 @@  discard block
 block discarded – undo
84 84
 	OC_API::setContentType();
85 85
 
86 86
 	$format = \OC::$server->getRequest()->getParam('format', 'xml');
87
-	$txt='Invalid query, please check the syntax. API specifications are here:'
87
+	$txt = 'Invalid query, please check the syntax. API specifications are here:'
88 88
 		.' http://www.freedesktop.org/wiki/Specifications/open-collaboration-services.'."\n";
89 89
 	OC_API::respond(new \OC\OCS\Result(null, \OCP\API::RESPOND_NOT_FOUND, $txt), $format);
90 90
 } catch (MethodNotAllowedException $e) {
@@ -99,7 +99,7 @@  discard block
 block discarded – undo
99 99
 	OC_API::setContentType();
100 100
 
101 101
 	$format = \OC::$server->getRequest()->getParam('format', 'xml');
102
-	$txt='Invalid query, please check the syntax. API specifications are here:'
102
+	$txt = 'Invalid query, please check the syntax. API specifications are here:'
103 103
 		.' http://www.freedesktop.org/wiki/Specifications/open-collaboration-services.'."\n";
104 104
 	OC_API::respond(new \OC\OCS\Result(null, \OCP\API::RESPOND_NOT_FOUND, $txt), $format);
105 105
 }
Please login to merge, or discard this patch.
lib/private/Console/Application.php 1 patch
Indentation   +173 added lines, -173 removed lines patch added patch discarded remove patch
@@ -45,187 +45,187 @@
 block discarded – undo
45 45
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
46 46
 
47 47
 class Application {
48
-	/** @var IConfig */
49
-	private $config;
50
-	/** @var EventDispatcherInterface */
51
-	private $dispatcher;
52
-	/** @var IRequest */
53
-	private $request;
54
-	/** @var ILogger  */
55
-	private $logger;
56
-	/** @var MemoryInfo */
57
-	private $memoryInfo;
48
+    /** @var IConfig */
49
+    private $config;
50
+    /** @var EventDispatcherInterface */
51
+    private $dispatcher;
52
+    /** @var IRequest */
53
+    private $request;
54
+    /** @var ILogger  */
55
+    private $logger;
56
+    /** @var MemoryInfo */
57
+    private $memoryInfo;
58 58
 
59
-	/**
60
-	 * @param IConfig $config
61
-	 * @param EventDispatcherInterface $dispatcher
62
-	 * @param IRequest $request
63
-	 * @param ILogger $logger
64
-	 * @param MemoryInfo $memoryInfo
65
-	 */
66
-	public function __construct(IConfig $config,
67
-								EventDispatcherInterface $dispatcher,
68
-								IRequest $request,
69
-								ILogger $logger,
70
-								MemoryInfo $memoryInfo) {
71
-		$defaults = \OC::$server->getThemingDefaults();
72
-		$this->config = $config;
73
-		$this->application = new SymfonyApplication($defaults->getName(), \OC_Util::getVersionString());
74
-		$this->dispatcher = $dispatcher;
75
-		$this->request = $request;
76
-		$this->logger = $logger;
77
-		$this->memoryInfo = $memoryInfo;
78
-	}
59
+    /**
60
+     * @param IConfig $config
61
+     * @param EventDispatcherInterface $dispatcher
62
+     * @param IRequest $request
63
+     * @param ILogger $logger
64
+     * @param MemoryInfo $memoryInfo
65
+     */
66
+    public function __construct(IConfig $config,
67
+                                EventDispatcherInterface $dispatcher,
68
+                                IRequest $request,
69
+                                ILogger $logger,
70
+                                MemoryInfo $memoryInfo) {
71
+        $defaults = \OC::$server->getThemingDefaults();
72
+        $this->config = $config;
73
+        $this->application = new SymfonyApplication($defaults->getName(), \OC_Util::getVersionString());
74
+        $this->dispatcher = $dispatcher;
75
+        $this->request = $request;
76
+        $this->logger = $logger;
77
+        $this->memoryInfo = $memoryInfo;
78
+    }
79 79
 
80
-	/**
81
-	 * @param InputInterface $input
82
-	 * @param ConsoleOutputInterface $output
83
-	 * @throws \Exception
84
-	 */
85
-	public function loadCommands(
86
-		InputInterface $input,
87
-		ConsoleOutputInterface $output
88
-	) {
89
-		// $application is required to be defined in the register_command scripts
90
-		$application = $this->application;
91
-		$inputDefinition = $application->getDefinition();
92
-		$inputDefinition->addOption(
93
-			new InputOption(
94
-				'no-warnings',
95
-				null,
96
-				InputOption::VALUE_NONE,
97
-				'Skip global warnings, show command output only',
98
-				null
99
-			)
100
-		);
101
-		try {
102
-			$input->bind($inputDefinition);
103
-		} catch (\RuntimeException $e) {
104
-			//expected if there are extra options
105
-		}
106
-		if ($input->getOption('no-warnings')) {
107
-			$output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
108
-		}
80
+    /**
81
+     * @param InputInterface $input
82
+     * @param ConsoleOutputInterface $output
83
+     * @throws \Exception
84
+     */
85
+    public function loadCommands(
86
+        InputInterface $input,
87
+        ConsoleOutputInterface $output
88
+    ) {
89
+        // $application is required to be defined in the register_command scripts
90
+        $application = $this->application;
91
+        $inputDefinition = $application->getDefinition();
92
+        $inputDefinition->addOption(
93
+            new InputOption(
94
+                'no-warnings',
95
+                null,
96
+                InputOption::VALUE_NONE,
97
+                'Skip global warnings, show command output only',
98
+                null
99
+            )
100
+        );
101
+        try {
102
+            $input->bind($inputDefinition);
103
+        } catch (\RuntimeException $e) {
104
+            //expected if there are extra options
105
+        }
106
+        if ($input->getOption('no-warnings')) {
107
+            $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
108
+        }
109 109
 
110
-		if ($this->memoryInfo->isMemoryLimitSufficient() === false) {
111
-			$output->getErrorOutput()->writeln(
112
-				'<comment>The current PHP memory limit ' .
113
-				'is below the recommended value of 512MB.</comment>'
114
-			);
115
-		}
110
+        if ($this->memoryInfo->isMemoryLimitSufficient() === false) {
111
+            $output->getErrorOutput()->writeln(
112
+                '<comment>The current PHP memory limit ' .
113
+                'is below the recommended value of 512MB.</comment>'
114
+            );
115
+        }
116 116
 
117
-		try {
118
-			require_once __DIR__ . '/../../../core/register_command.php';
119
-			if ($this->config->getSystemValue('installed', false)) {
120
-				if (\OCP\Util::needUpgrade()) {
121
-					throw new NeedsUpdateException();
122
-				} elseif ($this->config->getSystemValueBool('maintenance')) {
123
-					$this->writeMaintenanceModeInfo($input, $output);
124
-				} else {
125
-					OC_App::loadApps();
126
-					foreach (\OC::$server->getAppManager()->getInstalledApps() as $app) {
127
-						$appPath = \OC_App::getAppPath($app);
128
-						if ($appPath === false) {
129
-							continue;
130
-						}
131
-						// load commands using info.xml
132
-						$info = \OC_App::getAppInfo($app);
133
-						if (isset($info['commands'])) {
134
-							$this->loadCommandsFromInfoXml($info['commands']);
135
-						}
136
-						// load from register_command.php
137
-						\OC_App::registerAutoloading($app, $appPath);
138
-						$file = $appPath . '/appinfo/register_command.php';
139
-						if (file_exists($file)) {
140
-							try {
141
-								require $file;
142
-							} catch (\Exception $e) {
143
-								$this->logger->logException($e);
144
-							}
145
-						}
146
-					}
147
-				}
148
-			} else if ($input->getArgument('command') !== '_completion' && $input->getArgument('command') !== 'maintenance:install') {
149
-				$output->writeln("Nextcloud is not installed - only a limited number of commands are available");
150
-			}
151
-		} catch(NeedsUpdateException $e) {
152
-			if ($input->getArgument('command') !== '_completion') {
153
-				$output->writeln("Nextcloud or one of the apps require upgrade - only a limited number of commands are available");
154
-				$output->writeln("You may use your browser or the occ upgrade command to do the upgrade");
155
-			}
156
-		}
117
+        try {
118
+            require_once __DIR__ . '/../../../core/register_command.php';
119
+            if ($this->config->getSystemValue('installed', false)) {
120
+                if (\OCP\Util::needUpgrade()) {
121
+                    throw new NeedsUpdateException();
122
+                } elseif ($this->config->getSystemValueBool('maintenance')) {
123
+                    $this->writeMaintenanceModeInfo($input, $output);
124
+                } else {
125
+                    OC_App::loadApps();
126
+                    foreach (\OC::$server->getAppManager()->getInstalledApps() as $app) {
127
+                        $appPath = \OC_App::getAppPath($app);
128
+                        if ($appPath === false) {
129
+                            continue;
130
+                        }
131
+                        // load commands using info.xml
132
+                        $info = \OC_App::getAppInfo($app);
133
+                        if (isset($info['commands'])) {
134
+                            $this->loadCommandsFromInfoXml($info['commands']);
135
+                        }
136
+                        // load from register_command.php
137
+                        \OC_App::registerAutoloading($app, $appPath);
138
+                        $file = $appPath . '/appinfo/register_command.php';
139
+                        if (file_exists($file)) {
140
+                            try {
141
+                                require $file;
142
+                            } catch (\Exception $e) {
143
+                                $this->logger->logException($e);
144
+                            }
145
+                        }
146
+                    }
147
+                }
148
+            } else if ($input->getArgument('command') !== '_completion' && $input->getArgument('command') !== 'maintenance:install') {
149
+                $output->writeln("Nextcloud is not installed - only a limited number of commands are available");
150
+            }
151
+        } catch(NeedsUpdateException $e) {
152
+            if ($input->getArgument('command') !== '_completion') {
153
+                $output->writeln("Nextcloud or one of the apps require upgrade - only a limited number of commands are available");
154
+                $output->writeln("You may use your browser or the occ upgrade command to do the upgrade");
155
+            }
156
+        }
157 157
 
158
-		if ($input->getFirstArgument() !== 'check') {
159
-			$errors = \OC_Util::checkServer(\OC::$server->getSystemConfig());
160
-			if (!empty($errors)) {
161
-				foreach ($errors as $error) {
162
-					$output->writeln((string)$error['error']);
163
-					$output->writeln((string)$error['hint']);
164
-					$output->writeln('');
165
-				}
166
-				throw new \Exception("Environment not properly prepared.");
167
-			}
168
-		}
169
-	}
158
+        if ($input->getFirstArgument() !== 'check') {
159
+            $errors = \OC_Util::checkServer(\OC::$server->getSystemConfig());
160
+            if (!empty($errors)) {
161
+                foreach ($errors as $error) {
162
+                    $output->writeln((string)$error['error']);
163
+                    $output->writeln((string)$error['hint']);
164
+                    $output->writeln('');
165
+                }
166
+                throw new \Exception("Environment not properly prepared.");
167
+            }
168
+        }
169
+    }
170 170
 
171
-	/**
172
-	 * Write a maintenance mode info.
173
-	 * The commands "_completion" and "maintenance:mode" are excluded.
174
-	 *
175
-	 * @param InputInterface $input The input implementation for reading inputs.
176
-	 * @param ConsoleOutputInterface $output The output implementation
177
-	 * for writing outputs.
178
-	 * @return void
179
-	 */
180
-	private function writeMaintenanceModeInfo(
181
-		InputInterface $input, ConsoleOutputInterface $output
182
-	) {
183
-		if ($input->getArgument('command') !== '_completion'
184
-			&& $input->getArgument('command') !== 'maintenance:mode') {
185
-			$errOutput = $output->getErrorOutput();
186
-			$errOutput->writeln(
187
-				'<comment>Nextcloud is in maintenance mode - ' .
188
-				'no apps have been loaded</comment>' . PHP_EOL
189
-			);
190
-		}
191
-	}
171
+    /**
172
+     * Write a maintenance mode info.
173
+     * The commands "_completion" and "maintenance:mode" are excluded.
174
+     *
175
+     * @param InputInterface $input The input implementation for reading inputs.
176
+     * @param ConsoleOutputInterface $output The output implementation
177
+     * for writing outputs.
178
+     * @return void
179
+     */
180
+    private function writeMaintenanceModeInfo(
181
+        InputInterface $input, ConsoleOutputInterface $output
182
+    ) {
183
+        if ($input->getArgument('command') !== '_completion'
184
+            && $input->getArgument('command') !== 'maintenance:mode') {
185
+            $errOutput = $output->getErrorOutput();
186
+            $errOutput->writeln(
187
+                '<comment>Nextcloud is in maintenance mode - ' .
188
+                'no apps have been loaded</comment>' . PHP_EOL
189
+            );
190
+        }
191
+    }
192 192
 
193
-	/**
194
-	 * Sets whether to automatically exit after a command execution or not.
195
-	 *
196
-	 * @param bool $boolean Whether to automatically exit after a command execution or not
197
-	 */
198
-	public function setAutoExit($boolean) {
199
-		$this->application->setAutoExit($boolean);
200
-	}
193
+    /**
194
+     * Sets whether to automatically exit after a command execution or not.
195
+     *
196
+     * @param bool $boolean Whether to automatically exit after a command execution or not
197
+     */
198
+    public function setAutoExit($boolean) {
199
+        $this->application->setAutoExit($boolean);
200
+    }
201 201
 
202
-	/**
203
-	 * @param InputInterface $input
204
-	 * @param OutputInterface $output
205
-	 * @return int
206
-	 * @throws \Exception
207
-	 */
208
-	public function run(InputInterface $input = null, OutputInterface $output = null) {
209
-		$this->dispatcher->dispatch(ConsoleEvent::EVENT_RUN, new ConsoleEvent(
210
-			ConsoleEvent::EVENT_RUN,
211
-			$this->request->server['argv']
212
-		));
213
-		return $this->application->run($input, $output);
214
-	}
202
+    /**
203
+     * @param InputInterface $input
204
+     * @param OutputInterface $output
205
+     * @return int
206
+     * @throws \Exception
207
+     */
208
+    public function run(InputInterface $input = null, OutputInterface $output = null) {
209
+        $this->dispatcher->dispatch(ConsoleEvent::EVENT_RUN, new ConsoleEvent(
210
+            ConsoleEvent::EVENT_RUN,
211
+            $this->request->server['argv']
212
+        ));
213
+        return $this->application->run($input, $output);
214
+    }
215 215
 
216
-	private function loadCommandsFromInfoXml($commands) {
217
-		foreach ($commands as $command) {
218
-			try {
219
-				$c = \OC::$server->query($command);
220
-			} catch (QueryException $e) {
221
-				if (class_exists($command)) {
222
-					$c = new $command();
223
-				} else {
224
-					throw new \Exception("Console command '$command' is unknown and could not be loaded");
225
-				}
226
-			}
216
+    private function loadCommandsFromInfoXml($commands) {
217
+        foreach ($commands as $command) {
218
+            try {
219
+                $c = \OC::$server->query($command);
220
+            } catch (QueryException $e) {
221
+                if (class_exists($command)) {
222
+                    $c = new $command();
223
+                } else {
224
+                    throw new \Exception("Console command '$command' is unknown and could not be loaded");
225
+                }
226
+            }
227 227
 
228
-			$this->application->add($c);
229
-		}
230
-	}
228
+            $this->application->add($c);
229
+        }
230
+    }
231 231
 }
Please login to merge, or discard this patch.
lib/private/legacy/app.php 1 patch
Indentation   +1038 added lines, -1038 removed lines patch added patch discarded remove patch
@@ -64,1042 +64,1042 @@
 block discarded – undo
64 64
  * upgrading and removing apps.
65 65
  */
66 66
 class OC_App {
67
-	static private $adminForms = [];
68
-	static private $personalForms = [];
69
-	static private $appTypes = [];
70
-	static private $loadedApps = [];
71
-	static private $altLogin = [];
72
-	static private $alreadyRegistered = [];
73
-	static public $autoDisabledApps = [];
74
-	const officialApp = 200;
75
-
76
-	/**
77
-	 * clean the appId
78
-	 *
79
-	 * @param string $app AppId that needs to be cleaned
80
-	 * @return string
81
-	 */
82
-	public static function cleanAppId(string $app): string {
83
-		return str_replace(array('\0', '/', '\\', '..'), '', $app);
84
-	}
85
-
86
-	/**
87
-	 * Check if an app is loaded
88
-	 *
89
-	 * @param string $app
90
-	 * @return bool
91
-	 */
92
-	public static function isAppLoaded(string $app): bool {
93
-		return in_array($app, self::$loadedApps, true);
94
-	}
95
-
96
-	/**
97
-	 * loads all apps
98
-	 *
99
-	 * @param string[] $types
100
-	 * @return bool
101
-	 *
102
-	 * This function walks through the ownCloud directory and loads all apps
103
-	 * it can find. A directory contains an app if the file /appinfo/info.xml
104
-	 * exists.
105
-	 *
106
-	 * if $types is set to non-empty array, only apps of those types will be loaded
107
-	 */
108
-	public static function loadApps(array $types = []): bool {
109
-		if ((bool) \OC::$server->getSystemConfig()->getValue('maintenance', false)) {
110
-			return false;
111
-		}
112
-		// Load the enabled apps here
113
-		$apps = self::getEnabledApps();
114
-
115
-		// Add each apps' folder as allowed class path
116
-		foreach($apps as $app) {
117
-			$path = self::getAppPath($app);
118
-			if($path !== false) {
119
-				self::registerAutoloading($app, $path);
120
-			}
121
-		}
122
-
123
-		// prevent app.php from printing output
124
-		ob_start();
125
-		foreach ($apps as $app) {
126
-			if (($types === [] or self::isType($app, $types)) && !in_array($app, self::$loadedApps)) {
127
-				self::loadApp($app);
128
-			}
129
-		}
130
-		ob_end_clean();
131
-
132
-		return true;
133
-	}
134
-
135
-	/**
136
-	 * load a single app
137
-	 *
138
-	 * @param string $app
139
-	 * @throws Exception
140
-	 */
141
-	public static function loadApp(string $app) {
142
-		self::$loadedApps[] = $app;
143
-		$appPath = self::getAppPath($app);
144
-		if($appPath === false) {
145
-			return;
146
-		}
147
-
148
-		// in case someone calls loadApp() directly
149
-		self::registerAutoloading($app, $appPath);
150
-
151
-		if (is_file($appPath . '/appinfo/app.php')) {
152
-			\OC::$server->getEventLogger()->start('load_app_' . $app, 'Load app: ' . $app);
153
-			try {
154
-				self::requireAppFile($app);
155
-			} catch (Throwable $ex) {
156
-				\OC::$server->getLogger()->logException($ex);
157
-				if (!\OC::$server->getAppManager()->isShipped($app)) {
158
-					// Only disable apps which are not shipped
159
-					\OC::$server->getAppManager()->disableApp($app);
160
-					self::$autoDisabledApps[] = $app;
161
-				}
162
-			}
163
-			\OC::$server->getEventLogger()->end('load_app_' . $app);
164
-		}
165
-
166
-		$info = self::getAppInfo($app);
167
-		if (!empty($info['activity']['filters'])) {
168
-			foreach ($info['activity']['filters'] as $filter) {
169
-				\OC::$server->getActivityManager()->registerFilter($filter);
170
-			}
171
-		}
172
-		if (!empty($info['activity']['settings'])) {
173
-			foreach ($info['activity']['settings'] as $setting) {
174
-				\OC::$server->getActivityManager()->registerSetting($setting);
175
-			}
176
-		}
177
-		if (!empty($info['activity']['providers'])) {
178
-			foreach ($info['activity']['providers'] as $provider) {
179
-				\OC::$server->getActivityManager()->registerProvider($provider);
180
-			}
181
-		}
182
-
183
-		if (!empty($info['settings']['admin'])) {
184
-			foreach ($info['settings']['admin'] as $setting) {
185
-				\OC::$server->getSettingsManager()->registerSetting('admin', $setting);
186
-			}
187
-		}
188
-		if (!empty($info['settings']['admin-section'])) {
189
-			foreach ($info['settings']['admin-section'] as $section) {
190
-				\OC::$server->getSettingsManager()->registerSection('admin', $section);
191
-			}
192
-		}
193
-		if (!empty($info['settings']['personal'])) {
194
-			foreach ($info['settings']['personal'] as $setting) {
195
-				\OC::$server->getSettingsManager()->registerSetting('personal', $setting);
196
-			}
197
-		}
198
-		if (!empty($info['settings']['personal-section'])) {
199
-			foreach ($info['settings']['personal-section'] as $section) {
200
-				\OC::$server->getSettingsManager()->registerSection('personal', $section);
201
-			}
202
-		}
203
-
204
-		if (!empty($info['collaboration']['plugins'])) {
205
-			// deal with one or many plugin entries
206
-			$plugins = isset($info['collaboration']['plugins']['plugin']['@value']) ?
207
-				[$info['collaboration']['plugins']['plugin']] : $info['collaboration']['plugins']['plugin'];
208
-			foreach ($plugins as $plugin) {
209
-				if($plugin['@attributes']['type'] === 'collaborator-search') {
210
-					$pluginInfo = [
211
-						'shareType' => $plugin['@attributes']['share-type'],
212
-						'class' => $plugin['@value'],
213
-					];
214
-					\OC::$server->getCollaboratorSearch()->registerPlugin($pluginInfo);
215
-				} else if ($plugin['@attributes']['type'] === 'autocomplete-sort') {
216
-					\OC::$server->getAutoCompleteManager()->registerSorter($plugin['@value']);
217
-				}
218
-			}
219
-		}
220
-	}
221
-
222
-	/**
223
-	 * @internal
224
-	 * @param string $app
225
-	 * @param string $path
226
-	 */
227
-	public static function registerAutoloading(string $app, string $path) {
228
-		$key = $app . '-' . $path;
229
-		if(isset(self::$alreadyRegistered[$key])) {
230
-			return;
231
-		}
232
-
233
-		self::$alreadyRegistered[$key] = true;
234
-
235
-		// Register on PSR-4 composer autoloader
236
-		$appNamespace = \OC\AppFramework\App::buildAppNamespace($app);
237
-		\OC::$server->registerNamespace($app, $appNamespace);
238
-
239
-		if (file_exists($path . '/composer/autoload.php')) {
240
-			require_once $path . '/composer/autoload.php';
241
-		} else {
242
-			\OC::$composerAutoloader->addPsr4($appNamespace . '\\', $path . '/lib/', true);
243
-			// Register on legacy autoloader
244
-			\OC::$loader->addValidRoot($path);
245
-		}
246
-
247
-		// Register Test namespace only when testing
248
-		if (defined('PHPUNIT_RUN') || defined('CLI_TEST_RUN')) {
249
-			\OC::$composerAutoloader->addPsr4($appNamespace . '\\Tests\\', $path . '/tests/', true);
250
-		}
251
-	}
252
-
253
-	/**
254
-	 * Load app.php from the given app
255
-	 *
256
-	 * @param string $app app name
257
-	 * @throws Error
258
-	 */
259
-	private static function requireAppFile(string $app) {
260
-		// encapsulated here to avoid variable scope conflicts
261
-		require_once $app . '/appinfo/app.php';
262
-	}
263
-
264
-	/**
265
-	 * check if an app is of a specific type
266
-	 *
267
-	 * @param string $app
268
-	 * @param array $types
269
-	 * @return bool
270
-	 */
271
-	public static function isType(string $app, array $types): bool {
272
-		$appTypes = self::getAppTypes($app);
273
-		foreach ($types as $type) {
274
-			if (array_search($type, $appTypes) !== false) {
275
-				return true;
276
-			}
277
-		}
278
-		return false;
279
-	}
280
-
281
-	/**
282
-	 * get the types of an app
283
-	 *
284
-	 * @param string $app
285
-	 * @return array
286
-	 */
287
-	private static function getAppTypes(string $app): array {
288
-		//load the cache
289
-		if (count(self::$appTypes) == 0) {
290
-			self::$appTypes = \OC::$server->getAppConfig()->getValues(false, 'types');
291
-		}
292
-
293
-		if (isset(self::$appTypes[$app])) {
294
-			return explode(',', self::$appTypes[$app]);
295
-		}
296
-
297
-		return [];
298
-	}
299
-
300
-	/**
301
-	 * read app types from info.xml and cache them in the database
302
-	 */
303
-	public static function setAppTypes(string $app) {
304
-		$appManager = \OC::$server->getAppManager();
305
-		$appData = $appManager->getAppInfo($app);
306
-		if(!is_array($appData)) {
307
-			return;
308
-		}
309
-
310
-		if (isset($appData['types'])) {
311
-			$appTypes = implode(',', $appData['types']);
312
-		} else {
313
-			$appTypes = '';
314
-			$appData['types'] = [];
315
-		}
316
-
317
-		$config = \OC::$server->getConfig();
318
-		$config->setAppValue($app, 'types', $appTypes);
319
-
320
-		if ($appManager->hasProtectedAppType($appData['types'])) {
321
-			$enabled = $config->getAppValue($app, 'enabled', 'yes');
322
-			if ($enabled !== 'yes' && $enabled !== 'no') {
323
-				$config->setAppValue($app, 'enabled', 'yes');
324
-			}
325
-		}
326
-	}
327
-
328
-	/**
329
-	 * Returns apps enabled for the current user.
330
-	 *
331
-	 * @param bool $forceRefresh whether to refresh the cache
332
-	 * @param bool $all whether to return apps for all users, not only the
333
-	 * currently logged in one
334
-	 * @return string[]
335
-	 */
336
-	public static function getEnabledApps(bool $forceRefresh = false, bool $all = false): array {
337
-		if (!\OC::$server->getSystemConfig()->getValue('installed', false)) {
338
-			return [];
339
-		}
340
-		// in incognito mode or when logged out, $user will be false,
341
-		// which is also the case during an upgrade
342
-		$appManager = \OC::$server->getAppManager();
343
-		if ($all) {
344
-			$user = null;
345
-		} else {
346
-			$user = \OC::$server->getUserSession()->getUser();
347
-		}
348
-
349
-		if (is_null($user)) {
350
-			$apps = $appManager->getInstalledApps();
351
-		} else {
352
-			$apps = $appManager->getEnabledAppsForUser($user);
353
-		}
354
-		$apps = array_filter($apps, function ($app) {
355
-			return $app !== 'files';//we add this manually
356
-		});
357
-		sort($apps);
358
-		array_unshift($apps, 'files');
359
-		return $apps;
360
-	}
361
-
362
-	/**
363
-	 * checks whether or not an app is enabled
364
-	 *
365
-	 * @param string $app app
366
-	 * @return bool
367
-	 * @deprecated 13.0.0 use \OC::$server->getAppManager()->isEnabledForUser($appId)
368
-	 *
369
-	 * This function checks whether or not an app is enabled.
370
-	 */
371
-	public static function isEnabled(string $app): bool {
372
-		return \OC::$server->getAppManager()->isEnabledForUser($app);
373
-	}
374
-
375
-	/**
376
-	 * enables an app
377
-	 *
378
-	 * @param string $appId
379
-	 * @param array $groups (optional) when set, only these groups will have access to the app
380
-	 * @throws \Exception
381
-	 * @return void
382
-	 *
383
-	 * This function set an app as enabled in appconfig.
384
-	 */
385
-	public function enable(string $appId,
386
-						   array $groups = []) {
387
-
388
-		// Check if app is already downloaded
389
-		/** @var Installer $installer */
390
-		$installer = \OC::$server->query(Installer::class);
391
-		$isDownloaded = $installer->isDownloaded($appId);
392
-
393
-		if(!$isDownloaded) {
394
-			$installer->downloadApp($appId);
395
-		}
396
-
397
-		$installer->installApp($appId);
398
-
399
-		$appManager = \OC::$server->getAppManager();
400
-		if ($groups !== []) {
401
-			$groupManager = \OC::$server->getGroupManager();
402
-			$groupsList = [];
403
-			foreach ($groups as $group) {
404
-				$groupItem = $groupManager->get($group);
405
-				if ($groupItem instanceof \OCP\IGroup) {
406
-					$groupsList[] = $groupManager->get($group);
407
-				}
408
-			}
409
-			$appManager->enableAppForGroups($appId, $groupsList);
410
-		} else {
411
-			$appManager->enableApp($appId);
412
-		}
413
-	}
414
-
415
-	/**
416
-	 * Get the path where to install apps
417
-	 *
418
-	 * @return string|false
419
-	 */
420
-	public static function getInstallPath() {
421
-		if (\OC::$server->getSystemConfig()->getValue('appstoreenabled', true) == false) {
422
-			return false;
423
-		}
424
-
425
-		foreach (OC::$APPSROOTS as $dir) {
426
-			if (isset($dir['writable']) && $dir['writable'] === true) {
427
-				return $dir['path'];
428
-			}
429
-		}
430
-
431
-		\OCP\Util::writeLog('core', 'No application directories are marked as writable.', ILogger::ERROR);
432
-		return null;
433
-	}
434
-
435
-
436
-	/**
437
-	 * search for an app in all app-directories
438
-	 *
439
-	 * @param string $appId
440
-	 * @return false|string
441
-	 */
442
-	public static function findAppInDirectories(string $appId) {
443
-		$sanitizedAppId = self::cleanAppId($appId);
444
-		if($sanitizedAppId !== $appId) {
445
-			return false;
446
-		}
447
-		static $app_dir = [];
448
-
449
-		if (isset($app_dir[$appId])) {
450
-			return $app_dir[$appId];
451
-		}
452
-
453
-		$possibleApps = [];
454
-		foreach (OC::$APPSROOTS as $dir) {
455
-			if (file_exists($dir['path'] . '/' . $appId)) {
456
-				$possibleApps[] = $dir;
457
-			}
458
-		}
459
-
460
-		if (empty($possibleApps)) {
461
-			return false;
462
-		} elseif (count($possibleApps) === 1) {
463
-			$dir = array_shift($possibleApps);
464
-			$app_dir[$appId] = $dir;
465
-			return $dir;
466
-		} else {
467
-			$versionToLoad = [];
468
-			foreach ($possibleApps as $possibleApp) {
469
-				$version = self::getAppVersionByPath($possibleApp['path'] . '/' . $appId);
470
-				if (empty($versionToLoad) || version_compare($version, $versionToLoad['version'], '>')) {
471
-					$versionToLoad = array(
472
-						'dir' => $possibleApp,
473
-						'version' => $version,
474
-					);
475
-				}
476
-			}
477
-			$app_dir[$appId] = $versionToLoad['dir'];
478
-			return $versionToLoad['dir'];
479
-			//TODO - write test
480
-		}
481
-	}
482
-
483
-	/**
484
-	 * Get the directory for the given app.
485
-	 * If the app is defined in multiple directories, the first one is taken. (false if not found)
486
-	 *
487
-	 * @param string $appId
488
-	 * @return string|false
489
-	 */
490
-	public static function getAppPath(string $appId) {
491
-		if ($appId === null || trim($appId) === '') {
492
-			return false;
493
-		}
494
-
495
-		if (($dir = self::findAppInDirectories($appId)) != false) {
496
-			return $dir['path'] . '/' . $appId;
497
-		}
498
-		return false;
499
-	}
500
-
501
-	/**
502
-	 * Get the path for the given app on the access
503
-	 * If the app is defined in multiple directories, the first one is taken. (false if not found)
504
-	 *
505
-	 * @param string $appId
506
-	 * @return string|false
507
-	 */
508
-	public static function getAppWebPath(string $appId) {
509
-		if (($dir = self::findAppInDirectories($appId)) != false) {
510
-			return OC::$WEBROOT . $dir['url'] . '/' . $appId;
511
-		}
512
-		return false;
513
-	}
514
-
515
-	/**
516
-	 * get the last version of the app from appinfo/info.xml
517
-	 *
518
-	 * @param string $appId
519
-	 * @param bool $useCache
520
-	 * @return string
521
-	 * @deprecated 14.0.0 use \OC::$server->getAppManager()->getAppVersion()
522
-	 */
523
-	public static function getAppVersion(string $appId, bool $useCache = true): string {
524
-		return \OC::$server->getAppManager()->getAppVersion($appId, $useCache);
525
-	}
526
-
527
-	/**
528
-	 * get app's version based on it's path
529
-	 *
530
-	 * @param string $path
531
-	 * @return string
532
-	 */
533
-	public static function getAppVersionByPath(string $path): string {
534
-		$infoFile = $path . '/appinfo/info.xml';
535
-		$appData = \OC::$server->getAppManager()->getAppInfo($infoFile, true);
536
-		return isset($appData['version']) ? $appData['version'] : '';
537
-	}
538
-
539
-
540
-	/**
541
-	 * Read all app metadata from the info.xml file
542
-	 *
543
-	 * @param string $appId id of the app or the path of the info.xml file
544
-	 * @param bool $path
545
-	 * @param string $lang
546
-	 * @return array|null
547
-	 * @note all data is read from info.xml, not just pre-defined fields
548
-	 * @deprecated 14.0.0 use \OC::$server->getAppManager()->getAppInfo()
549
-	 */
550
-	public static function getAppInfo(string $appId, bool $path = false, string $lang = null) {
551
-		return \OC::$server->getAppManager()->getAppInfo($appId, $path, $lang);
552
-	}
553
-
554
-	/**
555
-	 * Returns the navigation
556
-	 *
557
-	 * @return array
558
-	 * @deprecated 14.0.0 use \OC::$server->getNavigationManager()->getAll()
559
-	 *
560
-	 * This function returns an array containing all entries added. The
561
-	 * entries are sorted by the key 'order' ascending. Additional to the keys
562
-	 * given for each app the following keys exist:
563
-	 *   - active: boolean, signals if the user is on this navigation entry
564
-	 */
565
-	public static function getNavigation(): array {
566
-		return OC::$server->getNavigationManager()->getAll();
567
-	}
568
-
569
-	/**
570
-	 * Returns the Settings Navigation
571
-	 *
572
-	 * @return string[]
573
-	 * @deprecated 14.0.0 use \OC::$server->getNavigationManager()->getAll('settings')
574
-	 *
575
-	 * This function returns an array containing all settings pages added. The
576
-	 * entries are sorted by the key 'order' ascending.
577
-	 */
578
-	public static function getSettingsNavigation(): array {
579
-		return OC::$server->getNavigationManager()->getAll('settings');
580
-	}
581
-
582
-	/**
583
-	 * get the id of loaded app
584
-	 *
585
-	 * @return string
586
-	 */
587
-	public static function getCurrentApp(): string {
588
-		$request = \OC::$server->getRequest();
589
-		$script = substr($request->getScriptName(), strlen(OC::$WEBROOT) + 1);
590
-		$topFolder = substr($script, 0, strpos($script, '/') ?: 0);
591
-		if (empty($topFolder)) {
592
-			$path_info = $request->getPathInfo();
593
-			if ($path_info) {
594
-				$topFolder = substr($path_info, 1, strpos($path_info, '/', 1) - 1);
595
-			}
596
-		}
597
-		if ($topFolder == 'apps') {
598
-			$length = strlen($topFolder);
599
-			return substr($script, $length + 1, strpos($script, '/', $length + 1) - $length - 1) ?: '';
600
-		} else {
601
-			return $topFolder;
602
-		}
603
-	}
604
-
605
-	/**
606
-	 * @param string $type
607
-	 * @return array
608
-	 */
609
-	public static function getForms(string $type): array {
610
-		$forms = [];
611
-		switch ($type) {
612
-			case 'admin':
613
-				$source = self::$adminForms;
614
-				break;
615
-			case 'personal':
616
-				$source = self::$personalForms;
617
-				break;
618
-			default:
619
-				return [];
620
-		}
621
-		foreach ($source as $form) {
622
-			$forms[] = include $form;
623
-		}
624
-		return $forms;
625
-	}
626
-
627
-	/**
628
-	 * register an admin form to be shown
629
-	 *
630
-	 * @param string $app
631
-	 * @param string $page
632
-	 */
633
-	public static function registerAdmin(string $app, string $page) {
634
-		self::$adminForms[] = $app . '/' . $page . '.php';
635
-	}
636
-
637
-	/**
638
-	 * register a personal form to be shown
639
-	 * @param string $app
640
-	 * @param string $page
641
-	 */
642
-	public static function registerPersonal(string $app, string $page) {
643
-		self::$personalForms[] = $app . '/' . $page . '.php';
644
-	}
645
-
646
-	/**
647
-	 * @param array $entry
648
-	 */
649
-	public static function registerLogIn(array $entry) {
650
-		self::$altLogin[] = $entry;
651
-	}
652
-
653
-	/**
654
-	 * @return array
655
-	 */
656
-	public static function getAlternativeLogIns(): array {
657
-		return self::$altLogin;
658
-	}
659
-
660
-	/**
661
-	 * get a list of all apps in the apps folder
662
-	 *
663
-	 * @return array an array of app names (string IDs)
664
-	 * @todo: change the name of this method to getInstalledApps, which is more accurate
665
-	 */
666
-	public static function getAllApps(): array {
667
-
668
-		$apps = [];
669
-
670
-		foreach (OC::$APPSROOTS as $apps_dir) {
671
-			if (!is_readable($apps_dir['path'])) {
672
-				\OCP\Util::writeLog('core', 'unable to read app folder : ' . $apps_dir['path'], ILogger::WARN);
673
-				continue;
674
-			}
675
-			$dh = opendir($apps_dir['path']);
676
-
677
-			if (is_resource($dh)) {
678
-				while (($file = readdir($dh)) !== false) {
679
-
680
-					if ($file[0] != '.' and is_dir($apps_dir['path'] . '/' . $file) and is_file($apps_dir['path'] . '/' . $file . '/appinfo/info.xml')) {
681
-
682
-						$apps[] = $file;
683
-					}
684
-				}
685
-			}
686
-		}
687
-
688
-		$apps = array_unique($apps);
689
-
690
-		return $apps;
691
-	}
692
-
693
-	/**
694
-	 * List all apps, this is used in apps.php
695
-	 *
696
-	 * @return array
697
-	 */
698
-	public function listAllApps(): array {
699
-		$installedApps = OC_App::getAllApps();
700
-
701
-		$appManager = \OC::$server->getAppManager();
702
-		//we don't want to show configuration for these
703
-		$blacklist = $appManager->getAlwaysEnabledApps();
704
-		$appList = [];
705
-		$langCode = \OC::$server->getL10N('core')->getLanguageCode();
706
-		$urlGenerator = \OC::$server->getURLGenerator();
707
-
708
-		foreach ($installedApps as $app) {
709
-			if (array_search($app, $blacklist) === false) {
710
-
711
-				$info = OC_App::getAppInfo($app, false, $langCode);
712
-				if (!is_array($info)) {
713
-					\OCP\Util::writeLog('core', 'Could not read app info file for app "' . $app . '"', ILogger::ERROR);
714
-					continue;
715
-				}
716
-
717
-				if (!isset($info['name'])) {
718
-					\OCP\Util::writeLog('core', 'App id "' . $app . '" has no name in appinfo', ILogger::ERROR);
719
-					continue;
720
-				}
721
-
722
-				$enabled = \OC::$server->getConfig()->getAppValue($app, 'enabled', 'no');
723
-				$info['groups'] = null;
724
-				if ($enabled === 'yes') {
725
-					$active = true;
726
-				} else if ($enabled === 'no') {
727
-					$active = false;
728
-				} else {
729
-					$active = true;
730
-					$info['groups'] = $enabled;
731
-				}
732
-
733
-				$info['active'] = $active;
734
-
735
-				if ($appManager->isShipped($app)) {
736
-					$info['internal'] = true;
737
-					$info['level'] = self::officialApp;
738
-					$info['removable'] = false;
739
-				} else {
740
-					$info['internal'] = false;
741
-					$info['removable'] = true;
742
-				}
743
-
744
-				$appPath = self::getAppPath($app);
745
-				if($appPath !== false) {
746
-					$appIcon = $appPath . '/img/' . $app . '.svg';
747
-					if (file_exists($appIcon)) {
748
-						$info['preview'] = $urlGenerator->imagePath($app, $app . '.svg');
749
-						$info['previewAsIcon'] = true;
750
-					} else {
751
-						$appIcon = $appPath . '/img/app.svg';
752
-						if (file_exists($appIcon)) {
753
-							$info['preview'] = $urlGenerator->imagePath($app, 'app.svg');
754
-							$info['previewAsIcon'] = true;
755
-						}
756
-					}
757
-				}
758
-				// fix documentation
759
-				if (isset($info['documentation']) && is_array($info['documentation'])) {
760
-					foreach ($info['documentation'] as $key => $url) {
761
-						// If it is not an absolute URL we assume it is a key
762
-						// i.e. admin-ldap will get converted to go.php?to=admin-ldap
763
-						if (stripos($url, 'https://') !== 0 && stripos($url, 'http://') !== 0) {
764
-							$url = $urlGenerator->linkToDocs($url);
765
-						}
766
-
767
-						$info['documentation'][$key] = $url;
768
-					}
769
-				}
770
-
771
-				$info['version'] = OC_App::getAppVersion($app);
772
-				$appList[] = $info;
773
-			}
774
-		}
775
-
776
-		return $appList;
777
-	}
778
-
779
-	public static function shouldUpgrade(string $app): bool {
780
-		$versions = self::getAppVersions();
781
-		$currentVersion = OC_App::getAppVersion($app);
782
-		if ($currentVersion && isset($versions[$app])) {
783
-			$installedVersion = $versions[$app];
784
-			if (!version_compare($currentVersion, $installedVersion, '=')) {
785
-				return true;
786
-			}
787
-		}
788
-		return false;
789
-	}
790
-
791
-	/**
792
-	 * Adjust the number of version parts of $version1 to match
793
-	 * the number of version parts of $version2.
794
-	 *
795
-	 * @param string $version1 version to adjust
796
-	 * @param string $version2 version to take the number of parts from
797
-	 * @return string shortened $version1
798
-	 */
799
-	private static function adjustVersionParts(string $version1, string $version2): string {
800
-		$version1 = explode('.', $version1);
801
-		$version2 = explode('.', $version2);
802
-		// reduce $version1 to match the number of parts in $version2
803
-		while (count($version1) > count($version2)) {
804
-			array_pop($version1);
805
-		}
806
-		// if $version1 does not have enough parts, add some
807
-		while (count($version1) < count($version2)) {
808
-			$version1[] = '0';
809
-		}
810
-		return implode('.', $version1);
811
-	}
812
-
813
-	/**
814
-	 * Check whether the current ownCloud version matches the given
815
-	 * application's version requirements.
816
-	 *
817
-	 * The comparison is made based on the number of parts that the
818
-	 * app info version has. For example for ownCloud 6.0.3 if the
819
-	 * app info version is expecting version 6.0, the comparison is
820
-	 * made on the first two parts of the ownCloud version.
821
-	 * This means that it's possible to specify "requiremin" => 6
822
-	 * and "requiremax" => 6 and it will still match ownCloud 6.0.3.
823
-	 *
824
-	 * @param string $ocVersion ownCloud version to check against
825
-	 * @param array $appInfo app info (from xml)
826
-	 *
827
-	 * @return boolean true if compatible, otherwise false
828
-	 */
829
-	public static function isAppCompatible(string $ocVersion, array $appInfo): bool {
830
-		$requireMin = '';
831
-		$requireMax = '';
832
-		if (isset($appInfo['dependencies']['nextcloud']['@attributes']['min-version'])) {
833
-			$requireMin = $appInfo['dependencies']['nextcloud']['@attributes']['min-version'];
834
-		} elseif (isset($appInfo['dependencies']['owncloud']['@attributes']['min-version'])) {
835
-			$requireMin = $appInfo['dependencies']['owncloud']['@attributes']['min-version'];
836
-		} else if (isset($appInfo['requiremin'])) {
837
-			$requireMin = $appInfo['requiremin'];
838
-		} else if (isset($appInfo['require'])) {
839
-			$requireMin = $appInfo['require'];
840
-		}
841
-
842
-		if (isset($appInfo['dependencies']['nextcloud']['@attributes']['max-version'])) {
843
-			$requireMax = $appInfo['dependencies']['nextcloud']['@attributes']['max-version'];
844
-		} elseif (isset($appInfo['dependencies']['owncloud']['@attributes']['max-version'])) {
845
-			$requireMax = $appInfo['dependencies']['owncloud']['@attributes']['max-version'];
846
-		} else if (isset($appInfo['requiremax'])) {
847
-			$requireMax = $appInfo['requiremax'];
848
-		}
849
-
850
-		if (!empty($requireMin)
851
-			&& version_compare(self::adjustVersionParts($ocVersion, $requireMin), $requireMin, '<')
852
-		) {
853
-
854
-			return false;
855
-		}
856
-
857
-		if (!empty($requireMax)
858
-			&& version_compare(self::adjustVersionParts($ocVersion, $requireMax), $requireMax, '>')
859
-		) {
860
-			return false;
861
-		}
862
-
863
-		return true;
864
-	}
865
-
866
-	/**
867
-	 * get the installed version of all apps
868
-	 */
869
-	public static function getAppVersions() {
870
-		static $versions;
871
-
872
-		if(!$versions) {
873
-			$appConfig = \OC::$server->getAppConfig();
874
-			$versions = $appConfig->getValues(false, 'installed_version');
875
-		}
876
-		return $versions;
877
-	}
878
-
879
-	/**
880
-	 * update the database for the app and call the update script
881
-	 *
882
-	 * @param string $appId
883
-	 * @return bool
884
-	 */
885
-	public static function updateApp(string $appId): bool {
886
-		$appPath = self::getAppPath($appId);
887
-		if($appPath === false) {
888
-			return false;
889
-		}
890
-		self::registerAutoloading($appId, $appPath);
891
-
892
-		\OC::$server->getAppManager()->clearAppsCache();
893
-		$appData = self::getAppInfo($appId);
894
-		self::executeRepairSteps($appId, $appData['repair-steps']['pre-migration']);
895
-
896
-		if (file_exists($appPath . '/appinfo/database.xml')) {
897
-			OC_DB::updateDbFromStructure($appPath . '/appinfo/database.xml');
898
-		} else {
899
-			$ms = new MigrationService($appId, \OC::$server->getDatabaseConnection());
900
-			$ms->migrate();
901
-		}
902
-
903
-		self::executeRepairSteps($appId, $appData['repair-steps']['post-migration']);
904
-		self::setupLiveMigrations($appId, $appData['repair-steps']['live-migration']);
905
-		// update appversion in app manager
906
-		\OC::$server->getAppManager()->clearAppsCache();
907
-		\OC::$server->getAppManager()->getAppVersion($appId, false);
908
-
909
-		// run upgrade code
910
-		if (file_exists($appPath . '/appinfo/update.php')) {
911
-			self::loadApp($appId);
912
-			include $appPath . '/appinfo/update.php';
913
-		}
914
-		self::setupBackgroundJobs($appData['background-jobs']);
915
-
916
-		//set remote/public handlers
917
-		if (array_key_exists('ocsid', $appData)) {
918
-			\OC::$server->getConfig()->setAppValue($appId, 'ocsid', $appData['ocsid']);
919
-		} elseif(\OC::$server->getConfig()->getAppValue($appId, 'ocsid', null) !== null) {
920
-			\OC::$server->getConfig()->deleteAppValue($appId, 'ocsid');
921
-		}
922
-		foreach ($appData['remote'] as $name => $path) {
923
-			\OC::$server->getConfig()->setAppValue('core', 'remote_' . $name, $appId . '/' . $path);
924
-		}
925
-		foreach ($appData['public'] as $name => $path) {
926
-			\OC::$server->getConfig()->setAppValue('core', 'public_' . $name, $appId . '/' . $path);
927
-		}
928
-
929
-		self::setAppTypes($appId);
930
-
931
-		$version = \OC_App::getAppVersion($appId);
932
-		\OC::$server->getConfig()->setAppValue($appId, 'installed_version', $version);
933
-
934
-		\OC::$server->getEventDispatcher()->dispatch(ManagerEvent::EVENT_APP_UPDATE, new ManagerEvent(
935
-			ManagerEvent::EVENT_APP_UPDATE, $appId
936
-		));
937
-
938
-		return true;
939
-	}
940
-
941
-	/**
942
-	 * @param string $appId
943
-	 * @param string[] $steps
944
-	 * @throws \OC\NeedsUpdateException
945
-	 */
946
-	public static function executeRepairSteps(string $appId, array $steps) {
947
-		if (empty($steps)) {
948
-			return;
949
-		}
950
-		// load the app
951
-		self::loadApp($appId);
952
-
953
-		$dispatcher = OC::$server->getEventDispatcher();
954
-
955
-		// load the steps
956
-		$r = new Repair([], $dispatcher);
957
-		foreach ($steps as $step) {
958
-			try {
959
-				$r->addStep($step);
960
-			} catch (Exception $ex) {
961
-				$r->emit('\OC\Repair', 'error', [$ex->getMessage()]);
962
-				\OC::$server->getLogger()->logException($ex);
963
-			}
964
-		}
965
-		// run the steps
966
-		$r->run();
967
-	}
968
-
969
-	public static function setupBackgroundJobs(array $jobs) {
970
-		$queue = \OC::$server->getJobList();
971
-		foreach ($jobs as $job) {
972
-			$queue->add($job);
973
-		}
974
-	}
975
-
976
-	/**
977
-	 * @param string $appId
978
-	 * @param string[] $steps
979
-	 */
980
-	private static function setupLiveMigrations(string $appId, array $steps) {
981
-		$queue = \OC::$server->getJobList();
982
-		foreach ($steps as $step) {
983
-			$queue->add('OC\Migration\BackgroundRepair', [
984
-				'app' => $appId,
985
-				'step' => $step]);
986
-		}
987
-	}
988
-
989
-	/**
990
-	 * @param string $appId
991
-	 * @return \OC\Files\View|false
992
-	 */
993
-	public static function getStorage(string $appId) {
994
-		if (\OC::$server->getAppManager()->isEnabledForUser($appId)) { //sanity check
995
-			if (\OC::$server->getUserSession()->isLoggedIn()) {
996
-				$view = new \OC\Files\View('/' . OC_User::getUser());
997
-				if (!$view->file_exists($appId)) {
998
-					$view->mkdir($appId);
999
-				}
1000
-				return new \OC\Files\View('/' . OC_User::getUser() . '/' . $appId);
1001
-			} else {
1002
-				\OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ', user not logged in', ILogger::ERROR);
1003
-				return false;
1004
-			}
1005
-		} else {
1006
-			\OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ' not enabled', ILogger::ERROR);
1007
-			return false;
1008
-		}
1009
-	}
1010
-
1011
-	protected static function findBestL10NOption(array $options, string $lang): string {
1012
-		// only a single option
1013
-		if (isset($options['@value'])) {
1014
-			return $options['@value'];
1015
-		}
1016
-
1017
-		$fallback = $similarLangFallback = $englishFallback = false;
1018
-
1019
-		$lang = strtolower($lang);
1020
-		$similarLang = $lang;
1021
-		if (strpos($similarLang, '_')) {
1022
-			// For "de_DE" we want to find "de" and the other way around
1023
-			$similarLang = substr($lang, 0, strpos($lang, '_'));
1024
-		}
1025
-
1026
-		foreach ($options as $option) {
1027
-			if (is_array($option)) {
1028
-				if ($fallback === false) {
1029
-					$fallback = $option['@value'];
1030
-				}
1031
-
1032
-				if (!isset($option['@attributes']['lang'])) {
1033
-					continue;
1034
-				}
1035
-
1036
-				$attributeLang = strtolower($option['@attributes']['lang']);
1037
-				if ($attributeLang === $lang) {
1038
-					return $option['@value'];
1039
-				}
1040
-
1041
-				if ($attributeLang === $similarLang) {
1042
-					$similarLangFallback = $option['@value'];
1043
-				} else if (strpos($attributeLang, $similarLang . '_') === 0) {
1044
-					if ($similarLangFallback === false) {
1045
-						$similarLangFallback =  $option['@value'];
1046
-					}
1047
-				}
1048
-			} else {
1049
-				$englishFallback = $option;
1050
-			}
1051
-		}
1052
-
1053
-		if ($similarLangFallback !== false) {
1054
-			return $similarLangFallback;
1055
-		} else if ($englishFallback !== false) {
1056
-			return $englishFallback;
1057
-		}
1058
-		return (string) $fallback;
1059
-	}
1060
-
1061
-	/**
1062
-	 * parses the app data array and enhanced the 'description' value
1063
-	 *
1064
-	 * @param array $data the app data
1065
-	 * @param string $lang
1066
-	 * @return array improved app data
1067
-	 */
1068
-	public static function parseAppInfo(array $data, $lang = null): array {
1069
-
1070
-		if ($lang && isset($data['name']) && is_array($data['name'])) {
1071
-			$data['name'] = self::findBestL10NOption($data['name'], $lang);
1072
-		}
1073
-		if ($lang && isset($data['summary']) && is_array($data['summary'])) {
1074
-			$data['summary'] = self::findBestL10NOption($data['summary'], $lang);
1075
-		}
1076
-		if ($lang && isset($data['description']) && is_array($data['description'])) {
1077
-			$data['description'] = trim(self::findBestL10NOption($data['description'], $lang));
1078
-		} else if (isset($data['description']) && is_string($data['description'])) {
1079
-			$data['description'] = trim($data['description']);
1080
-		} else  {
1081
-			$data['description'] = '';
1082
-		}
1083
-
1084
-		return $data;
1085
-	}
1086
-
1087
-	/**
1088
-	 * @param \OCP\IConfig $config
1089
-	 * @param \OCP\IL10N $l
1090
-	 * @param array $info
1091
-	 * @throws \Exception
1092
-	 */
1093
-	public static function checkAppDependencies(\OCP\IConfig $config, \OCP\IL10N $l, array $info) {
1094
-		$dependencyAnalyzer = new DependencyAnalyzer(new Platform($config), $l);
1095
-		$missing = $dependencyAnalyzer->analyze($info);
1096
-		if (!empty($missing)) {
1097
-			$missingMsg = implode(PHP_EOL, $missing);
1098
-			throw new \Exception(
1099
-				$l->t('App "%1$s" cannot be installed because the following dependencies are not fulfilled: %2$s',
1100
-					[$info['name'], $missingMsg]
1101
-				)
1102
-			);
1103
-		}
1104
-	}
67
+    static private $adminForms = [];
68
+    static private $personalForms = [];
69
+    static private $appTypes = [];
70
+    static private $loadedApps = [];
71
+    static private $altLogin = [];
72
+    static private $alreadyRegistered = [];
73
+    static public $autoDisabledApps = [];
74
+    const officialApp = 200;
75
+
76
+    /**
77
+     * clean the appId
78
+     *
79
+     * @param string $app AppId that needs to be cleaned
80
+     * @return string
81
+     */
82
+    public static function cleanAppId(string $app): string {
83
+        return str_replace(array('\0', '/', '\\', '..'), '', $app);
84
+    }
85
+
86
+    /**
87
+     * Check if an app is loaded
88
+     *
89
+     * @param string $app
90
+     * @return bool
91
+     */
92
+    public static function isAppLoaded(string $app): bool {
93
+        return in_array($app, self::$loadedApps, true);
94
+    }
95
+
96
+    /**
97
+     * loads all apps
98
+     *
99
+     * @param string[] $types
100
+     * @return bool
101
+     *
102
+     * This function walks through the ownCloud directory and loads all apps
103
+     * it can find. A directory contains an app if the file /appinfo/info.xml
104
+     * exists.
105
+     *
106
+     * if $types is set to non-empty array, only apps of those types will be loaded
107
+     */
108
+    public static function loadApps(array $types = []): bool {
109
+        if ((bool) \OC::$server->getSystemConfig()->getValue('maintenance', false)) {
110
+            return false;
111
+        }
112
+        // Load the enabled apps here
113
+        $apps = self::getEnabledApps();
114
+
115
+        // Add each apps' folder as allowed class path
116
+        foreach($apps as $app) {
117
+            $path = self::getAppPath($app);
118
+            if($path !== false) {
119
+                self::registerAutoloading($app, $path);
120
+            }
121
+        }
122
+
123
+        // prevent app.php from printing output
124
+        ob_start();
125
+        foreach ($apps as $app) {
126
+            if (($types === [] or self::isType($app, $types)) && !in_array($app, self::$loadedApps)) {
127
+                self::loadApp($app);
128
+            }
129
+        }
130
+        ob_end_clean();
131
+
132
+        return true;
133
+    }
134
+
135
+    /**
136
+     * load a single app
137
+     *
138
+     * @param string $app
139
+     * @throws Exception
140
+     */
141
+    public static function loadApp(string $app) {
142
+        self::$loadedApps[] = $app;
143
+        $appPath = self::getAppPath($app);
144
+        if($appPath === false) {
145
+            return;
146
+        }
147
+
148
+        // in case someone calls loadApp() directly
149
+        self::registerAutoloading($app, $appPath);
150
+
151
+        if (is_file($appPath . '/appinfo/app.php')) {
152
+            \OC::$server->getEventLogger()->start('load_app_' . $app, 'Load app: ' . $app);
153
+            try {
154
+                self::requireAppFile($app);
155
+            } catch (Throwable $ex) {
156
+                \OC::$server->getLogger()->logException($ex);
157
+                if (!\OC::$server->getAppManager()->isShipped($app)) {
158
+                    // Only disable apps which are not shipped
159
+                    \OC::$server->getAppManager()->disableApp($app);
160
+                    self::$autoDisabledApps[] = $app;
161
+                }
162
+            }
163
+            \OC::$server->getEventLogger()->end('load_app_' . $app);
164
+        }
165
+
166
+        $info = self::getAppInfo($app);
167
+        if (!empty($info['activity']['filters'])) {
168
+            foreach ($info['activity']['filters'] as $filter) {
169
+                \OC::$server->getActivityManager()->registerFilter($filter);
170
+            }
171
+        }
172
+        if (!empty($info['activity']['settings'])) {
173
+            foreach ($info['activity']['settings'] as $setting) {
174
+                \OC::$server->getActivityManager()->registerSetting($setting);
175
+            }
176
+        }
177
+        if (!empty($info['activity']['providers'])) {
178
+            foreach ($info['activity']['providers'] as $provider) {
179
+                \OC::$server->getActivityManager()->registerProvider($provider);
180
+            }
181
+        }
182
+
183
+        if (!empty($info['settings']['admin'])) {
184
+            foreach ($info['settings']['admin'] as $setting) {
185
+                \OC::$server->getSettingsManager()->registerSetting('admin', $setting);
186
+            }
187
+        }
188
+        if (!empty($info['settings']['admin-section'])) {
189
+            foreach ($info['settings']['admin-section'] as $section) {
190
+                \OC::$server->getSettingsManager()->registerSection('admin', $section);
191
+            }
192
+        }
193
+        if (!empty($info['settings']['personal'])) {
194
+            foreach ($info['settings']['personal'] as $setting) {
195
+                \OC::$server->getSettingsManager()->registerSetting('personal', $setting);
196
+            }
197
+        }
198
+        if (!empty($info['settings']['personal-section'])) {
199
+            foreach ($info['settings']['personal-section'] as $section) {
200
+                \OC::$server->getSettingsManager()->registerSection('personal', $section);
201
+            }
202
+        }
203
+
204
+        if (!empty($info['collaboration']['plugins'])) {
205
+            // deal with one or many plugin entries
206
+            $plugins = isset($info['collaboration']['plugins']['plugin']['@value']) ?
207
+                [$info['collaboration']['plugins']['plugin']] : $info['collaboration']['plugins']['plugin'];
208
+            foreach ($plugins as $plugin) {
209
+                if($plugin['@attributes']['type'] === 'collaborator-search') {
210
+                    $pluginInfo = [
211
+                        'shareType' => $plugin['@attributes']['share-type'],
212
+                        'class' => $plugin['@value'],
213
+                    ];
214
+                    \OC::$server->getCollaboratorSearch()->registerPlugin($pluginInfo);
215
+                } else if ($plugin['@attributes']['type'] === 'autocomplete-sort') {
216
+                    \OC::$server->getAutoCompleteManager()->registerSorter($plugin['@value']);
217
+                }
218
+            }
219
+        }
220
+    }
221
+
222
+    /**
223
+     * @internal
224
+     * @param string $app
225
+     * @param string $path
226
+     */
227
+    public static function registerAutoloading(string $app, string $path) {
228
+        $key = $app . '-' . $path;
229
+        if(isset(self::$alreadyRegistered[$key])) {
230
+            return;
231
+        }
232
+
233
+        self::$alreadyRegistered[$key] = true;
234
+
235
+        // Register on PSR-4 composer autoloader
236
+        $appNamespace = \OC\AppFramework\App::buildAppNamespace($app);
237
+        \OC::$server->registerNamespace($app, $appNamespace);
238
+
239
+        if (file_exists($path . '/composer/autoload.php')) {
240
+            require_once $path . '/composer/autoload.php';
241
+        } else {
242
+            \OC::$composerAutoloader->addPsr4($appNamespace . '\\', $path . '/lib/', true);
243
+            // Register on legacy autoloader
244
+            \OC::$loader->addValidRoot($path);
245
+        }
246
+
247
+        // Register Test namespace only when testing
248
+        if (defined('PHPUNIT_RUN') || defined('CLI_TEST_RUN')) {
249
+            \OC::$composerAutoloader->addPsr4($appNamespace . '\\Tests\\', $path . '/tests/', true);
250
+        }
251
+    }
252
+
253
+    /**
254
+     * Load app.php from the given app
255
+     *
256
+     * @param string $app app name
257
+     * @throws Error
258
+     */
259
+    private static function requireAppFile(string $app) {
260
+        // encapsulated here to avoid variable scope conflicts
261
+        require_once $app . '/appinfo/app.php';
262
+    }
263
+
264
+    /**
265
+     * check if an app is of a specific type
266
+     *
267
+     * @param string $app
268
+     * @param array $types
269
+     * @return bool
270
+     */
271
+    public static function isType(string $app, array $types): bool {
272
+        $appTypes = self::getAppTypes($app);
273
+        foreach ($types as $type) {
274
+            if (array_search($type, $appTypes) !== false) {
275
+                return true;
276
+            }
277
+        }
278
+        return false;
279
+    }
280
+
281
+    /**
282
+     * get the types of an app
283
+     *
284
+     * @param string $app
285
+     * @return array
286
+     */
287
+    private static function getAppTypes(string $app): array {
288
+        //load the cache
289
+        if (count(self::$appTypes) == 0) {
290
+            self::$appTypes = \OC::$server->getAppConfig()->getValues(false, 'types');
291
+        }
292
+
293
+        if (isset(self::$appTypes[$app])) {
294
+            return explode(',', self::$appTypes[$app]);
295
+        }
296
+
297
+        return [];
298
+    }
299
+
300
+    /**
301
+     * read app types from info.xml and cache them in the database
302
+     */
303
+    public static function setAppTypes(string $app) {
304
+        $appManager = \OC::$server->getAppManager();
305
+        $appData = $appManager->getAppInfo($app);
306
+        if(!is_array($appData)) {
307
+            return;
308
+        }
309
+
310
+        if (isset($appData['types'])) {
311
+            $appTypes = implode(',', $appData['types']);
312
+        } else {
313
+            $appTypes = '';
314
+            $appData['types'] = [];
315
+        }
316
+
317
+        $config = \OC::$server->getConfig();
318
+        $config->setAppValue($app, 'types', $appTypes);
319
+
320
+        if ($appManager->hasProtectedAppType($appData['types'])) {
321
+            $enabled = $config->getAppValue($app, 'enabled', 'yes');
322
+            if ($enabled !== 'yes' && $enabled !== 'no') {
323
+                $config->setAppValue($app, 'enabled', 'yes');
324
+            }
325
+        }
326
+    }
327
+
328
+    /**
329
+     * Returns apps enabled for the current user.
330
+     *
331
+     * @param bool $forceRefresh whether to refresh the cache
332
+     * @param bool $all whether to return apps for all users, not only the
333
+     * currently logged in one
334
+     * @return string[]
335
+     */
336
+    public static function getEnabledApps(bool $forceRefresh = false, bool $all = false): array {
337
+        if (!\OC::$server->getSystemConfig()->getValue('installed', false)) {
338
+            return [];
339
+        }
340
+        // in incognito mode or when logged out, $user will be false,
341
+        // which is also the case during an upgrade
342
+        $appManager = \OC::$server->getAppManager();
343
+        if ($all) {
344
+            $user = null;
345
+        } else {
346
+            $user = \OC::$server->getUserSession()->getUser();
347
+        }
348
+
349
+        if (is_null($user)) {
350
+            $apps = $appManager->getInstalledApps();
351
+        } else {
352
+            $apps = $appManager->getEnabledAppsForUser($user);
353
+        }
354
+        $apps = array_filter($apps, function ($app) {
355
+            return $app !== 'files';//we add this manually
356
+        });
357
+        sort($apps);
358
+        array_unshift($apps, 'files');
359
+        return $apps;
360
+    }
361
+
362
+    /**
363
+     * checks whether or not an app is enabled
364
+     *
365
+     * @param string $app app
366
+     * @return bool
367
+     * @deprecated 13.0.0 use \OC::$server->getAppManager()->isEnabledForUser($appId)
368
+     *
369
+     * This function checks whether or not an app is enabled.
370
+     */
371
+    public static function isEnabled(string $app): bool {
372
+        return \OC::$server->getAppManager()->isEnabledForUser($app);
373
+    }
374
+
375
+    /**
376
+     * enables an app
377
+     *
378
+     * @param string $appId
379
+     * @param array $groups (optional) when set, only these groups will have access to the app
380
+     * @throws \Exception
381
+     * @return void
382
+     *
383
+     * This function set an app as enabled in appconfig.
384
+     */
385
+    public function enable(string $appId,
386
+                            array $groups = []) {
387
+
388
+        // Check if app is already downloaded
389
+        /** @var Installer $installer */
390
+        $installer = \OC::$server->query(Installer::class);
391
+        $isDownloaded = $installer->isDownloaded($appId);
392
+
393
+        if(!$isDownloaded) {
394
+            $installer->downloadApp($appId);
395
+        }
396
+
397
+        $installer->installApp($appId);
398
+
399
+        $appManager = \OC::$server->getAppManager();
400
+        if ($groups !== []) {
401
+            $groupManager = \OC::$server->getGroupManager();
402
+            $groupsList = [];
403
+            foreach ($groups as $group) {
404
+                $groupItem = $groupManager->get($group);
405
+                if ($groupItem instanceof \OCP\IGroup) {
406
+                    $groupsList[] = $groupManager->get($group);
407
+                }
408
+            }
409
+            $appManager->enableAppForGroups($appId, $groupsList);
410
+        } else {
411
+            $appManager->enableApp($appId);
412
+        }
413
+    }
414
+
415
+    /**
416
+     * Get the path where to install apps
417
+     *
418
+     * @return string|false
419
+     */
420
+    public static function getInstallPath() {
421
+        if (\OC::$server->getSystemConfig()->getValue('appstoreenabled', true) == false) {
422
+            return false;
423
+        }
424
+
425
+        foreach (OC::$APPSROOTS as $dir) {
426
+            if (isset($dir['writable']) && $dir['writable'] === true) {
427
+                return $dir['path'];
428
+            }
429
+        }
430
+
431
+        \OCP\Util::writeLog('core', 'No application directories are marked as writable.', ILogger::ERROR);
432
+        return null;
433
+    }
434
+
435
+
436
+    /**
437
+     * search for an app in all app-directories
438
+     *
439
+     * @param string $appId
440
+     * @return false|string
441
+     */
442
+    public static function findAppInDirectories(string $appId) {
443
+        $sanitizedAppId = self::cleanAppId($appId);
444
+        if($sanitizedAppId !== $appId) {
445
+            return false;
446
+        }
447
+        static $app_dir = [];
448
+
449
+        if (isset($app_dir[$appId])) {
450
+            return $app_dir[$appId];
451
+        }
452
+
453
+        $possibleApps = [];
454
+        foreach (OC::$APPSROOTS as $dir) {
455
+            if (file_exists($dir['path'] . '/' . $appId)) {
456
+                $possibleApps[] = $dir;
457
+            }
458
+        }
459
+
460
+        if (empty($possibleApps)) {
461
+            return false;
462
+        } elseif (count($possibleApps) === 1) {
463
+            $dir = array_shift($possibleApps);
464
+            $app_dir[$appId] = $dir;
465
+            return $dir;
466
+        } else {
467
+            $versionToLoad = [];
468
+            foreach ($possibleApps as $possibleApp) {
469
+                $version = self::getAppVersionByPath($possibleApp['path'] . '/' . $appId);
470
+                if (empty($versionToLoad) || version_compare($version, $versionToLoad['version'], '>')) {
471
+                    $versionToLoad = array(
472
+                        'dir' => $possibleApp,
473
+                        'version' => $version,
474
+                    );
475
+                }
476
+            }
477
+            $app_dir[$appId] = $versionToLoad['dir'];
478
+            return $versionToLoad['dir'];
479
+            //TODO - write test
480
+        }
481
+    }
482
+
483
+    /**
484
+     * Get the directory for the given app.
485
+     * If the app is defined in multiple directories, the first one is taken. (false if not found)
486
+     *
487
+     * @param string $appId
488
+     * @return string|false
489
+     */
490
+    public static function getAppPath(string $appId) {
491
+        if ($appId === null || trim($appId) === '') {
492
+            return false;
493
+        }
494
+
495
+        if (($dir = self::findAppInDirectories($appId)) != false) {
496
+            return $dir['path'] . '/' . $appId;
497
+        }
498
+        return false;
499
+    }
500
+
501
+    /**
502
+     * Get the path for the given app on the access
503
+     * If the app is defined in multiple directories, the first one is taken. (false if not found)
504
+     *
505
+     * @param string $appId
506
+     * @return string|false
507
+     */
508
+    public static function getAppWebPath(string $appId) {
509
+        if (($dir = self::findAppInDirectories($appId)) != false) {
510
+            return OC::$WEBROOT . $dir['url'] . '/' . $appId;
511
+        }
512
+        return false;
513
+    }
514
+
515
+    /**
516
+     * get the last version of the app from appinfo/info.xml
517
+     *
518
+     * @param string $appId
519
+     * @param bool $useCache
520
+     * @return string
521
+     * @deprecated 14.0.0 use \OC::$server->getAppManager()->getAppVersion()
522
+     */
523
+    public static function getAppVersion(string $appId, bool $useCache = true): string {
524
+        return \OC::$server->getAppManager()->getAppVersion($appId, $useCache);
525
+    }
526
+
527
+    /**
528
+     * get app's version based on it's path
529
+     *
530
+     * @param string $path
531
+     * @return string
532
+     */
533
+    public static function getAppVersionByPath(string $path): string {
534
+        $infoFile = $path . '/appinfo/info.xml';
535
+        $appData = \OC::$server->getAppManager()->getAppInfo($infoFile, true);
536
+        return isset($appData['version']) ? $appData['version'] : '';
537
+    }
538
+
539
+
540
+    /**
541
+     * Read all app metadata from the info.xml file
542
+     *
543
+     * @param string $appId id of the app or the path of the info.xml file
544
+     * @param bool $path
545
+     * @param string $lang
546
+     * @return array|null
547
+     * @note all data is read from info.xml, not just pre-defined fields
548
+     * @deprecated 14.0.0 use \OC::$server->getAppManager()->getAppInfo()
549
+     */
550
+    public static function getAppInfo(string $appId, bool $path = false, string $lang = null) {
551
+        return \OC::$server->getAppManager()->getAppInfo($appId, $path, $lang);
552
+    }
553
+
554
+    /**
555
+     * Returns the navigation
556
+     *
557
+     * @return array
558
+     * @deprecated 14.0.0 use \OC::$server->getNavigationManager()->getAll()
559
+     *
560
+     * This function returns an array containing all entries added. The
561
+     * entries are sorted by the key 'order' ascending. Additional to the keys
562
+     * given for each app the following keys exist:
563
+     *   - active: boolean, signals if the user is on this navigation entry
564
+     */
565
+    public static function getNavigation(): array {
566
+        return OC::$server->getNavigationManager()->getAll();
567
+    }
568
+
569
+    /**
570
+     * Returns the Settings Navigation
571
+     *
572
+     * @return string[]
573
+     * @deprecated 14.0.0 use \OC::$server->getNavigationManager()->getAll('settings')
574
+     *
575
+     * This function returns an array containing all settings pages added. The
576
+     * entries are sorted by the key 'order' ascending.
577
+     */
578
+    public static function getSettingsNavigation(): array {
579
+        return OC::$server->getNavigationManager()->getAll('settings');
580
+    }
581
+
582
+    /**
583
+     * get the id of loaded app
584
+     *
585
+     * @return string
586
+     */
587
+    public static function getCurrentApp(): string {
588
+        $request = \OC::$server->getRequest();
589
+        $script = substr($request->getScriptName(), strlen(OC::$WEBROOT) + 1);
590
+        $topFolder = substr($script, 0, strpos($script, '/') ?: 0);
591
+        if (empty($topFolder)) {
592
+            $path_info = $request->getPathInfo();
593
+            if ($path_info) {
594
+                $topFolder = substr($path_info, 1, strpos($path_info, '/', 1) - 1);
595
+            }
596
+        }
597
+        if ($topFolder == 'apps') {
598
+            $length = strlen($topFolder);
599
+            return substr($script, $length + 1, strpos($script, '/', $length + 1) - $length - 1) ?: '';
600
+        } else {
601
+            return $topFolder;
602
+        }
603
+    }
604
+
605
+    /**
606
+     * @param string $type
607
+     * @return array
608
+     */
609
+    public static function getForms(string $type): array {
610
+        $forms = [];
611
+        switch ($type) {
612
+            case 'admin':
613
+                $source = self::$adminForms;
614
+                break;
615
+            case 'personal':
616
+                $source = self::$personalForms;
617
+                break;
618
+            default:
619
+                return [];
620
+        }
621
+        foreach ($source as $form) {
622
+            $forms[] = include $form;
623
+        }
624
+        return $forms;
625
+    }
626
+
627
+    /**
628
+     * register an admin form to be shown
629
+     *
630
+     * @param string $app
631
+     * @param string $page
632
+     */
633
+    public static function registerAdmin(string $app, string $page) {
634
+        self::$adminForms[] = $app . '/' . $page . '.php';
635
+    }
636
+
637
+    /**
638
+     * register a personal form to be shown
639
+     * @param string $app
640
+     * @param string $page
641
+     */
642
+    public static function registerPersonal(string $app, string $page) {
643
+        self::$personalForms[] = $app . '/' . $page . '.php';
644
+    }
645
+
646
+    /**
647
+     * @param array $entry
648
+     */
649
+    public static function registerLogIn(array $entry) {
650
+        self::$altLogin[] = $entry;
651
+    }
652
+
653
+    /**
654
+     * @return array
655
+     */
656
+    public static function getAlternativeLogIns(): array {
657
+        return self::$altLogin;
658
+    }
659
+
660
+    /**
661
+     * get a list of all apps in the apps folder
662
+     *
663
+     * @return array an array of app names (string IDs)
664
+     * @todo: change the name of this method to getInstalledApps, which is more accurate
665
+     */
666
+    public static function getAllApps(): array {
667
+
668
+        $apps = [];
669
+
670
+        foreach (OC::$APPSROOTS as $apps_dir) {
671
+            if (!is_readable($apps_dir['path'])) {
672
+                \OCP\Util::writeLog('core', 'unable to read app folder : ' . $apps_dir['path'], ILogger::WARN);
673
+                continue;
674
+            }
675
+            $dh = opendir($apps_dir['path']);
676
+
677
+            if (is_resource($dh)) {
678
+                while (($file = readdir($dh)) !== false) {
679
+
680
+                    if ($file[0] != '.' and is_dir($apps_dir['path'] . '/' . $file) and is_file($apps_dir['path'] . '/' . $file . '/appinfo/info.xml')) {
681
+
682
+                        $apps[] = $file;
683
+                    }
684
+                }
685
+            }
686
+        }
687
+
688
+        $apps = array_unique($apps);
689
+
690
+        return $apps;
691
+    }
692
+
693
+    /**
694
+     * List all apps, this is used in apps.php
695
+     *
696
+     * @return array
697
+     */
698
+    public function listAllApps(): array {
699
+        $installedApps = OC_App::getAllApps();
700
+
701
+        $appManager = \OC::$server->getAppManager();
702
+        //we don't want to show configuration for these
703
+        $blacklist = $appManager->getAlwaysEnabledApps();
704
+        $appList = [];
705
+        $langCode = \OC::$server->getL10N('core')->getLanguageCode();
706
+        $urlGenerator = \OC::$server->getURLGenerator();
707
+
708
+        foreach ($installedApps as $app) {
709
+            if (array_search($app, $blacklist) === false) {
710
+
711
+                $info = OC_App::getAppInfo($app, false, $langCode);
712
+                if (!is_array($info)) {
713
+                    \OCP\Util::writeLog('core', 'Could not read app info file for app "' . $app . '"', ILogger::ERROR);
714
+                    continue;
715
+                }
716
+
717
+                if (!isset($info['name'])) {
718
+                    \OCP\Util::writeLog('core', 'App id "' . $app . '" has no name in appinfo', ILogger::ERROR);
719
+                    continue;
720
+                }
721
+
722
+                $enabled = \OC::$server->getConfig()->getAppValue($app, 'enabled', 'no');
723
+                $info['groups'] = null;
724
+                if ($enabled === 'yes') {
725
+                    $active = true;
726
+                } else if ($enabled === 'no') {
727
+                    $active = false;
728
+                } else {
729
+                    $active = true;
730
+                    $info['groups'] = $enabled;
731
+                }
732
+
733
+                $info['active'] = $active;
734
+
735
+                if ($appManager->isShipped($app)) {
736
+                    $info['internal'] = true;
737
+                    $info['level'] = self::officialApp;
738
+                    $info['removable'] = false;
739
+                } else {
740
+                    $info['internal'] = false;
741
+                    $info['removable'] = true;
742
+                }
743
+
744
+                $appPath = self::getAppPath($app);
745
+                if($appPath !== false) {
746
+                    $appIcon = $appPath . '/img/' . $app . '.svg';
747
+                    if (file_exists($appIcon)) {
748
+                        $info['preview'] = $urlGenerator->imagePath($app, $app . '.svg');
749
+                        $info['previewAsIcon'] = true;
750
+                    } else {
751
+                        $appIcon = $appPath . '/img/app.svg';
752
+                        if (file_exists($appIcon)) {
753
+                            $info['preview'] = $urlGenerator->imagePath($app, 'app.svg');
754
+                            $info['previewAsIcon'] = true;
755
+                        }
756
+                    }
757
+                }
758
+                // fix documentation
759
+                if (isset($info['documentation']) && is_array($info['documentation'])) {
760
+                    foreach ($info['documentation'] as $key => $url) {
761
+                        // If it is not an absolute URL we assume it is a key
762
+                        // i.e. admin-ldap will get converted to go.php?to=admin-ldap
763
+                        if (stripos($url, 'https://') !== 0 && stripos($url, 'http://') !== 0) {
764
+                            $url = $urlGenerator->linkToDocs($url);
765
+                        }
766
+
767
+                        $info['documentation'][$key] = $url;
768
+                    }
769
+                }
770
+
771
+                $info['version'] = OC_App::getAppVersion($app);
772
+                $appList[] = $info;
773
+            }
774
+        }
775
+
776
+        return $appList;
777
+    }
778
+
779
+    public static function shouldUpgrade(string $app): bool {
780
+        $versions = self::getAppVersions();
781
+        $currentVersion = OC_App::getAppVersion($app);
782
+        if ($currentVersion && isset($versions[$app])) {
783
+            $installedVersion = $versions[$app];
784
+            if (!version_compare($currentVersion, $installedVersion, '=')) {
785
+                return true;
786
+            }
787
+        }
788
+        return false;
789
+    }
790
+
791
+    /**
792
+     * Adjust the number of version parts of $version1 to match
793
+     * the number of version parts of $version2.
794
+     *
795
+     * @param string $version1 version to adjust
796
+     * @param string $version2 version to take the number of parts from
797
+     * @return string shortened $version1
798
+     */
799
+    private static function adjustVersionParts(string $version1, string $version2): string {
800
+        $version1 = explode('.', $version1);
801
+        $version2 = explode('.', $version2);
802
+        // reduce $version1 to match the number of parts in $version2
803
+        while (count($version1) > count($version2)) {
804
+            array_pop($version1);
805
+        }
806
+        // if $version1 does not have enough parts, add some
807
+        while (count($version1) < count($version2)) {
808
+            $version1[] = '0';
809
+        }
810
+        return implode('.', $version1);
811
+    }
812
+
813
+    /**
814
+     * Check whether the current ownCloud version matches the given
815
+     * application's version requirements.
816
+     *
817
+     * The comparison is made based on the number of parts that the
818
+     * app info version has. For example for ownCloud 6.0.3 if the
819
+     * app info version is expecting version 6.0, the comparison is
820
+     * made on the first two parts of the ownCloud version.
821
+     * This means that it's possible to specify "requiremin" => 6
822
+     * and "requiremax" => 6 and it will still match ownCloud 6.0.3.
823
+     *
824
+     * @param string $ocVersion ownCloud version to check against
825
+     * @param array $appInfo app info (from xml)
826
+     *
827
+     * @return boolean true if compatible, otherwise false
828
+     */
829
+    public static function isAppCompatible(string $ocVersion, array $appInfo): bool {
830
+        $requireMin = '';
831
+        $requireMax = '';
832
+        if (isset($appInfo['dependencies']['nextcloud']['@attributes']['min-version'])) {
833
+            $requireMin = $appInfo['dependencies']['nextcloud']['@attributes']['min-version'];
834
+        } elseif (isset($appInfo['dependencies']['owncloud']['@attributes']['min-version'])) {
835
+            $requireMin = $appInfo['dependencies']['owncloud']['@attributes']['min-version'];
836
+        } else if (isset($appInfo['requiremin'])) {
837
+            $requireMin = $appInfo['requiremin'];
838
+        } else if (isset($appInfo['require'])) {
839
+            $requireMin = $appInfo['require'];
840
+        }
841
+
842
+        if (isset($appInfo['dependencies']['nextcloud']['@attributes']['max-version'])) {
843
+            $requireMax = $appInfo['dependencies']['nextcloud']['@attributes']['max-version'];
844
+        } elseif (isset($appInfo['dependencies']['owncloud']['@attributes']['max-version'])) {
845
+            $requireMax = $appInfo['dependencies']['owncloud']['@attributes']['max-version'];
846
+        } else if (isset($appInfo['requiremax'])) {
847
+            $requireMax = $appInfo['requiremax'];
848
+        }
849
+
850
+        if (!empty($requireMin)
851
+            && version_compare(self::adjustVersionParts($ocVersion, $requireMin), $requireMin, '<')
852
+        ) {
853
+
854
+            return false;
855
+        }
856
+
857
+        if (!empty($requireMax)
858
+            && version_compare(self::adjustVersionParts($ocVersion, $requireMax), $requireMax, '>')
859
+        ) {
860
+            return false;
861
+        }
862
+
863
+        return true;
864
+    }
865
+
866
+    /**
867
+     * get the installed version of all apps
868
+     */
869
+    public static function getAppVersions() {
870
+        static $versions;
871
+
872
+        if(!$versions) {
873
+            $appConfig = \OC::$server->getAppConfig();
874
+            $versions = $appConfig->getValues(false, 'installed_version');
875
+        }
876
+        return $versions;
877
+    }
878
+
879
+    /**
880
+     * update the database for the app and call the update script
881
+     *
882
+     * @param string $appId
883
+     * @return bool
884
+     */
885
+    public static function updateApp(string $appId): bool {
886
+        $appPath = self::getAppPath($appId);
887
+        if($appPath === false) {
888
+            return false;
889
+        }
890
+        self::registerAutoloading($appId, $appPath);
891
+
892
+        \OC::$server->getAppManager()->clearAppsCache();
893
+        $appData = self::getAppInfo($appId);
894
+        self::executeRepairSteps($appId, $appData['repair-steps']['pre-migration']);
895
+
896
+        if (file_exists($appPath . '/appinfo/database.xml')) {
897
+            OC_DB::updateDbFromStructure($appPath . '/appinfo/database.xml');
898
+        } else {
899
+            $ms = new MigrationService($appId, \OC::$server->getDatabaseConnection());
900
+            $ms->migrate();
901
+        }
902
+
903
+        self::executeRepairSteps($appId, $appData['repair-steps']['post-migration']);
904
+        self::setupLiveMigrations($appId, $appData['repair-steps']['live-migration']);
905
+        // update appversion in app manager
906
+        \OC::$server->getAppManager()->clearAppsCache();
907
+        \OC::$server->getAppManager()->getAppVersion($appId, false);
908
+
909
+        // run upgrade code
910
+        if (file_exists($appPath . '/appinfo/update.php')) {
911
+            self::loadApp($appId);
912
+            include $appPath . '/appinfo/update.php';
913
+        }
914
+        self::setupBackgroundJobs($appData['background-jobs']);
915
+
916
+        //set remote/public handlers
917
+        if (array_key_exists('ocsid', $appData)) {
918
+            \OC::$server->getConfig()->setAppValue($appId, 'ocsid', $appData['ocsid']);
919
+        } elseif(\OC::$server->getConfig()->getAppValue($appId, 'ocsid', null) !== null) {
920
+            \OC::$server->getConfig()->deleteAppValue($appId, 'ocsid');
921
+        }
922
+        foreach ($appData['remote'] as $name => $path) {
923
+            \OC::$server->getConfig()->setAppValue('core', 'remote_' . $name, $appId . '/' . $path);
924
+        }
925
+        foreach ($appData['public'] as $name => $path) {
926
+            \OC::$server->getConfig()->setAppValue('core', 'public_' . $name, $appId . '/' . $path);
927
+        }
928
+
929
+        self::setAppTypes($appId);
930
+
931
+        $version = \OC_App::getAppVersion($appId);
932
+        \OC::$server->getConfig()->setAppValue($appId, 'installed_version', $version);
933
+
934
+        \OC::$server->getEventDispatcher()->dispatch(ManagerEvent::EVENT_APP_UPDATE, new ManagerEvent(
935
+            ManagerEvent::EVENT_APP_UPDATE, $appId
936
+        ));
937
+
938
+        return true;
939
+    }
940
+
941
+    /**
942
+     * @param string $appId
943
+     * @param string[] $steps
944
+     * @throws \OC\NeedsUpdateException
945
+     */
946
+    public static function executeRepairSteps(string $appId, array $steps) {
947
+        if (empty($steps)) {
948
+            return;
949
+        }
950
+        // load the app
951
+        self::loadApp($appId);
952
+
953
+        $dispatcher = OC::$server->getEventDispatcher();
954
+
955
+        // load the steps
956
+        $r = new Repair([], $dispatcher);
957
+        foreach ($steps as $step) {
958
+            try {
959
+                $r->addStep($step);
960
+            } catch (Exception $ex) {
961
+                $r->emit('\OC\Repair', 'error', [$ex->getMessage()]);
962
+                \OC::$server->getLogger()->logException($ex);
963
+            }
964
+        }
965
+        // run the steps
966
+        $r->run();
967
+    }
968
+
969
+    public static function setupBackgroundJobs(array $jobs) {
970
+        $queue = \OC::$server->getJobList();
971
+        foreach ($jobs as $job) {
972
+            $queue->add($job);
973
+        }
974
+    }
975
+
976
+    /**
977
+     * @param string $appId
978
+     * @param string[] $steps
979
+     */
980
+    private static function setupLiveMigrations(string $appId, array $steps) {
981
+        $queue = \OC::$server->getJobList();
982
+        foreach ($steps as $step) {
983
+            $queue->add('OC\Migration\BackgroundRepair', [
984
+                'app' => $appId,
985
+                'step' => $step]);
986
+        }
987
+    }
988
+
989
+    /**
990
+     * @param string $appId
991
+     * @return \OC\Files\View|false
992
+     */
993
+    public static function getStorage(string $appId) {
994
+        if (\OC::$server->getAppManager()->isEnabledForUser($appId)) { //sanity check
995
+            if (\OC::$server->getUserSession()->isLoggedIn()) {
996
+                $view = new \OC\Files\View('/' . OC_User::getUser());
997
+                if (!$view->file_exists($appId)) {
998
+                    $view->mkdir($appId);
999
+                }
1000
+                return new \OC\Files\View('/' . OC_User::getUser() . '/' . $appId);
1001
+            } else {
1002
+                \OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ', user not logged in', ILogger::ERROR);
1003
+                return false;
1004
+            }
1005
+        } else {
1006
+            \OCP\Util::writeLog('core', 'Can\'t get app storage, app ' . $appId . ' not enabled', ILogger::ERROR);
1007
+            return false;
1008
+        }
1009
+    }
1010
+
1011
+    protected static function findBestL10NOption(array $options, string $lang): string {
1012
+        // only a single option
1013
+        if (isset($options['@value'])) {
1014
+            return $options['@value'];
1015
+        }
1016
+
1017
+        $fallback = $similarLangFallback = $englishFallback = false;
1018
+
1019
+        $lang = strtolower($lang);
1020
+        $similarLang = $lang;
1021
+        if (strpos($similarLang, '_')) {
1022
+            // For "de_DE" we want to find "de" and the other way around
1023
+            $similarLang = substr($lang, 0, strpos($lang, '_'));
1024
+        }
1025
+
1026
+        foreach ($options as $option) {
1027
+            if (is_array($option)) {
1028
+                if ($fallback === false) {
1029
+                    $fallback = $option['@value'];
1030
+                }
1031
+
1032
+                if (!isset($option['@attributes']['lang'])) {
1033
+                    continue;
1034
+                }
1035
+
1036
+                $attributeLang = strtolower($option['@attributes']['lang']);
1037
+                if ($attributeLang === $lang) {
1038
+                    return $option['@value'];
1039
+                }
1040
+
1041
+                if ($attributeLang === $similarLang) {
1042
+                    $similarLangFallback = $option['@value'];
1043
+                } else if (strpos($attributeLang, $similarLang . '_') === 0) {
1044
+                    if ($similarLangFallback === false) {
1045
+                        $similarLangFallback =  $option['@value'];
1046
+                    }
1047
+                }
1048
+            } else {
1049
+                $englishFallback = $option;
1050
+            }
1051
+        }
1052
+
1053
+        if ($similarLangFallback !== false) {
1054
+            return $similarLangFallback;
1055
+        } else if ($englishFallback !== false) {
1056
+            return $englishFallback;
1057
+        }
1058
+        return (string) $fallback;
1059
+    }
1060
+
1061
+    /**
1062
+     * parses the app data array and enhanced the 'description' value
1063
+     *
1064
+     * @param array $data the app data
1065
+     * @param string $lang
1066
+     * @return array improved app data
1067
+     */
1068
+    public static function parseAppInfo(array $data, $lang = null): array {
1069
+
1070
+        if ($lang && isset($data['name']) && is_array($data['name'])) {
1071
+            $data['name'] = self::findBestL10NOption($data['name'], $lang);
1072
+        }
1073
+        if ($lang && isset($data['summary']) && is_array($data['summary'])) {
1074
+            $data['summary'] = self::findBestL10NOption($data['summary'], $lang);
1075
+        }
1076
+        if ($lang && isset($data['description']) && is_array($data['description'])) {
1077
+            $data['description'] = trim(self::findBestL10NOption($data['description'], $lang));
1078
+        } else if (isset($data['description']) && is_string($data['description'])) {
1079
+            $data['description'] = trim($data['description']);
1080
+        } else  {
1081
+            $data['description'] = '';
1082
+        }
1083
+
1084
+        return $data;
1085
+    }
1086
+
1087
+    /**
1088
+     * @param \OCP\IConfig $config
1089
+     * @param \OCP\IL10N $l
1090
+     * @param array $info
1091
+     * @throws \Exception
1092
+     */
1093
+    public static function checkAppDependencies(\OCP\IConfig $config, \OCP\IL10N $l, array $info) {
1094
+        $dependencyAnalyzer = new DependencyAnalyzer(new Platform($config), $l);
1095
+        $missing = $dependencyAnalyzer->analyze($info);
1096
+        if (!empty($missing)) {
1097
+            $missingMsg = implode(PHP_EOL, $missing);
1098
+            throw new \Exception(
1099
+                $l->t('App "%1$s" cannot be installed because the following dependencies are not fulfilled: %2$s',
1100
+                    [$info['name'], $missingMsg]
1101
+                )
1102
+            );
1103
+        }
1104
+    }
1105 1105
 }
Please login to merge, or discard this patch.
lib/private/Route/Router.php 1 patch
Indentation   +307 added lines, -307 removed lines patch added patch discarded remove patch
@@ -45,337 +45,337 @@
 block discarded – undo
45 45
 use Symfony\Component\Routing\Exception\ResourceNotFoundException;
46 46
 
47 47
 class Router implements IRouter {
48
-	/** @var RouteCollection[] */
49
-	protected $collections = [];
50
-	/** @var null|RouteCollection */
51
-	protected $collection = null;
52
-	/** @var null|string */
53
-	protected $collectionName = null;
54
-	/** @var null|RouteCollection */
55
-	protected $root = null;
56
-	/** @var null|UrlGenerator */
57
-	protected $generator = null;
58
-	/** @var string[] */
59
-	protected $routingFiles;
60
-	/** @var bool */
61
-	protected $loaded = false;
62
-	/** @var array */
63
-	protected $loadedApps = [];
64
-	/** @var ILogger */
65
-	protected $logger;
66
-	/** @var RequestContext */
67
-	protected $context;
48
+    /** @var RouteCollection[] */
49
+    protected $collections = [];
50
+    /** @var null|RouteCollection */
51
+    protected $collection = null;
52
+    /** @var null|string */
53
+    protected $collectionName = null;
54
+    /** @var null|RouteCollection */
55
+    protected $root = null;
56
+    /** @var null|UrlGenerator */
57
+    protected $generator = null;
58
+    /** @var string[] */
59
+    protected $routingFiles;
60
+    /** @var bool */
61
+    protected $loaded = false;
62
+    /** @var array */
63
+    protected $loadedApps = [];
64
+    /** @var ILogger */
65
+    protected $logger;
66
+    /** @var RequestContext */
67
+    protected $context;
68 68
 
69
-	/**
70
-	 * @param ILogger $logger
71
-	 */
72
-	public function __construct(ILogger $logger) {
73
-		$this->logger = $logger;
74
-		$baseUrl = \OC::$WEBROOT;
75
-		if(!(\OC::$server->getConfig()->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true')) {
76
-			$baseUrl = \OC::$server->getURLGenerator()->linkTo('', 'index.php');
77
-		}
78
-		if (!\OC::$CLI && isset($_SERVER['REQUEST_METHOD'])) {
79
-			$method = $_SERVER['REQUEST_METHOD'];
80
-		} else {
81
-			$method = 'GET';
82
-		}
83
-		$request = \OC::$server->getRequest();
84
-		$host = $request->getServerHost();
85
-		$schema = $request->getServerProtocol();
86
-		$this->context = new RequestContext($baseUrl, $method, $host, $schema);
87
-		// TODO cache
88
-		$this->root = $this->getCollection('root');
89
-	}
69
+    /**
70
+     * @param ILogger $logger
71
+     */
72
+    public function __construct(ILogger $logger) {
73
+        $this->logger = $logger;
74
+        $baseUrl = \OC::$WEBROOT;
75
+        if(!(\OC::$server->getConfig()->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true')) {
76
+            $baseUrl = \OC::$server->getURLGenerator()->linkTo('', 'index.php');
77
+        }
78
+        if (!\OC::$CLI && isset($_SERVER['REQUEST_METHOD'])) {
79
+            $method = $_SERVER['REQUEST_METHOD'];
80
+        } else {
81
+            $method = 'GET';
82
+        }
83
+        $request = \OC::$server->getRequest();
84
+        $host = $request->getServerHost();
85
+        $schema = $request->getServerProtocol();
86
+        $this->context = new RequestContext($baseUrl, $method, $host, $schema);
87
+        // TODO cache
88
+        $this->root = $this->getCollection('root');
89
+    }
90 90
 
91
-	/**
92
-	 * Get the files to load the routes from
93
-	 *
94
-	 * @return string[]
95
-	 */
96
-	public function getRoutingFiles() {
97
-		if (!isset($this->routingFiles)) {
98
-			$this->routingFiles = [];
99
-			foreach (\OC_APP::getEnabledApps() as $app) {
100
-				$appPath = \OC_App::getAppPath($app);
101
-				if($appPath !== false) {
102
-					$file = $appPath . '/appinfo/routes.php';
103
-					if (file_exists($file)) {
104
-						$this->routingFiles[$app] = $file;
105
-					}
106
-				}
107
-			}
108
-		}
109
-		return $this->routingFiles;
110
-	}
91
+    /**
92
+     * Get the files to load the routes from
93
+     *
94
+     * @return string[]
95
+     */
96
+    public function getRoutingFiles() {
97
+        if (!isset($this->routingFiles)) {
98
+            $this->routingFiles = [];
99
+            foreach (\OC_APP::getEnabledApps() as $app) {
100
+                $appPath = \OC_App::getAppPath($app);
101
+                if($appPath !== false) {
102
+                    $file = $appPath . '/appinfo/routes.php';
103
+                    if (file_exists($file)) {
104
+                        $this->routingFiles[$app] = $file;
105
+                    }
106
+                }
107
+            }
108
+        }
109
+        return $this->routingFiles;
110
+    }
111 111
 
112
-	/**
113
-	 * Loads the routes
114
-	 *
115
-	 * @param null|string $app
116
-	 */
117
-	public function loadRoutes($app = null) {
118
-		if(is_string($app)) {
119
-			$app = \OC_App::cleanAppId($app);
120
-		}
112
+    /**
113
+     * Loads the routes
114
+     *
115
+     * @param null|string $app
116
+     */
117
+    public function loadRoutes($app = null) {
118
+        if(is_string($app)) {
119
+            $app = \OC_App::cleanAppId($app);
120
+        }
121 121
 
122
-		$requestedApp = $app;
123
-		if ($this->loaded) {
124
-			return;
125
-		}
126
-		if (is_null($app)) {
127
-			$this->loaded = true;
128
-			$routingFiles = $this->getRoutingFiles();
129
-		} else {
130
-			if (isset($this->loadedApps[$app])) {
131
-				return;
132
-			}
133
-			$file = \OC_App::getAppPath($app) . '/appinfo/routes.php';
134
-			if ($file !== false && file_exists($file)) {
135
-				$routingFiles = [$app => $file];
136
-			} else {
137
-				$routingFiles = [];
138
-			}
139
-		}
140
-		\OC::$server->getEventLogger()->start('loadroutes' . $requestedApp, 'Loading Routes');
141
-		foreach ($routingFiles as $app => $file) {
142
-			if (!isset($this->loadedApps[$app])) {
143
-				if (!\OC_App::isAppLoaded($app)) {
144
-					// app MUST be loaded before app routes
145
-					// try again next time loadRoutes() is called
146
-					$this->loaded = false;
147
-					continue;
148
-				}
149
-				$this->loadedApps[$app] = true;
150
-				$this->useCollection($app);
151
-				$this->requireRouteFile($file, $app);
152
-				$collection = $this->getCollection($app);
153
-				$collection->addPrefix('/apps/' . $app);
154
-				$this->root->addCollection($collection);
122
+        $requestedApp = $app;
123
+        if ($this->loaded) {
124
+            return;
125
+        }
126
+        if (is_null($app)) {
127
+            $this->loaded = true;
128
+            $routingFiles = $this->getRoutingFiles();
129
+        } else {
130
+            if (isset($this->loadedApps[$app])) {
131
+                return;
132
+            }
133
+            $file = \OC_App::getAppPath($app) . '/appinfo/routes.php';
134
+            if ($file !== false && file_exists($file)) {
135
+                $routingFiles = [$app => $file];
136
+            } else {
137
+                $routingFiles = [];
138
+            }
139
+        }
140
+        \OC::$server->getEventLogger()->start('loadroutes' . $requestedApp, 'Loading Routes');
141
+        foreach ($routingFiles as $app => $file) {
142
+            if (!isset($this->loadedApps[$app])) {
143
+                if (!\OC_App::isAppLoaded($app)) {
144
+                    // app MUST be loaded before app routes
145
+                    // try again next time loadRoutes() is called
146
+                    $this->loaded = false;
147
+                    continue;
148
+                }
149
+                $this->loadedApps[$app] = true;
150
+                $this->useCollection($app);
151
+                $this->requireRouteFile($file, $app);
152
+                $collection = $this->getCollection($app);
153
+                $collection->addPrefix('/apps/' . $app);
154
+                $this->root->addCollection($collection);
155 155
 
156
-				// Also add the OCS collection
157
-				$collection = $this->getCollection($app.'.ocs');
158
-				$collection->addPrefix('/ocsapp');
159
-				$this->root->addCollection($collection);
160
-			}
161
-		}
162
-		if (!isset($this->loadedApps['core'])) {
163
-			$this->loadedApps['core'] = true;
164
-			$this->useCollection('root');
165
-			require_once __DIR__ . '/../../../settings/routes.php';
166
-			require_once __DIR__ . '/../../../core/routes.php';
156
+                // Also add the OCS collection
157
+                $collection = $this->getCollection($app.'.ocs');
158
+                $collection->addPrefix('/ocsapp');
159
+                $this->root->addCollection($collection);
160
+            }
161
+        }
162
+        if (!isset($this->loadedApps['core'])) {
163
+            $this->loadedApps['core'] = true;
164
+            $this->useCollection('root');
165
+            require_once __DIR__ . '/../../../settings/routes.php';
166
+            require_once __DIR__ . '/../../../core/routes.php';
167 167
 
168
-			// Also add the OCS collection
169
-			$collection = $this->getCollection('root.ocs');
170
-			$collection->addPrefix('/ocsapp');
171
-			$this->root->addCollection($collection);
172
-		}
173
-		if ($this->loaded) {
174
-			$collection = $this->getCollection('ocs');
175
-			$collection->addPrefix('/ocs');
176
-			$this->root->addCollection($collection);
177
-		}
178
-		\OC::$server->getEventLogger()->end('loadroutes' . $requestedApp);
179
-	}
168
+            // Also add the OCS collection
169
+            $collection = $this->getCollection('root.ocs');
170
+            $collection->addPrefix('/ocsapp');
171
+            $this->root->addCollection($collection);
172
+        }
173
+        if ($this->loaded) {
174
+            $collection = $this->getCollection('ocs');
175
+            $collection->addPrefix('/ocs');
176
+            $this->root->addCollection($collection);
177
+        }
178
+        \OC::$server->getEventLogger()->end('loadroutes' . $requestedApp);
179
+    }
180 180
 
181
-	/**
182
-	 * @return string
183
-	 * @deprecated
184
-	 */
185
-	public function getCacheKey() {
186
-		return '';
187
-	}
181
+    /**
182
+     * @return string
183
+     * @deprecated
184
+     */
185
+    public function getCacheKey() {
186
+        return '';
187
+    }
188 188
 
189
-	/**
190
-	 * @param string $name
191
-	 * @return \Symfony\Component\Routing\RouteCollection
192
-	 */
193
-	protected function getCollection($name) {
194
-		if (!isset($this->collections[$name])) {
195
-			$this->collections[$name] = new RouteCollection();
196
-		}
197
-		return $this->collections[$name];
198
-	}
189
+    /**
190
+     * @param string $name
191
+     * @return \Symfony\Component\Routing\RouteCollection
192
+     */
193
+    protected function getCollection($name) {
194
+        if (!isset($this->collections[$name])) {
195
+            $this->collections[$name] = new RouteCollection();
196
+        }
197
+        return $this->collections[$name];
198
+    }
199 199
 
200
-	/**
201
-	 * Sets the collection to use for adding routes
202
-	 *
203
-	 * @param string $name Name of the collection to use.
204
-	 * @return void
205
-	 */
206
-	public function useCollection($name) {
207
-		$this->collection = $this->getCollection($name);
208
-		$this->collectionName = $name;
209
-	}
200
+    /**
201
+     * Sets the collection to use for adding routes
202
+     *
203
+     * @param string $name Name of the collection to use.
204
+     * @return void
205
+     */
206
+    public function useCollection($name) {
207
+        $this->collection = $this->getCollection($name);
208
+        $this->collectionName = $name;
209
+    }
210 210
 
211
-	/**
212
-	 * returns the current collection name in use for adding routes
213
-	 *
214
-	 * @return string the collection name
215
-	 */
216
-	public function getCurrentCollection() {
217
-		return $this->collectionName;
218
-	}
211
+    /**
212
+     * returns the current collection name in use for adding routes
213
+     *
214
+     * @return string the collection name
215
+     */
216
+    public function getCurrentCollection() {
217
+        return $this->collectionName;
218
+    }
219 219
 
220 220
 
221
-	/**
222
-	 * Create a \OC\Route\Route.
223
-	 *
224
-	 * @param string $name Name of the route to create.
225
-	 * @param string $pattern The pattern to match
226
-	 * @param array $defaults An array of default parameter values
227
-	 * @param array $requirements An array of requirements for parameters (regexes)
228
-	 * @return \OC\Route\Route
229
-	 */
230
-	public function create($name,
231
-						   $pattern,
232
-						   array $defaults = [],
233
-						   array $requirements = []) {
234
-		$route = new Route($pattern, $defaults, $requirements);
235
-		$this->collection->add($name, $route);
236
-		return $route;
237
-	}
221
+    /**
222
+     * Create a \OC\Route\Route.
223
+     *
224
+     * @param string $name Name of the route to create.
225
+     * @param string $pattern The pattern to match
226
+     * @param array $defaults An array of default parameter values
227
+     * @param array $requirements An array of requirements for parameters (regexes)
228
+     * @return \OC\Route\Route
229
+     */
230
+    public function create($name,
231
+                            $pattern,
232
+                            array $defaults = [],
233
+                            array $requirements = []) {
234
+        $route = new Route($pattern, $defaults, $requirements);
235
+        $this->collection->add($name, $route);
236
+        return $route;
237
+    }
238 238
 
239
-	/**
240
-	 * Find the route matching $url
241
-	 *
242
-	 * @param string $url The url to find
243
-	 * @throws \Exception
244
-	 * @return void
245
-	 */
246
-	public function match($url) {
247
-		if (substr($url, 0, 6) === '/apps/') {
248
-			// empty string / 'apps' / $app / rest of the route
249
-			list(, , $app,) = explode('/', $url, 4);
239
+    /**
240
+     * Find the route matching $url
241
+     *
242
+     * @param string $url The url to find
243
+     * @throws \Exception
244
+     * @return void
245
+     */
246
+    public function match($url) {
247
+        if (substr($url, 0, 6) === '/apps/') {
248
+            // empty string / 'apps' / $app / rest of the route
249
+            list(, , $app,) = explode('/', $url, 4);
250 250
 
251
-			$app = \OC_App::cleanAppId($app);
252
-			\OC::$REQUESTEDAPP = $app;
253
-			$this->loadRoutes($app);
254
-		} else if (substr($url, 0, 13) === '/ocsapp/apps/') {
255
-			// empty string / 'ocsapp' / 'apps' / $app / rest of the route
256
-			list(, , , $app,) = explode('/', $url, 5);
251
+            $app = \OC_App::cleanAppId($app);
252
+            \OC::$REQUESTEDAPP = $app;
253
+            $this->loadRoutes($app);
254
+        } else if (substr($url, 0, 13) === '/ocsapp/apps/') {
255
+            // empty string / 'ocsapp' / 'apps' / $app / rest of the route
256
+            list(, , , $app,) = explode('/', $url, 5);
257 257
 
258
-			$app = \OC_App::cleanAppId($app);
259
-			\OC::$REQUESTEDAPP = $app;
260
-			$this->loadRoutes($app);
261
-		} else if (substr($url, 0, 6) === '/core/' or substr($url, 0, 10) === '/settings/') {
262
-			\OC::$REQUESTEDAPP = $url;
263
-			if (!\OC::$server->getConfig()->getSystemValueBool('maintenance') && !Util::needUpgrade()) {
264
-				\OC_App::loadApps();
265
-			}
266
-			$this->loadRoutes('core');
267
-		} else {
268
-			$this->loadRoutes();
269
-		}
258
+            $app = \OC_App::cleanAppId($app);
259
+            \OC::$REQUESTEDAPP = $app;
260
+            $this->loadRoutes($app);
261
+        } else if (substr($url, 0, 6) === '/core/' or substr($url, 0, 10) === '/settings/') {
262
+            \OC::$REQUESTEDAPP = $url;
263
+            if (!\OC::$server->getConfig()->getSystemValueBool('maintenance') && !Util::needUpgrade()) {
264
+                \OC_App::loadApps();
265
+            }
266
+            $this->loadRoutes('core');
267
+        } else {
268
+            $this->loadRoutes();
269
+        }
270 270
 
271
-		$matcher = new UrlMatcher($this->root, $this->context);
272
-		try {
273
-			$parameters = $matcher->match($url);
274
-		} catch (ResourceNotFoundException $e) {
275
-			if (substr($url, -1) !== '/') {
276
-				// We allow links to apps/files? for backwards compatibility reasons
277
-				// However, since Symfony does not allow empty route names, the route
278
-				// we need to match is '/', so we need to append the '/' here.
279
-				try {
280
-					$parameters = $matcher->match($url . '/');
281
-				} catch (ResourceNotFoundException $newException) {
282
-					// If we still didn't match a route, we throw the original exception
283
-					throw $e;
284
-				}
285
-			} else {
286
-				throw $e;
287
-			}
288
-		}
271
+        $matcher = new UrlMatcher($this->root, $this->context);
272
+        try {
273
+            $parameters = $matcher->match($url);
274
+        } catch (ResourceNotFoundException $e) {
275
+            if (substr($url, -1) !== '/') {
276
+                // We allow links to apps/files? for backwards compatibility reasons
277
+                // However, since Symfony does not allow empty route names, the route
278
+                // we need to match is '/', so we need to append the '/' here.
279
+                try {
280
+                    $parameters = $matcher->match($url . '/');
281
+                } catch (ResourceNotFoundException $newException) {
282
+                    // If we still didn't match a route, we throw the original exception
283
+                    throw $e;
284
+                }
285
+            } else {
286
+                throw $e;
287
+            }
288
+        }
289 289
 
290
-		\OC::$server->getEventLogger()->start('run_route', 'Run route');
291
-		if (isset($parameters['action'])) {
292
-			$action = $parameters['action'];
293
-			if (!is_callable($action)) {
294
-				throw new \Exception('not a callable action');
295
-			}
296
-			unset($parameters['action']);
297
-			call_user_func($action, $parameters);
298
-		} elseif (isset($parameters['file'])) {
299
-			include $parameters['file'];
300
-		} else {
301
-			throw new \Exception('no action available');
302
-		}
303
-		\OC::$server->getEventLogger()->end('run_route');
304
-	}
290
+        \OC::$server->getEventLogger()->start('run_route', 'Run route');
291
+        if (isset($parameters['action'])) {
292
+            $action = $parameters['action'];
293
+            if (!is_callable($action)) {
294
+                throw new \Exception('not a callable action');
295
+            }
296
+            unset($parameters['action']);
297
+            call_user_func($action, $parameters);
298
+        } elseif (isset($parameters['file'])) {
299
+            include $parameters['file'];
300
+        } else {
301
+            throw new \Exception('no action available');
302
+        }
303
+        \OC::$server->getEventLogger()->end('run_route');
304
+    }
305 305
 
306
-	/**
307
-	 * Get the url generator
308
-	 *
309
-	 * @return \Symfony\Component\Routing\Generator\UrlGenerator
310
-	 *
311
-	 */
312
-	public function getGenerator() {
313
-		if (null !== $this->generator) {
314
-			return $this->generator;
315
-		}
306
+    /**
307
+     * Get the url generator
308
+     *
309
+     * @return \Symfony\Component\Routing\Generator\UrlGenerator
310
+     *
311
+     */
312
+    public function getGenerator() {
313
+        if (null !== $this->generator) {
314
+            return $this->generator;
315
+        }
316 316
 
317
-		return $this->generator = new UrlGenerator($this->root, $this->context);
318
-	}
317
+        return $this->generator = new UrlGenerator($this->root, $this->context);
318
+    }
319 319
 
320
-	/**
321
-	 * Generate url based on $name and $parameters
322
-	 *
323
-	 * @param string $name Name of the route to use.
324
-	 * @param array $parameters Parameters for the route
325
-	 * @param bool $absolute
326
-	 * @return string
327
-	 */
328
-	public function generate($name,
329
-							 $parameters = [],
330
-							 $absolute = false) {
331
-		$this->loadRoutes();
332
-		try {
333
-			$referenceType = UrlGenerator::ABSOLUTE_URL;
334
-			if ($absolute === false) {
335
-				$referenceType = UrlGenerator::ABSOLUTE_PATH;
336
-			}
337
-			return $this->getGenerator()->generate($name, $parameters, $referenceType);
338
-		} catch (RouteNotFoundException $e) {
339
-			$this->logger->logException($e);
340
-			return '';
341
-		}
342
-	}
320
+    /**
321
+     * Generate url based on $name and $parameters
322
+     *
323
+     * @param string $name Name of the route to use.
324
+     * @param array $parameters Parameters for the route
325
+     * @param bool $absolute
326
+     * @return string
327
+     */
328
+    public function generate($name,
329
+                                $parameters = [],
330
+                                $absolute = false) {
331
+        $this->loadRoutes();
332
+        try {
333
+            $referenceType = UrlGenerator::ABSOLUTE_URL;
334
+            if ($absolute === false) {
335
+                $referenceType = UrlGenerator::ABSOLUTE_PATH;
336
+            }
337
+            return $this->getGenerator()->generate($name, $parameters, $referenceType);
338
+        } catch (RouteNotFoundException $e) {
339
+            $this->logger->logException($e);
340
+            return '';
341
+        }
342
+    }
343 343
 
344
-	/**
345
-	 * To isolate the variable scope used inside the $file it is required in it's own method
346
-	 *
347
-	 * @param string $file the route file location to include
348
-	 * @param string $appName
349
-	 */
350
-	private function requireRouteFile($file, $appName) {
351
-		$this->setupRoutes(include_once $file, $appName);
352
-	}
344
+    /**
345
+     * To isolate the variable scope used inside the $file it is required in it's own method
346
+     *
347
+     * @param string $file the route file location to include
348
+     * @param string $appName
349
+     */
350
+    private function requireRouteFile($file, $appName) {
351
+        $this->setupRoutes(include_once $file, $appName);
352
+    }
353 353
 
354 354
 
355
-	/**
356
-	 * If a routes.php file returns an array, try to set up the application and
357
-	 * register the routes for the app. The application class will be chosen by
358
-	 * camelcasing the appname, e.g.: my_app will be turned into
359
-	 * \OCA\MyApp\AppInfo\Application. If that class does not exist, a default
360
-	 * App will be intialized. This makes it optional to ship an
361
-	 * appinfo/application.php by using the built in query resolver
362
-	 *
363
-	 * @param array $routes the application routes
364
-	 * @param string $appName the name of the app.
365
-	 */
366
-	private function setupRoutes($routes, $appName) {
367
-		if (is_array($routes)) {
368
-			$appNameSpace = App::buildAppNamespace($appName);
355
+    /**
356
+     * If a routes.php file returns an array, try to set up the application and
357
+     * register the routes for the app. The application class will be chosen by
358
+     * camelcasing the appname, e.g.: my_app will be turned into
359
+     * \OCA\MyApp\AppInfo\Application. If that class does not exist, a default
360
+     * App will be intialized. This makes it optional to ship an
361
+     * appinfo/application.php by using the built in query resolver
362
+     *
363
+     * @param array $routes the application routes
364
+     * @param string $appName the name of the app.
365
+     */
366
+    private function setupRoutes($routes, $appName) {
367
+        if (is_array($routes)) {
368
+            $appNameSpace = App::buildAppNamespace($appName);
369 369
 
370
-			$applicationClassName = $appNameSpace . '\\AppInfo\\Application';
370
+            $applicationClassName = $appNameSpace . '\\AppInfo\\Application';
371 371
 
372
-			if (class_exists($applicationClassName)) {
373
-				$application = new $applicationClassName();
374
-			} else {
375
-				$application = new App($appName);
376
-			}
372
+            if (class_exists($applicationClassName)) {
373
+                $application = new $applicationClassName();
374
+            } else {
375
+                $application = new App($appName);
376
+            }
377 377
 
378
-			$application->registerRoutes($this, $routes);
379
-		}
380
-	}
378
+            $application->registerRoutes($this, $routes);
379
+        }
380
+    }
381 381
 }
Please login to merge, or discard this patch.
lib/private/Updater.php 2 patches
Indentation   +558 added lines, -558 removed lines patch added patch discarded remove patch
@@ -54,563 +54,563 @@
 block discarded – undo
54 54
  */
55 55
 class Updater extends BasicEmitter {
56 56
 
57
-	/** @var ILogger $log */
58
-	private $log;
59
-
60
-	/** @var IConfig */
61
-	private $config;
62
-
63
-	/** @var Checker */
64
-	private $checker;
65
-
66
-	/** @var Installer */
67
-	private $installer;
68
-
69
-	private $logLevelNames = [
70
-		0 => 'Debug',
71
-		1 => 'Info',
72
-		2 => 'Warning',
73
-		3 => 'Error',
74
-		4 => 'Fatal',
75
-	];
76
-
77
-	/**
78
-	 * @param IConfig $config
79
-	 * @param Checker $checker
80
-	 * @param ILogger $log
81
-	 * @param Installer $installer
82
-	 */
83
-	public function __construct(IConfig $config,
84
-								Checker $checker,
85
-								ILogger $log = null,
86
-								Installer $installer) {
87
-		$this->log = $log;
88
-		$this->config = $config;
89
-		$this->checker = $checker;
90
-		$this->installer = $installer;
91
-	}
92
-
93
-	/**
94
-	 * runs the update actions in maintenance mode, does not upgrade the source files
95
-	 * except the main .htaccess file
96
-	 *
97
-	 * @return bool true if the operation succeeded, false otherwise
98
-	 */
99
-	public function upgrade() {
100
-		$this->emitRepairEvents();
101
-		$this->logAllEvents();
102
-
103
-		$logLevel = $this->config->getSystemValue('loglevel', ILogger::WARN);
104
-		$this->emit('\OC\Updater', 'setDebugLogLevel', [ $logLevel, $this->logLevelNames[$logLevel] ]);
105
-		$this->config->setSystemValue('loglevel', ILogger::DEBUG);
106
-
107
-		$wasMaintenanceModeEnabled = $this->config->getSystemValueBool('maintenance');
108
-
109
-		if(!$wasMaintenanceModeEnabled) {
110
-			$this->config->setSystemValue('maintenance', true);
111
-			$this->emit('\OC\Updater', 'maintenanceEnabled');
112
-		}
113
-
114
-		$installedVersion = $this->config->getSystemValue('version', '0.0.0');
115
-		$currentVersion = implode('.', \OCP\Util::getVersion());
116
-
117
-		$this->log->debug('starting upgrade from ' . $installedVersion . ' to ' . $currentVersion, array('app' => 'core'));
118
-
119
-		$success = true;
120
-		try {
121
-			$this->doUpgrade($currentVersion, $installedVersion);
122
-		} catch (HintException $exception) {
123
-			$this->log->logException($exception, ['app' => 'core']);
124
-			$this->emit('\OC\Updater', 'failure', array($exception->getMessage() . ': ' .$exception->getHint()));
125
-			$success = false;
126
-		} catch (\Exception $exception) {
127
-			$this->log->logException($exception, ['app' => 'core']);
128
-			$this->emit('\OC\Updater', 'failure', array(get_class($exception) . ': ' .$exception->getMessage()));
129
-			$success = false;
130
-		}
131
-
132
-		$this->emit('\OC\Updater', 'updateEnd', array($success));
133
-
134
-		if(!$wasMaintenanceModeEnabled && $success) {
135
-			$this->config->setSystemValue('maintenance', false);
136
-			$this->emit('\OC\Updater', 'maintenanceDisabled');
137
-		} else {
138
-			$this->emit('\OC\Updater', 'maintenanceActive');
139
-		}
140
-
141
-		$this->emit('\OC\Updater', 'resetLogLevel', [ $logLevel, $this->logLevelNames[$logLevel] ]);
142
-		$this->config->setSystemValue('loglevel', $logLevel);
143
-		$this->config->setSystemValue('installed', true);
144
-
145
-		return $success;
146
-	}
147
-
148
-	/**
149
-	 * Return version from which this version is allowed to upgrade from
150
-	 *
151
-	 * @return array allowed previous versions per vendor
152
-	 */
153
-	private function getAllowedPreviousVersions() {
154
-		// this should really be a JSON file
155
-		require \OC::$SERVERROOT . '/version.php';
156
-		/** @var array $OC_VersionCanBeUpgradedFrom */
157
-		return $OC_VersionCanBeUpgradedFrom;
158
-	}
159
-
160
-	/**
161
-	 * Return vendor from which this version was published
162
-	 *
163
-	 * @return string Get the vendor
164
-	 */
165
-	private function getVendor() {
166
-		// this should really be a JSON file
167
-		require \OC::$SERVERROOT . '/version.php';
168
-		/** @var string $vendor */
169
-		return (string) $vendor;
170
-	}
171
-
172
-	/**
173
-	 * Whether an upgrade to a specified version is possible
174
-	 * @param string $oldVersion
175
-	 * @param string $newVersion
176
-	 * @param array $allowedPreviousVersions
177
-	 * @return bool
178
-	 */
179
-	public function isUpgradePossible($oldVersion, $newVersion, array $allowedPreviousVersions) {
180
-		$version = explode('.', $oldVersion);
181
-		$majorMinor = $version[0] . '.' . $version[1];
182
-
183
-		$currentVendor = $this->config->getAppValue('core', 'vendor', '');
184
-
185
-		// Vendor was not set correctly on install, so we have to white-list known versions
186
-		if ($currentVendor === '' && isset($allowedPreviousVersions['owncloud'][$oldVersion])) {
187
-			$currentVendor = 'owncloud';
188
-		}
189
-
190
-		if ($currentVendor === 'nextcloud') {
191
-			return isset($allowedPreviousVersions[$currentVendor][$majorMinor])
192
-				&& (version_compare($oldVersion, $newVersion, '<=') ||
193
-					$this->config->getSystemValue('debug', false));
194
-		}
195
-
196
-		// Check if the instance can be migrated
197
-		return isset($allowedPreviousVersions[$currentVendor][$majorMinor]) ||
198
-			isset($allowedPreviousVersions[$currentVendor][$oldVersion]);
199
-	}
200
-
201
-	/**
202
-	 * runs the update actions in maintenance mode, does not upgrade the source files
203
-	 * except the main .htaccess file
204
-	 *
205
-	 * @param string $currentVersion current version to upgrade to
206
-	 * @param string $installedVersion previous version from which to upgrade from
207
-	 *
208
-	 * @throws \Exception
209
-	 */
210
-	private function doUpgrade($currentVersion, $installedVersion) {
211
-		// Stop update if the update is over several major versions
212
-		$allowedPreviousVersions = $this->getAllowedPreviousVersions();
213
-		if (!$this->isUpgradePossible($installedVersion, $currentVersion, $allowedPreviousVersions)) {
214
-			throw new \Exception('Updates between multiple major versions and downgrades are unsupported.');
215
-		}
216
-
217
-		// Update .htaccess files
218
-		try {
219
-			Setup::updateHtaccess();
220
-			Setup::protectDataDirectory();
221
-		} catch (\Exception $e) {
222
-			throw new \Exception($e->getMessage());
223
-		}
224
-
225
-		// create empty file in data dir, so we can later find
226
-		// out that this is indeed an ownCloud data directory
227
-		// (in case it didn't exist before)
228
-		file_put_contents($this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', '');
229
-
230
-		// pre-upgrade repairs
231
-		$repair = new Repair(Repair::getBeforeUpgradeRepairSteps(), \OC::$server->getEventDispatcher());
232
-		$repair->run();
233
-
234
-		$this->doCoreUpgrade();
235
-
236
-		try {
237
-			// TODO: replace with the new repair step mechanism https://github.com/owncloud/core/pull/24378
238
-			Setup::installBackgroundJobs();
239
-		} catch (\Exception $e) {
240
-			throw new \Exception($e->getMessage());
241
-		}
242
-
243
-		// update all shipped apps
244
-		$this->checkAppsRequirements();
245
-		$this->doAppUpgrade();
246
-
247
-		// Update the appfetchers version so it downloads the correct list from the appstore
248
-		\OC::$server->getAppFetcher()->setVersion($currentVersion);
249
-
250
-		// upgrade appstore apps
251
-		$this->upgradeAppStoreApps(\OC::$server->getAppManager()->getInstalledApps());
252
-		$this->upgradeAppStoreApps(\OC_App::$autoDisabledApps, true);
253
-
254
-		// install new shipped apps on upgrade
255
-		OC_App::loadApps(['authentication']);
256
-		$errors = Installer::installShippedApps(true);
257
-		foreach ($errors as $appId => $exception) {
258
-			/** @var \Exception $exception */
259
-			$this->log->logException($exception, ['app' => $appId]);
260
-			$this->emit('\OC\Updater', 'failure', [$appId . ': ' . $exception->getMessage()]);
261
-		}
262
-
263
-		// post-upgrade repairs
264
-		$repair = new Repair(Repair::getRepairSteps(), \OC::$server->getEventDispatcher());
265
-		$repair->run();
266
-
267
-		//Invalidate update feed
268
-		$this->config->setAppValue('core', 'lastupdatedat', 0);
269
-
270
-		// Check for code integrity if not disabled
271
-		if(\OC::$server->getIntegrityCodeChecker()->isCodeCheckEnforced()) {
272
-			$this->emit('\OC\Updater', 'startCheckCodeIntegrity');
273
-			$this->checker->runInstanceVerification();
274
-			$this->emit('\OC\Updater', 'finishedCheckCodeIntegrity');
275
-		}
276
-
277
-		// only set the final version if everything went well
278
-		$this->config->setSystemValue('version', implode('.', Util::getVersion()));
279
-		$this->config->setAppValue('core', 'vendor', $this->getVendor());
280
-	}
281
-
282
-	protected function doCoreUpgrade() {
283
-		$this->emit('\OC\Updater', 'dbUpgradeBefore');
284
-
285
-		// execute core migrations
286
-		$ms = new MigrationService('core', \OC::$server->getDatabaseConnection());
287
-		$ms->migrate();
288
-
289
-		$this->emit('\OC\Updater', 'dbUpgrade');
290
-	}
291
-
292
-	/**
293
-	 * @param string $version the oc version to check app compatibility with
294
-	 */
295
-	protected function checkAppUpgrade($version) {
296
-		$apps = \OC_App::getEnabledApps();
297
-		$this->emit('\OC\Updater', 'appUpgradeCheckBefore');
298
-
299
-		$appManager = \OC::$server->getAppManager();
300
-		foreach ($apps as $appId) {
301
-			$info = \OC_App::getAppInfo($appId);
302
-			$compatible = \OC_App::isAppCompatible($version, $info);
303
-			$isShipped = $appManager->isShipped($appId);
304
-
305
-			if ($compatible && $isShipped && \OC_App::shouldUpgrade($appId)) {
306
-				/**
307
-				 * FIXME: The preupdate check is performed before the database migration, otherwise database changes
308
-				 * are not possible anymore within it. - Consider this when touching the code.
309
-				 * @link https://github.com/owncloud/core/issues/10980
310
-				 * @see \OC_App::updateApp
311
-				 */
312
-				if (file_exists(\OC_App::getAppPath($appId) . '/appinfo/preupdate.php')) {
313
-					$this->includePreUpdate($appId);
314
-				}
315
-				if (file_exists(\OC_App::getAppPath($appId) . '/appinfo/database.xml')) {
316
-					$this->emit('\OC\Updater', 'appSimulateUpdate', array($appId));
317
-					\OC_DB::simulateUpdateDbFromStructure(\OC_App::getAppPath($appId) . '/appinfo/database.xml');
318
-				}
319
-			}
320
-		}
321
-
322
-		$this->emit('\OC\Updater', 'appUpgradeCheck');
323
-	}
324
-
325
-	/**
326
-	 * Includes the pre-update file. Done here to prevent namespace mixups.
327
-	 * @param string $appId
328
-	 */
329
-	private function includePreUpdate($appId) {
330
-		include \OC_App::getAppPath($appId) . '/appinfo/preupdate.php';
331
-	}
332
-
333
-	/**
334
-	 * upgrades all apps within a major ownCloud upgrade. Also loads "priority"
335
-	 * (types authentication, filesystem, logging, in that order) afterwards.
336
-	 *
337
-	 * @throws NeedsUpdateException
338
-	 */
339
-	protected function doAppUpgrade() {
340
-		$apps = \OC_App::getEnabledApps();
341
-		$priorityTypes = array('authentication', 'filesystem', 'logging');
342
-		$pseudoOtherType = 'other';
343
-		$stacks = array($pseudoOtherType => array());
344
-
345
-		foreach ($apps as $appId) {
346
-			$priorityType = false;
347
-			foreach ($priorityTypes as $type) {
348
-				if(!isset($stacks[$type])) {
349
-					$stacks[$type] = array();
350
-				}
351
-				if (\OC_App::isType($appId, [$type])) {
352
-					$stacks[$type][] = $appId;
353
-					$priorityType = true;
354
-					break;
355
-				}
356
-			}
357
-			if (!$priorityType) {
358
-				$stacks[$pseudoOtherType][] = $appId;
359
-			}
360
-		}
361
-		foreach ($stacks as $type => $stack) {
362
-			foreach ($stack as $appId) {
363
-				if (\OC_App::shouldUpgrade($appId)) {
364
-					$this->emit('\OC\Updater', 'appUpgradeStarted', [$appId, \OC_App::getAppVersion($appId)]);
365
-					\OC_App::updateApp($appId);
366
-					$this->emit('\OC\Updater', 'appUpgrade', [$appId, \OC_App::getAppVersion($appId)]);
367
-				}
368
-				if($type !== $pseudoOtherType) {
369
-					// load authentication, filesystem and logging apps after
370
-					// upgrading them. Other apps my need to rely on modifying
371
-					// user and/or filesystem aspects.
372
-					\OC_App::loadApp($appId);
373
-				}
374
-			}
375
-		}
376
-	}
377
-
378
-	/**
379
-	 * check if the current enabled apps are compatible with the current
380
-	 * ownCloud version. disable them if not.
381
-	 * This is important if you upgrade ownCloud and have non ported 3rd
382
-	 * party apps installed.
383
-	 *
384
-	 * @return array
385
-	 * @throws \Exception
386
-	 */
387
-	private function checkAppsRequirements() {
388
-		$isCoreUpgrade = $this->isCodeUpgrade();
389
-		$apps = OC_App::getEnabledApps();
390
-		$version = implode('.', Util::getVersion());
391
-		$disabledApps = [];
392
-		$appManager = \OC::$server->getAppManager();
393
-		foreach ($apps as $app) {
394
-			// check if the app is compatible with this version of ownCloud
395
-			$info = OC_App::getAppInfo($app);
396
-			if($info === null || !OC_App::isAppCompatible($version, $info)) {
397
-				if ($appManager->isShipped($app)) {
398
-					throw new \UnexpectedValueException('The files of the app "' . $app . '" were not correctly replaced before running the update');
399
-				}
400
-				\OC::$server->getAppManager()->disableApp($app);
401
-				$this->emit('\OC\Updater', 'incompatibleAppDisabled', array($app));
402
-			}
403
-			// no need to disable any app in case this is a non-core upgrade
404
-			if (!$isCoreUpgrade) {
405
-				continue;
406
-			}
407
-			// shipped apps will remain enabled
408
-			if ($appManager->isShipped($app)) {
409
-				continue;
410
-			}
411
-			// authentication and session apps will remain enabled as well
412
-			if (OC_App::isType($app, ['session', 'authentication'])) {
413
-				continue;
414
-			}
415
-		}
416
-		return $disabledApps;
417
-	}
418
-
419
-	/**
420
-	 * @return bool
421
-	 */
422
-	private function isCodeUpgrade() {
423
-		$installedVersion = $this->config->getSystemValue('version', '0.0.0');
424
-		$currentVersion = implode('.', Util::getVersion());
425
-		if (version_compare($currentVersion, $installedVersion, '>')) {
426
-			return true;
427
-		}
428
-		return false;
429
-	}
430
-
431
-	/**
432
-	 * @param array $disabledApps
433
-	 * @param bool $reenable
434
-	 * @throws \Exception
435
-	 */
436
-	private function upgradeAppStoreApps(array $disabledApps, $reenable = false) {
437
-		foreach($disabledApps as $app) {
438
-			try {
439
-				$this->emit('\OC\Updater', 'checkAppStoreAppBefore', [$app]);
440
-				if ($this->installer->isUpdateAvailable($app)) {
441
-					$this->emit('\OC\Updater', 'upgradeAppStoreApp', [$app]);
442
-					$this->installer->updateAppstoreApp($app);
443
-				}
444
-				$this->emit('\OC\Updater', 'checkAppStoreApp', [$app]);
445
-
446
-				if ($reenable) {
447
-					$ocApp = new \OC_App();
448
-					$ocApp->enable($app);
449
-				}
450
-			} catch (\Exception $ex) {
451
-				$this->log->logException($ex, ['app' => 'core']);
452
-			}
453
-		}
454
-	}
455
-
456
-	/**
457
-	 * Forward messages emitted by the repair routine
458
-	 */
459
-	private function emitRepairEvents() {
460
-		$dispatcher = \OC::$server->getEventDispatcher();
461
-		$dispatcher->addListener('\OC\Repair::warning', function ($event) {
462
-			if ($event instanceof GenericEvent) {
463
-				$this->emit('\OC\Updater', 'repairWarning', $event->getArguments());
464
-			}
465
-		});
466
-		$dispatcher->addListener('\OC\Repair::error', function ($event) {
467
-			if ($event instanceof GenericEvent) {
468
-				$this->emit('\OC\Updater', 'repairError', $event->getArguments());
469
-			}
470
-		});
471
-		$dispatcher->addListener('\OC\Repair::info', function ($event) {
472
-			if ($event instanceof GenericEvent) {
473
-				$this->emit('\OC\Updater', 'repairInfo', $event->getArguments());
474
-			}
475
-		});
476
-		$dispatcher->addListener('\OC\Repair::step', function ($event) {
477
-			if ($event instanceof GenericEvent) {
478
-				$this->emit('\OC\Updater', 'repairStep', $event->getArguments());
479
-			}
480
-		});
481
-	}
482
-
483
-	private function logAllEvents() {
484
-		$log = $this->log;
485
-
486
-		$dispatcher = \OC::$server->getEventDispatcher();
487
-		$dispatcher->addListener('\OC\DB\Migrator::executeSql', function($event) use ($log) {
488
-			if (!$event instanceof GenericEvent) {
489
-				return;
490
-			}
491
-			$log->info('\OC\DB\Migrator::executeSql: ' . $event->getSubject() . ' (' . $event->getArgument(0) . ' of ' . $event->getArgument(1) . ')', ['app' => 'updater']);
492
-		});
493
-		$dispatcher->addListener('\OC\DB\Migrator::checkTable', function($event) use ($log) {
494
-			if (!$event instanceof GenericEvent) {
495
-				return;
496
-			}
497
-			$log->info('\OC\DB\Migrator::checkTable: ' . $event->getSubject() . ' (' . $event->getArgument(0) . ' of ' . $event->getArgument(1) . ')', ['app' => 'updater']);
498
-		});
499
-
500
-		$repairListener = function($event) use ($log) {
501
-			if (!$event instanceof GenericEvent) {
502
-				return;
503
-			}
504
-			switch ($event->getSubject()) {
505
-				case '\OC\Repair::startProgress':
506
-					$log->info('\OC\Repair::startProgress: Starting ... ' . $event->getArgument(1) .  ' (' . $event->getArgument(0) . ')', ['app' => 'updater']);
507
-					break;
508
-				case '\OC\Repair::advance':
509
-					$desc = $event->getArgument(1);
510
-					if (empty($desc)) {
511
-						$desc = '';
512
-					}
513
-					$log->info('\OC\Repair::advance: ' . $desc . ' (' . $event->getArgument(0) . ')', ['app' => 'updater']);
514
-
515
-					break;
516
-				case '\OC\Repair::finishProgress':
517
-					$log->info('\OC\Repair::finishProgress', ['app' => 'updater']);
518
-					break;
519
-				case '\OC\Repair::step':
520
-					$log->info('\OC\Repair::step: Repair step: ' . $event->getArgument(0), ['app' => 'updater']);
521
-					break;
522
-				case '\OC\Repair::info':
523
-					$log->info('\OC\Repair::info: Repair info: ' . $event->getArgument(0), ['app' => 'updater']);
524
-					break;
525
-				case '\OC\Repair::warning':
526
-					$log->warning('\OC\Repair::warning: Repair warning: ' . $event->getArgument(0), ['app' => 'updater']);
527
-					break;
528
-				case '\OC\Repair::error':
529
-					$log->error('\OC\Repair::error: Repair error: ' . $event->getArgument(0), ['app' => 'updater']);
530
-					break;
531
-			}
532
-		};
533
-
534
-		$dispatcher->addListener('\OC\Repair::startProgress', $repairListener);
535
-		$dispatcher->addListener('\OC\Repair::advance', $repairListener);
536
-		$dispatcher->addListener('\OC\Repair::finishProgress', $repairListener);
537
-		$dispatcher->addListener('\OC\Repair::step', $repairListener);
538
-		$dispatcher->addListener('\OC\Repair::info', $repairListener);
539
-		$dispatcher->addListener('\OC\Repair::warning', $repairListener);
540
-		$dispatcher->addListener('\OC\Repair::error', $repairListener);
541
-
542
-
543
-		$this->listen('\OC\Updater', 'maintenanceEnabled', function () use($log) {
544
-			$log->info('\OC\Updater::maintenanceEnabled: Turned on maintenance mode', ['app' => 'updater']);
545
-		});
546
-		$this->listen('\OC\Updater', 'maintenanceDisabled', function () use($log) {
547
-			$log->info('\OC\Updater::maintenanceDisabled: Turned off maintenance mode', ['app' => 'updater']);
548
-		});
549
-		$this->listen('\OC\Updater', 'maintenanceActive', function () use($log) {
550
-			$log->info('\OC\Updater::maintenanceActive: Maintenance mode is kept active', ['app' => 'updater']);
551
-		});
552
-		$this->listen('\OC\Updater', 'updateEnd', function ($success) use($log) {
553
-			if ($success) {
554
-				$log->info('\OC\Updater::updateEnd: Update successful', ['app' => 'updater']);
555
-			} else {
556
-				$log->error('\OC\Updater::updateEnd: Update failed', ['app' => 'updater']);
557
-			}
558
-		});
559
-		$this->listen('\OC\Updater', 'dbUpgradeBefore', function () use($log) {
560
-			$log->info('\OC\Updater::dbUpgradeBefore: Updating database schema', ['app' => 'updater']);
561
-		});
562
-		$this->listen('\OC\Updater', 'dbUpgrade', function () use($log) {
563
-			$log->info('\OC\Updater::dbUpgrade: Updated database', ['app' => 'updater']);
564
-		});
565
-		$this->listen('\OC\Updater', 'dbSimulateUpgradeBefore', function () use($log) {
566
-			$log->info('\OC\Updater::dbSimulateUpgradeBefore: Checking whether the database schema can be updated (this can take a long time depending on the database size)', ['app' => 'updater']);
567
-		});
568
-		$this->listen('\OC\Updater', 'dbSimulateUpgrade', function () use($log) {
569
-			$log->info('\OC\Updater::dbSimulateUpgrade: Checked database schema update', ['app' => 'updater']);
570
-		});
571
-		$this->listen('\OC\Updater', 'incompatibleAppDisabled', function ($app) use($log) {
572
-			$log->info('\OC\Updater::incompatibleAppDisabled: Disabled incompatible app: ' . $app, ['app' => 'updater']);
573
-		});
574
-		$this->listen('\OC\Updater', 'checkAppStoreAppBefore', function ($app) use($log) {
575
-			$log->info('\OC\Updater::checkAppStoreAppBefore: Checking for update of app "' . $app . '" in appstore', ['app' => 'updater']);
576
-		});
577
-		$this->listen('\OC\Updater', 'upgradeAppStoreApp', function ($app) use($log) {
578
-			$log->info('\OC\Updater::upgradeAppStoreApp: Update app "' . $app . '" from appstore', ['app' => 'updater']);
579
-		});
580
-		$this->listen('\OC\Updater', 'checkAppStoreApp', function ($app) use($log) {
581
-			$log->info('\OC\Updater::checkAppStoreApp: Checked for update of app "' . $app . '" in appstore', ['app' => 'updater']);
582
-		});
583
-		$this->listen('\OC\Updater', 'appUpgradeCheckBefore', function () use ($log) {
584
-			$log->info('\OC\Updater::appUpgradeCheckBefore: Checking updates of apps', ['app' => 'updater']);
585
-		});
586
-		$this->listen('\OC\Updater', 'appSimulateUpdate', function ($app) use ($log) {
587
-			$log->info('\OC\Updater::appSimulateUpdate: Checking whether the database schema for <' . $app . '> can be updated (this can take a long time depending on the database size)', ['app' => 'updater']);
588
-		});
589
-		$this->listen('\OC\Updater', 'appUpgradeCheck', function () use ($log) {
590
-			$log->info('\OC\Updater::appUpgradeCheck: Checked database schema update for apps', ['app' => 'updater']);
591
-		});
592
-		$this->listen('\OC\Updater', 'appUpgradeStarted', function ($app) use ($log) {
593
-			$log->info('\OC\Updater::appUpgradeStarted: Updating <' . $app . '> ...', ['app' => 'updater']);
594
-		});
595
-		$this->listen('\OC\Updater', 'appUpgrade', function ($app, $version) use ($log) {
596
-			$log->info('\OC\Updater::appUpgrade: Updated <' . $app . '> to ' . $version, ['app' => 'updater']);
597
-		});
598
-		$this->listen('\OC\Updater', 'failure', function ($message) use($log) {
599
-			$log->error('\OC\Updater::failure: ' . $message, ['app' => 'updater']);
600
-		});
601
-		$this->listen('\OC\Updater', 'setDebugLogLevel', function () use($log) {
602
-			$log->info('\OC\Updater::setDebugLogLevel: Set log level to debug', ['app' => 'updater']);
603
-		});
604
-		$this->listen('\OC\Updater', 'resetLogLevel', function ($logLevel, $logLevelName) use($log) {
605
-			$log->info('\OC\Updater::resetLogLevel: Reset log level to ' . $logLevelName . '(' . $logLevel . ')', ['app' => 'updater']);
606
-		});
607
-		$this->listen('\OC\Updater', 'startCheckCodeIntegrity', function () use($log) {
608
-			$log->info('\OC\Updater::startCheckCodeIntegrity: Starting code integrity check...', ['app' => 'updater']);
609
-		});
610
-		$this->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function () use($log) {
611
-			$log->info('\OC\Updater::finishedCheckCodeIntegrity: Finished code integrity check', ['app' => 'updater']);
612
-		});
613
-
614
-	}
57
+    /** @var ILogger $log */
58
+    private $log;
59
+
60
+    /** @var IConfig */
61
+    private $config;
62
+
63
+    /** @var Checker */
64
+    private $checker;
65
+
66
+    /** @var Installer */
67
+    private $installer;
68
+
69
+    private $logLevelNames = [
70
+        0 => 'Debug',
71
+        1 => 'Info',
72
+        2 => 'Warning',
73
+        3 => 'Error',
74
+        4 => 'Fatal',
75
+    ];
76
+
77
+    /**
78
+     * @param IConfig $config
79
+     * @param Checker $checker
80
+     * @param ILogger $log
81
+     * @param Installer $installer
82
+     */
83
+    public function __construct(IConfig $config,
84
+                                Checker $checker,
85
+                                ILogger $log = null,
86
+                                Installer $installer) {
87
+        $this->log = $log;
88
+        $this->config = $config;
89
+        $this->checker = $checker;
90
+        $this->installer = $installer;
91
+    }
92
+
93
+    /**
94
+     * runs the update actions in maintenance mode, does not upgrade the source files
95
+     * except the main .htaccess file
96
+     *
97
+     * @return bool true if the operation succeeded, false otherwise
98
+     */
99
+    public function upgrade() {
100
+        $this->emitRepairEvents();
101
+        $this->logAllEvents();
102
+
103
+        $logLevel = $this->config->getSystemValue('loglevel', ILogger::WARN);
104
+        $this->emit('\OC\Updater', 'setDebugLogLevel', [ $logLevel, $this->logLevelNames[$logLevel] ]);
105
+        $this->config->setSystemValue('loglevel', ILogger::DEBUG);
106
+
107
+        $wasMaintenanceModeEnabled = $this->config->getSystemValueBool('maintenance');
108
+
109
+        if(!$wasMaintenanceModeEnabled) {
110
+            $this->config->setSystemValue('maintenance', true);
111
+            $this->emit('\OC\Updater', 'maintenanceEnabled');
112
+        }
113
+
114
+        $installedVersion = $this->config->getSystemValue('version', '0.0.0');
115
+        $currentVersion = implode('.', \OCP\Util::getVersion());
116
+
117
+        $this->log->debug('starting upgrade from ' . $installedVersion . ' to ' . $currentVersion, array('app' => 'core'));
118
+
119
+        $success = true;
120
+        try {
121
+            $this->doUpgrade($currentVersion, $installedVersion);
122
+        } catch (HintException $exception) {
123
+            $this->log->logException($exception, ['app' => 'core']);
124
+            $this->emit('\OC\Updater', 'failure', array($exception->getMessage() . ': ' .$exception->getHint()));
125
+            $success = false;
126
+        } catch (\Exception $exception) {
127
+            $this->log->logException($exception, ['app' => 'core']);
128
+            $this->emit('\OC\Updater', 'failure', array(get_class($exception) . ': ' .$exception->getMessage()));
129
+            $success = false;
130
+        }
131
+
132
+        $this->emit('\OC\Updater', 'updateEnd', array($success));
133
+
134
+        if(!$wasMaintenanceModeEnabled && $success) {
135
+            $this->config->setSystemValue('maintenance', false);
136
+            $this->emit('\OC\Updater', 'maintenanceDisabled');
137
+        } else {
138
+            $this->emit('\OC\Updater', 'maintenanceActive');
139
+        }
140
+
141
+        $this->emit('\OC\Updater', 'resetLogLevel', [ $logLevel, $this->logLevelNames[$logLevel] ]);
142
+        $this->config->setSystemValue('loglevel', $logLevel);
143
+        $this->config->setSystemValue('installed', true);
144
+
145
+        return $success;
146
+    }
147
+
148
+    /**
149
+     * Return version from which this version is allowed to upgrade from
150
+     *
151
+     * @return array allowed previous versions per vendor
152
+     */
153
+    private function getAllowedPreviousVersions() {
154
+        // this should really be a JSON file
155
+        require \OC::$SERVERROOT . '/version.php';
156
+        /** @var array $OC_VersionCanBeUpgradedFrom */
157
+        return $OC_VersionCanBeUpgradedFrom;
158
+    }
159
+
160
+    /**
161
+     * Return vendor from which this version was published
162
+     *
163
+     * @return string Get the vendor
164
+     */
165
+    private function getVendor() {
166
+        // this should really be a JSON file
167
+        require \OC::$SERVERROOT . '/version.php';
168
+        /** @var string $vendor */
169
+        return (string) $vendor;
170
+    }
171
+
172
+    /**
173
+     * Whether an upgrade to a specified version is possible
174
+     * @param string $oldVersion
175
+     * @param string $newVersion
176
+     * @param array $allowedPreviousVersions
177
+     * @return bool
178
+     */
179
+    public function isUpgradePossible($oldVersion, $newVersion, array $allowedPreviousVersions) {
180
+        $version = explode('.', $oldVersion);
181
+        $majorMinor = $version[0] . '.' . $version[1];
182
+
183
+        $currentVendor = $this->config->getAppValue('core', 'vendor', '');
184
+
185
+        // Vendor was not set correctly on install, so we have to white-list known versions
186
+        if ($currentVendor === '' && isset($allowedPreviousVersions['owncloud'][$oldVersion])) {
187
+            $currentVendor = 'owncloud';
188
+        }
189
+
190
+        if ($currentVendor === 'nextcloud') {
191
+            return isset($allowedPreviousVersions[$currentVendor][$majorMinor])
192
+                && (version_compare($oldVersion, $newVersion, '<=') ||
193
+                    $this->config->getSystemValue('debug', false));
194
+        }
195
+
196
+        // Check if the instance can be migrated
197
+        return isset($allowedPreviousVersions[$currentVendor][$majorMinor]) ||
198
+            isset($allowedPreviousVersions[$currentVendor][$oldVersion]);
199
+    }
200
+
201
+    /**
202
+     * runs the update actions in maintenance mode, does not upgrade the source files
203
+     * except the main .htaccess file
204
+     *
205
+     * @param string $currentVersion current version to upgrade to
206
+     * @param string $installedVersion previous version from which to upgrade from
207
+     *
208
+     * @throws \Exception
209
+     */
210
+    private function doUpgrade($currentVersion, $installedVersion) {
211
+        // Stop update if the update is over several major versions
212
+        $allowedPreviousVersions = $this->getAllowedPreviousVersions();
213
+        if (!$this->isUpgradePossible($installedVersion, $currentVersion, $allowedPreviousVersions)) {
214
+            throw new \Exception('Updates between multiple major versions and downgrades are unsupported.');
215
+        }
216
+
217
+        // Update .htaccess files
218
+        try {
219
+            Setup::updateHtaccess();
220
+            Setup::protectDataDirectory();
221
+        } catch (\Exception $e) {
222
+            throw new \Exception($e->getMessage());
223
+        }
224
+
225
+        // create empty file in data dir, so we can later find
226
+        // out that this is indeed an ownCloud data directory
227
+        // (in case it didn't exist before)
228
+        file_put_contents($this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', '');
229
+
230
+        // pre-upgrade repairs
231
+        $repair = new Repair(Repair::getBeforeUpgradeRepairSteps(), \OC::$server->getEventDispatcher());
232
+        $repair->run();
233
+
234
+        $this->doCoreUpgrade();
235
+
236
+        try {
237
+            // TODO: replace with the new repair step mechanism https://github.com/owncloud/core/pull/24378
238
+            Setup::installBackgroundJobs();
239
+        } catch (\Exception $e) {
240
+            throw new \Exception($e->getMessage());
241
+        }
242
+
243
+        // update all shipped apps
244
+        $this->checkAppsRequirements();
245
+        $this->doAppUpgrade();
246
+
247
+        // Update the appfetchers version so it downloads the correct list from the appstore
248
+        \OC::$server->getAppFetcher()->setVersion($currentVersion);
249
+
250
+        // upgrade appstore apps
251
+        $this->upgradeAppStoreApps(\OC::$server->getAppManager()->getInstalledApps());
252
+        $this->upgradeAppStoreApps(\OC_App::$autoDisabledApps, true);
253
+
254
+        // install new shipped apps on upgrade
255
+        OC_App::loadApps(['authentication']);
256
+        $errors = Installer::installShippedApps(true);
257
+        foreach ($errors as $appId => $exception) {
258
+            /** @var \Exception $exception */
259
+            $this->log->logException($exception, ['app' => $appId]);
260
+            $this->emit('\OC\Updater', 'failure', [$appId . ': ' . $exception->getMessage()]);
261
+        }
262
+
263
+        // post-upgrade repairs
264
+        $repair = new Repair(Repair::getRepairSteps(), \OC::$server->getEventDispatcher());
265
+        $repair->run();
266
+
267
+        //Invalidate update feed
268
+        $this->config->setAppValue('core', 'lastupdatedat', 0);
269
+
270
+        // Check for code integrity if not disabled
271
+        if(\OC::$server->getIntegrityCodeChecker()->isCodeCheckEnforced()) {
272
+            $this->emit('\OC\Updater', 'startCheckCodeIntegrity');
273
+            $this->checker->runInstanceVerification();
274
+            $this->emit('\OC\Updater', 'finishedCheckCodeIntegrity');
275
+        }
276
+
277
+        // only set the final version if everything went well
278
+        $this->config->setSystemValue('version', implode('.', Util::getVersion()));
279
+        $this->config->setAppValue('core', 'vendor', $this->getVendor());
280
+    }
281
+
282
+    protected function doCoreUpgrade() {
283
+        $this->emit('\OC\Updater', 'dbUpgradeBefore');
284
+
285
+        // execute core migrations
286
+        $ms = new MigrationService('core', \OC::$server->getDatabaseConnection());
287
+        $ms->migrate();
288
+
289
+        $this->emit('\OC\Updater', 'dbUpgrade');
290
+    }
291
+
292
+    /**
293
+     * @param string $version the oc version to check app compatibility with
294
+     */
295
+    protected function checkAppUpgrade($version) {
296
+        $apps = \OC_App::getEnabledApps();
297
+        $this->emit('\OC\Updater', 'appUpgradeCheckBefore');
298
+
299
+        $appManager = \OC::$server->getAppManager();
300
+        foreach ($apps as $appId) {
301
+            $info = \OC_App::getAppInfo($appId);
302
+            $compatible = \OC_App::isAppCompatible($version, $info);
303
+            $isShipped = $appManager->isShipped($appId);
304
+
305
+            if ($compatible && $isShipped && \OC_App::shouldUpgrade($appId)) {
306
+                /**
307
+                 * FIXME: The preupdate check is performed before the database migration, otherwise database changes
308
+                 * are not possible anymore within it. - Consider this when touching the code.
309
+                 * @link https://github.com/owncloud/core/issues/10980
310
+                 * @see \OC_App::updateApp
311
+                 */
312
+                if (file_exists(\OC_App::getAppPath($appId) . '/appinfo/preupdate.php')) {
313
+                    $this->includePreUpdate($appId);
314
+                }
315
+                if (file_exists(\OC_App::getAppPath($appId) . '/appinfo/database.xml')) {
316
+                    $this->emit('\OC\Updater', 'appSimulateUpdate', array($appId));
317
+                    \OC_DB::simulateUpdateDbFromStructure(\OC_App::getAppPath($appId) . '/appinfo/database.xml');
318
+                }
319
+            }
320
+        }
321
+
322
+        $this->emit('\OC\Updater', 'appUpgradeCheck');
323
+    }
324
+
325
+    /**
326
+     * Includes the pre-update file. Done here to prevent namespace mixups.
327
+     * @param string $appId
328
+     */
329
+    private function includePreUpdate($appId) {
330
+        include \OC_App::getAppPath($appId) . '/appinfo/preupdate.php';
331
+    }
332
+
333
+    /**
334
+     * upgrades all apps within a major ownCloud upgrade. Also loads "priority"
335
+     * (types authentication, filesystem, logging, in that order) afterwards.
336
+     *
337
+     * @throws NeedsUpdateException
338
+     */
339
+    protected function doAppUpgrade() {
340
+        $apps = \OC_App::getEnabledApps();
341
+        $priorityTypes = array('authentication', 'filesystem', 'logging');
342
+        $pseudoOtherType = 'other';
343
+        $stacks = array($pseudoOtherType => array());
344
+
345
+        foreach ($apps as $appId) {
346
+            $priorityType = false;
347
+            foreach ($priorityTypes as $type) {
348
+                if(!isset($stacks[$type])) {
349
+                    $stacks[$type] = array();
350
+                }
351
+                if (\OC_App::isType($appId, [$type])) {
352
+                    $stacks[$type][] = $appId;
353
+                    $priorityType = true;
354
+                    break;
355
+                }
356
+            }
357
+            if (!$priorityType) {
358
+                $stacks[$pseudoOtherType][] = $appId;
359
+            }
360
+        }
361
+        foreach ($stacks as $type => $stack) {
362
+            foreach ($stack as $appId) {
363
+                if (\OC_App::shouldUpgrade($appId)) {
364
+                    $this->emit('\OC\Updater', 'appUpgradeStarted', [$appId, \OC_App::getAppVersion($appId)]);
365
+                    \OC_App::updateApp($appId);
366
+                    $this->emit('\OC\Updater', 'appUpgrade', [$appId, \OC_App::getAppVersion($appId)]);
367
+                }
368
+                if($type !== $pseudoOtherType) {
369
+                    // load authentication, filesystem and logging apps after
370
+                    // upgrading them. Other apps my need to rely on modifying
371
+                    // user and/or filesystem aspects.
372
+                    \OC_App::loadApp($appId);
373
+                }
374
+            }
375
+        }
376
+    }
377
+
378
+    /**
379
+     * check if the current enabled apps are compatible with the current
380
+     * ownCloud version. disable them if not.
381
+     * This is important if you upgrade ownCloud and have non ported 3rd
382
+     * party apps installed.
383
+     *
384
+     * @return array
385
+     * @throws \Exception
386
+     */
387
+    private function checkAppsRequirements() {
388
+        $isCoreUpgrade = $this->isCodeUpgrade();
389
+        $apps = OC_App::getEnabledApps();
390
+        $version = implode('.', Util::getVersion());
391
+        $disabledApps = [];
392
+        $appManager = \OC::$server->getAppManager();
393
+        foreach ($apps as $app) {
394
+            // check if the app is compatible with this version of ownCloud
395
+            $info = OC_App::getAppInfo($app);
396
+            if($info === null || !OC_App::isAppCompatible($version, $info)) {
397
+                if ($appManager->isShipped($app)) {
398
+                    throw new \UnexpectedValueException('The files of the app "' . $app . '" were not correctly replaced before running the update');
399
+                }
400
+                \OC::$server->getAppManager()->disableApp($app);
401
+                $this->emit('\OC\Updater', 'incompatibleAppDisabled', array($app));
402
+            }
403
+            // no need to disable any app in case this is a non-core upgrade
404
+            if (!$isCoreUpgrade) {
405
+                continue;
406
+            }
407
+            // shipped apps will remain enabled
408
+            if ($appManager->isShipped($app)) {
409
+                continue;
410
+            }
411
+            // authentication and session apps will remain enabled as well
412
+            if (OC_App::isType($app, ['session', 'authentication'])) {
413
+                continue;
414
+            }
415
+        }
416
+        return $disabledApps;
417
+    }
418
+
419
+    /**
420
+     * @return bool
421
+     */
422
+    private function isCodeUpgrade() {
423
+        $installedVersion = $this->config->getSystemValue('version', '0.0.0');
424
+        $currentVersion = implode('.', Util::getVersion());
425
+        if (version_compare($currentVersion, $installedVersion, '>')) {
426
+            return true;
427
+        }
428
+        return false;
429
+    }
430
+
431
+    /**
432
+     * @param array $disabledApps
433
+     * @param bool $reenable
434
+     * @throws \Exception
435
+     */
436
+    private function upgradeAppStoreApps(array $disabledApps, $reenable = false) {
437
+        foreach($disabledApps as $app) {
438
+            try {
439
+                $this->emit('\OC\Updater', 'checkAppStoreAppBefore', [$app]);
440
+                if ($this->installer->isUpdateAvailable($app)) {
441
+                    $this->emit('\OC\Updater', 'upgradeAppStoreApp', [$app]);
442
+                    $this->installer->updateAppstoreApp($app);
443
+                }
444
+                $this->emit('\OC\Updater', 'checkAppStoreApp', [$app]);
445
+
446
+                if ($reenable) {
447
+                    $ocApp = new \OC_App();
448
+                    $ocApp->enable($app);
449
+                }
450
+            } catch (\Exception $ex) {
451
+                $this->log->logException($ex, ['app' => 'core']);
452
+            }
453
+        }
454
+    }
455
+
456
+    /**
457
+     * Forward messages emitted by the repair routine
458
+     */
459
+    private function emitRepairEvents() {
460
+        $dispatcher = \OC::$server->getEventDispatcher();
461
+        $dispatcher->addListener('\OC\Repair::warning', function ($event) {
462
+            if ($event instanceof GenericEvent) {
463
+                $this->emit('\OC\Updater', 'repairWarning', $event->getArguments());
464
+            }
465
+        });
466
+        $dispatcher->addListener('\OC\Repair::error', function ($event) {
467
+            if ($event instanceof GenericEvent) {
468
+                $this->emit('\OC\Updater', 'repairError', $event->getArguments());
469
+            }
470
+        });
471
+        $dispatcher->addListener('\OC\Repair::info', function ($event) {
472
+            if ($event instanceof GenericEvent) {
473
+                $this->emit('\OC\Updater', 'repairInfo', $event->getArguments());
474
+            }
475
+        });
476
+        $dispatcher->addListener('\OC\Repair::step', function ($event) {
477
+            if ($event instanceof GenericEvent) {
478
+                $this->emit('\OC\Updater', 'repairStep', $event->getArguments());
479
+            }
480
+        });
481
+    }
482
+
483
+    private function logAllEvents() {
484
+        $log = $this->log;
485
+
486
+        $dispatcher = \OC::$server->getEventDispatcher();
487
+        $dispatcher->addListener('\OC\DB\Migrator::executeSql', function($event) use ($log) {
488
+            if (!$event instanceof GenericEvent) {
489
+                return;
490
+            }
491
+            $log->info('\OC\DB\Migrator::executeSql: ' . $event->getSubject() . ' (' . $event->getArgument(0) . ' of ' . $event->getArgument(1) . ')', ['app' => 'updater']);
492
+        });
493
+        $dispatcher->addListener('\OC\DB\Migrator::checkTable', function($event) use ($log) {
494
+            if (!$event instanceof GenericEvent) {
495
+                return;
496
+            }
497
+            $log->info('\OC\DB\Migrator::checkTable: ' . $event->getSubject() . ' (' . $event->getArgument(0) . ' of ' . $event->getArgument(1) . ')', ['app' => 'updater']);
498
+        });
499
+
500
+        $repairListener = function($event) use ($log) {
501
+            if (!$event instanceof GenericEvent) {
502
+                return;
503
+            }
504
+            switch ($event->getSubject()) {
505
+                case '\OC\Repair::startProgress':
506
+                    $log->info('\OC\Repair::startProgress: Starting ... ' . $event->getArgument(1) .  ' (' . $event->getArgument(0) . ')', ['app' => 'updater']);
507
+                    break;
508
+                case '\OC\Repair::advance':
509
+                    $desc = $event->getArgument(1);
510
+                    if (empty($desc)) {
511
+                        $desc = '';
512
+                    }
513
+                    $log->info('\OC\Repair::advance: ' . $desc . ' (' . $event->getArgument(0) . ')', ['app' => 'updater']);
514
+
515
+                    break;
516
+                case '\OC\Repair::finishProgress':
517
+                    $log->info('\OC\Repair::finishProgress', ['app' => 'updater']);
518
+                    break;
519
+                case '\OC\Repair::step':
520
+                    $log->info('\OC\Repair::step: Repair step: ' . $event->getArgument(0), ['app' => 'updater']);
521
+                    break;
522
+                case '\OC\Repair::info':
523
+                    $log->info('\OC\Repair::info: Repair info: ' . $event->getArgument(0), ['app' => 'updater']);
524
+                    break;
525
+                case '\OC\Repair::warning':
526
+                    $log->warning('\OC\Repair::warning: Repair warning: ' . $event->getArgument(0), ['app' => 'updater']);
527
+                    break;
528
+                case '\OC\Repair::error':
529
+                    $log->error('\OC\Repair::error: Repair error: ' . $event->getArgument(0), ['app' => 'updater']);
530
+                    break;
531
+            }
532
+        };
533
+
534
+        $dispatcher->addListener('\OC\Repair::startProgress', $repairListener);
535
+        $dispatcher->addListener('\OC\Repair::advance', $repairListener);
536
+        $dispatcher->addListener('\OC\Repair::finishProgress', $repairListener);
537
+        $dispatcher->addListener('\OC\Repair::step', $repairListener);
538
+        $dispatcher->addListener('\OC\Repair::info', $repairListener);
539
+        $dispatcher->addListener('\OC\Repair::warning', $repairListener);
540
+        $dispatcher->addListener('\OC\Repair::error', $repairListener);
541
+
542
+
543
+        $this->listen('\OC\Updater', 'maintenanceEnabled', function () use($log) {
544
+            $log->info('\OC\Updater::maintenanceEnabled: Turned on maintenance mode', ['app' => 'updater']);
545
+        });
546
+        $this->listen('\OC\Updater', 'maintenanceDisabled', function () use($log) {
547
+            $log->info('\OC\Updater::maintenanceDisabled: Turned off maintenance mode', ['app' => 'updater']);
548
+        });
549
+        $this->listen('\OC\Updater', 'maintenanceActive', function () use($log) {
550
+            $log->info('\OC\Updater::maintenanceActive: Maintenance mode is kept active', ['app' => 'updater']);
551
+        });
552
+        $this->listen('\OC\Updater', 'updateEnd', function ($success) use($log) {
553
+            if ($success) {
554
+                $log->info('\OC\Updater::updateEnd: Update successful', ['app' => 'updater']);
555
+            } else {
556
+                $log->error('\OC\Updater::updateEnd: Update failed', ['app' => 'updater']);
557
+            }
558
+        });
559
+        $this->listen('\OC\Updater', 'dbUpgradeBefore', function () use($log) {
560
+            $log->info('\OC\Updater::dbUpgradeBefore: Updating database schema', ['app' => 'updater']);
561
+        });
562
+        $this->listen('\OC\Updater', 'dbUpgrade', function () use($log) {
563
+            $log->info('\OC\Updater::dbUpgrade: Updated database', ['app' => 'updater']);
564
+        });
565
+        $this->listen('\OC\Updater', 'dbSimulateUpgradeBefore', function () use($log) {
566
+            $log->info('\OC\Updater::dbSimulateUpgradeBefore: Checking whether the database schema can be updated (this can take a long time depending on the database size)', ['app' => 'updater']);
567
+        });
568
+        $this->listen('\OC\Updater', 'dbSimulateUpgrade', function () use($log) {
569
+            $log->info('\OC\Updater::dbSimulateUpgrade: Checked database schema update', ['app' => 'updater']);
570
+        });
571
+        $this->listen('\OC\Updater', 'incompatibleAppDisabled', function ($app) use($log) {
572
+            $log->info('\OC\Updater::incompatibleAppDisabled: Disabled incompatible app: ' . $app, ['app' => 'updater']);
573
+        });
574
+        $this->listen('\OC\Updater', 'checkAppStoreAppBefore', function ($app) use($log) {
575
+            $log->info('\OC\Updater::checkAppStoreAppBefore: Checking for update of app "' . $app . '" in appstore', ['app' => 'updater']);
576
+        });
577
+        $this->listen('\OC\Updater', 'upgradeAppStoreApp', function ($app) use($log) {
578
+            $log->info('\OC\Updater::upgradeAppStoreApp: Update app "' . $app . '" from appstore', ['app' => 'updater']);
579
+        });
580
+        $this->listen('\OC\Updater', 'checkAppStoreApp', function ($app) use($log) {
581
+            $log->info('\OC\Updater::checkAppStoreApp: Checked for update of app "' . $app . '" in appstore', ['app' => 'updater']);
582
+        });
583
+        $this->listen('\OC\Updater', 'appUpgradeCheckBefore', function () use ($log) {
584
+            $log->info('\OC\Updater::appUpgradeCheckBefore: Checking updates of apps', ['app' => 'updater']);
585
+        });
586
+        $this->listen('\OC\Updater', 'appSimulateUpdate', function ($app) use ($log) {
587
+            $log->info('\OC\Updater::appSimulateUpdate: Checking whether the database schema for <' . $app . '> can be updated (this can take a long time depending on the database size)', ['app' => 'updater']);
588
+        });
589
+        $this->listen('\OC\Updater', 'appUpgradeCheck', function () use ($log) {
590
+            $log->info('\OC\Updater::appUpgradeCheck: Checked database schema update for apps', ['app' => 'updater']);
591
+        });
592
+        $this->listen('\OC\Updater', 'appUpgradeStarted', function ($app) use ($log) {
593
+            $log->info('\OC\Updater::appUpgradeStarted: Updating <' . $app . '> ...', ['app' => 'updater']);
594
+        });
595
+        $this->listen('\OC\Updater', 'appUpgrade', function ($app, $version) use ($log) {
596
+            $log->info('\OC\Updater::appUpgrade: Updated <' . $app . '> to ' . $version, ['app' => 'updater']);
597
+        });
598
+        $this->listen('\OC\Updater', 'failure', function ($message) use($log) {
599
+            $log->error('\OC\Updater::failure: ' . $message, ['app' => 'updater']);
600
+        });
601
+        $this->listen('\OC\Updater', 'setDebugLogLevel', function () use($log) {
602
+            $log->info('\OC\Updater::setDebugLogLevel: Set log level to debug', ['app' => 'updater']);
603
+        });
604
+        $this->listen('\OC\Updater', 'resetLogLevel', function ($logLevel, $logLevelName) use($log) {
605
+            $log->info('\OC\Updater::resetLogLevel: Reset log level to ' . $logLevelName . '(' . $logLevel . ')', ['app' => 'updater']);
606
+        });
607
+        $this->listen('\OC\Updater', 'startCheckCodeIntegrity', function () use($log) {
608
+            $log->info('\OC\Updater::startCheckCodeIntegrity: Starting code integrity check...', ['app' => 'updater']);
609
+        });
610
+        $this->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function () use($log) {
611
+            $log->info('\OC\Updater::finishedCheckCodeIntegrity: Finished code integrity check', ['app' => 'updater']);
612
+        });
613
+
614
+    }
615 615
 
616 616
 }
Please login to merge, or discard this patch.
Spacing   +65 added lines, -65 removed lines patch added patch discarded remove patch
@@ -101,12 +101,12 @@  discard block
 block discarded – undo
101 101
 		$this->logAllEvents();
102 102
 
103 103
 		$logLevel = $this->config->getSystemValue('loglevel', ILogger::WARN);
104
-		$this->emit('\OC\Updater', 'setDebugLogLevel', [ $logLevel, $this->logLevelNames[$logLevel] ]);
104
+		$this->emit('\OC\Updater', 'setDebugLogLevel', [$logLevel, $this->logLevelNames[$logLevel]]);
105 105
 		$this->config->setSystemValue('loglevel', ILogger::DEBUG);
106 106
 
107 107
 		$wasMaintenanceModeEnabled = $this->config->getSystemValueBool('maintenance');
108 108
 
109
-		if(!$wasMaintenanceModeEnabled) {
109
+		if (!$wasMaintenanceModeEnabled) {
110 110
 			$this->config->setSystemValue('maintenance', true);
111 111
 			$this->emit('\OC\Updater', 'maintenanceEnabled');
112 112
 		}
@@ -114,31 +114,31 @@  discard block
 block discarded – undo
114 114
 		$installedVersion = $this->config->getSystemValue('version', '0.0.0');
115 115
 		$currentVersion = implode('.', \OCP\Util::getVersion());
116 116
 
117
-		$this->log->debug('starting upgrade from ' . $installedVersion . ' to ' . $currentVersion, array('app' => 'core'));
117
+		$this->log->debug('starting upgrade from '.$installedVersion.' to '.$currentVersion, array('app' => 'core'));
118 118
 
119 119
 		$success = true;
120 120
 		try {
121 121
 			$this->doUpgrade($currentVersion, $installedVersion);
122 122
 		} catch (HintException $exception) {
123 123
 			$this->log->logException($exception, ['app' => 'core']);
124
-			$this->emit('\OC\Updater', 'failure', array($exception->getMessage() . ': ' .$exception->getHint()));
124
+			$this->emit('\OC\Updater', 'failure', array($exception->getMessage().': '.$exception->getHint()));
125 125
 			$success = false;
126 126
 		} catch (\Exception $exception) {
127 127
 			$this->log->logException($exception, ['app' => 'core']);
128
-			$this->emit('\OC\Updater', 'failure', array(get_class($exception) . ': ' .$exception->getMessage()));
128
+			$this->emit('\OC\Updater', 'failure', array(get_class($exception).': '.$exception->getMessage()));
129 129
 			$success = false;
130 130
 		}
131 131
 
132 132
 		$this->emit('\OC\Updater', 'updateEnd', array($success));
133 133
 
134
-		if(!$wasMaintenanceModeEnabled && $success) {
134
+		if (!$wasMaintenanceModeEnabled && $success) {
135 135
 			$this->config->setSystemValue('maintenance', false);
136 136
 			$this->emit('\OC\Updater', 'maintenanceDisabled');
137 137
 		} else {
138 138
 			$this->emit('\OC\Updater', 'maintenanceActive');
139 139
 		}
140 140
 
141
-		$this->emit('\OC\Updater', 'resetLogLevel', [ $logLevel, $this->logLevelNames[$logLevel] ]);
141
+		$this->emit('\OC\Updater', 'resetLogLevel', [$logLevel, $this->logLevelNames[$logLevel]]);
142 142
 		$this->config->setSystemValue('loglevel', $logLevel);
143 143
 		$this->config->setSystemValue('installed', true);
144 144
 
@@ -152,7 +152,7 @@  discard block
 block discarded – undo
152 152
 	 */
153 153
 	private function getAllowedPreviousVersions() {
154 154
 		// this should really be a JSON file
155
-		require \OC::$SERVERROOT . '/version.php';
155
+		require \OC::$SERVERROOT.'/version.php';
156 156
 		/** @var array $OC_VersionCanBeUpgradedFrom */
157 157
 		return $OC_VersionCanBeUpgradedFrom;
158 158
 	}
@@ -164,7 +164,7 @@  discard block
 block discarded – undo
164 164
 	 */
165 165
 	private function getVendor() {
166 166
 		// this should really be a JSON file
167
-		require \OC::$SERVERROOT . '/version.php';
167
+		require \OC::$SERVERROOT.'/version.php';
168 168
 		/** @var string $vendor */
169 169
 		return (string) $vendor;
170 170
 	}
@@ -178,7 +178,7 @@  discard block
 block discarded – undo
178 178
 	 */
179 179
 	public function isUpgradePossible($oldVersion, $newVersion, array $allowedPreviousVersions) {
180 180
 		$version = explode('.', $oldVersion);
181
-		$majorMinor = $version[0] . '.' . $version[1];
181
+		$majorMinor = $version[0].'.'.$version[1];
182 182
 
183 183
 		$currentVendor = $this->config->getAppValue('core', 'vendor', '');
184 184
 
@@ -225,7 +225,7 @@  discard block
 block discarded – undo
225 225
 		// create empty file in data dir, so we can later find
226 226
 		// out that this is indeed an ownCloud data directory
227 227
 		// (in case it didn't exist before)
228
-		file_put_contents($this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', '');
228
+		file_put_contents($this->config->getSystemValue('datadirectory', \OC::$SERVERROOT.'/data').'/.ocdata', '');
229 229
 
230 230
 		// pre-upgrade repairs
231 231
 		$repair = new Repair(Repair::getBeforeUpgradeRepairSteps(), \OC::$server->getEventDispatcher());
@@ -257,7 +257,7 @@  discard block
 block discarded – undo
257 257
 		foreach ($errors as $appId => $exception) {
258 258
 			/** @var \Exception $exception */
259 259
 			$this->log->logException($exception, ['app' => $appId]);
260
-			$this->emit('\OC\Updater', 'failure', [$appId . ': ' . $exception->getMessage()]);
260
+			$this->emit('\OC\Updater', 'failure', [$appId.': '.$exception->getMessage()]);
261 261
 		}
262 262
 
263 263
 		// post-upgrade repairs
@@ -268,7 +268,7 @@  discard block
 block discarded – undo
268 268
 		$this->config->setAppValue('core', 'lastupdatedat', 0);
269 269
 
270 270
 		// Check for code integrity if not disabled
271
-		if(\OC::$server->getIntegrityCodeChecker()->isCodeCheckEnforced()) {
271
+		if (\OC::$server->getIntegrityCodeChecker()->isCodeCheckEnforced()) {
272 272
 			$this->emit('\OC\Updater', 'startCheckCodeIntegrity');
273 273
 			$this->checker->runInstanceVerification();
274 274
 			$this->emit('\OC\Updater', 'finishedCheckCodeIntegrity');
@@ -309,12 +309,12 @@  discard block
 block discarded – undo
309 309
 				 * @link https://github.com/owncloud/core/issues/10980
310 310
 				 * @see \OC_App::updateApp
311 311
 				 */
312
-				if (file_exists(\OC_App::getAppPath($appId) . '/appinfo/preupdate.php')) {
312
+				if (file_exists(\OC_App::getAppPath($appId).'/appinfo/preupdate.php')) {
313 313
 					$this->includePreUpdate($appId);
314 314
 				}
315
-				if (file_exists(\OC_App::getAppPath($appId) . '/appinfo/database.xml')) {
315
+				if (file_exists(\OC_App::getAppPath($appId).'/appinfo/database.xml')) {
316 316
 					$this->emit('\OC\Updater', 'appSimulateUpdate', array($appId));
317
-					\OC_DB::simulateUpdateDbFromStructure(\OC_App::getAppPath($appId) . '/appinfo/database.xml');
317
+					\OC_DB::simulateUpdateDbFromStructure(\OC_App::getAppPath($appId).'/appinfo/database.xml');
318 318
 				}
319 319
 			}
320 320
 		}
@@ -327,7 +327,7 @@  discard block
 block discarded – undo
327 327
 	 * @param string $appId
328 328
 	 */
329 329
 	private function includePreUpdate($appId) {
330
-		include \OC_App::getAppPath($appId) . '/appinfo/preupdate.php';
330
+		include \OC_App::getAppPath($appId).'/appinfo/preupdate.php';
331 331
 	}
332 332
 
333 333
 	/**
@@ -345,7 +345,7 @@  discard block
 block discarded – undo
345 345
 		foreach ($apps as $appId) {
346 346
 			$priorityType = false;
347 347
 			foreach ($priorityTypes as $type) {
348
-				if(!isset($stacks[$type])) {
348
+				if (!isset($stacks[$type])) {
349 349
 					$stacks[$type] = array();
350 350
 				}
351 351
 				if (\OC_App::isType($appId, [$type])) {
@@ -365,7 +365,7 @@  discard block
 block discarded – undo
365 365
 					\OC_App::updateApp($appId);
366 366
 					$this->emit('\OC\Updater', 'appUpgrade', [$appId, \OC_App::getAppVersion($appId)]);
367 367
 				}
368
-				if($type !== $pseudoOtherType) {
368
+				if ($type !== $pseudoOtherType) {
369 369
 					// load authentication, filesystem and logging apps after
370 370
 					// upgrading them. Other apps my need to rely on modifying
371 371
 					// user and/or filesystem aspects.
@@ -393,9 +393,9 @@  discard block
 block discarded – undo
393 393
 		foreach ($apps as $app) {
394 394
 			// check if the app is compatible with this version of ownCloud
395 395
 			$info = OC_App::getAppInfo($app);
396
-			if($info === null || !OC_App::isAppCompatible($version, $info)) {
396
+			if ($info === null || !OC_App::isAppCompatible($version, $info)) {
397 397
 				if ($appManager->isShipped($app)) {
398
-					throw new \UnexpectedValueException('The files of the app "' . $app . '" were not correctly replaced before running the update');
398
+					throw new \UnexpectedValueException('The files of the app "'.$app.'" were not correctly replaced before running the update');
399 399
 				}
400 400
 				\OC::$server->getAppManager()->disableApp($app);
401 401
 				$this->emit('\OC\Updater', 'incompatibleAppDisabled', array($app));
@@ -434,7 +434,7 @@  discard block
 block discarded – undo
434 434
 	 * @throws \Exception
435 435
 	 */
436 436
 	private function upgradeAppStoreApps(array $disabledApps, $reenable = false) {
437
-		foreach($disabledApps as $app) {
437
+		foreach ($disabledApps as $app) {
438 438
 			try {
439 439
 				$this->emit('\OC\Updater', 'checkAppStoreAppBefore', [$app]);
440 440
 				if ($this->installer->isUpdateAvailable($app)) {
@@ -458,22 +458,22 @@  discard block
 block discarded – undo
458 458
 	 */
459 459
 	private function emitRepairEvents() {
460 460
 		$dispatcher = \OC::$server->getEventDispatcher();
461
-		$dispatcher->addListener('\OC\Repair::warning', function ($event) {
461
+		$dispatcher->addListener('\OC\Repair::warning', function($event) {
462 462
 			if ($event instanceof GenericEvent) {
463 463
 				$this->emit('\OC\Updater', 'repairWarning', $event->getArguments());
464 464
 			}
465 465
 		});
466
-		$dispatcher->addListener('\OC\Repair::error', function ($event) {
466
+		$dispatcher->addListener('\OC\Repair::error', function($event) {
467 467
 			if ($event instanceof GenericEvent) {
468 468
 				$this->emit('\OC\Updater', 'repairError', $event->getArguments());
469 469
 			}
470 470
 		});
471
-		$dispatcher->addListener('\OC\Repair::info', function ($event) {
471
+		$dispatcher->addListener('\OC\Repair::info', function($event) {
472 472
 			if ($event instanceof GenericEvent) {
473 473
 				$this->emit('\OC\Updater', 'repairInfo', $event->getArguments());
474 474
 			}
475 475
 		});
476
-		$dispatcher->addListener('\OC\Repair::step', function ($event) {
476
+		$dispatcher->addListener('\OC\Repair::step', function($event) {
477 477
 			if ($event instanceof GenericEvent) {
478 478
 				$this->emit('\OC\Updater', 'repairStep', $event->getArguments());
479 479
 			}
@@ -488,13 +488,13 @@  discard block
 block discarded – undo
488 488
 			if (!$event instanceof GenericEvent) {
489 489
 				return;
490 490
 			}
491
-			$log->info('\OC\DB\Migrator::executeSql: ' . $event->getSubject() . ' (' . $event->getArgument(0) . ' of ' . $event->getArgument(1) . ')', ['app' => 'updater']);
491
+			$log->info('\OC\DB\Migrator::executeSql: '.$event->getSubject().' ('.$event->getArgument(0).' of '.$event->getArgument(1).')', ['app' => 'updater']);
492 492
 		});
493 493
 		$dispatcher->addListener('\OC\DB\Migrator::checkTable', function($event) use ($log) {
494 494
 			if (!$event instanceof GenericEvent) {
495 495
 				return;
496 496
 			}
497
-			$log->info('\OC\DB\Migrator::checkTable: ' . $event->getSubject() . ' (' . $event->getArgument(0) . ' of ' . $event->getArgument(1) . ')', ['app' => 'updater']);
497
+			$log->info('\OC\DB\Migrator::checkTable: '.$event->getSubject().' ('.$event->getArgument(0).' of '.$event->getArgument(1).')', ['app' => 'updater']);
498 498
 		});
499 499
 
500 500
 		$repairListener = function($event) use ($log) {
@@ -503,30 +503,30 @@  discard block
 block discarded – undo
503 503
 			}
504 504
 			switch ($event->getSubject()) {
505 505
 				case '\OC\Repair::startProgress':
506
-					$log->info('\OC\Repair::startProgress: Starting ... ' . $event->getArgument(1) .  ' (' . $event->getArgument(0) . ')', ['app' => 'updater']);
506
+					$log->info('\OC\Repair::startProgress: Starting ... '.$event->getArgument(1).' ('.$event->getArgument(0).')', ['app' => 'updater']);
507 507
 					break;
508 508
 				case '\OC\Repair::advance':
509 509
 					$desc = $event->getArgument(1);
510 510
 					if (empty($desc)) {
511 511
 						$desc = '';
512 512
 					}
513
-					$log->info('\OC\Repair::advance: ' . $desc . ' (' . $event->getArgument(0) . ')', ['app' => 'updater']);
513
+					$log->info('\OC\Repair::advance: '.$desc.' ('.$event->getArgument(0).')', ['app' => 'updater']);
514 514
 
515 515
 					break;
516 516
 				case '\OC\Repair::finishProgress':
517 517
 					$log->info('\OC\Repair::finishProgress', ['app' => 'updater']);
518 518
 					break;
519 519
 				case '\OC\Repair::step':
520
-					$log->info('\OC\Repair::step: Repair step: ' . $event->getArgument(0), ['app' => 'updater']);
520
+					$log->info('\OC\Repair::step: Repair step: '.$event->getArgument(0), ['app' => 'updater']);
521 521
 					break;
522 522
 				case '\OC\Repair::info':
523
-					$log->info('\OC\Repair::info: Repair info: ' . $event->getArgument(0), ['app' => 'updater']);
523
+					$log->info('\OC\Repair::info: Repair info: '.$event->getArgument(0), ['app' => 'updater']);
524 524
 					break;
525 525
 				case '\OC\Repair::warning':
526
-					$log->warning('\OC\Repair::warning: Repair warning: ' . $event->getArgument(0), ['app' => 'updater']);
526
+					$log->warning('\OC\Repair::warning: Repair warning: '.$event->getArgument(0), ['app' => 'updater']);
527 527
 					break;
528 528
 				case '\OC\Repair::error':
529
-					$log->error('\OC\Repair::error: Repair error: ' . $event->getArgument(0), ['app' => 'updater']);
529
+					$log->error('\OC\Repair::error: Repair error: '.$event->getArgument(0), ['app' => 'updater']);
530 530
 					break;
531 531
 			}
532 532
 		};
@@ -540,74 +540,74 @@  discard block
 block discarded – undo
540 540
 		$dispatcher->addListener('\OC\Repair::error', $repairListener);
541 541
 
542 542
 
543
-		$this->listen('\OC\Updater', 'maintenanceEnabled', function () use($log) {
543
+		$this->listen('\OC\Updater', 'maintenanceEnabled', function() use($log) {
544 544
 			$log->info('\OC\Updater::maintenanceEnabled: Turned on maintenance mode', ['app' => 'updater']);
545 545
 		});
546
-		$this->listen('\OC\Updater', 'maintenanceDisabled', function () use($log) {
546
+		$this->listen('\OC\Updater', 'maintenanceDisabled', function() use($log) {
547 547
 			$log->info('\OC\Updater::maintenanceDisabled: Turned off maintenance mode', ['app' => 'updater']);
548 548
 		});
549
-		$this->listen('\OC\Updater', 'maintenanceActive', function () use($log) {
549
+		$this->listen('\OC\Updater', 'maintenanceActive', function() use($log) {
550 550
 			$log->info('\OC\Updater::maintenanceActive: Maintenance mode is kept active', ['app' => 'updater']);
551 551
 		});
552
-		$this->listen('\OC\Updater', 'updateEnd', function ($success) use($log) {
552
+		$this->listen('\OC\Updater', 'updateEnd', function($success) use($log) {
553 553
 			if ($success) {
554 554
 				$log->info('\OC\Updater::updateEnd: Update successful', ['app' => 'updater']);
555 555
 			} else {
556 556
 				$log->error('\OC\Updater::updateEnd: Update failed', ['app' => 'updater']);
557 557
 			}
558 558
 		});
559
-		$this->listen('\OC\Updater', 'dbUpgradeBefore', function () use($log) {
559
+		$this->listen('\OC\Updater', 'dbUpgradeBefore', function() use($log) {
560 560
 			$log->info('\OC\Updater::dbUpgradeBefore: Updating database schema', ['app' => 'updater']);
561 561
 		});
562
-		$this->listen('\OC\Updater', 'dbUpgrade', function () use($log) {
562
+		$this->listen('\OC\Updater', 'dbUpgrade', function() use($log) {
563 563
 			$log->info('\OC\Updater::dbUpgrade: Updated database', ['app' => 'updater']);
564 564
 		});
565
-		$this->listen('\OC\Updater', 'dbSimulateUpgradeBefore', function () use($log) {
565
+		$this->listen('\OC\Updater', 'dbSimulateUpgradeBefore', function() use($log) {
566 566
 			$log->info('\OC\Updater::dbSimulateUpgradeBefore: Checking whether the database schema can be updated (this can take a long time depending on the database size)', ['app' => 'updater']);
567 567
 		});
568
-		$this->listen('\OC\Updater', 'dbSimulateUpgrade', function () use($log) {
568
+		$this->listen('\OC\Updater', 'dbSimulateUpgrade', function() use($log) {
569 569
 			$log->info('\OC\Updater::dbSimulateUpgrade: Checked database schema update', ['app' => 'updater']);
570 570
 		});
571
-		$this->listen('\OC\Updater', 'incompatibleAppDisabled', function ($app) use($log) {
572
-			$log->info('\OC\Updater::incompatibleAppDisabled: Disabled incompatible app: ' . $app, ['app' => 'updater']);
571
+		$this->listen('\OC\Updater', 'incompatibleAppDisabled', function($app) use($log) {
572
+			$log->info('\OC\Updater::incompatibleAppDisabled: Disabled incompatible app: '.$app, ['app' => 'updater']);
573 573
 		});
574
-		$this->listen('\OC\Updater', 'checkAppStoreAppBefore', function ($app) use($log) {
575
-			$log->info('\OC\Updater::checkAppStoreAppBefore: Checking for update of app "' . $app . '" in appstore', ['app' => 'updater']);
574
+		$this->listen('\OC\Updater', 'checkAppStoreAppBefore', function($app) use($log) {
575
+			$log->info('\OC\Updater::checkAppStoreAppBefore: Checking for update of app "'.$app.'" in appstore', ['app' => 'updater']);
576 576
 		});
577
-		$this->listen('\OC\Updater', 'upgradeAppStoreApp', function ($app) use($log) {
578
-			$log->info('\OC\Updater::upgradeAppStoreApp: Update app "' . $app . '" from appstore', ['app' => 'updater']);
577
+		$this->listen('\OC\Updater', 'upgradeAppStoreApp', function($app) use($log) {
578
+			$log->info('\OC\Updater::upgradeAppStoreApp: Update app "'.$app.'" from appstore', ['app' => 'updater']);
579 579
 		});
580
-		$this->listen('\OC\Updater', 'checkAppStoreApp', function ($app) use($log) {
581
-			$log->info('\OC\Updater::checkAppStoreApp: Checked for update of app "' . $app . '" in appstore', ['app' => 'updater']);
580
+		$this->listen('\OC\Updater', 'checkAppStoreApp', function($app) use($log) {
581
+			$log->info('\OC\Updater::checkAppStoreApp: Checked for update of app "'.$app.'" in appstore', ['app' => 'updater']);
582 582
 		});
583
-		$this->listen('\OC\Updater', 'appUpgradeCheckBefore', function () use ($log) {
583
+		$this->listen('\OC\Updater', 'appUpgradeCheckBefore', function() use ($log) {
584 584
 			$log->info('\OC\Updater::appUpgradeCheckBefore: Checking updates of apps', ['app' => 'updater']);
585 585
 		});
586
-		$this->listen('\OC\Updater', 'appSimulateUpdate', function ($app) use ($log) {
587
-			$log->info('\OC\Updater::appSimulateUpdate: Checking whether the database schema for <' . $app . '> can be updated (this can take a long time depending on the database size)', ['app' => 'updater']);
586
+		$this->listen('\OC\Updater', 'appSimulateUpdate', function($app) use ($log) {
587
+			$log->info('\OC\Updater::appSimulateUpdate: Checking whether the database schema for <'.$app.'> can be updated (this can take a long time depending on the database size)', ['app' => 'updater']);
588 588
 		});
589
-		$this->listen('\OC\Updater', 'appUpgradeCheck', function () use ($log) {
589
+		$this->listen('\OC\Updater', 'appUpgradeCheck', function() use ($log) {
590 590
 			$log->info('\OC\Updater::appUpgradeCheck: Checked database schema update for apps', ['app' => 'updater']);
591 591
 		});
592
-		$this->listen('\OC\Updater', 'appUpgradeStarted', function ($app) use ($log) {
593
-			$log->info('\OC\Updater::appUpgradeStarted: Updating <' . $app . '> ...', ['app' => 'updater']);
592
+		$this->listen('\OC\Updater', 'appUpgradeStarted', function($app) use ($log) {
593
+			$log->info('\OC\Updater::appUpgradeStarted: Updating <'.$app.'> ...', ['app' => 'updater']);
594 594
 		});
595
-		$this->listen('\OC\Updater', 'appUpgrade', function ($app, $version) use ($log) {
596
-			$log->info('\OC\Updater::appUpgrade: Updated <' . $app . '> to ' . $version, ['app' => 'updater']);
595
+		$this->listen('\OC\Updater', 'appUpgrade', function($app, $version) use ($log) {
596
+			$log->info('\OC\Updater::appUpgrade: Updated <'.$app.'> to '.$version, ['app' => 'updater']);
597 597
 		});
598
-		$this->listen('\OC\Updater', 'failure', function ($message) use($log) {
599
-			$log->error('\OC\Updater::failure: ' . $message, ['app' => 'updater']);
598
+		$this->listen('\OC\Updater', 'failure', function($message) use($log) {
599
+			$log->error('\OC\Updater::failure: '.$message, ['app' => 'updater']);
600 600
 		});
601
-		$this->listen('\OC\Updater', 'setDebugLogLevel', function () use($log) {
601
+		$this->listen('\OC\Updater', 'setDebugLogLevel', function() use($log) {
602 602
 			$log->info('\OC\Updater::setDebugLogLevel: Set log level to debug', ['app' => 'updater']);
603 603
 		});
604
-		$this->listen('\OC\Updater', 'resetLogLevel', function ($logLevel, $logLevelName) use($log) {
605
-			$log->info('\OC\Updater::resetLogLevel: Reset log level to ' . $logLevelName . '(' . $logLevel . ')', ['app' => 'updater']);
604
+		$this->listen('\OC\Updater', 'resetLogLevel', function($logLevel, $logLevelName) use($log) {
605
+			$log->info('\OC\Updater::resetLogLevel: Reset log level to '.$logLevelName.'('.$logLevel.')', ['app' => 'updater']);
606 606
 		});
607
-		$this->listen('\OC\Updater', 'startCheckCodeIntegrity', function () use($log) {
607
+		$this->listen('\OC\Updater', 'startCheckCodeIntegrity', function() use($log) {
608 608
 			$log->info('\OC\Updater::startCheckCodeIntegrity: Starting code integrity check...', ['app' => 'updater']);
609 609
 		});
610
-		$this->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function () use($log) {
610
+		$this->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function() use($log) {
611 611
 			$log->info('\OC\Updater::finishedCheckCodeIntegrity: Finished code integrity check', ['app' => 'updater']);
612 612
 		});
613 613
 
Please login to merge, or discard this patch.
lib/private/AllConfig.php 1 patch
Indentation   +491 added lines, -491 removed lines patch added patch discarded remove patch
@@ -39,495 +39,495 @@
 block discarded – undo
39 39
  * Class to combine all the configuration options ownCloud offers
40 40
  */
41 41
 class AllConfig implements \OCP\IConfig {
42
-	/** @var SystemConfig */
43
-	private $systemConfig;
44
-
45
-	/** @var IDBConnection */
46
-	private $connection;
47
-
48
-	/**
49
-	 * 3 dimensional array with the following structure:
50
-	 * [ $userId =>
51
-	 *     [ $appId =>
52
-	 *         [ $key => $value ]
53
-	 *     ]
54
-	 * ]
55
-	 *
56
-	 * database table: preferences
57
-	 *
58
-	 * methods that use this:
59
-	 *   - setUserValue
60
-	 *   - getUserValue
61
-	 *   - getUserKeys
62
-	 *   - deleteUserValue
63
-	 *   - deleteAllUserValues
64
-	 *   - deleteAppFromAllUsers
65
-	 *
66
-	 * @var CappedMemoryCache $userCache
67
-	 */
68
-	private $userCache;
69
-
70
-	/**
71
-	 * @param SystemConfig $systemConfig
72
-	 */
73
-	public function __construct(SystemConfig $systemConfig) {
74
-		$this->userCache = new CappedMemoryCache();
75
-		$this->systemConfig = $systemConfig;
76
-	}
77
-
78
-	/**
79
-	 * TODO - FIXME This fixes an issue with base.php that cause cyclic
80
-	 * dependencies, especially with autoconfig setup
81
-	 *
82
-	 * Replace this by properly injected database connection. Currently the
83
-	 * base.php triggers the getDatabaseConnection too early which causes in
84
-	 * autoconfig setup case a too early distributed database connection and
85
-	 * the autoconfig then needs to reinit all already initialized dependencies
86
-	 * that use the database connection.
87
-	 *
88
-	 * otherwise a SQLite database is created in the wrong directory
89
-	 * because the database connection was created with an uninitialized config
90
-	 */
91
-	private function fixDIInit() {
92
-		if($this->connection === null) {
93
-			$this->connection = \OC::$server->getDatabaseConnection();
94
-		}
95
-	}
96
-
97
-	/**
98
-	 * Sets and deletes system wide values
99
-	 *
100
-	 * @param array $configs Associative array with `key => value` pairs
101
-	 *                       If value is null, the config key will be deleted
102
-	 */
103
-	public function setSystemValues(array $configs) {
104
-		$this->systemConfig->setValues($configs);
105
-	}
106
-
107
-	/**
108
-	 * Sets a new system wide value
109
-	 *
110
-	 * @param string $key the key of the value, under which will be saved
111
-	 * @param mixed $value the value that should be stored
112
-	 */
113
-	public function setSystemValue($key, $value) {
114
-		$this->systemConfig->setValue($key, $value);
115
-	}
116
-
117
-	/**
118
-	 * Looks up a system wide defined value
119
-	 *
120
-	 * @param string $key the key of the value, under which it was saved
121
-	 * @param mixed $default the default value to be returned if the value isn't set
122
-	 * @return mixed the value or $default
123
-	 */
124
-	public function getSystemValue($key, $default = '') {
125
-		return $this->systemConfig->getValue($key, $default);
126
-	}
127
-
128
-	/**
129
-	 * Looks up a boolean system wide defined value
130
-	 *
131
-	 * @param string $key the key of the value, under which it was saved
132
-	 * @param mixed $default the default value to be returned if the value isn't set
133
-	 * @return mixed the value or $default
134
-	 * @since 16.0.0
135
-	 */
136
-	public function getSystemValueBool(string $key, bool $default = false): bool {
137
-		return (bool) $this->getSystemValue($key, $default);
138
-	}
139
-
140
-	/**
141
-	 * Looks up an integer system wide defined value
142
-	 *
143
-	 * @param string $key the key of the value, under which it was saved
144
-	 * @param mixed $default the default value to be returned if the value isn't set
145
-	 * @return mixed the value or $default
146
-	 * @since 16.0.0
147
-	 */
148
-	public function getSystemValueInt(string $key, int $default = 0): int {
149
-		return (int) $this->getSystemValue($key, $default);
150
-	}
151
-
152
-	/**
153
-	 * Looks up a string system wide defined value
154
-	 *
155
-	 * @param string $key the key of the value, under which it was saved
156
-	 * @param mixed $default the default value to be returned if the value isn't set
157
-	 * @return mixed the value or $default
158
-	 * @since 16.0.0
159
-	 */
160
-	public function getSystemValueString(string $key, string $default = ''): string {
161
-		return (string) $this->getSystemValue($key, $default);
162
-	}
163
-
164
-	/**
165
-	 * Looks up a system wide defined value and filters out sensitive data
166
-	 *
167
-	 * @param string $key the key of the value, under which it was saved
168
-	 * @param mixed $default the default value to be returned if the value isn't set
169
-	 * @return mixed the value or $default
170
-	 */
171
-	public function getFilteredSystemValue($key, $default = '') {
172
-		return $this->systemConfig->getFilteredValue($key, $default);
173
-	}
174
-
175
-	/**
176
-	 * Delete a system wide defined value
177
-	 *
178
-	 * @param string $key the key of the value, under which it was saved
179
-	 */
180
-	public function deleteSystemValue($key) {
181
-		$this->systemConfig->deleteValue($key);
182
-	}
183
-
184
-	/**
185
-	 * Get all keys stored for an app
186
-	 *
187
-	 * @param string $appName the appName that we stored the value under
188
-	 * @return string[] the keys stored for the app
189
-	 */
190
-	public function getAppKeys($appName) {
191
-		return \OC::$server->query(\OC\AppConfig::class)->getKeys($appName);
192
-	}
193
-
194
-	/**
195
-	 * Writes a new app wide value
196
-	 *
197
-	 * @param string $appName the appName that we want to store the value under
198
-	 * @param string $key the key of the value, under which will be saved
199
-	 * @param string|float|int $value the value that should be stored
200
-	 */
201
-	public function setAppValue($appName, $key, $value) {
202
-		\OC::$server->query(\OC\AppConfig::class)->setValue($appName, $key, $value);
203
-	}
204
-
205
-	/**
206
-	 * Looks up an app wide defined value
207
-	 *
208
-	 * @param string $appName the appName that we stored the value under
209
-	 * @param string $key the key of the value, under which it was saved
210
-	 * @param string $default the default value to be returned if the value isn't set
211
-	 * @return string the saved value
212
-	 */
213
-	public function getAppValue($appName, $key, $default = '') {
214
-		return \OC::$server->query(\OC\AppConfig::class)->getValue($appName, $key, $default);
215
-	}
216
-
217
-	/**
218
-	 * Delete an app wide defined value
219
-	 *
220
-	 * @param string $appName the appName that we stored the value under
221
-	 * @param string $key the key of the value, under which it was saved
222
-	 */
223
-	public function deleteAppValue($appName, $key) {
224
-		\OC::$server->query(\OC\AppConfig::class)->deleteKey($appName, $key);
225
-	}
226
-
227
-	/**
228
-	 * Removes all keys in appconfig belonging to the app
229
-	 *
230
-	 * @param string $appName the appName the configs are stored under
231
-	 */
232
-	public function deleteAppValues($appName) {
233
-		\OC::$server->query(\OC\AppConfig::class)->deleteApp($appName);
234
-	}
235
-
236
-
237
-	/**
238
-	 * Set a user defined value
239
-	 *
240
-	 * @param string $userId the userId of the user that we want to store the value under
241
-	 * @param string $appName the appName that we want to store the value under
242
-	 * @param string $key the key under which the value is being stored
243
-	 * @param string|float|int $value the value that you want to store
244
-	 * @param string $preCondition only update if the config value was previously the value passed as $preCondition
245
-	 * @throws \OCP\PreConditionNotMetException if a precondition is specified and is not met
246
-	 * @throws \UnexpectedValueException when trying to store an unexpected value
247
-	 */
248
-	public function setUserValue($userId, $appName, $key, $value, $preCondition = null) {
249
-		if (!is_int($value) && !is_float($value) && !is_string($value)) {
250
-			throw new \UnexpectedValueException('Only integers, floats and strings are allowed as value');
251
-		}
252
-
253
-		// TODO - FIXME
254
-		$this->fixDIInit();
255
-
256
-		$prevValue = $this->getUserValue($userId, $appName, $key, null);
257
-
258
-		if ($prevValue !== null) {
259
-			if ($prevValue === (string)$value) {
260
-				return;
261
-			} else if ($preCondition !== null && $prevValue !== (string)$preCondition) {
262
-				throw new PreConditionNotMetException();
263
-			} else {
264
-				$qb = $this->connection->getQueryBuilder();
265
-				$qb->update('preferences')
266
-					->set('configvalue', $qb->createNamedParameter($value))
267
-					->where($qb->expr()->eq('userid', $qb->createNamedParameter($userId)))
268
-					->andWhere($qb->expr()->eq('appid', $qb->createNamedParameter($appName)))
269
-					->andWhere($qb->expr()->eq('configkey', $qb->createNamedParameter($key)));
270
-				$qb->execute();
271
-
272
-				$this->userCache[$userId][$appName][$key] = (string)$value;
273
-				return;
274
-			}
275
-		}
276
-
277
-		$preconditionArray = [];
278
-		if (isset($preCondition)) {
279
-			$preconditionArray = [
280
-				'configvalue' => $preCondition,
281
-			];
282
-		}
283
-
284
-		$this->connection->setValues('preferences', [
285
-			'userid' => $userId,
286
-			'appid' => $appName,
287
-			'configkey' => $key,
288
-		], [
289
-			'configvalue' => $value,
290
-		], $preconditionArray);
291
-
292
-		// only add to the cache if we already loaded data for the user
293
-		if (isset($this->userCache[$userId])) {
294
-			if (!isset($this->userCache[$userId][$appName])) {
295
-				$this->userCache[$userId][$appName] = array();
296
-			}
297
-			$this->userCache[$userId][$appName][$key] = (string)$value;
298
-		}
299
-	}
300
-
301
-	/**
302
-	 * Getting a user defined value
303
-	 *
304
-	 * @param string $userId the userId of the user that we want to store the value under
305
-	 * @param string $appName the appName that we stored the value under
306
-	 * @param string $key the key under which the value is being stored
307
-	 * @param mixed $default the default value to be returned if the value isn't set
308
-	 * @return string
309
-	 */
310
-	public function getUserValue($userId, $appName, $key, $default = '') {
311
-		$data = $this->getUserValues($userId);
312
-		if (isset($data[$appName]) and isset($data[$appName][$key])) {
313
-			return $data[$appName][$key];
314
-		} else {
315
-			return $default;
316
-		}
317
-	}
318
-
319
-	/**
320
-	 * Get the keys of all stored by an app for the user
321
-	 *
322
-	 * @param string $userId the userId of the user that we want to store the value under
323
-	 * @param string $appName the appName that we stored the value under
324
-	 * @return string[]
325
-	 */
326
-	public function getUserKeys($userId, $appName) {
327
-		$data = $this->getUserValues($userId);
328
-		if (isset($data[$appName])) {
329
-			return array_keys($data[$appName]);
330
-		} else {
331
-			return array();
332
-		}
333
-	}
334
-
335
-	/**
336
-	 * Delete a user value
337
-	 *
338
-	 * @param string $userId the userId of the user that we want to store the value under
339
-	 * @param string $appName the appName that we stored the value under
340
-	 * @param string $key the key under which the value is being stored
341
-	 */
342
-	public function deleteUserValue($userId, $appName, $key) {
343
-		// TODO - FIXME
344
-		$this->fixDIInit();
345
-
346
-		$sql  = 'DELETE FROM `*PREFIX*preferences` '.
347
-				'WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?';
348
-		$this->connection->executeUpdate($sql, array($userId, $appName, $key));
349
-
350
-		if (isset($this->userCache[$userId]) and isset($this->userCache[$userId][$appName])) {
351
-			unset($this->userCache[$userId][$appName][$key]);
352
-		}
353
-	}
354
-
355
-	/**
356
-	 * Delete all user values
357
-	 *
358
-	 * @param string $userId the userId of the user that we want to remove all values from
359
-	 */
360
-	public function deleteAllUserValues($userId) {
361
-		// TODO - FIXME
362
-		$this->fixDIInit();
363
-
364
-		$sql  = 'DELETE FROM `*PREFIX*preferences` '.
365
-			'WHERE `userid` = ?';
366
-		$this->connection->executeUpdate($sql, array($userId));
367
-
368
-		unset($this->userCache[$userId]);
369
-	}
370
-
371
-	/**
372
-	 * Delete all user related values of one app
373
-	 *
374
-	 * @param string $appName the appName of the app that we want to remove all values from
375
-	 */
376
-	public function deleteAppFromAllUsers($appName) {
377
-		// TODO - FIXME
378
-		$this->fixDIInit();
379
-
380
-		$sql  = 'DELETE FROM `*PREFIX*preferences` '.
381
-				'WHERE `appid` = ?';
382
-		$this->connection->executeUpdate($sql, array($appName));
383
-
384
-		foreach ($this->userCache as &$userCache) {
385
-			unset($userCache[$appName]);
386
-		}
387
-	}
388
-
389
-	/**
390
-	 * Returns all user configs sorted by app of one user
391
-	 *
392
-	 * @param string $userId the user ID to get the app configs from
393
-	 * @return array[] - 2 dimensional array with the following structure:
394
-	 *     [ $appId =>
395
-	 *         [ $key => $value ]
396
-	 *     ]
397
-	 */
398
-	private function getUserValues($userId) {
399
-		if (isset($this->userCache[$userId])) {
400
-			return $this->userCache[$userId];
401
-		}
402
-		if ($userId === null || $userId === '') {
403
-			$this->userCache[$userId]=array();
404
-			return $this->userCache[$userId];
405
-		}
406
-
407
-		// TODO - FIXME
408
-		$this->fixDIInit();
409
-
410
-		$data = array();
411
-		$query = 'SELECT `appid`, `configkey`, `configvalue` FROM `*PREFIX*preferences` WHERE `userid` = ?';
412
-		$result = $this->connection->executeQuery($query, array($userId));
413
-		while ($row = $result->fetch()) {
414
-			$appId = $row['appid'];
415
-			if (!isset($data[$appId])) {
416
-				$data[$appId] = array();
417
-			}
418
-			$data[$appId][$row['configkey']] = $row['configvalue'];
419
-		}
420
-		$this->userCache[$userId] = $data;
421
-		return $data;
422
-	}
423
-
424
-	/**
425
-	 * Fetches a mapped list of userId -> value, for a specified app and key and a list of user IDs.
426
-	 *
427
-	 * @param string $appName app to get the value for
428
-	 * @param string $key the key to get the value for
429
-	 * @param array $userIds the user IDs to fetch the values for
430
-	 * @return array Mapped values: userId => value
431
-	 */
432
-	public function getUserValueForUsers($appName, $key, $userIds) {
433
-		// TODO - FIXME
434
-		$this->fixDIInit();
435
-
436
-		if (empty($userIds) || !is_array($userIds)) {
437
-			return array();
438
-		}
439
-
440
-		$chunkedUsers = array_chunk($userIds, 50, true);
441
-		$placeholders50 = implode(',', array_fill(0, 50, '?'));
442
-
443
-		$userValues = array();
444
-		foreach ($chunkedUsers as $chunk) {
445
-			$queryParams = $chunk;
446
-			// create [$app, $key, $chunkedUsers]
447
-			array_unshift($queryParams, $key);
448
-			array_unshift($queryParams, $appName);
449
-
450
-			$placeholders = (count($chunk) === 50) ? $placeholders50 :  implode(',', array_fill(0, count($chunk), '?'));
451
-
452
-			$query    = 'SELECT `userid`, `configvalue` ' .
453
-						'FROM `*PREFIX*preferences` ' .
454
-						'WHERE `appid` = ? AND `configkey` = ? ' .
455
-						'AND `userid` IN (' . $placeholders . ')';
456
-			$result = $this->connection->executeQuery($query, $queryParams);
457
-
458
-			while ($row = $result->fetch()) {
459
-				$userValues[$row['userid']] = $row['configvalue'];
460
-			}
461
-		}
462
-
463
-		return $userValues;
464
-	}
465
-
466
-	/**
467
-	 * Determines the users that have the given value set for a specific app-key-pair
468
-	 *
469
-	 * @param string $appName the app to get the user for
470
-	 * @param string $key the key to get the user for
471
-	 * @param string $value the value to get the user for
472
-	 * @return array of user IDs
473
-	 */
474
-	public function getUsersForUserValue($appName, $key, $value) {
475
-		// TODO - FIXME
476
-		$this->fixDIInit();
477
-
478
-		$sql  = 'SELECT `userid` FROM `*PREFIX*preferences` ' .
479
-				'WHERE `appid` = ? AND `configkey` = ? ';
480
-
481
-		if($this->getSystemValue('dbtype', 'sqlite') === 'oci') {
482
-			//oracle hack: need to explicitly cast CLOB to CHAR for comparison
483
-			$sql .= 'AND to_char(`configvalue`) = ?';
484
-		} else {
485
-			$sql .= 'AND `configvalue` = ?';
486
-		}
487
-
488
-		$result = $this->connection->executeQuery($sql, array($appName, $key, $value));
489
-
490
-		$userIDs = array();
491
-		while ($row = $result->fetch()) {
492
-			$userIDs[] = $row['userid'];
493
-		}
494
-
495
-		return $userIDs;
496
-	}
497
-
498
-	/**
499
-	 * Determines the users that have the given value set for a specific app-key-pair
500
-	 *
501
-	 * @param string $appName the app to get the user for
502
-	 * @param string $key the key to get the user for
503
-	 * @param string $value the value to get the user for
504
-	 * @return array of user IDs
505
-	 */
506
-	public function getUsersForUserValueCaseInsensitive($appName, $key, $value) {
507
-		// TODO - FIXME
508
-		$this->fixDIInit();
509
-
510
-		$sql  = 'SELECT `userid` FROM `*PREFIX*preferences` ' .
511
-			'WHERE `appid` = ? AND `configkey` = ? ';
512
-
513
-		if($this->getSystemValue('dbtype', 'sqlite') === 'oci') {
514
-			//oracle hack: need to explicitly cast CLOB to CHAR for comparison
515
-			$sql .= 'AND LOWER(to_char(`configvalue`)) = LOWER(?)';
516
-		} else {
517
-			$sql .= 'AND LOWER(`configvalue`) = LOWER(?)';
518
-		}
519
-
520
-		$result = $this->connection->executeQuery($sql, array($appName, $key, $value));
521
-
522
-		$userIDs = array();
523
-		while ($row = $result->fetch()) {
524
-			$userIDs[] = $row['userid'];
525
-		}
526
-
527
-		return $userIDs;
528
-	}
529
-
530
-	public function getSystemConfig() {
531
-		return $this->systemConfig;
532
-	}
42
+    /** @var SystemConfig */
43
+    private $systemConfig;
44
+
45
+    /** @var IDBConnection */
46
+    private $connection;
47
+
48
+    /**
49
+     * 3 dimensional array with the following structure:
50
+     * [ $userId =>
51
+     *     [ $appId =>
52
+     *         [ $key => $value ]
53
+     *     ]
54
+     * ]
55
+     *
56
+     * database table: preferences
57
+     *
58
+     * methods that use this:
59
+     *   - setUserValue
60
+     *   - getUserValue
61
+     *   - getUserKeys
62
+     *   - deleteUserValue
63
+     *   - deleteAllUserValues
64
+     *   - deleteAppFromAllUsers
65
+     *
66
+     * @var CappedMemoryCache $userCache
67
+     */
68
+    private $userCache;
69
+
70
+    /**
71
+     * @param SystemConfig $systemConfig
72
+     */
73
+    public function __construct(SystemConfig $systemConfig) {
74
+        $this->userCache = new CappedMemoryCache();
75
+        $this->systemConfig = $systemConfig;
76
+    }
77
+
78
+    /**
79
+     * TODO - FIXME This fixes an issue with base.php that cause cyclic
80
+     * dependencies, especially with autoconfig setup
81
+     *
82
+     * Replace this by properly injected database connection. Currently the
83
+     * base.php triggers the getDatabaseConnection too early which causes in
84
+     * autoconfig setup case a too early distributed database connection and
85
+     * the autoconfig then needs to reinit all already initialized dependencies
86
+     * that use the database connection.
87
+     *
88
+     * otherwise a SQLite database is created in the wrong directory
89
+     * because the database connection was created with an uninitialized config
90
+     */
91
+    private function fixDIInit() {
92
+        if($this->connection === null) {
93
+            $this->connection = \OC::$server->getDatabaseConnection();
94
+        }
95
+    }
96
+
97
+    /**
98
+     * Sets and deletes system wide values
99
+     *
100
+     * @param array $configs Associative array with `key => value` pairs
101
+     *                       If value is null, the config key will be deleted
102
+     */
103
+    public function setSystemValues(array $configs) {
104
+        $this->systemConfig->setValues($configs);
105
+    }
106
+
107
+    /**
108
+     * Sets a new system wide value
109
+     *
110
+     * @param string $key the key of the value, under which will be saved
111
+     * @param mixed $value the value that should be stored
112
+     */
113
+    public function setSystemValue($key, $value) {
114
+        $this->systemConfig->setValue($key, $value);
115
+    }
116
+
117
+    /**
118
+     * Looks up a system wide defined value
119
+     *
120
+     * @param string $key the key of the value, under which it was saved
121
+     * @param mixed $default the default value to be returned if the value isn't set
122
+     * @return mixed the value or $default
123
+     */
124
+    public function getSystemValue($key, $default = '') {
125
+        return $this->systemConfig->getValue($key, $default);
126
+    }
127
+
128
+    /**
129
+     * Looks up a boolean system wide defined value
130
+     *
131
+     * @param string $key the key of the value, under which it was saved
132
+     * @param mixed $default the default value to be returned if the value isn't set
133
+     * @return mixed the value or $default
134
+     * @since 16.0.0
135
+     */
136
+    public function getSystemValueBool(string $key, bool $default = false): bool {
137
+        return (bool) $this->getSystemValue($key, $default);
138
+    }
139
+
140
+    /**
141
+     * Looks up an integer system wide defined value
142
+     *
143
+     * @param string $key the key of the value, under which it was saved
144
+     * @param mixed $default the default value to be returned if the value isn't set
145
+     * @return mixed the value or $default
146
+     * @since 16.0.0
147
+     */
148
+    public function getSystemValueInt(string $key, int $default = 0): int {
149
+        return (int) $this->getSystemValue($key, $default);
150
+    }
151
+
152
+    /**
153
+     * Looks up a string system wide defined value
154
+     *
155
+     * @param string $key the key of the value, under which it was saved
156
+     * @param mixed $default the default value to be returned if the value isn't set
157
+     * @return mixed the value or $default
158
+     * @since 16.0.0
159
+     */
160
+    public function getSystemValueString(string $key, string $default = ''): string {
161
+        return (string) $this->getSystemValue($key, $default);
162
+    }
163
+
164
+    /**
165
+     * Looks up a system wide defined value and filters out sensitive data
166
+     *
167
+     * @param string $key the key of the value, under which it was saved
168
+     * @param mixed $default the default value to be returned if the value isn't set
169
+     * @return mixed the value or $default
170
+     */
171
+    public function getFilteredSystemValue($key, $default = '') {
172
+        return $this->systemConfig->getFilteredValue($key, $default);
173
+    }
174
+
175
+    /**
176
+     * Delete a system wide defined value
177
+     *
178
+     * @param string $key the key of the value, under which it was saved
179
+     */
180
+    public function deleteSystemValue($key) {
181
+        $this->systemConfig->deleteValue($key);
182
+    }
183
+
184
+    /**
185
+     * Get all keys stored for an app
186
+     *
187
+     * @param string $appName the appName that we stored the value under
188
+     * @return string[] the keys stored for the app
189
+     */
190
+    public function getAppKeys($appName) {
191
+        return \OC::$server->query(\OC\AppConfig::class)->getKeys($appName);
192
+    }
193
+
194
+    /**
195
+     * Writes a new app wide value
196
+     *
197
+     * @param string $appName the appName that we want to store the value under
198
+     * @param string $key the key of the value, under which will be saved
199
+     * @param string|float|int $value the value that should be stored
200
+     */
201
+    public function setAppValue($appName, $key, $value) {
202
+        \OC::$server->query(\OC\AppConfig::class)->setValue($appName, $key, $value);
203
+    }
204
+
205
+    /**
206
+     * Looks up an app wide defined value
207
+     *
208
+     * @param string $appName the appName that we stored the value under
209
+     * @param string $key the key of the value, under which it was saved
210
+     * @param string $default the default value to be returned if the value isn't set
211
+     * @return string the saved value
212
+     */
213
+    public function getAppValue($appName, $key, $default = '') {
214
+        return \OC::$server->query(\OC\AppConfig::class)->getValue($appName, $key, $default);
215
+    }
216
+
217
+    /**
218
+     * Delete an app wide defined value
219
+     *
220
+     * @param string $appName the appName that we stored the value under
221
+     * @param string $key the key of the value, under which it was saved
222
+     */
223
+    public function deleteAppValue($appName, $key) {
224
+        \OC::$server->query(\OC\AppConfig::class)->deleteKey($appName, $key);
225
+    }
226
+
227
+    /**
228
+     * Removes all keys in appconfig belonging to the app
229
+     *
230
+     * @param string $appName the appName the configs are stored under
231
+     */
232
+    public function deleteAppValues($appName) {
233
+        \OC::$server->query(\OC\AppConfig::class)->deleteApp($appName);
234
+    }
235
+
236
+
237
+    /**
238
+     * Set a user defined value
239
+     *
240
+     * @param string $userId the userId of the user that we want to store the value under
241
+     * @param string $appName the appName that we want to store the value under
242
+     * @param string $key the key under which the value is being stored
243
+     * @param string|float|int $value the value that you want to store
244
+     * @param string $preCondition only update if the config value was previously the value passed as $preCondition
245
+     * @throws \OCP\PreConditionNotMetException if a precondition is specified and is not met
246
+     * @throws \UnexpectedValueException when trying to store an unexpected value
247
+     */
248
+    public function setUserValue($userId, $appName, $key, $value, $preCondition = null) {
249
+        if (!is_int($value) && !is_float($value) && !is_string($value)) {
250
+            throw new \UnexpectedValueException('Only integers, floats and strings are allowed as value');
251
+        }
252
+
253
+        // TODO - FIXME
254
+        $this->fixDIInit();
255
+
256
+        $prevValue = $this->getUserValue($userId, $appName, $key, null);
257
+
258
+        if ($prevValue !== null) {
259
+            if ($prevValue === (string)$value) {
260
+                return;
261
+            } else if ($preCondition !== null && $prevValue !== (string)$preCondition) {
262
+                throw new PreConditionNotMetException();
263
+            } else {
264
+                $qb = $this->connection->getQueryBuilder();
265
+                $qb->update('preferences')
266
+                    ->set('configvalue', $qb->createNamedParameter($value))
267
+                    ->where($qb->expr()->eq('userid', $qb->createNamedParameter($userId)))
268
+                    ->andWhere($qb->expr()->eq('appid', $qb->createNamedParameter($appName)))
269
+                    ->andWhere($qb->expr()->eq('configkey', $qb->createNamedParameter($key)));
270
+                $qb->execute();
271
+
272
+                $this->userCache[$userId][$appName][$key] = (string)$value;
273
+                return;
274
+            }
275
+        }
276
+
277
+        $preconditionArray = [];
278
+        if (isset($preCondition)) {
279
+            $preconditionArray = [
280
+                'configvalue' => $preCondition,
281
+            ];
282
+        }
283
+
284
+        $this->connection->setValues('preferences', [
285
+            'userid' => $userId,
286
+            'appid' => $appName,
287
+            'configkey' => $key,
288
+        ], [
289
+            'configvalue' => $value,
290
+        ], $preconditionArray);
291
+
292
+        // only add to the cache if we already loaded data for the user
293
+        if (isset($this->userCache[$userId])) {
294
+            if (!isset($this->userCache[$userId][$appName])) {
295
+                $this->userCache[$userId][$appName] = array();
296
+            }
297
+            $this->userCache[$userId][$appName][$key] = (string)$value;
298
+        }
299
+    }
300
+
301
+    /**
302
+     * Getting a user defined value
303
+     *
304
+     * @param string $userId the userId of the user that we want to store the value under
305
+     * @param string $appName the appName that we stored the value under
306
+     * @param string $key the key under which the value is being stored
307
+     * @param mixed $default the default value to be returned if the value isn't set
308
+     * @return string
309
+     */
310
+    public function getUserValue($userId, $appName, $key, $default = '') {
311
+        $data = $this->getUserValues($userId);
312
+        if (isset($data[$appName]) and isset($data[$appName][$key])) {
313
+            return $data[$appName][$key];
314
+        } else {
315
+            return $default;
316
+        }
317
+    }
318
+
319
+    /**
320
+     * Get the keys of all stored by an app for the user
321
+     *
322
+     * @param string $userId the userId of the user that we want to store the value under
323
+     * @param string $appName the appName that we stored the value under
324
+     * @return string[]
325
+     */
326
+    public function getUserKeys($userId, $appName) {
327
+        $data = $this->getUserValues($userId);
328
+        if (isset($data[$appName])) {
329
+            return array_keys($data[$appName]);
330
+        } else {
331
+            return array();
332
+        }
333
+    }
334
+
335
+    /**
336
+     * Delete a user value
337
+     *
338
+     * @param string $userId the userId of the user that we want to store the value under
339
+     * @param string $appName the appName that we stored the value under
340
+     * @param string $key the key under which the value is being stored
341
+     */
342
+    public function deleteUserValue($userId, $appName, $key) {
343
+        // TODO - FIXME
344
+        $this->fixDIInit();
345
+
346
+        $sql  = 'DELETE FROM `*PREFIX*preferences` '.
347
+                'WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?';
348
+        $this->connection->executeUpdate($sql, array($userId, $appName, $key));
349
+
350
+        if (isset($this->userCache[$userId]) and isset($this->userCache[$userId][$appName])) {
351
+            unset($this->userCache[$userId][$appName][$key]);
352
+        }
353
+    }
354
+
355
+    /**
356
+     * Delete all user values
357
+     *
358
+     * @param string $userId the userId of the user that we want to remove all values from
359
+     */
360
+    public function deleteAllUserValues($userId) {
361
+        // TODO - FIXME
362
+        $this->fixDIInit();
363
+
364
+        $sql  = 'DELETE FROM `*PREFIX*preferences` '.
365
+            'WHERE `userid` = ?';
366
+        $this->connection->executeUpdate($sql, array($userId));
367
+
368
+        unset($this->userCache[$userId]);
369
+    }
370
+
371
+    /**
372
+     * Delete all user related values of one app
373
+     *
374
+     * @param string $appName the appName of the app that we want to remove all values from
375
+     */
376
+    public function deleteAppFromAllUsers($appName) {
377
+        // TODO - FIXME
378
+        $this->fixDIInit();
379
+
380
+        $sql  = 'DELETE FROM `*PREFIX*preferences` '.
381
+                'WHERE `appid` = ?';
382
+        $this->connection->executeUpdate($sql, array($appName));
383
+
384
+        foreach ($this->userCache as &$userCache) {
385
+            unset($userCache[$appName]);
386
+        }
387
+    }
388
+
389
+    /**
390
+     * Returns all user configs sorted by app of one user
391
+     *
392
+     * @param string $userId the user ID to get the app configs from
393
+     * @return array[] - 2 dimensional array with the following structure:
394
+     *     [ $appId =>
395
+     *         [ $key => $value ]
396
+     *     ]
397
+     */
398
+    private function getUserValues($userId) {
399
+        if (isset($this->userCache[$userId])) {
400
+            return $this->userCache[$userId];
401
+        }
402
+        if ($userId === null || $userId === '') {
403
+            $this->userCache[$userId]=array();
404
+            return $this->userCache[$userId];
405
+        }
406
+
407
+        // TODO - FIXME
408
+        $this->fixDIInit();
409
+
410
+        $data = array();
411
+        $query = 'SELECT `appid`, `configkey`, `configvalue` FROM `*PREFIX*preferences` WHERE `userid` = ?';
412
+        $result = $this->connection->executeQuery($query, array($userId));
413
+        while ($row = $result->fetch()) {
414
+            $appId = $row['appid'];
415
+            if (!isset($data[$appId])) {
416
+                $data[$appId] = array();
417
+            }
418
+            $data[$appId][$row['configkey']] = $row['configvalue'];
419
+        }
420
+        $this->userCache[$userId] = $data;
421
+        return $data;
422
+    }
423
+
424
+    /**
425
+     * Fetches a mapped list of userId -> value, for a specified app and key and a list of user IDs.
426
+     *
427
+     * @param string $appName app to get the value for
428
+     * @param string $key the key to get the value for
429
+     * @param array $userIds the user IDs to fetch the values for
430
+     * @return array Mapped values: userId => value
431
+     */
432
+    public function getUserValueForUsers($appName, $key, $userIds) {
433
+        // TODO - FIXME
434
+        $this->fixDIInit();
435
+
436
+        if (empty($userIds) || !is_array($userIds)) {
437
+            return array();
438
+        }
439
+
440
+        $chunkedUsers = array_chunk($userIds, 50, true);
441
+        $placeholders50 = implode(',', array_fill(0, 50, '?'));
442
+
443
+        $userValues = array();
444
+        foreach ($chunkedUsers as $chunk) {
445
+            $queryParams = $chunk;
446
+            // create [$app, $key, $chunkedUsers]
447
+            array_unshift($queryParams, $key);
448
+            array_unshift($queryParams, $appName);
449
+
450
+            $placeholders = (count($chunk) === 50) ? $placeholders50 :  implode(',', array_fill(0, count($chunk), '?'));
451
+
452
+            $query    = 'SELECT `userid`, `configvalue` ' .
453
+                        'FROM `*PREFIX*preferences` ' .
454
+                        'WHERE `appid` = ? AND `configkey` = ? ' .
455
+                        'AND `userid` IN (' . $placeholders . ')';
456
+            $result = $this->connection->executeQuery($query, $queryParams);
457
+
458
+            while ($row = $result->fetch()) {
459
+                $userValues[$row['userid']] = $row['configvalue'];
460
+            }
461
+        }
462
+
463
+        return $userValues;
464
+    }
465
+
466
+    /**
467
+     * Determines the users that have the given value set for a specific app-key-pair
468
+     *
469
+     * @param string $appName the app to get the user for
470
+     * @param string $key the key to get the user for
471
+     * @param string $value the value to get the user for
472
+     * @return array of user IDs
473
+     */
474
+    public function getUsersForUserValue($appName, $key, $value) {
475
+        // TODO - FIXME
476
+        $this->fixDIInit();
477
+
478
+        $sql  = 'SELECT `userid` FROM `*PREFIX*preferences` ' .
479
+                'WHERE `appid` = ? AND `configkey` = ? ';
480
+
481
+        if($this->getSystemValue('dbtype', 'sqlite') === 'oci') {
482
+            //oracle hack: need to explicitly cast CLOB to CHAR for comparison
483
+            $sql .= 'AND to_char(`configvalue`) = ?';
484
+        } else {
485
+            $sql .= 'AND `configvalue` = ?';
486
+        }
487
+
488
+        $result = $this->connection->executeQuery($sql, array($appName, $key, $value));
489
+
490
+        $userIDs = array();
491
+        while ($row = $result->fetch()) {
492
+            $userIDs[] = $row['userid'];
493
+        }
494
+
495
+        return $userIDs;
496
+    }
497
+
498
+    /**
499
+     * Determines the users that have the given value set for a specific app-key-pair
500
+     *
501
+     * @param string $appName the app to get the user for
502
+     * @param string $key the key to get the user for
503
+     * @param string $value the value to get the user for
504
+     * @return array of user IDs
505
+     */
506
+    public function getUsersForUserValueCaseInsensitive($appName, $key, $value) {
507
+        // TODO - FIXME
508
+        $this->fixDIInit();
509
+
510
+        $sql  = 'SELECT `userid` FROM `*PREFIX*preferences` ' .
511
+            'WHERE `appid` = ? AND `configkey` = ? ';
512
+
513
+        if($this->getSystemValue('dbtype', 'sqlite') === 'oci') {
514
+            //oracle hack: need to explicitly cast CLOB to CHAR for comparison
515
+            $sql .= 'AND LOWER(to_char(`configvalue`)) = LOWER(?)';
516
+        } else {
517
+            $sql .= 'AND LOWER(`configvalue`) = LOWER(?)';
518
+        }
519
+
520
+        $result = $this->connection->executeQuery($sql, array($appName, $key, $value));
521
+
522
+        $userIDs = array();
523
+        while ($row = $result->fetch()) {
524
+            $userIDs[] = $row['userid'];
525
+        }
526
+
527
+        return $userIDs;
528
+    }
529
+
530
+    public function getSystemConfig() {
531
+        return $this->systemConfig;
532
+    }
533 533
 }
Please login to merge, or discard this patch.
lib/base.php 2 patches
Indentation   +995 added lines, -995 removed lines patch added patch discarded remove patch
@@ -68,1001 +68,1001 @@
 block discarded – undo
68 68
  * OC_autoload!
69 69
  */
70 70
 class OC {
71
-	/**
72
-	 * Associative array for autoloading. classname => filename
73
-	 */
74
-	public static $CLASSPATH = array();
75
-	/**
76
-	 * The installation path for Nextcloud  on the server (e.g. /srv/http/nextcloud)
77
-	 */
78
-	public static $SERVERROOT = '';
79
-	/**
80
-	 * the current request path relative to the Nextcloud root (e.g. files/index.php)
81
-	 */
82
-	private static $SUBURI = '';
83
-	/**
84
-	 * the Nextcloud root path for http requests (e.g. nextcloud/)
85
-	 */
86
-	public static $WEBROOT = '';
87
-	/**
88
-	 * The installation path array of the apps folder on the server (e.g. /srv/http/nextcloud) 'path' and
89
-	 * web path in 'url'
90
-	 */
91
-	public static $APPSROOTS = array();
92
-
93
-	/**
94
-	 * @var string
95
-	 */
96
-	public static $configDir;
97
-
98
-	/**
99
-	 * requested app
100
-	 */
101
-	public static $REQUESTEDAPP = '';
102
-
103
-	/**
104
-	 * check if Nextcloud runs in cli mode
105
-	 */
106
-	public static $CLI = false;
107
-
108
-	/**
109
-	 * @var \OC\Autoloader $loader
110
-	 */
111
-	public static $loader = null;
112
-
113
-	/** @var \Composer\Autoload\ClassLoader $composerAutoloader */
114
-	public static $composerAutoloader = null;
115
-
116
-	/**
117
-	 * @var \OC\Server
118
-	 */
119
-	public static $server = null;
120
-
121
-	/**
122
-	 * @var \OC\Config
123
-	 */
124
-	private static $config = null;
125
-
126
-	/**
127
-	 * @throws \RuntimeException when the 3rdparty directory is missing or
128
-	 * the app path list is empty or contains an invalid path
129
-	 */
130
-	public static function initPaths() {
131
-		if(defined('PHPUNIT_CONFIG_DIR')) {
132
-			self::$configDir = OC::$SERVERROOT . '/' . PHPUNIT_CONFIG_DIR . '/';
133
-		} elseif(defined('PHPUNIT_RUN') and PHPUNIT_RUN and is_dir(OC::$SERVERROOT . '/tests/config/')) {
134
-			self::$configDir = OC::$SERVERROOT . '/tests/config/';
135
-		} elseif($dir = getenv('NEXTCLOUD_CONFIG_DIR')) {
136
-			self::$configDir = rtrim($dir, '/') . '/';
137
-		} else {
138
-			self::$configDir = OC::$SERVERROOT . '/config/';
139
-		}
140
-		self::$config = new \OC\Config(self::$configDir);
141
-
142
-		OC::$SUBURI = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"]), strlen(OC::$SERVERROOT)));
143
-		/**
144
-		 * FIXME: The following lines are required because we can't yet instantiate
145
-		 *        \OC::$server->getRequest() since \OC::$server does not yet exist.
146
-		 */
147
-		$params = [
148
-			'server' => [
149
-				'SCRIPT_NAME' => $_SERVER['SCRIPT_NAME'],
150
-				'SCRIPT_FILENAME' => $_SERVER['SCRIPT_FILENAME'],
151
-			],
152
-		];
153
-		$fakeRequest = new \OC\AppFramework\Http\Request($params, null, new \OC\AllConfig(new \OC\SystemConfig(self::$config)));
154
-		$scriptName = $fakeRequest->getScriptName();
155
-		if (substr($scriptName, -1) == '/') {
156
-			$scriptName .= 'index.php';
157
-			//make sure suburi follows the same rules as scriptName
158
-			if (substr(OC::$SUBURI, -9) != 'index.php') {
159
-				if (substr(OC::$SUBURI, -1) != '/') {
160
-					OC::$SUBURI = OC::$SUBURI . '/';
161
-				}
162
-				OC::$SUBURI = OC::$SUBURI . 'index.php';
163
-			}
164
-		}
165
-
166
-
167
-		if (OC::$CLI) {
168
-			OC::$WEBROOT = self::$config->getValue('overwritewebroot', '');
169
-		} else {
170
-			if (substr($scriptName, 0 - strlen(OC::$SUBURI)) === OC::$SUBURI) {
171
-				OC::$WEBROOT = substr($scriptName, 0, 0 - strlen(OC::$SUBURI));
172
-
173
-				if (OC::$WEBROOT != '' && OC::$WEBROOT[0] !== '/') {
174
-					OC::$WEBROOT = '/' . OC::$WEBROOT;
175
-				}
176
-			} else {
177
-				// The scriptName is not ending with OC::$SUBURI
178
-				// This most likely means that we are calling from CLI.
179
-				// However some cron jobs still need to generate
180
-				// a web URL, so we use overwritewebroot as a fallback.
181
-				OC::$WEBROOT = self::$config->getValue('overwritewebroot', '');
182
-			}
183
-
184
-			// Resolve /nextcloud to /nextcloud/ to ensure to always have a trailing
185
-			// slash which is required by URL generation.
186
-			if (isset($_SERVER['REQUEST_URI']) && $_SERVER['REQUEST_URI'] === \OC::$WEBROOT &&
187
-					substr($_SERVER['REQUEST_URI'], -1) !== '/') {
188
-				header('Location: '.\OC::$WEBROOT.'/');
189
-				exit();
190
-			}
191
-		}
192
-
193
-		// search the apps folder
194
-		$config_paths = self::$config->getValue('apps_paths', array());
195
-		if (!empty($config_paths)) {
196
-			foreach ($config_paths as $paths) {
197
-				if (isset($paths['url']) && isset($paths['path'])) {
198
-					$paths['url'] = rtrim($paths['url'], '/');
199
-					$paths['path'] = rtrim($paths['path'], '/');
200
-					OC::$APPSROOTS[] = $paths;
201
-				}
202
-			}
203
-		} elseif (file_exists(OC::$SERVERROOT . '/apps')) {
204
-			OC::$APPSROOTS[] = array('path' => OC::$SERVERROOT . '/apps', 'url' => '/apps', 'writable' => true);
205
-		} elseif (file_exists(OC::$SERVERROOT . '/../apps')) {
206
-			OC::$APPSROOTS[] = array(
207
-				'path' => rtrim(dirname(OC::$SERVERROOT), '/') . '/apps',
208
-				'url' => '/apps',
209
-				'writable' => true
210
-			);
211
-		}
212
-
213
-		if (empty(OC::$APPSROOTS)) {
214
-			throw new \RuntimeException('apps directory not found! Please put the Nextcloud apps folder in the Nextcloud folder'
215
-				. ' or the folder above. You can also configure the location in the config.php file.');
216
-		}
217
-		$paths = array();
218
-		foreach (OC::$APPSROOTS as $path) {
219
-			$paths[] = $path['path'];
220
-			if (!is_dir($path['path'])) {
221
-				throw new \RuntimeException(sprintf('App directory "%s" not found! Please put the Nextcloud apps folder in the'
222
-					. ' Nextcloud folder or the folder above. You can also configure the location in the'
223
-					. ' config.php file.', $path['path']));
224
-			}
225
-		}
226
-
227
-		// set the right include path
228
-		set_include_path(
229
-			implode(PATH_SEPARATOR, $paths)
230
-		);
231
-	}
232
-
233
-	public static function checkConfig() {
234
-		$l = \OC::$server->getL10N('lib');
235
-
236
-		// Create config if it does not already exist
237
-		$configFilePath = self::$configDir .'/config.php';
238
-		if(!file_exists($configFilePath)) {
239
-			@touch($configFilePath);
240
-		}
241
-
242
-		// Check if config is writable
243
-		$configFileWritable = is_writable($configFilePath);
244
-		if (!$configFileWritable && !OC_Helper::isReadOnlyConfigEnabled()
245
-			|| !$configFileWritable && \OCP\Util::needUpgrade()) {
246
-
247
-			$urlGenerator = \OC::$server->getURLGenerator();
248
-
249
-			if (self::$CLI) {
250
-				echo $l->t('Cannot write into "config" directory!')."\n";
251
-				echo $l->t('This can usually be fixed by giving the webserver write access to the config directory')."\n";
252
-				echo $l->t('See %s', [ $urlGenerator->linkToDocs('admin-dir_permissions') ])."\n";
253
-				echo "\n";
254
-				echo $l->t('Or, if you prefer to keep config.php file read only, set the option "config_is_read_only" to true in it.')."\n";
255
-				echo $l->t('See %s', [ $urlGenerator->linkToDocs('admin-config') ])."\n";
256
-				exit;
257
-			} else {
258
-				OC_Template::printErrorPage(
259
-					$l->t('Cannot write into "config" directory!'),
260
-					$l->t('This can usually be fixed by giving the webserver write access to the config directory. See %s',
261
-					[ $urlGenerator->linkToDocs('admin-dir_permissions') ]) . '. '
262
-					. $l->t('Or, if you prefer to keep config.php file read only, set the option "config_is_read_only" to true in it. See %s',
263
-					[ $urlGenerator->linkToDocs('admin-config') ] ),
264
-					503
265
-				);
266
-			}
267
-		}
268
-	}
269
-
270
-	public static function checkInstalled() {
271
-		if (defined('OC_CONSOLE')) {
272
-			return;
273
-		}
274
-		// Redirect to installer if not installed
275
-		if (!\OC::$server->getSystemConfig()->getValue('installed', false) && OC::$SUBURI !== '/index.php' && OC::$SUBURI !== '/status.php') {
276
-			if (OC::$CLI) {
277
-				throw new Exception('Not installed');
278
-			} else {
279
-				$url = OC::$WEBROOT . '/index.php';
280
-				header('Location: ' . $url);
281
-			}
282
-			exit();
283
-		}
284
-	}
285
-
286
-	public static function checkMaintenanceMode() {
287
-		// Allow ajax update script to execute without being stopped
288
-		if (((bool) \OC::$server->getSystemConfig()->getValue('maintenance', false)) && OC::$SUBURI != '/core/ajax/update.php') {
289
-			// send http status 503
290
-			http_response_code(503);
291
-			header('Retry-After: 120');
292
-
293
-			// render error page
294
-			$template = new OC_Template('', 'update.user', 'guest');
295
-			OC_Util::addScript('maintenance-check');
296
-			OC_Util::addStyle('core', 'guest');
297
-			$template->printPage();
298
-			die();
299
-		}
300
-	}
301
-
302
-	/**
303
-	 * Prints the upgrade page
304
-	 *
305
-	 * @param \OC\SystemConfig $systemConfig
306
-	 */
307
-	private static function printUpgradePage(\OC\SystemConfig $systemConfig) {
308
-		$disableWebUpdater = $systemConfig->getValue('upgrade.disable-web', false);
309
-		$tooBig = false;
310
-		if (!$disableWebUpdater) {
311
-			$apps = \OC::$server->getAppManager();
312
-			if ($apps->isInstalled('user_ldap')) {
313
-				$qb = \OC::$server->getDatabaseConnection()->getQueryBuilder();
314
-
315
-				$result = $qb->select($qb->func()->count('*', 'user_count'))
316
-					->from('ldap_user_mapping')
317
-					->execute();
318
-				$row = $result->fetch();
319
-				$result->closeCursor();
320
-
321
-				$tooBig = ($row['user_count'] > 50);
322
-			}
323
-			if (!$tooBig && $apps->isInstalled('user_saml')) {
324
-				$qb = \OC::$server->getDatabaseConnection()->getQueryBuilder();
325
-
326
-				$result = $qb->select($qb->func()->count('*', 'user_count'))
327
-					->from('user_saml_users')
328
-					->execute();
329
-				$row = $result->fetch();
330
-				$result->closeCursor();
331
-
332
-				$tooBig = ($row['user_count'] > 50);
333
-			}
334
-			if (!$tooBig) {
335
-				// count users
336
-				$stats = \OC::$server->getUserManager()->countUsers();
337
-				$totalUsers = array_sum($stats);
338
-				$tooBig = ($totalUsers > 50);
339
-			}
340
-		}
341
-		$ignoreTooBigWarning = isset($_GET['IKnowThatThisIsABigInstanceAndTheUpdateRequestCouldRunIntoATimeoutAndHowToRestoreABackup']) &&
342
-			$_GET['IKnowThatThisIsABigInstanceAndTheUpdateRequestCouldRunIntoATimeoutAndHowToRestoreABackup'] === 'IAmSuperSureToDoThis';
343
-
344
-		if ($disableWebUpdater || ($tooBig && !$ignoreTooBigWarning)) {
345
-			// send http status 503
346
-			http_response_code(503);
347
-			header('Retry-After: 120');
348
-
349
-			// render error page
350
-			$template = new OC_Template('', 'update.use-cli', 'guest');
351
-			$template->assign('productName', 'nextcloud'); // for now
352
-			$template->assign('version', OC_Util::getVersionString());
353
-			$template->assign('tooBig', $tooBig);
354
-
355
-			$template->printPage();
356
-			die();
357
-		}
358
-
359
-		// check whether this is a core update or apps update
360
-		$installedVersion = $systemConfig->getValue('version', '0.0.0');
361
-		$currentVersion = implode('.', \OCP\Util::getVersion());
362
-
363
-		// if not a core upgrade, then it's apps upgrade
364
-		$isAppsOnlyUpgrade = version_compare($currentVersion, $installedVersion, '=');
365
-
366
-		$oldTheme = $systemConfig->getValue('theme');
367
-		$systemConfig->setValue('theme', '');
368
-		OC_Util::addScript('config'); // needed for web root
369
-		OC_Util::addScript('update');
370
-
371
-		/** @var \OC\App\AppManager $appManager */
372
-		$appManager = \OC::$server->getAppManager();
373
-
374
-		$tmpl = new OC_Template('', 'update.admin', 'guest');
375
-		$tmpl->assign('version', OC_Util::getVersionString());
376
-		$tmpl->assign('isAppsOnlyUpgrade', $isAppsOnlyUpgrade);
377
-
378
-		// get third party apps
379
-		$ocVersion = \OCP\Util::getVersion();
380
-		$ocVersion = implode('.', $ocVersion);
381
-		$incompatibleApps = $appManager->getIncompatibleApps($ocVersion);
382
-		$incompatibleShippedApps = [];
383
-		foreach ($incompatibleApps as $appInfo) {
384
-			if ($appManager->isShipped($appInfo['id'])) {
385
-				$incompatibleShippedApps[] = $appInfo['name'] . ' (' . $appInfo['id'] . ')';
386
-			}
387
-		}
388
-
389
-		if (!empty($incompatibleShippedApps)) {
390
-			$l = \OC::$server->getL10N('core');
391
-			$hint = $l->t('The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server.', [implode(', ', $incompatibleShippedApps)]);
392
-			throw new \OC\HintException('The files of the app ' . implode(', ', $incompatibleShippedApps) . ' were not replaced correctly. Make sure it is a version compatible with the server.', $hint);
393
-		}
394
-
395
-		$tmpl->assign('appsToUpgrade', $appManager->getAppsNeedingUpgrade($ocVersion));
396
-		$tmpl->assign('incompatibleAppsList', $incompatibleApps);
397
-		$tmpl->assign('productName', 'Nextcloud'); // for now
398
-		$tmpl->assign('oldTheme', $oldTheme);
399
-		$tmpl->printPage();
400
-	}
401
-
402
-	public static function initSession() {
403
-		if(self::$server->getRequest()->getServerProtocol() === 'https') {
404
-			ini_set('session.cookie_secure', true);
405
-		}
406
-
407
-		// prevents javascript from accessing php session cookies
408
-		ini_set('session.cookie_httponly', 'true');
409
-
410
-		// set the cookie path to the Nextcloud directory
411
-		$cookie_path = OC::$WEBROOT ? : '/';
412
-		ini_set('session.cookie_path', $cookie_path);
413
-
414
-		// Let the session name be changed in the initSession Hook
415
-		$sessionName = OC_Util::getInstanceId();
416
-
417
-		try {
418
-			// Allow session apps to create a custom session object
419
-			$useCustomSession = false;
420
-			$session = self::$server->getSession();
421
-			OC_Hook::emit('OC', 'initSession', array('session' => &$session, 'sessionName' => &$sessionName, 'useCustomSession' => &$useCustomSession));
422
-			if (!$useCustomSession) {
423
-				// set the session name to the instance id - which is unique
424
-				$session = new \OC\Session\Internal($sessionName);
425
-			}
426
-
427
-			$cryptoWrapper = \OC::$server->getSessionCryptoWrapper();
428
-			$session = $cryptoWrapper->wrapSession($session);
429
-			self::$server->setSession($session);
430
-
431
-			// if session can't be started break with http 500 error
432
-		} catch (Exception $e) {
433
-			\OC::$server->getLogger()->logException($e, ['app' => 'base']);
434
-			//show the user a detailed error page
435
-			OC_Template::printExceptionErrorPage($e, 500);
436
-			die();
437
-		}
438
-
439
-		$sessionLifeTime = self::getSessionLifeTime();
440
-
441
-		// session timeout
442
-		if ($session->exists('LAST_ACTIVITY') && (time() - $session->get('LAST_ACTIVITY') > $sessionLifeTime)) {
443
-			if (isset($_COOKIE[session_name()])) {
444
-				setcookie(session_name(), '', -1, self::$WEBROOT ? : '/');
445
-			}
446
-			\OC::$server->getUserSession()->logout();
447
-		}
448
-
449
-		$session->set('LAST_ACTIVITY', time());
450
-	}
451
-
452
-	/**
453
-	 * @return string
454
-	 */
455
-	private static function getSessionLifeTime() {
456
-		return \OC::$server->getConfig()->getSystemValue('session_lifetime', 60 * 60 * 24);
457
-	}
458
-
459
-	public static function loadAppClassPaths() {
460
-		foreach (OC_App::getEnabledApps() as $app) {
461
-			$appPath = OC_App::getAppPath($app);
462
-			if ($appPath === false) {
463
-				continue;
464
-			}
465
-
466
-			$file = $appPath . '/appinfo/classpath.php';
467
-			if (file_exists($file)) {
468
-				require_once $file;
469
-			}
470
-		}
471
-	}
472
-
473
-	/**
474
-	 * Try to set some values to the required Nextcloud default
475
-	 */
476
-	public static function setRequiredIniValues() {
477
-		@ini_set('default_charset', 'UTF-8');
478
-		@ini_set('gd.jpeg_ignore_warning', '1');
479
-	}
480
-
481
-	/**
482
-	 * Send the same site cookies
483
-	 */
484
-	private static function sendSameSiteCookies() {
485
-		$cookieParams = session_get_cookie_params();
486
-		$secureCookie = ($cookieParams['secure'] === true) ? 'secure; ' : '';
487
-		$policies = [
488
-			'lax',
489
-			'strict',
490
-		];
491
-
492
-		// Append __Host to the cookie if it meets the requirements
493
-		$cookiePrefix = '';
494
-		if($cookieParams['secure'] === true && $cookieParams['path'] === '/') {
495
-			$cookiePrefix = '__Host-';
496
-		}
497
-
498
-		foreach($policies as $policy) {
499
-			header(
500
-				sprintf(
501
-					'Set-Cookie: %snc_sameSiteCookie%s=true; path=%s; httponly;' . $secureCookie . 'expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=%s',
502
-					$cookiePrefix,
503
-					$policy,
504
-					$cookieParams['path'],
505
-					$policy
506
-				),
507
-				false
508
-			);
509
-		}
510
-	}
511
-
512
-	/**
513
-	 * Same Site cookie to further mitigate CSRF attacks. This cookie has to
514
-	 * be set in every request if cookies are sent to add a second level of
515
-	 * defense against CSRF.
516
-	 *
517
-	 * If the cookie is not sent this will set the cookie and reload the page.
518
-	 * We use an additional cookie since we want to protect logout CSRF and
519
-	 * also we can't directly interfere with PHP's session mechanism.
520
-	 */
521
-	private static function performSameSiteCookieProtection() {
522
-		$request = \OC::$server->getRequest();
523
-
524
-		// Some user agents are notorious and don't really properly follow HTTP
525
-		// specifications. For those, have an automated opt-out. Since the protection
526
-		// for remote.php is applied in base.php as starting point we need to opt out
527
-		// here.
528
-		$incompatibleUserAgents = \OC::$server->getConfig()->getSystemValue('csrf.optout');
529
-
530
-		// Fallback, if csrf.optout is unset
531
-		if (!is_array($incompatibleUserAgents)) {
532
-			$incompatibleUserAgents = [
533
-				// OS X Finder
534
-				'/^WebDAVFS/',
535
-				// Windows webdav drive
536
-				'/^Microsoft-WebDAV-MiniRedir/',
537
-			];
538
-		}
539
-
540
-		if($request->isUserAgent($incompatibleUserAgents)) {
541
-			return;
542
-		}
543
-
544
-		if(count($_COOKIE) > 0) {
545
-			$requestUri = $request->getScriptName();
546
-			$processingScript = explode('/', $requestUri);
547
-			$processingScript = $processingScript[count($processingScript)-1];
548
-
549
-			// index.php routes are handled in the middleware
550
-			if($processingScript === 'index.php') {
551
-				return;
552
-			}
553
-
554
-			// All other endpoints require the lax and the strict cookie
555
-			if(!$request->passesStrictCookieCheck()) {
556
-				self::sendSameSiteCookies();
557
-				// Debug mode gets access to the resources without strict cookie
558
-				// due to the fact that the SabreDAV browser also lives there.
559
-				if(!\OC::$server->getConfig()->getSystemValue('debug', false)) {
560
-					http_response_code(\OCP\AppFramework\Http::STATUS_SERVICE_UNAVAILABLE);
561
-					exit();
562
-				}
563
-			}
564
-		} elseif(!isset($_COOKIE['nc_sameSiteCookielax']) || !isset($_COOKIE['nc_sameSiteCookiestrict'])) {
565
-			self::sendSameSiteCookies();
566
-		}
567
-	}
568
-
569
-	public static function init() {
570
-		// calculate the root directories
571
-		OC::$SERVERROOT = str_replace("\\", '/', substr(__DIR__, 0, -4));
572
-
573
-		// register autoloader
574
-		$loaderStart = microtime(true);
575
-		require_once __DIR__ . '/autoloader.php';
576
-		self::$loader = new \OC\Autoloader([
577
-			OC::$SERVERROOT . '/lib/private/legacy',
578
-		]);
579
-		if (defined('PHPUNIT_RUN')) {
580
-			self::$loader->addValidRoot(OC::$SERVERROOT . '/tests');
581
-		}
582
-		spl_autoload_register(array(self::$loader, 'load'));
583
-		$loaderEnd = microtime(true);
584
-
585
-		self::$CLI = (php_sapi_name() == 'cli');
586
-
587
-		// Add default composer PSR-4 autoloader
588
-		self::$composerAutoloader = require_once OC::$SERVERROOT . '/lib/composer/autoload.php';
589
-
590
-		try {
591
-			self::initPaths();
592
-			// setup 3rdparty autoloader
593
-			$vendorAutoLoad = OC::$SERVERROOT. '/3rdparty/autoload.php';
594
-			if (!file_exists($vendorAutoLoad)) {
595
-				throw new \RuntimeException('Composer autoloader not found, unable to continue. Check the folder "3rdparty". Running "git submodule update --init" will initialize the git submodule that handles the subfolder "3rdparty".');
596
-			}
597
-			require_once $vendorAutoLoad;
598
-
599
-		} catch (\RuntimeException $e) {
600
-			if (!self::$CLI) {
601
-				http_response_code(503);
602
-			}
603
-			// we can't use the template error page here, because this needs the
604
-			// DI container which isn't available yet
605
-			print($e->getMessage());
606
-			exit();
607
-		}
608
-
609
-		// setup the basic server
610
-		self::$server = new \OC\Server(\OC::$WEBROOT, self::$config);
611
-		\OC::$server->getEventLogger()->log('autoloader', 'Autoloader', $loaderStart, $loaderEnd);
612
-		\OC::$server->getEventLogger()->start('boot', 'Initialize');
613
-
614
-		// Don't display errors and log them
615
-		error_reporting(E_ALL | E_STRICT);
616
-		@ini_set('display_errors', '0');
617
-		@ini_set('log_errors', '1');
618
-
619
-		if(!date_default_timezone_set('UTC')) {
620
-			throw new \RuntimeException('Could not set timezone to UTC');
621
-		}
622
-
623
-		//try to configure php to enable big file uploads.
624
-		//this doesn´t work always depending on the webserver and php configuration.
625
-		//Let´s try to overwrite some defaults anyway
626
-
627
-		//try to set the maximum execution time to 60min
628
-		if (strpos(@ini_get('disable_functions'), 'set_time_limit') === false) {
629
-			@set_time_limit(3600);
630
-		}
631
-		@ini_set('max_execution_time', '3600');
632
-		@ini_set('max_input_time', '3600');
633
-
634
-		//try to set the maximum filesize to 10G
635
-		@ini_set('upload_max_filesize', '10G');
636
-		@ini_set('post_max_size', '10G');
637
-		@ini_set('file_uploads', '50');
638
-
639
-		self::setRequiredIniValues();
640
-		self::handleAuthHeaders();
641
-		self::registerAutoloaderCache();
642
-
643
-		// initialize intl fallback is necessary
644
-		\Patchwork\Utf8\Bootup::initIntl();
645
-		OC_Util::isSetLocaleWorking();
646
-
647
-		if (!defined('PHPUNIT_RUN')) {
648
-			OC\Log\ErrorHandler::setLogger(\OC::$server->getLogger());
649
-			$debug = \OC::$server->getConfig()->getSystemValue('debug', false);
650
-			OC\Log\ErrorHandler::register($debug);
651
-		}
652
-
653
-		\OC::$server->getEventLogger()->start('init_session', 'Initialize session');
654
-		OC_App::loadApps(array('session'));
655
-		if (!self::$CLI) {
656
-			self::initSession();
657
-		}
658
-		\OC::$server->getEventLogger()->end('init_session');
659
-		self::checkConfig();
660
-		self::checkInstalled();
661
-
662
-		OC_Response::addSecurityHeaders();
663
-
664
-		self::performSameSiteCookieProtection();
665
-
666
-		if (!defined('OC_CONSOLE')) {
667
-			$errors = OC_Util::checkServer(\OC::$server->getSystemConfig());
668
-			if (count($errors) > 0) {
669
-				if (self::$CLI) {
670
-					// Convert l10n string into regular string for usage in database
671
-					$staticErrors = [];
672
-					foreach ($errors as $error) {
673
-						echo $error['error'] . "\n";
674
-						echo $error['hint'] . "\n\n";
675
-						$staticErrors[] = [
676
-							'error' => (string)$error['error'],
677
-							'hint' => (string)$error['hint'],
678
-						];
679
-					}
680
-
681
-					try {
682
-						\OC::$server->getConfig()->setAppValue('core', 'cronErrors', json_encode($staticErrors));
683
-					} catch (\Exception $e) {
684
-						echo('Writing to database failed');
685
-					}
686
-					exit(1);
687
-				} else {
688
-					http_response_code(503);
689
-					OC_Util::addStyle('guest');
690
-					OC_Template::printGuestPage('', 'error', array('errors' => $errors));
691
-					exit;
692
-				}
693
-			} elseif (self::$CLI && \OC::$server->getConfig()->getSystemValue('installed', false)) {
694
-				\OC::$server->getConfig()->deleteAppValue('core', 'cronErrors');
695
-			}
696
-		}
697
-		//try to set the session lifetime
698
-		$sessionLifeTime = self::getSessionLifeTime();
699
-		@ini_set('gc_maxlifetime', (string)$sessionLifeTime);
700
-
701
-		$systemConfig = \OC::$server->getSystemConfig();
702
-
703
-		// User and Groups
704
-		if (!$systemConfig->getValue("installed", false)) {
705
-			self::$server->getSession()->set('user_id', '');
706
-		}
707
-
708
-		OC_User::useBackend(new \OC\User\Database());
709
-		\OC::$server->getGroupManager()->addBackend(new \OC\Group\Database());
710
-
711
-		// Subscribe to the hook
712
-		\OCP\Util::connectHook(
713
-			'\OCA\Files_Sharing\API\Server2Server',
714
-			'preLoginNameUsedAsUserName',
715
-			'\OC\User\Database',
716
-			'preLoginNameUsedAsUserName'
717
-		);
718
-
719
-		//setup extra user backends
720
-		if (!\OCP\Util::needUpgrade()) {
721
-			OC_User::setupBackends();
722
-		} else {
723
-			// Run upgrades in incognito mode
724
-			OC_User::setIncognitoMode(true);
725
-		}
726
-
727
-		self::registerCleanupHooks();
728
-		self::registerFilesystemHooks();
729
-		self::registerShareHooks();
730
-		self::registerEncryptionWrapper();
731
-		self::registerEncryptionHooks();
732
-		self::registerAccountHooks();
733
-
734
-		// Make sure that the application class is not loaded before the database is setup
735
-		if ($systemConfig->getValue("installed", false)) {
736
-			$settings = new \OC\Settings\Application();
737
-			$settings->register();
738
-		}
739
-
740
-		//make sure temporary files are cleaned up
741
-		$tmpManager = \OC::$server->getTempManager();
742
-		register_shutdown_function(array($tmpManager, 'clean'));
743
-		$lockProvider = \OC::$server->getLockingProvider();
744
-		register_shutdown_function(array($lockProvider, 'releaseAll'));
745
-
746
-		// Check whether the sample configuration has been copied
747
-		if($systemConfig->getValue('copied_sample_config', false)) {
748
-			$l = \OC::$server->getL10N('lib');
749
-			OC_Template::printErrorPage(
750
-				$l->t('Sample configuration detected'),
751
-				$l->t('It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php'),
752
-				503
753
-			);
754
-			return;
755
-		}
756
-
757
-		$request = \OC::$server->getRequest();
758
-		$host = $request->getInsecureServerHost();
759
-		/**
760
-		 * if the host passed in headers isn't trusted
761
-		 * FIXME: Should not be in here at all :see_no_evil:
762
-		 */
763
-		if (!OC::$CLI
764
-			// overwritehost is always trusted, workaround to not have to make
765
-			// \OC\AppFramework\Http\Request::getOverwriteHost public
766
-			&& self::$server->getConfig()->getSystemValue('overwritehost') === ''
767
-			&& !\OC::$server->getTrustedDomainHelper()->isTrustedDomain($host)
768
-			&& self::$server->getConfig()->getSystemValue('installed', false)
769
-		) {
770
-			// Allow access to CSS resources
771
-			$isScssRequest = false;
772
-			if(strpos($request->getPathInfo(), '/css/') === 0) {
773
-				$isScssRequest = true;
774
-			}
775
-
776
-			if(substr($request->getRequestUri(), -11) === '/status.php') {
777
-				http_response_code(400);
778
-				header('Content-Type: application/json');
779
-				echo '{"error": "Trusted domain error.", "code": 15}';
780
-				exit();
781
-			}
782
-
783
-			if (!$isScssRequest) {
784
-				http_response_code(400);
785
-
786
-				\OC::$server->getLogger()->info(
787
-					'Trusted domain error. "{remoteAddress}" tried to access using "{host}" as host.',
788
-					[
789
-						'app' => 'core',
790
-						'remoteAddress' => $request->getRemoteAddress(),
791
-						'host' => $host,
792
-					]
793
-				);
794
-
795
-				$tmpl = new OCP\Template('core', 'untrustedDomain', 'guest');
796
-				$tmpl->assign('docUrl', \OC::$server->getURLGenerator()->linkToDocs('admin-trusted-domains'));
797
-				$tmpl->printPage();
798
-
799
-				exit();
800
-			}
801
-		}
802
-		\OC::$server->getEventLogger()->end('boot');
803
-	}
804
-
805
-	/**
806
-	 * register hooks for the cleanup of cache and bruteforce protection
807
-	 */
808
-	public static function registerCleanupHooks() {
809
-		//don't try to do this before we are properly setup
810
-		if (\OC::$server->getSystemConfig()->getValue('installed', false) && !\OCP\Util::needUpgrade()) {
811
-
812
-			// NOTE: This will be replaced to use OCP
813
-			$userSession = self::$server->getUserSession();
814
-			$userSession->listen('\OC\User', 'postLogin', function () use ($userSession) {
815
-				if (!defined('PHPUNIT_RUN')) {
816
-					// reset brute force delay for this IP address and username
817
-					$uid = \OC::$server->getUserSession()->getUser()->getUID();
818
-					$request = \OC::$server->getRequest();
819
-					$throttler = \OC::$server->getBruteForceThrottler();
820
-					$throttler->resetDelay($request->getRemoteAddress(), 'login', ['user' => $uid]);
821
-				}
822
-
823
-				try {
824
-					$cache = new \OC\Cache\File();
825
-					$cache->gc();
826
-				} catch (\OC\ServerNotAvailableException $e) {
827
-					// not a GC exception, pass it on
828
-					throw $e;
829
-				} catch (\OC\ForbiddenException $e) {
830
-					// filesystem blocked for this request, ignore
831
-				} catch (\Exception $e) {
832
-					// a GC exception should not prevent users from using OC,
833
-					// so log the exception
834
-					\OC::$server->getLogger()->logException($e, [
835
-						'message' => 'Exception when running cache gc.',
836
-						'level' => ILogger::WARN,
837
-						'app' => 'core',
838
-					]);
839
-				}
840
-			});
841
-		}
842
-	}
843
-
844
-	private static function registerEncryptionWrapper() {
845
-		$manager = self::$server->getEncryptionManager();
846
-		\OCP\Util::connectHook('OC_Filesystem', 'preSetup', $manager, 'setupStorage');
847
-	}
848
-
849
-	private static function registerEncryptionHooks() {
850
-		$enabled = self::$server->getEncryptionManager()->isEnabled();
851
-		if ($enabled) {
852
-			\OCP\Util::connectHook(Share::class, 'post_shared', HookManager::class, 'postShared');
853
-			\OCP\Util::connectHook(Share::class, 'post_unshare', HookManager::class, 'postUnshared');
854
-			\OCP\Util::connectHook('OC_Filesystem', 'post_rename', HookManager::class, 'postRename');
855
-			\OCP\Util::connectHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', HookManager::class, 'postRestore');
856
-		}
857
-	}
858
-
859
-	private static function registerAccountHooks() {
860
-		$hookHandler = new \OC\Accounts\Hooks(\OC::$server->getLogger());
861
-		\OCP\Util::connectHook('OC_User', 'changeUser', $hookHandler, 'changeUserHook');
862
-	}
863
-
864
-	/**
865
-	 * register hooks for the filesystem
866
-	 */
867
-	public static function registerFilesystemHooks() {
868
-		// Check for blacklisted files
869
-		OC_Hook::connect('OC_Filesystem', 'write', Filesystem::class, 'isBlacklisted');
870
-		OC_Hook::connect('OC_Filesystem', 'rename', Filesystem::class, 'isBlacklisted');
871
-	}
872
-
873
-	/**
874
-	 * register hooks for sharing
875
-	 */
876
-	public static function registerShareHooks() {
877
-		if (\OC::$server->getSystemConfig()->getValue('installed')) {
878
-			OC_Hook::connect('OC_User', 'post_deleteUser', Hooks::class, 'post_deleteUser');
879
-			OC_Hook::connect('OC_User', 'post_removeFromGroup', Hooks::class, 'post_removeFromGroup');
880
-			OC_Hook::connect('OC_User', 'post_deleteGroup', Hooks::class, 'post_deleteGroup');
881
-		}
882
-	}
883
-
884
-	protected static function registerAutoloaderCache() {
885
-		// The class loader takes an optional low-latency cache, which MUST be
886
-		// namespaced. The instanceid is used for namespacing, but might be
887
-		// unavailable at this point. Furthermore, it might not be possible to
888
-		// generate an instanceid via \OC_Util::getInstanceId() because the
889
-		// config file may not be writable. As such, we only register a class
890
-		// loader cache if instanceid is available without trying to create one.
891
-		$instanceId = \OC::$server->getSystemConfig()->getValue('instanceid', null);
892
-		if ($instanceId) {
893
-			try {
894
-				$memcacheFactory = \OC::$server->getMemCacheFactory();
895
-				self::$loader->setMemoryCache($memcacheFactory->createLocal('Autoloader'));
896
-			} catch (\Exception $ex) {
897
-			}
898
-		}
899
-	}
900
-
901
-	/**
902
-	 * Handle the request
903
-	 */
904
-	public static function handleRequest() {
905
-
906
-		\OC::$server->getEventLogger()->start('handle_request', 'Handle request');
907
-		$systemConfig = \OC::$server->getSystemConfig();
908
-		// load all the classpaths from the enabled apps so they are available
909
-		// in the routing files of each app
910
-		OC::loadAppClassPaths();
911
-
912
-		// Check if Nextcloud is installed or in maintenance (update) mode
913
-		if (!$systemConfig->getValue('installed', false)) {
914
-			\OC::$server->getSession()->clear();
915
-			$setupHelper = new OC\Setup(
916
-				$systemConfig,
917
-				\OC::$server->getIniWrapper(),
918
-				\OC::$server->getL10N('lib'),
919
-				\OC::$server->query(\OCP\Defaults::class),
920
-				\OC::$server->getLogger(),
921
-				\OC::$server->getSecureRandom(),
922
-				\OC::$server->query(\OC\Installer::class)
923
-			);
924
-			$controller = new OC\Core\Controller\SetupController($setupHelper);
925
-			$controller->run($_POST);
926
-			exit();
927
-		}
928
-
929
-		$request = \OC::$server->getRequest();
930
-		$requestPath = $request->getRawPathInfo();
931
-		if ($requestPath === '/heartbeat') {
932
-			return;
933
-		}
934
-		if (substr($requestPath, -3) !== '.js') { // we need these files during the upgrade
935
-			self::checkMaintenanceMode();
936
-
937
-			if (\OCP\Util::needUpgrade()) {
938
-				if (function_exists('opcache_reset')) {
939
-					opcache_reset();
940
-				}
941
-				if (!((bool) $systemConfig->getValue('maintenance', false))) {
942
-					self::printUpgradePage($systemConfig);
943
-					exit();
944
-				}
945
-			}
946
-		}
947
-
948
-		// emergency app disabling
949
-		if ($requestPath === '/disableapp'
950
-			&& $request->getMethod() === 'POST'
951
-			&& ((array)$request->getParam('appid')) !== ''
952
-		) {
953
-			\OC_JSON::callCheck();
954
-			\OC_JSON::checkAdminUser();
955
-			$appIds = (array)$request->getParam('appid');
956
-			foreach($appIds as $appId) {
957
-				$appId = \OC_App::cleanAppId($appId);
958
-				\OC::$server->getAppManager()->disableApp($appId);
959
-			}
960
-			\OC_JSON::success();
961
-			exit();
962
-		}
963
-
964
-		// Always load authentication apps
965
-		OC_App::loadApps(['authentication']);
966
-
967
-		// Load minimum set of apps
968
-		if (!\OCP\Util::needUpgrade()
969
-			&& !((bool) $systemConfig->getValue('maintenance', false))) {
970
-			// For logged-in users: Load everything
971
-			if(\OC::$server->getUserSession()->isLoggedIn()) {
972
-				OC_App::loadApps();
973
-			} else {
974
-				// For guests: Load only filesystem and logging
975
-				OC_App::loadApps(array('filesystem', 'logging'));
976
-				self::handleLogin($request);
977
-			}
978
-		}
979
-
980
-		if (!self::$CLI) {
981
-			try {
982
-				if (!((bool) $systemConfig->getValue('maintenance', false)) && !\OCP\Util::needUpgrade()) {
983
-					OC_App::loadApps(array('filesystem', 'logging'));
984
-					OC_App::loadApps();
985
-				}
986
-				OC_Util::setupFS();
987
-				OC::$server->getRouter()->match(\OC::$server->getRequest()->getRawPathInfo());
988
-				return;
989
-			} catch (Symfony\Component\Routing\Exception\ResourceNotFoundException $e) {
990
-				//header('HTTP/1.0 404 Not Found');
991
-			} catch (Symfony\Component\Routing\Exception\MethodNotAllowedException $e) {
992
-				http_response_code(405);
993
-				return;
994
-			}
995
-		}
996
-
997
-		// Handle WebDAV
998
-		if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PROPFIND') {
999
-			// not allowed any more to prevent people
1000
-			// mounting this root directly.
1001
-			// Users need to mount remote.php/webdav instead.
1002
-			http_response_code(405);
1003
-			return;
1004
-		}
1005
-
1006
-		// Someone is logged in
1007
-		if (\OC::$server->getUserSession()->isLoggedIn()) {
1008
-			OC_App::loadApps();
1009
-			OC_User::setupBackends();
1010
-			OC_Util::setupFS();
1011
-			// FIXME
1012
-			// Redirect to default application
1013
-			OC_Util::redirectToDefaultPage();
1014
-		} else {
1015
-			// Not handled and not logged in
1016
-			header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute('core.login.showLoginForm'));
1017
-		}
1018
-	}
1019
-
1020
-	/**
1021
-	 * Check login: apache auth, auth token, basic auth
1022
-	 *
1023
-	 * @param OCP\IRequest $request
1024
-	 * @return boolean
1025
-	 */
1026
-	static function handleLogin(OCP\IRequest $request) {
1027
-		$userSession = self::$server->getUserSession();
1028
-		if (OC_User::handleApacheAuth()) {
1029
-			return true;
1030
-		}
1031
-		if ($userSession->tryTokenLogin($request)) {
1032
-			return true;
1033
-		}
1034
-		if (isset($_COOKIE['nc_username'])
1035
-			&& isset($_COOKIE['nc_token'])
1036
-			&& isset($_COOKIE['nc_session_id'])
1037
-			&& $userSession->loginWithCookie($_COOKIE['nc_username'], $_COOKIE['nc_token'], $_COOKIE['nc_session_id'])) {
1038
-			return true;
1039
-		}
1040
-		if ($userSession->tryBasicAuthLogin($request, \OC::$server->getBruteForceThrottler())) {
1041
-			return true;
1042
-		}
1043
-		return false;
1044
-	}
1045
-
1046
-	protected static function handleAuthHeaders() {
1047
-		//copy http auth headers for apache+php-fcgid work around
1048
-		if (isset($_SERVER['HTTP_XAUTHORIZATION']) && !isset($_SERVER['HTTP_AUTHORIZATION'])) {
1049
-			$_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['HTTP_XAUTHORIZATION'];
1050
-		}
1051
-
1052
-		// Extract PHP_AUTH_USER/PHP_AUTH_PW from other headers if necessary.
1053
-		$vars = array(
1054
-			'HTTP_AUTHORIZATION', // apache+php-cgi work around
1055
-			'REDIRECT_HTTP_AUTHORIZATION', // apache+php-cgi alternative
1056
-		);
1057
-		foreach ($vars as $var) {
1058
-			if (isset($_SERVER[$var]) && preg_match('/Basic\s+(.*)$/i', $_SERVER[$var], $matches)) {
1059
-				list($name, $password) = explode(':', base64_decode($matches[1]), 2);
1060
-				$_SERVER['PHP_AUTH_USER'] = $name;
1061
-				$_SERVER['PHP_AUTH_PW'] = $password;
1062
-				break;
1063
-			}
1064
-		}
1065
-	}
71
+    /**
72
+     * Associative array for autoloading. classname => filename
73
+     */
74
+    public static $CLASSPATH = array();
75
+    /**
76
+     * The installation path for Nextcloud  on the server (e.g. /srv/http/nextcloud)
77
+     */
78
+    public static $SERVERROOT = '';
79
+    /**
80
+     * the current request path relative to the Nextcloud root (e.g. files/index.php)
81
+     */
82
+    private static $SUBURI = '';
83
+    /**
84
+     * the Nextcloud root path for http requests (e.g. nextcloud/)
85
+     */
86
+    public static $WEBROOT = '';
87
+    /**
88
+     * The installation path array of the apps folder on the server (e.g. /srv/http/nextcloud) 'path' and
89
+     * web path in 'url'
90
+     */
91
+    public static $APPSROOTS = array();
92
+
93
+    /**
94
+     * @var string
95
+     */
96
+    public static $configDir;
97
+
98
+    /**
99
+     * requested app
100
+     */
101
+    public static $REQUESTEDAPP = '';
102
+
103
+    /**
104
+     * check if Nextcloud runs in cli mode
105
+     */
106
+    public static $CLI = false;
107
+
108
+    /**
109
+     * @var \OC\Autoloader $loader
110
+     */
111
+    public static $loader = null;
112
+
113
+    /** @var \Composer\Autoload\ClassLoader $composerAutoloader */
114
+    public static $composerAutoloader = null;
115
+
116
+    /**
117
+     * @var \OC\Server
118
+     */
119
+    public static $server = null;
120
+
121
+    /**
122
+     * @var \OC\Config
123
+     */
124
+    private static $config = null;
125
+
126
+    /**
127
+     * @throws \RuntimeException when the 3rdparty directory is missing or
128
+     * the app path list is empty or contains an invalid path
129
+     */
130
+    public static function initPaths() {
131
+        if(defined('PHPUNIT_CONFIG_DIR')) {
132
+            self::$configDir = OC::$SERVERROOT . '/' . PHPUNIT_CONFIG_DIR . '/';
133
+        } elseif(defined('PHPUNIT_RUN') and PHPUNIT_RUN and is_dir(OC::$SERVERROOT . '/tests/config/')) {
134
+            self::$configDir = OC::$SERVERROOT . '/tests/config/';
135
+        } elseif($dir = getenv('NEXTCLOUD_CONFIG_DIR')) {
136
+            self::$configDir = rtrim($dir, '/') . '/';
137
+        } else {
138
+            self::$configDir = OC::$SERVERROOT . '/config/';
139
+        }
140
+        self::$config = new \OC\Config(self::$configDir);
141
+
142
+        OC::$SUBURI = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"]), strlen(OC::$SERVERROOT)));
143
+        /**
144
+         * FIXME: The following lines are required because we can't yet instantiate
145
+         *        \OC::$server->getRequest() since \OC::$server does not yet exist.
146
+         */
147
+        $params = [
148
+            'server' => [
149
+                'SCRIPT_NAME' => $_SERVER['SCRIPT_NAME'],
150
+                'SCRIPT_FILENAME' => $_SERVER['SCRIPT_FILENAME'],
151
+            ],
152
+        ];
153
+        $fakeRequest = new \OC\AppFramework\Http\Request($params, null, new \OC\AllConfig(new \OC\SystemConfig(self::$config)));
154
+        $scriptName = $fakeRequest->getScriptName();
155
+        if (substr($scriptName, -1) == '/') {
156
+            $scriptName .= 'index.php';
157
+            //make sure suburi follows the same rules as scriptName
158
+            if (substr(OC::$SUBURI, -9) != 'index.php') {
159
+                if (substr(OC::$SUBURI, -1) != '/') {
160
+                    OC::$SUBURI = OC::$SUBURI . '/';
161
+                }
162
+                OC::$SUBURI = OC::$SUBURI . 'index.php';
163
+            }
164
+        }
165
+
166
+
167
+        if (OC::$CLI) {
168
+            OC::$WEBROOT = self::$config->getValue('overwritewebroot', '');
169
+        } else {
170
+            if (substr($scriptName, 0 - strlen(OC::$SUBURI)) === OC::$SUBURI) {
171
+                OC::$WEBROOT = substr($scriptName, 0, 0 - strlen(OC::$SUBURI));
172
+
173
+                if (OC::$WEBROOT != '' && OC::$WEBROOT[0] !== '/') {
174
+                    OC::$WEBROOT = '/' . OC::$WEBROOT;
175
+                }
176
+            } else {
177
+                // The scriptName is not ending with OC::$SUBURI
178
+                // This most likely means that we are calling from CLI.
179
+                // However some cron jobs still need to generate
180
+                // a web URL, so we use overwritewebroot as a fallback.
181
+                OC::$WEBROOT = self::$config->getValue('overwritewebroot', '');
182
+            }
183
+
184
+            // Resolve /nextcloud to /nextcloud/ to ensure to always have a trailing
185
+            // slash which is required by URL generation.
186
+            if (isset($_SERVER['REQUEST_URI']) && $_SERVER['REQUEST_URI'] === \OC::$WEBROOT &&
187
+                    substr($_SERVER['REQUEST_URI'], -1) !== '/') {
188
+                header('Location: '.\OC::$WEBROOT.'/');
189
+                exit();
190
+            }
191
+        }
192
+
193
+        // search the apps folder
194
+        $config_paths = self::$config->getValue('apps_paths', array());
195
+        if (!empty($config_paths)) {
196
+            foreach ($config_paths as $paths) {
197
+                if (isset($paths['url']) && isset($paths['path'])) {
198
+                    $paths['url'] = rtrim($paths['url'], '/');
199
+                    $paths['path'] = rtrim($paths['path'], '/');
200
+                    OC::$APPSROOTS[] = $paths;
201
+                }
202
+            }
203
+        } elseif (file_exists(OC::$SERVERROOT . '/apps')) {
204
+            OC::$APPSROOTS[] = array('path' => OC::$SERVERROOT . '/apps', 'url' => '/apps', 'writable' => true);
205
+        } elseif (file_exists(OC::$SERVERROOT . '/../apps')) {
206
+            OC::$APPSROOTS[] = array(
207
+                'path' => rtrim(dirname(OC::$SERVERROOT), '/') . '/apps',
208
+                'url' => '/apps',
209
+                'writable' => true
210
+            );
211
+        }
212
+
213
+        if (empty(OC::$APPSROOTS)) {
214
+            throw new \RuntimeException('apps directory not found! Please put the Nextcloud apps folder in the Nextcloud folder'
215
+                . ' or the folder above. You can also configure the location in the config.php file.');
216
+        }
217
+        $paths = array();
218
+        foreach (OC::$APPSROOTS as $path) {
219
+            $paths[] = $path['path'];
220
+            if (!is_dir($path['path'])) {
221
+                throw new \RuntimeException(sprintf('App directory "%s" not found! Please put the Nextcloud apps folder in the'
222
+                    . ' Nextcloud folder or the folder above. You can also configure the location in the'
223
+                    . ' config.php file.', $path['path']));
224
+            }
225
+        }
226
+
227
+        // set the right include path
228
+        set_include_path(
229
+            implode(PATH_SEPARATOR, $paths)
230
+        );
231
+    }
232
+
233
+    public static function checkConfig() {
234
+        $l = \OC::$server->getL10N('lib');
235
+
236
+        // Create config if it does not already exist
237
+        $configFilePath = self::$configDir .'/config.php';
238
+        if(!file_exists($configFilePath)) {
239
+            @touch($configFilePath);
240
+        }
241
+
242
+        // Check if config is writable
243
+        $configFileWritable = is_writable($configFilePath);
244
+        if (!$configFileWritable && !OC_Helper::isReadOnlyConfigEnabled()
245
+            || !$configFileWritable && \OCP\Util::needUpgrade()) {
246
+
247
+            $urlGenerator = \OC::$server->getURLGenerator();
248
+
249
+            if (self::$CLI) {
250
+                echo $l->t('Cannot write into "config" directory!')."\n";
251
+                echo $l->t('This can usually be fixed by giving the webserver write access to the config directory')."\n";
252
+                echo $l->t('See %s', [ $urlGenerator->linkToDocs('admin-dir_permissions') ])."\n";
253
+                echo "\n";
254
+                echo $l->t('Or, if you prefer to keep config.php file read only, set the option "config_is_read_only" to true in it.')."\n";
255
+                echo $l->t('See %s', [ $urlGenerator->linkToDocs('admin-config') ])."\n";
256
+                exit;
257
+            } else {
258
+                OC_Template::printErrorPage(
259
+                    $l->t('Cannot write into "config" directory!'),
260
+                    $l->t('This can usually be fixed by giving the webserver write access to the config directory. See %s',
261
+                    [ $urlGenerator->linkToDocs('admin-dir_permissions') ]) . '. '
262
+                    . $l->t('Or, if you prefer to keep config.php file read only, set the option "config_is_read_only" to true in it. See %s',
263
+                    [ $urlGenerator->linkToDocs('admin-config') ] ),
264
+                    503
265
+                );
266
+            }
267
+        }
268
+    }
269
+
270
+    public static function checkInstalled() {
271
+        if (defined('OC_CONSOLE')) {
272
+            return;
273
+        }
274
+        // Redirect to installer if not installed
275
+        if (!\OC::$server->getSystemConfig()->getValue('installed', false) && OC::$SUBURI !== '/index.php' && OC::$SUBURI !== '/status.php') {
276
+            if (OC::$CLI) {
277
+                throw new Exception('Not installed');
278
+            } else {
279
+                $url = OC::$WEBROOT . '/index.php';
280
+                header('Location: ' . $url);
281
+            }
282
+            exit();
283
+        }
284
+    }
285
+
286
+    public static function checkMaintenanceMode() {
287
+        // Allow ajax update script to execute without being stopped
288
+        if (((bool) \OC::$server->getSystemConfig()->getValue('maintenance', false)) && OC::$SUBURI != '/core/ajax/update.php') {
289
+            // send http status 503
290
+            http_response_code(503);
291
+            header('Retry-After: 120');
292
+
293
+            // render error page
294
+            $template = new OC_Template('', 'update.user', 'guest');
295
+            OC_Util::addScript('maintenance-check');
296
+            OC_Util::addStyle('core', 'guest');
297
+            $template->printPage();
298
+            die();
299
+        }
300
+    }
301
+
302
+    /**
303
+     * Prints the upgrade page
304
+     *
305
+     * @param \OC\SystemConfig $systemConfig
306
+     */
307
+    private static function printUpgradePage(\OC\SystemConfig $systemConfig) {
308
+        $disableWebUpdater = $systemConfig->getValue('upgrade.disable-web', false);
309
+        $tooBig = false;
310
+        if (!$disableWebUpdater) {
311
+            $apps = \OC::$server->getAppManager();
312
+            if ($apps->isInstalled('user_ldap')) {
313
+                $qb = \OC::$server->getDatabaseConnection()->getQueryBuilder();
314
+
315
+                $result = $qb->select($qb->func()->count('*', 'user_count'))
316
+                    ->from('ldap_user_mapping')
317
+                    ->execute();
318
+                $row = $result->fetch();
319
+                $result->closeCursor();
320
+
321
+                $tooBig = ($row['user_count'] > 50);
322
+            }
323
+            if (!$tooBig && $apps->isInstalled('user_saml')) {
324
+                $qb = \OC::$server->getDatabaseConnection()->getQueryBuilder();
325
+
326
+                $result = $qb->select($qb->func()->count('*', 'user_count'))
327
+                    ->from('user_saml_users')
328
+                    ->execute();
329
+                $row = $result->fetch();
330
+                $result->closeCursor();
331
+
332
+                $tooBig = ($row['user_count'] > 50);
333
+            }
334
+            if (!$tooBig) {
335
+                // count users
336
+                $stats = \OC::$server->getUserManager()->countUsers();
337
+                $totalUsers = array_sum($stats);
338
+                $tooBig = ($totalUsers > 50);
339
+            }
340
+        }
341
+        $ignoreTooBigWarning = isset($_GET['IKnowThatThisIsABigInstanceAndTheUpdateRequestCouldRunIntoATimeoutAndHowToRestoreABackup']) &&
342
+            $_GET['IKnowThatThisIsABigInstanceAndTheUpdateRequestCouldRunIntoATimeoutAndHowToRestoreABackup'] === 'IAmSuperSureToDoThis';
343
+
344
+        if ($disableWebUpdater || ($tooBig && !$ignoreTooBigWarning)) {
345
+            // send http status 503
346
+            http_response_code(503);
347
+            header('Retry-After: 120');
348
+
349
+            // render error page
350
+            $template = new OC_Template('', 'update.use-cli', 'guest');
351
+            $template->assign('productName', 'nextcloud'); // for now
352
+            $template->assign('version', OC_Util::getVersionString());
353
+            $template->assign('tooBig', $tooBig);
354
+
355
+            $template->printPage();
356
+            die();
357
+        }
358
+
359
+        // check whether this is a core update or apps update
360
+        $installedVersion = $systemConfig->getValue('version', '0.0.0');
361
+        $currentVersion = implode('.', \OCP\Util::getVersion());
362
+
363
+        // if not a core upgrade, then it's apps upgrade
364
+        $isAppsOnlyUpgrade = version_compare($currentVersion, $installedVersion, '=');
365
+
366
+        $oldTheme = $systemConfig->getValue('theme');
367
+        $systemConfig->setValue('theme', '');
368
+        OC_Util::addScript('config'); // needed for web root
369
+        OC_Util::addScript('update');
370
+
371
+        /** @var \OC\App\AppManager $appManager */
372
+        $appManager = \OC::$server->getAppManager();
373
+
374
+        $tmpl = new OC_Template('', 'update.admin', 'guest');
375
+        $tmpl->assign('version', OC_Util::getVersionString());
376
+        $tmpl->assign('isAppsOnlyUpgrade', $isAppsOnlyUpgrade);
377
+
378
+        // get third party apps
379
+        $ocVersion = \OCP\Util::getVersion();
380
+        $ocVersion = implode('.', $ocVersion);
381
+        $incompatibleApps = $appManager->getIncompatibleApps($ocVersion);
382
+        $incompatibleShippedApps = [];
383
+        foreach ($incompatibleApps as $appInfo) {
384
+            if ($appManager->isShipped($appInfo['id'])) {
385
+                $incompatibleShippedApps[] = $appInfo['name'] . ' (' . $appInfo['id'] . ')';
386
+            }
387
+        }
388
+
389
+        if (!empty($incompatibleShippedApps)) {
390
+            $l = \OC::$server->getL10N('core');
391
+            $hint = $l->t('The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server.', [implode(', ', $incompatibleShippedApps)]);
392
+            throw new \OC\HintException('The files of the app ' . implode(', ', $incompatibleShippedApps) . ' were not replaced correctly. Make sure it is a version compatible with the server.', $hint);
393
+        }
394
+
395
+        $tmpl->assign('appsToUpgrade', $appManager->getAppsNeedingUpgrade($ocVersion));
396
+        $tmpl->assign('incompatibleAppsList', $incompatibleApps);
397
+        $tmpl->assign('productName', 'Nextcloud'); // for now
398
+        $tmpl->assign('oldTheme', $oldTheme);
399
+        $tmpl->printPage();
400
+    }
401
+
402
+    public static function initSession() {
403
+        if(self::$server->getRequest()->getServerProtocol() === 'https') {
404
+            ini_set('session.cookie_secure', true);
405
+        }
406
+
407
+        // prevents javascript from accessing php session cookies
408
+        ini_set('session.cookie_httponly', 'true');
409
+
410
+        // set the cookie path to the Nextcloud directory
411
+        $cookie_path = OC::$WEBROOT ? : '/';
412
+        ini_set('session.cookie_path', $cookie_path);
413
+
414
+        // Let the session name be changed in the initSession Hook
415
+        $sessionName = OC_Util::getInstanceId();
416
+
417
+        try {
418
+            // Allow session apps to create a custom session object
419
+            $useCustomSession = false;
420
+            $session = self::$server->getSession();
421
+            OC_Hook::emit('OC', 'initSession', array('session' => &$session, 'sessionName' => &$sessionName, 'useCustomSession' => &$useCustomSession));
422
+            if (!$useCustomSession) {
423
+                // set the session name to the instance id - which is unique
424
+                $session = new \OC\Session\Internal($sessionName);
425
+            }
426
+
427
+            $cryptoWrapper = \OC::$server->getSessionCryptoWrapper();
428
+            $session = $cryptoWrapper->wrapSession($session);
429
+            self::$server->setSession($session);
430
+
431
+            // if session can't be started break with http 500 error
432
+        } catch (Exception $e) {
433
+            \OC::$server->getLogger()->logException($e, ['app' => 'base']);
434
+            //show the user a detailed error page
435
+            OC_Template::printExceptionErrorPage($e, 500);
436
+            die();
437
+        }
438
+
439
+        $sessionLifeTime = self::getSessionLifeTime();
440
+
441
+        // session timeout
442
+        if ($session->exists('LAST_ACTIVITY') && (time() - $session->get('LAST_ACTIVITY') > $sessionLifeTime)) {
443
+            if (isset($_COOKIE[session_name()])) {
444
+                setcookie(session_name(), '', -1, self::$WEBROOT ? : '/');
445
+            }
446
+            \OC::$server->getUserSession()->logout();
447
+        }
448
+
449
+        $session->set('LAST_ACTIVITY', time());
450
+    }
451
+
452
+    /**
453
+     * @return string
454
+     */
455
+    private static function getSessionLifeTime() {
456
+        return \OC::$server->getConfig()->getSystemValue('session_lifetime', 60 * 60 * 24);
457
+    }
458
+
459
+    public static function loadAppClassPaths() {
460
+        foreach (OC_App::getEnabledApps() as $app) {
461
+            $appPath = OC_App::getAppPath($app);
462
+            if ($appPath === false) {
463
+                continue;
464
+            }
465
+
466
+            $file = $appPath . '/appinfo/classpath.php';
467
+            if (file_exists($file)) {
468
+                require_once $file;
469
+            }
470
+        }
471
+    }
472
+
473
+    /**
474
+     * Try to set some values to the required Nextcloud default
475
+     */
476
+    public static function setRequiredIniValues() {
477
+        @ini_set('default_charset', 'UTF-8');
478
+        @ini_set('gd.jpeg_ignore_warning', '1');
479
+    }
480
+
481
+    /**
482
+     * Send the same site cookies
483
+     */
484
+    private static function sendSameSiteCookies() {
485
+        $cookieParams = session_get_cookie_params();
486
+        $secureCookie = ($cookieParams['secure'] === true) ? 'secure; ' : '';
487
+        $policies = [
488
+            'lax',
489
+            'strict',
490
+        ];
491
+
492
+        // Append __Host to the cookie if it meets the requirements
493
+        $cookiePrefix = '';
494
+        if($cookieParams['secure'] === true && $cookieParams['path'] === '/') {
495
+            $cookiePrefix = '__Host-';
496
+        }
497
+
498
+        foreach($policies as $policy) {
499
+            header(
500
+                sprintf(
501
+                    'Set-Cookie: %snc_sameSiteCookie%s=true; path=%s; httponly;' . $secureCookie . 'expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=%s',
502
+                    $cookiePrefix,
503
+                    $policy,
504
+                    $cookieParams['path'],
505
+                    $policy
506
+                ),
507
+                false
508
+            );
509
+        }
510
+    }
511
+
512
+    /**
513
+     * Same Site cookie to further mitigate CSRF attacks. This cookie has to
514
+     * be set in every request if cookies are sent to add a second level of
515
+     * defense against CSRF.
516
+     *
517
+     * If the cookie is not sent this will set the cookie and reload the page.
518
+     * We use an additional cookie since we want to protect logout CSRF and
519
+     * also we can't directly interfere with PHP's session mechanism.
520
+     */
521
+    private static function performSameSiteCookieProtection() {
522
+        $request = \OC::$server->getRequest();
523
+
524
+        // Some user agents are notorious and don't really properly follow HTTP
525
+        // specifications. For those, have an automated opt-out. Since the protection
526
+        // for remote.php is applied in base.php as starting point we need to opt out
527
+        // here.
528
+        $incompatibleUserAgents = \OC::$server->getConfig()->getSystemValue('csrf.optout');
529
+
530
+        // Fallback, if csrf.optout is unset
531
+        if (!is_array($incompatibleUserAgents)) {
532
+            $incompatibleUserAgents = [
533
+                // OS X Finder
534
+                '/^WebDAVFS/',
535
+                // Windows webdav drive
536
+                '/^Microsoft-WebDAV-MiniRedir/',
537
+            ];
538
+        }
539
+
540
+        if($request->isUserAgent($incompatibleUserAgents)) {
541
+            return;
542
+        }
543
+
544
+        if(count($_COOKIE) > 0) {
545
+            $requestUri = $request->getScriptName();
546
+            $processingScript = explode('/', $requestUri);
547
+            $processingScript = $processingScript[count($processingScript)-1];
548
+
549
+            // index.php routes are handled in the middleware
550
+            if($processingScript === 'index.php') {
551
+                return;
552
+            }
553
+
554
+            // All other endpoints require the lax and the strict cookie
555
+            if(!$request->passesStrictCookieCheck()) {
556
+                self::sendSameSiteCookies();
557
+                // Debug mode gets access to the resources without strict cookie
558
+                // due to the fact that the SabreDAV browser also lives there.
559
+                if(!\OC::$server->getConfig()->getSystemValue('debug', false)) {
560
+                    http_response_code(\OCP\AppFramework\Http::STATUS_SERVICE_UNAVAILABLE);
561
+                    exit();
562
+                }
563
+            }
564
+        } elseif(!isset($_COOKIE['nc_sameSiteCookielax']) || !isset($_COOKIE['nc_sameSiteCookiestrict'])) {
565
+            self::sendSameSiteCookies();
566
+        }
567
+    }
568
+
569
+    public static function init() {
570
+        // calculate the root directories
571
+        OC::$SERVERROOT = str_replace("\\", '/', substr(__DIR__, 0, -4));
572
+
573
+        // register autoloader
574
+        $loaderStart = microtime(true);
575
+        require_once __DIR__ . '/autoloader.php';
576
+        self::$loader = new \OC\Autoloader([
577
+            OC::$SERVERROOT . '/lib/private/legacy',
578
+        ]);
579
+        if (defined('PHPUNIT_RUN')) {
580
+            self::$loader->addValidRoot(OC::$SERVERROOT . '/tests');
581
+        }
582
+        spl_autoload_register(array(self::$loader, 'load'));
583
+        $loaderEnd = microtime(true);
584
+
585
+        self::$CLI = (php_sapi_name() == 'cli');
586
+
587
+        // Add default composer PSR-4 autoloader
588
+        self::$composerAutoloader = require_once OC::$SERVERROOT . '/lib/composer/autoload.php';
589
+
590
+        try {
591
+            self::initPaths();
592
+            // setup 3rdparty autoloader
593
+            $vendorAutoLoad = OC::$SERVERROOT. '/3rdparty/autoload.php';
594
+            if (!file_exists($vendorAutoLoad)) {
595
+                throw new \RuntimeException('Composer autoloader not found, unable to continue. Check the folder "3rdparty". Running "git submodule update --init" will initialize the git submodule that handles the subfolder "3rdparty".');
596
+            }
597
+            require_once $vendorAutoLoad;
598
+
599
+        } catch (\RuntimeException $e) {
600
+            if (!self::$CLI) {
601
+                http_response_code(503);
602
+            }
603
+            // we can't use the template error page here, because this needs the
604
+            // DI container which isn't available yet
605
+            print($e->getMessage());
606
+            exit();
607
+        }
608
+
609
+        // setup the basic server
610
+        self::$server = new \OC\Server(\OC::$WEBROOT, self::$config);
611
+        \OC::$server->getEventLogger()->log('autoloader', 'Autoloader', $loaderStart, $loaderEnd);
612
+        \OC::$server->getEventLogger()->start('boot', 'Initialize');
613
+
614
+        // Don't display errors and log them
615
+        error_reporting(E_ALL | E_STRICT);
616
+        @ini_set('display_errors', '0');
617
+        @ini_set('log_errors', '1');
618
+
619
+        if(!date_default_timezone_set('UTC')) {
620
+            throw new \RuntimeException('Could not set timezone to UTC');
621
+        }
622
+
623
+        //try to configure php to enable big file uploads.
624
+        //this doesn´t work always depending on the webserver and php configuration.
625
+        //Let´s try to overwrite some defaults anyway
626
+
627
+        //try to set the maximum execution time to 60min
628
+        if (strpos(@ini_get('disable_functions'), 'set_time_limit') === false) {
629
+            @set_time_limit(3600);
630
+        }
631
+        @ini_set('max_execution_time', '3600');
632
+        @ini_set('max_input_time', '3600');
633
+
634
+        //try to set the maximum filesize to 10G
635
+        @ini_set('upload_max_filesize', '10G');
636
+        @ini_set('post_max_size', '10G');
637
+        @ini_set('file_uploads', '50');
638
+
639
+        self::setRequiredIniValues();
640
+        self::handleAuthHeaders();
641
+        self::registerAutoloaderCache();
642
+
643
+        // initialize intl fallback is necessary
644
+        \Patchwork\Utf8\Bootup::initIntl();
645
+        OC_Util::isSetLocaleWorking();
646
+
647
+        if (!defined('PHPUNIT_RUN')) {
648
+            OC\Log\ErrorHandler::setLogger(\OC::$server->getLogger());
649
+            $debug = \OC::$server->getConfig()->getSystemValue('debug', false);
650
+            OC\Log\ErrorHandler::register($debug);
651
+        }
652
+
653
+        \OC::$server->getEventLogger()->start('init_session', 'Initialize session');
654
+        OC_App::loadApps(array('session'));
655
+        if (!self::$CLI) {
656
+            self::initSession();
657
+        }
658
+        \OC::$server->getEventLogger()->end('init_session');
659
+        self::checkConfig();
660
+        self::checkInstalled();
661
+
662
+        OC_Response::addSecurityHeaders();
663
+
664
+        self::performSameSiteCookieProtection();
665
+
666
+        if (!defined('OC_CONSOLE')) {
667
+            $errors = OC_Util::checkServer(\OC::$server->getSystemConfig());
668
+            if (count($errors) > 0) {
669
+                if (self::$CLI) {
670
+                    // Convert l10n string into regular string for usage in database
671
+                    $staticErrors = [];
672
+                    foreach ($errors as $error) {
673
+                        echo $error['error'] . "\n";
674
+                        echo $error['hint'] . "\n\n";
675
+                        $staticErrors[] = [
676
+                            'error' => (string)$error['error'],
677
+                            'hint' => (string)$error['hint'],
678
+                        ];
679
+                    }
680
+
681
+                    try {
682
+                        \OC::$server->getConfig()->setAppValue('core', 'cronErrors', json_encode($staticErrors));
683
+                    } catch (\Exception $e) {
684
+                        echo('Writing to database failed');
685
+                    }
686
+                    exit(1);
687
+                } else {
688
+                    http_response_code(503);
689
+                    OC_Util::addStyle('guest');
690
+                    OC_Template::printGuestPage('', 'error', array('errors' => $errors));
691
+                    exit;
692
+                }
693
+            } elseif (self::$CLI && \OC::$server->getConfig()->getSystemValue('installed', false)) {
694
+                \OC::$server->getConfig()->deleteAppValue('core', 'cronErrors');
695
+            }
696
+        }
697
+        //try to set the session lifetime
698
+        $sessionLifeTime = self::getSessionLifeTime();
699
+        @ini_set('gc_maxlifetime', (string)$sessionLifeTime);
700
+
701
+        $systemConfig = \OC::$server->getSystemConfig();
702
+
703
+        // User and Groups
704
+        if (!$systemConfig->getValue("installed", false)) {
705
+            self::$server->getSession()->set('user_id', '');
706
+        }
707
+
708
+        OC_User::useBackend(new \OC\User\Database());
709
+        \OC::$server->getGroupManager()->addBackend(new \OC\Group\Database());
710
+
711
+        // Subscribe to the hook
712
+        \OCP\Util::connectHook(
713
+            '\OCA\Files_Sharing\API\Server2Server',
714
+            'preLoginNameUsedAsUserName',
715
+            '\OC\User\Database',
716
+            'preLoginNameUsedAsUserName'
717
+        );
718
+
719
+        //setup extra user backends
720
+        if (!\OCP\Util::needUpgrade()) {
721
+            OC_User::setupBackends();
722
+        } else {
723
+            // Run upgrades in incognito mode
724
+            OC_User::setIncognitoMode(true);
725
+        }
726
+
727
+        self::registerCleanupHooks();
728
+        self::registerFilesystemHooks();
729
+        self::registerShareHooks();
730
+        self::registerEncryptionWrapper();
731
+        self::registerEncryptionHooks();
732
+        self::registerAccountHooks();
733
+
734
+        // Make sure that the application class is not loaded before the database is setup
735
+        if ($systemConfig->getValue("installed", false)) {
736
+            $settings = new \OC\Settings\Application();
737
+            $settings->register();
738
+        }
739
+
740
+        //make sure temporary files are cleaned up
741
+        $tmpManager = \OC::$server->getTempManager();
742
+        register_shutdown_function(array($tmpManager, 'clean'));
743
+        $lockProvider = \OC::$server->getLockingProvider();
744
+        register_shutdown_function(array($lockProvider, 'releaseAll'));
745
+
746
+        // Check whether the sample configuration has been copied
747
+        if($systemConfig->getValue('copied_sample_config', false)) {
748
+            $l = \OC::$server->getL10N('lib');
749
+            OC_Template::printErrorPage(
750
+                $l->t('Sample configuration detected'),
751
+                $l->t('It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php'),
752
+                503
753
+            );
754
+            return;
755
+        }
756
+
757
+        $request = \OC::$server->getRequest();
758
+        $host = $request->getInsecureServerHost();
759
+        /**
760
+         * if the host passed in headers isn't trusted
761
+         * FIXME: Should not be in here at all :see_no_evil:
762
+         */
763
+        if (!OC::$CLI
764
+            // overwritehost is always trusted, workaround to not have to make
765
+            // \OC\AppFramework\Http\Request::getOverwriteHost public
766
+            && self::$server->getConfig()->getSystemValue('overwritehost') === ''
767
+            && !\OC::$server->getTrustedDomainHelper()->isTrustedDomain($host)
768
+            && self::$server->getConfig()->getSystemValue('installed', false)
769
+        ) {
770
+            // Allow access to CSS resources
771
+            $isScssRequest = false;
772
+            if(strpos($request->getPathInfo(), '/css/') === 0) {
773
+                $isScssRequest = true;
774
+            }
775
+
776
+            if(substr($request->getRequestUri(), -11) === '/status.php') {
777
+                http_response_code(400);
778
+                header('Content-Type: application/json');
779
+                echo '{"error": "Trusted domain error.", "code": 15}';
780
+                exit();
781
+            }
782
+
783
+            if (!$isScssRequest) {
784
+                http_response_code(400);
785
+
786
+                \OC::$server->getLogger()->info(
787
+                    'Trusted domain error. "{remoteAddress}" tried to access using "{host}" as host.',
788
+                    [
789
+                        'app' => 'core',
790
+                        'remoteAddress' => $request->getRemoteAddress(),
791
+                        'host' => $host,
792
+                    ]
793
+                );
794
+
795
+                $tmpl = new OCP\Template('core', 'untrustedDomain', 'guest');
796
+                $tmpl->assign('docUrl', \OC::$server->getURLGenerator()->linkToDocs('admin-trusted-domains'));
797
+                $tmpl->printPage();
798
+
799
+                exit();
800
+            }
801
+        }
802
+        \OC::$server->getEventLogger()->end('boot');
803
+    }
804
+
805
+    /**
806
+     * register hooks for the cleanup of cache and bruteforce protection
807
+     */
808
+    public static function registerCleanupHooks() {
809
+        //don't try to do this before we are properly setup
810
+        if (\OC::$server->getSystemConfig()->getValue('installed', false) && !\OCP\Util::needUpgrade()) {
811
+
812
+            // NOTE: This will be replaced to use OCP
813
+            $userSession = self::$server->getUserSession();
814
+            $userSession->listen('\OC\User', 'postLogin', function () use ($userSession) {
815
+                if (!defined('PHPUNIT_RUN')) {
816
+                    // reset brute force delay for this IP address and username
817
+                    $uid = \OC::$server->getUserSession()->getUser()->getUID();
818
+                    $request = \OC::$server->getRequest();
819
+                    $throttler = \OC::$server->getBruteForceThrottler();
820
+                    $throttler->resetDelay($request->getRemoteAddress(), 'login', ['user' => $uid]);
821
+                }
822
+
823
+                try {
824
+                    $cache = new \OC\Cache\File();
825
+                    $cache->gc();
826
+                } catch (\OC\ServerNotAvailableException $e) {
827
+                    // not a GC exception, pass it on
828
+                    throw $e;
829
+                } catch (\OC\ForbiddenException $e) {
830
+                    // filesystem blocked for this request, ignore
831
+                } catch (\Exception $e) {
832
+                    // a GC exception should not prevent users from using OC,
833
+                    // so log the exception
834
+                    \OC::$server->getLogger()->logException($e, [
835
+                        'message' => 'Exception when running cache gc.',
836
+                        'level' => ILogger::WARN,
837
+                        'app' => 'core',
838
+                    ]);
839
+                }
840
+            });
841
+        }
842
+    }
843
+
844
+    private static function registerEncryptionWrapper() {
845
+        $manager = self::$server->getEncryptionManager();
846
+        \OCP\Util::connectHook('OC_Filesystem', 'preSetup', $manager, 'setupStorage');
847
+    }
848
+
849
+    private static function registerEncryptionHooks() {
850
+        $enabled = self::$server->getEncryptionManager()->isEnabled();
851
+        if ($enabled) {
852
+            \OCP\Util::connectHook(Share::class, 'post_shared', HookManager::class, 'postShared');
853
+            \OCP\Util::connectHook(Share::class, 'post_unshare', HookManager::class, 'postUnshared');
854
+            \OCP\Util::connectHook('OC_Filesystem', 'post_rename', HookManager::class, 'postRename');
855
+            \OCP\Util::connectHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', HookManager::class, 'postRestore');
856
+        }
857
+    }
858
+
859
+    private static function registerAccountHooks() {
860
+        $hookHandler = new \OC\Accounts\Hooks(\OC::$server->getLogger());
861
+        \OCP\Util::connectHook('OC_User', 'changeUser', $hookHandler, 'changeUserHook');
862
+    }
863
+
864
+    /**
865
+     * register hooks for the filesystem
866
+     */
867
+    public static function registerFilesystemHooks() {
868
+        // Check for blacklisted files
869
+        OC_Hook::connect('OC_Filesystem', 'write', Filesystem::class, 'isBlacklisted');
870
+        OC_Hook::connect('OC_Filesystem', 'rename', Filesystem::class, 'isBlacklisted');
871
+    }
872
+
873
+    /**
874
+     * register hooks for sharing
875
+     */
876
+    public static function registerShareHooks() {
877
+        if (\OC::$server->getSystemConfig()->getValue('installed')) {
878
+            OC_Hook::connect('OC_User', 'post_deleteUser', Hooks::class, 'post_deleteUser');
879
+            OC_Hook::connect('OC_User', 'post_removeFromGroup', Hooks::class, 'post_removeFromGroup');
880
+            OC_Hook::connect('OC_User', 'post_deleteGroup', Hooks::class, 'post_deleteGroup');
881
+        }
882
+    }
883
+
884
+    protected static function registerAutoloaderCache() {
885
+        // The class loader takes an optional low-latency cache, which MUST be
886
+        // namespaced. The instanceid is used for namespacing, but might be
887
+        // unavailable at this point. Furthermore, it might not be possible to
888
+        // generate an instanceid via \OC_Util::getInstanceId() because the
889
+        // config file may not be writable. As such, we only register a class
890
+        // loader cache if instanceid is available without trying to create one.
891
+        $instanceId = \OC::$server->getSystemConfig()->getValue('instanceid', null);
892
+        if ($instanceId) {
893
+            try {
894
+                $memcacheFactory = \OC::$server->getMemCacheFactory();
895
+                self::$loader->setMemoryCache($memcacheFactory->createLocal('Autoloader'));
896
+            } catch (\Exception $ex) {
897
+            }
898
+        }
899
+    }
900
+
901
+    /**
902
+     * Handle the request
903
+     */
904
+    public static function handleRequest() {
905
+
906
+        \OC::$server->getEventLogger()->start('handle_request', 'Handle request');
907
+        $systemConfig = \OC::$server->getSystemConfig();
908
+        // load all the classpaths from the enabled apps so they are available
909
+        // in the routing files of each app
910
+        OC::loadAppClassPaths();
911
+
912
+        // Check if Nextcloud is installed or in maintenance (update) mode
913
+        if (!$systemConfig->getValue('installed', false)) {
914
+            \OC::$server->getSession()->clear();
915
+            $setupHelper = new OC\Setup(
916
+                $systemConfig,
917
+                \OC::$server->getIniWrapper(),
918
+                \OC::$server->getL10N('lib'),
919
+                \OC::$server->query(\OCP\Defaults::class),
920
+                \OC::$server->getLogger(),
921
+                \OC::$server->getSecureRandom(),
922
+                \OC::$server->query(\OC\Installer::class)
923
+            );
924
+            $controller = new OC\Core\Controller\SetupController($setupHelper);
925
+            $controller->run($_POST);
926
+            exit();
927
+        }
928
+
929
+        $request = \OC::$server->getRequest();
930
+        $requestPath = $request->getRawPathInfo();
931
+        if ($requestPath === '/heartbeat') {
932
+            return;
933
+        }
934
+        if (substr($requestPath, -3) !== '.js') { // we need these files during the upgrade
935
+            self::checkMaintenanceMode();
936
+
937
+            if (\OCP\Util::needUpgrade()) {
938
+                if (function_exists('opcache_reset')) {
939
+                    opcache_reset();
940
+                }
941
+                if (!((bool) $systemConfig->getValue('maintenance', false))) {
942
+                    self::printUpgradePage($systemConfig);
943
+                    exit();
944
+                }
945
+            }
946
+        }
947
+
948
+        // emergency app disabling
949
+        if ($requestPath === '/disableapp'
950
+            && $request->getMethod() === 'POST'
951
+            && ((array)$request->getParam('appid')) !== ''
952
+        ) {
953
+            \OC_JSON::callCheck();
954
+            \OC_JSON::checkAdminUser();
955
+            $appIds = (array)$request->getParam('appid');
956
+            foreach($appIds as $appId) {
957
+                $appId = \OC_App::cleanAppId($appId);
958
+                \OC::$server->getAppManager()->disableApp($appId);
959
+            }
960
+            \OC_JSON::success();
961
+            exit();
962
+        }
963
+
964
+        // Always load authentication apps
965
+        OC_App::loadApps(['authentication']);
966
+
967
+        // Load minimum set of apps
968
+        if (!\OCP\Util::needUpgrade()
969
+            && !((bool) $systemConfig->getValue('maintenance', false))) {
970
+            // For logged-in users: Load everything
971
+            if(\OC::$server->getUserSession()->isLoggedIn()) {
972
+                OC_App::loadApps();
973
+            } else {
974
+                // For guests: Load only filesystem and logging
975
+                OC_App::loadApps(array('filesystem', 'logging'));
976
+                self::handleLogin($request);
977
+            }
978
+        }
979
+
980
+        if (!self::$CLI) {
981
+            try {
982
+                if (!((bool) $systemConfig->getValue('maintenance', false)) && !\OCP\Util::needUpgrade()) {
983
+                    OC_App::loadApps(array('filesystem', 'logging'));
984
+                    OC_App::loadApps();
985
+                }
986
+                OC_Util::setupFS();
987
+                OC::$server->getRouter()->match(\OC::$server->getRequest()->getRawPathInfo());
988
+                return;
989
+            } catch (Symfony\Component\Routing\Exception\ResourceNotFoundException $e) {
990
+                //header('HTTP/1.0 404 Not Found');
991
+            } catch (Symfony\Component\Routing\Exception\MethodNotAllowedException $e) {
992
+                http_response_code(405);
993
+                return;
994
+            }
995
+        }
996
+
997
+        // Handle WebDAV
998
+        if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PROPFIND') {
999
+            // not allowed any more to prevent people
1000
+            // mounting this root directly.
1001
+            // Users need to mount remote.php/webdav instead.
1002
+            http_response_code(405);
1003
+            return;
1004
+        }
1005
+
1006
+        // Someone is logged in
1007
+        if (\OC::$server->getUserSession()->isLoggedIn()) {
1008
+            OC_App::loadApps();
1009
+            OC_User::setupBackends();
1010
+            OC_Util::setupFS();
1011
+            // FIXME
1012
+            // Redirect to default application
1013
+            OC_Util::redirectToDefaultPage();
1014
+        } else {
1015
+            // Not handled and not logged in
1016
+            header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute('core.login.showLoginForm'));
1017
+        }
1018
+    }
1019
+
1020
+    /**
1021
+     * Check login: apache auth, auth token, basic auth
1022
+     *
1023
+     * @param OCP\IRequest $request
1024
+     * @return boolean
1025
+     */
1026
+    static function handleLogin(OCP\IRequest $request) {
1027
+        $userSession = self::$server->getUserSession();
1028
+        if (OC_User::handleApacheAuth()) {
1029
+            return true;
1030
+        }
1031
+        if ($userSession->tryTokenLogin($request)) {
1032
+            return true;
1033
+        }
1034
+        if (isset($_COOKIE['nc_username'])
1035
+            && isset($_COOKIE['nc_token'])
1036
+            && isset($_COOKIE['nc_session_id'])
1037
+            && $userSession->loginWithCookie($_COOKIE['nc_username'], $_COOKIE['nc_token'], $_COOKIE['nc_session_id'])) {
1038
+            return true;
1039
+        }
1040
+        if ($userSession->tryBasicAuthLogin($request, \OC::$server->getBruteForceThrottler())) {
1041
+            return true;
1042
+        }
1043
+        return false;
1044
+    }
1045
+
1046
+    protected static function handleAuthHeaders() {
1047
+        //copy http auth headers for apache+php-fcgid work around
1048
+        if (isset($_SERVER['HTTP_XAUTHORIZATION']) && !isset($_SERVER['HTTP_AUTHORIZATION'])) {
1049
+            $_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['HTTP_XAUTHORIZATION'];
1050
+        }
1051
+
1052
+        // Extract PHP_AUTH_USER/PHP_AUTH_PW from other headers if necessary.
1053
+        $vars = array(
1054
+            'HTTP_AUTHORIZATION', // apache+php-cgi work around
1055
+            'REDIRECT_HTTP_AUTHORIZATION', // apache+php-cgi alternative
1056
+        );
1057
+        foreach ($vars as $var) {
1058
+            if (isset($_SERVER[$var]) && preg_match('/Basic\s+(.*)$/i', $_SERVER[$var], $matches)) {
1059
+                list($name, $password) = explode(':', base64_decode($matches[1]), 2);
1060
+                $_SERVER['PHP_AUTH_USER'] = $name;
1061
+                $_SERVER['PHP_AUTH_PW'] = $password;
1062
+                break;
1063
+            }
1064
+        }
1065
+    }
1066 1066
 }
1067 1067
 
1068 1068
 OC::init();
Please login to merge, or discard this patch.
Spacing   +57 added lines, -57 removed lines patch added patch discarded remove patch
@@ -128,14 +128,14 @@  discard block
 block discarded – undo
128 128
 	 * the app path list is empty or contains an invalid path
129 129
 	 */
130 130
 	public static function initPaths() {
131
-		if(defined('PHPUNIT_CONFIG_DIR')) {
132
-			self::$configDir = OC::$SERVERROOT . '/' . PHPUNIT_CONFIG_DIR . '/';
133
-		} elseif(defined('PHPUNIT_RUN') and PHPUNIT_RUN and is_dir(OC::$SERVERROOT . '/tests/config/')) {
134
-			self::$configDir = OC::$SERVERROOT . '/tests/config/';
135
-		} elseif($dir = getenv('NEXTCLOUD_CONFIG_DIR')) {
136
-			self::$configDir = rtrim($dir, '/') . '/';
131
+		if (defined('PHPUNIT_CONFIG_DIR')) {
132
+			self::$configDir = OC::$SERVERROOT.'/'.PHPUNIT_CONFIG_DIR.'/';
133
+		} elseif (defined('PHPUNIT_RUN') and PHPUNIT_RUN and is_dir(OC::$SERVERROOT.'/tests/config/')) {
134
+			self::$configDir = OC::$SERVERROOT.'/tests/config/';
135
+		} elseif ($dir = getenv('NEXTCLOUD_CONFIG_DIR')) {
136
+			self::$configDir = rtrim($dir, '/').'/';
137 137
 		} else {
138
-			self::$configDir = OC::$SERVERROOT . '/config/';
138
+			self::$configDir = OC::$SERVERROOT.'/config/';
139 139
 		}
140 140
 		self::$config = new \OC\Config(self::$configDir);
141 141
 
@@ -157,9 +157,9 @@  discard block
 block discarded – undo
157 157
 			//make sure suburi follows the same rules as scriptName
158 158
 			if (substr(OC::$SUBURI, -9) != 'index.php') {
159 159
 				if (substr(OC::$SUBURI, -1) != '/') {
160
-					OC::$SUBURI = OC::$SUBURI . '/';
160
+					OC::$SUBURI = OC::$SUBURI.'/';
161 161
 				}
162
-				OC::$SUBURI = OC::$SUBURI . 'index.php';
162
+				OC::$SUBURI = OC::$SUBURI.'index.php';
163 163
 			}
164 164
 		}
165 165
 
@@ -171,7 +171,7 @@  discard block
 block discarded – undo
171 171
 				OC::$WEBROOT = substr($scriptName, 0, 0 - strlen(OC::$SUBURI));
172 172
 
173 173
 				if (OC::$WEBROOT != '' && OC::$WEBROOT[0] !== '/') {
174
-					OC::$WEBROOT = '/' . OC::$WEBROOT;
174
+					OC::$WEBROOT = '/'.OC::$WEBROOT;
175 175
 				}
176 176
 			} else {
177 177
 				// The scriptName is not ending with OC::$SUBURI
@@ -200,11 +200,11 @@  discard block
 block discarded – undo
200 200
 					OC::$APPSROOTS[] = $paths;
201 201
 				}
202 202
 			}
203
-		} elseif (file_exists(OC::$SERVERROOT . '/apps')) {
204
-			OC::$APPSROOTS[] = array('path' => OC::$SERVERROOT . '/apps', 'url' => '/apps', 'writable' => true);
205
-		} elseif (file_exists(OC::$SERVERROOT . '/../apps')) {
203
+		} elseif (file_exists(OC::$SERVERROOT.'/apps')) {
204
+			OC::$APPSROOTS[] = array('path' => OC::$SERVERROOT.'/apps', 'url' => '/apps', 'writable' => true);
205
+		} elseif (file_exists(OC::$SERVERROOT.'/../apps')) {
206 206
 			OC::$APPSROOTS[] = array(
207
-				'path' => rtrim(dirname(OC::$SERVERROOT), '/') . '/apps',
207
+				'path' => rtrim(dirname(OC::$SERVERROOT), '/').'/apps',
208 208
 				'url' => '/apps',
209 209
 				'writable' => true
210 210
 			);
@@ -234,8 +234,8 @@  discard block
 block discarded – undo
234 234
 		$l = \OC::$server->getL10N('lib');
235 235
 
236 236
 		// Create config if it does not already exist
237
-		$configFilePath = self::$configDir .'/config.php';
238
-		if(!file_exists($configFilePath)) {
237
+		$configFilePath = self::$configDir.'/config.php';
238
+		if (!file_exists($configFilePath)) {
239 239
 			@touch($configFilePath);
240 240
 		}
241 241
 
@@ -249,18 +249,18 @@  discard block
 block discarded – undo
249 249
 			if (self::$CLI) {
250 250
 				echo $l->t('Cannot write into "config" directory!')."\n";
251 251
 				echo $l->t('This can usually be fixed by giving the webserver write access to the config directory')."\n";
252
-				echo $l->t('See %s', [ $urlGenerator->linkToDocs('admin-dir_permissions') ])."\n";
252
+				echo $l->t('See %s', [$urlGenerator->linkToDocs('admin-dir_permissions')])."\n";
253 253
 				echo "\n";
254 254
 				echo $l->t('Or, if you prefer to keep config.php file read only, set the option "config_is_read_only" to true in it.')."\n";
255
-				echo $l->t('See %s', [ $urlGenerator->linkToDocs('admin-config') ])."\n";
255
+				echo $l->t('See %s', [$urlGenerator->linkToDocs('admin-config')])."\n";
256 256
 				exit;
257 257
 			} else {
258 258
 				OC_Template::printErrorPage(
259 259
 					$l->t('Cannot write into "config" directory!'),
260 260
 					$l->t('This can usually be fixed by giving the webserver write access to the config directory. See %s',
261
-					[ $urlGenerator->linkToDocs('admin-dir_permissions') ]) . '. '
261
+					[$urlGenerator->linkToDocs('admin-dir_permissions')]).'. '
262 262
 					. $l->t('Or, if you prefer to keep config.php file read only, set the option "config_is_read_only" to true in it. See %s',
263
-					[ $urlGenerator->linkToDocs('admin-config') ] ),
263
+					[$urlGenerator->linkToDocs('admin-config')]),
264 264
 					503
265 265
 				);
266 266
 			}
@@ -276,8 +276,8 @@  discard block
 block discarded – undo
276 276
 			if (OC::$CLI) {
277 277
 				throw new Exception('Not installed');
278 278
 			} else {
279
-				$url = OC::$WEBROOT . '/index.php';
280
-				header('Location: ' . $url);
279
+				$url = OC::$WEBROOT.'/index.php';
280
+				header('Location: '.$url);
281 281
 			}
282 282
 			exit();
283 283
 		}
@@ -382,14 +382,14 @@  discard block
 block discarded – undo
382 382
 		$incompatibleShippedApps = [];
383 383
 		foreach ($incompatibleApps as $appInfo) {
384 384
 			if ($appManager->isShipped($appInfo['id'])) {
385
-				$incompatibleShippedApps[] = $appInfo['name'] . ' (' . $appInfo['id'] . ')';
385
+				$incompatibleShippedApps[] = $appInfo['name'].' ('.$appInfo['id'].')';
386 386
 			}
387 387
 		}
388 388
 
389 389
 		if (!empty($incompatibleShippedApps)) {
390 390
 			$l = \OC::$server->getL10N('core');
391 391
 			$hint = $l->t('The files of the app %$1s were not replaced correctly. Make sure it is a version compatible with the server.', [implode(', ', $incompatibleShippedApps)]);
392
-			throw new \OC\HintException('The files of the app ' . implode(', ', $incompatibleShippedApps) . ' were not replaced correctly. Make sure it is a version compatible with the server.', $hint);
392
+			throw new \OC\HintException('The files of the app '.implode(', ', $incompatibleShippedApps).' were not replaced correctly. Make sure it is a version compatible with the server.', $hint);
393 393
 		}
394 394
 
395 395
 		$tmpl->assign('appsToUpgrade', $appManager->getAppsNeedingUpgrade($ocVersion));
@@ -400,7 +400,7 @@  discard block
 block discarded – undo
400 400
 	}
401 401
 
402 402
 	public static function initSession() {
403
-		if(self::$server->getRequest()->getServerProtocol() === 'https') {
403
+		if (self::$server->getRequest()->getServerProtocol() === 'https') {
404 404
 			ini_set('session.cookie_secure', true);
405 405
 		}
406 406
 
@@ -408,7 +408,7 @@  discard block
 block discarded – undo
408 408
 		ini_set('session.cookie_httponly', 'true');
409 409
 
410 410
 		// set the cookie path to the Nextcloud directory
411
-		$cookie_path = OC::$WEBROOT ? : '/';
411
+		$cookie_path = OC::$WEBROOT ?: '/';
412 412
 		ini_set('session.cookie_path', $cookie_path);
413 413
 
414 414
 		// Let the session name be changed in the initSession Hook
@@ -441,7 +441,7 @@  discard block
 block discarded – undo
441 441
 		// session timeout
442 442
 		if ($session->exists('LAST_ACTIVITY') && (time() - $session->get('LAST_ACTIVITY') > $sessionLifeTime)) {
443 443
 			if (isset($_COOKIE[session_name()])) {
444
-				setcookie(session_name(), '', -1, self::$WEBROOT ? : '/');
444
+				setcookie(session_name(), '', -1, self::$WEBROOT ?: '/');
445 445
 			}
446 446
 			\OC::$server->getUserSession()->logout();
447 447
 		}
@@ -463,7 +463,7 @@  discard block
 block discarded – undo
463 463
 				continue;
464 464
 			}
465 465
 
466
-			$file = $appPath . '/appinfo/classpath.php';
466
+			$file = $appPath.'/appinfo/classpath.php';
467 467
 			if (file_exists($file)) {
468 468
 				require_once $file;
469 469
 			}
@@ -491,14 +491,14 @@  discard block
 block discarded – undo
491 491
 
492 492
 		// Append __Host to the cookie if it meets the requirements
493 493
 		$cookiePrefix = '';
494
-		if($cookieParams['secure'] === true && $cookieParams['path'] === '/') {
494
+		if ($cookieParams['secure'] === true && $cookieParams['path'] === '/') {
495 495
 			$cookiePrefix = '__Host-';
496 496
 		}
497 497
 
498
-		foreach($policies as $policy) {
498
+		foreach ($policies as $policy) {
499 499
 			header(
500 500
 				sprintf(
501
-					'Set-Cookie: %snc_sameSiteCookie%s=true; path=%s; httponly;' . $secureCookie . 'expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=%s',
501
+					'Set-Cookie: %snc_sameSiteCookie%s=true; path=%s; httponly;'.$secureCookie.'expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=%s',
502 502
 					$cookiePrefix,
503 503
 					$policy,
504 504
 					$cookieParams['path'],
@@ -537,31 +537,31 @@  discard block
 block discarded – undo
537 537
 			];
538 538
 		}
539 539
 
540
-		if($request->isUserAgent($incompatibleUserAgents)) {
540
+		if ($request->isUserAgent($incompatibleUserAgents)) {
541 541
 			return;
542 542
 		}
543 543
 
544
-		if(count($_COOKIE) > 0) {
544
+		if (count($_COOKIE) > 0) {
545 545
 			$requestUri = $request->getScriptName();
546 546
 			$processingScript = explode('/', $requestUri);
547
-			$processingScript = $processingScript[count($processingScript)-1];
547
+			$processingScript = $processingScript[count($processingScript) - 1];
548 548
 
549 549
 			// index.php routes are handled in the middleware
550
-			if($processingScript === 'index.php') {
550
+			if ($processingScript === 'index.php') {
551 551
 				return;
552 552
 			}
553 553
 
554 554
 			// All other endpoints require the lax and the strict cookie
555
-			if(!$request->passesStrictCookieCheck()) {
555
+			if (!$request->passesStrictCookieCheck()) {
556 556
 				self::sendSameSiteCookies();
557 557
 				// Debug mode gets access to the resources without strict cookie
558 558
 				// due to the fact that the SabreDAV browser also lives there.
559
-				if(!\OC::$server->getConfig()->getSystemValue('debug', false)) {
559
+				if (!\OC::$server->getConfig()->getSystemValue('debug', false)) {
560 560
 					http_response_code(\OCP\AppFramework\Http::STATUS_SERVICE_UNAVAILABLE);
561 561
 					exit();
562 562
 				}
563 563
 			}
564
-		} elseif(!isset($_COOKIE['nc_sameSiteCookielax']) || !isset($_COOKIE['nc_sameSiteCookiestrict'])) {
564
+		} elseif (!isset($_COOKIE['nc_sameSiteCookielax']) || !isset($_COOKIE['nc_sameSiteCookiestrict'])) {
565 565
 			self::sendSameSiteCookies();
566 566
 		}
567 567
 	}
@@ -572,12 +572,12 @@  discard block
 block discarded – undo
572 572
 
573 573
 		// register autoloader
574 574
 		$loaderStart = microtime(true);
575
-		require_once __DIR__ . '/autoloader.php';
575
+		require_once __DIR__.'/autoloader.php';
576 576
 		self::$loader = new \OC\Autoloader([
577
-			OC::$SERVERROOT . '/lib/private/legacy',
577
+			OC::$SERVERROOT.'/lib/private/legacy',
578 578
 		]);
579 579
 		if (defined('PHPUNIT_RUN')) {
580
-			self::$loader->addValidRoot(OC::$SERVERROOT . '/tests');
580
+			self::$loader->addValidRoot(OC::$SERVERROOT.'/tests');
581 581
 		}
582 582
 		spl_autoload_register(array(self::$loader, 'load'));
583 583
 		$loaderEnd = microtime(true);
@@ -585,12 +585,12 @@  discard block
 block discarded – undo
585 585
 		self::$CLI = (php_sapi_name() == 'cli');
586 586
 
587 587
 		// Add default composer PSR-4 autoloader
588
-		self::$composerAutoloader = require_once OC::$SERVERROOT . '/lib/composer/autoload.php';
588
+		self::$composerAutoloader = require_once OC::$SERVERROOT.'/lib/composer/autoload.php';
589 589
 
590 590
 		try {
591 591
 			self::initPaths();
592 592
 			// setup 3rdparty autoloader
593
-			$vendorAutoLoad = OC::$SERVERROOT. '/3rdparty/autoload.php';
593
+			$vendorAutoLoad = OC::$SERVERROOT.'/3rdparty/autoload.php';
594 594
 			if (!file_exists($vendorAutoLoad)) {
595 595
 				throw new \RuntimeException('Composer autoloader not found, unable to continue. Check the folder "3rdparty". Running "git submodule update --init" will initialize the git submodule that handles the subfolder "3rdparty".');
596 596
 			}
@@ -616,7 +616,7 @@  discard block
 block discarded – undo
616 616
 		@ini_set('display_errors', '0');
617 617
 		@ini_set('log_errors', '1');
618 618
 
619
-		if(!date_default_timezone_set('UTC')) {
619
+		if (!date_default_timezone_set('UTC')) {
620 620
 			throw new \RuntimeException('Could not set timezone to UTC');
621 621
 		}
622 622
 
@@ -670,11 +670,11 @@  discard block
 block discarded – undo
670 670
 					// Convert l10n string into regular string for usage in database
671 671
 					$staticErrors = [];
672 672
 					foreach ($errors as $error) {
673
-						echo $error['error'] . "\n";
674
-						echo $error['hint'] . "\n\n";
673
+						echo $error['error']."\n";
674
+						echo $error['hint']."\n\n";
675 675
 						$staticErrors[] = [
676
-							'error' => (string)$error['error'],
677
-							'hint' => (string)$error['hint'],
676
+							'error' => (string) $error['error'],
677
+							'hint' => (string) $error['hint'],
678 678
 						];
679 679
 					}
680 680
 
@@ -696,7 +696,7 @@  discard block
 block discarded – undo
696 696
 		}
697 697
 		//try to set the session lifetime
698 698
 		$sessionLifeTime = self::getSessionLifeTime();
699
-		@ini_set('gc_maxlifetime', (string)$sessionLifeTime);
699
+		@ini_set('gc_maxlifetime', (string) $sessionLifeTime);
700 700
 
701 701
 		$systemConfig = \OC::$server->getSystemConfig();
702 702
 
@@ -744,7 +744,7 @@  discard block
 block discarded – undo
744 744
 		register_shutdown_function(array($lockProvider, 'releaseAll'));
745 745
 
746 746
 		// Check whether the sample configuration has been copied
747
-		if($systemConfig->getValue('copied_sample_config', false)) {
747
+		if ($systemConfig->getValue('copied_sample_config', false)) {
748 748
 			$l = \OC::$server->getL10N('lib');
749 749
 			OC_Template::printErrorPage(
750 750
 				$l->t('Sample configuration detected'),
@@ -769,11 +769,11 @@  discard block
 block discarded – undo
769 769
 		) {
770 770
 			// Allow access to CSS resources
771 771
 			$isScssRequest = false;
772
-			if(strpos($request->getPathInfo(), '/css/') === 0) {
772
+			if (strpos($request->getPathInfo(), '/css/') === 0) {
773 773
 				$isScssRequest = true;
774 774
 			}
775 775
 
776
-			if(substr($request->getRequestUri(), -11) === '/status.php') {
776
+			if (substr($request->getRequestUri(), -11) === '/status.php') {
777 777
 				http_response_code(400);
778 778
 				header('Content-Type: application/json');
779 779
 				echo '{"error": "Trusted domain error.", "code": 15}';
@@ -811,7 +811,7 @@  discard block
 block discarded – undo
811 811
 
812 812
 			// NOTE: This will be replaced to use OCP
813 813
 			$userSession = self::$server->getUserSession();
814
-			$userSession->listen('\OC\User', 'postLogin', function () use ($userSession) {
814
+			$userSession->listen('\OC\User', 'postLogin', function() use ($userSession) {
815 815
 				if (!defined('PHPUNIT_RUN')) {
816 816
 					// reset brute force delay for this IP address and username
817 817
 					$uid = \OC::$server->getUserSession()->getUser()->getUID();
@@ -948,12 +948,12 @@  discard block
 block discarded – undo
948 948
 		// emergency app disabling
949 949
 		if ($requestPath === '/disableapp'
950 950
 			&& $request->getMethod() === 'POST'
951
-			&& ((array)$request->getParam('appid')) !== ''
951
+			&& ((array) $request->getParam('appid')) !== ''
952 952
 		) {
953 953
 			\OC_JSON::callCheck();
954 954
 			\OC_JSON::checkAdminUser();
955
-			$appIds = (array)$request->getParam('appid');
956
-			foreach($appIds as $appId) {
955
+			$appIds = (array) $request->getParam('appid');
956
+			foreach ($appIds as $appId) {
957 957
 				$appId = \OC_App::cleanAppId($appId);
958 958
 				\OC::$server->getAppManager()->disableApp($appId);
959 959
 			}
@@ -968,7 +968,7 @@  discard block
 block discarded – undo
968 968
 		if (!\OCP\Util::needUpgrade()
969 969
 			&& !((bool) $systemConfig->getValue('maintenance', false))) {
970 970
 			// For logged-in users: Load everything
971
-			if(\OC::$server->getUserSession()->isLoggedIn()) {
971
+			if (\OC::$server->getUserSession()->isLoggedIn()) {
972 972
 				OC_App::loadApps();
973 973
 			} else {
974 974
 				// For guests: Load only filesystem and logging
Please login to merge, or discard this patch.
lib/public/IConfig.php 1 patch
Indentation   +191 added lines, -191 removed lines patch added patch discarded remove patch
@@ -41,217 +41,217 @@
 block discarded – undo
41 41
  * @since 6.0.0
42 42
  */
43 43
 interface IConfig {
44
-	/**
45
-	 * @since 8.2.0
46
-	 */
47
-	const SENSITIVE_VALUE = '***REMOVED SENSITIVE VALUE***';
44
+    /**
45
+     * @since 8.2.0
46
+     */
47
+    const SENSITIVE_VALUE = '***REMOVED SENSITIVE VALUE***';
48 48
 
49
-	/**
50
-	 * Sets and deletes system wide values
51
-	 *
52
-	 * @param array $configs Associative array with `key => value` pairs
53
-	 *                       If value is null, the config key will be deleted
54
-	 * @since 8.0.0
55
-	 */
56
-	public function setSystemValues(array $configs);
49
+    /**
50
+     * Sets and deletes system wide values
51
+     *
52
+     * @param array $configs Associative array with `key => value` pairs
53
+     *                       If value is null, the config key will be deleted
54
+     * @since 8.0.0
55
+     */
56
+    public function setSystemValues(array $configs);
57 57
 
58
-	/**
59
-	 * Sets a new system wide value
60
-	 *
61
-	 * @param string $key the key of the value, under which will be saved
62
-	 * @param mixed $value the value that should be stored
63
-	 * @since 8.0.0
64
-	 */
65
-	public function setSystemValue($key, $value);
58
+    /**
59
+     * Sets a new system wide value
60
+     *
61
+     * @param string $key the key of the value, under which will be saved
62
+     * @param mixed $value the value that should be stored
63
+     * @since 8.0.0
64
+     */
65
+    public function setSystemValue($key, $value);
66 66
 
67
-	/**
68
-	 * Looks up a system wide defined value
69
-	 *
70
-	 * @param string $key the key of the value, under which it was saved
71
-	 * @param mixed $default the default value to be returned if the value isn't set
72
-	 * @return mixed the value or $default
73
-	 * @since 6.0.0 - parameter $default was added in 7.0.0
74
-	 */
75
-	public function getSystemValue($key, $default = '');
67
+    /**
68
+     * Looks up a system wide defined value
69
+     *
70
+     * @param string $key the key of the value, under which it was saved
71
+     * @param mixed $default the default value to be returned if the value isn't set
72
+     * @return mixed the value or $default
73
+     * @since 6.0.0 - parameter $default was added in 7.0.0
74
+     */
75
+    public function getSystemValue($key, $default = '');
76 76
 
77
-	/**
78
-	 * Looks up a boolean system wide defined value
79
-	 *
80
-	 * @param string $key the key of the value, under which it was saved
81
-	 * @param bool $default the default value to be returned if the value isn't set
82
-	 * @return bool the value or $default
83
-	 * @since 16.0.0
84
-	 */
85
-	public function getSystemValueBool(string $key, bool $default = false): bool;
77
+    /**
78
+     * Looks up a boolean system wide defined value
79
+     *
80
+     * @param string $key the key of the value, under which it was saved
81
+     * @param bool $default the default value to be returned if the value isn't set
82
+     * @return bool the value or $default
83
+     * @since 16.0.0
84
+     */
85
+    public function getSystemValueBool(string $key, bool $default = false): bool;
86 86
 
87
-	/**
88
-	 * Looks up an integer system wide defined value
89
-	 *
90
-	 * @param string $key the key of the value, under which it was saved
91
-	 * @param int $default the default value to be returned if the value isn't set
92
-	 * @return int the value or $default
93
-	 * @since 16.0.0
94
-	 */
95
-	public function getSystemValueInt(string $key, int $default = 0): int;
87
+    /**
88
+     * Looks up an integer system wide defined value
89
+     *
90
+     * @param string $key the key of the value, under which it was saved
91
+     * @param int $default the default value to be returned if the value isn't set
92
+     * @return int the value or $default
93
+     * @since 16.0.0
94
+     */
95
+    public function getSystemValueInt(string $key, int $default = 0): int;
96 96
 
97
-	/**
98
-	 * Looks up a string system wide defined value
99
-	 *
100
-	 * @param string $key the key of the value, under which it was saved
101
-	 * @param string $default the default value to be returned if the value isn't set
102
-	 * @return string the value or $default
103
-	 * @since 16.0.0
104
-	 */
105
-	public function getSystemValueString(string $key, string $default = ''): string;
97
+    /**
98
+     * Looks up a string system wide defined value
99
+     *
100
+     * @param string $key the key of the value, under which it was saved
101
+     * @param string $default the default value to be returned if the value isn't set
102
+     * @return string the value or $default
103
+     * @since 16.0.0
104
+     */
105
+    public function getSystemValueString(string $key, string $default = ''): string;
106 106
 
107
-	/**
108
-	 * Looks up a system wide defined value and filters out sensitive data
109
-	 *
110
-	 * @param string $key the key of the value, under which it was saved
111
-	 * @param mixed $default the default value to be returned if the value isn't set
112
-	 * @return mixed the value or $default
113
-	 * @since 8.2.0
114
-	 */
115
-	public function getFilteredSystemValue($key, $default = '');
107
+    /**
108
+     * Looks up a system wide defined value and filters out sensitive data
109
+     *
110
+     * @param string $key the key of the value, under which it was saved
111
+     * @param mixed $default the default value to be returned if the value isn't set
112
+     * @return mixed the value or $default
113
+     * @since 8.2.0
114
+     */
115
+    public function getFilteredSystemValue($key, $default = '');
116 116
 
117
-	/**
118
-	 * Delete a system wide defined value
119
-	 *
120
-	 * @param string $key the key of the value, under which it was saved
121
-	 * @since 8.0.0
122
-	 */
123
-	public function deleteSystemValue($key);
117
+    /**
118
+     * Delete a system wide defined value
119
+     *
120
+     * @param string $key the key of the value, under which it was saved
121
+     * @since 8.0.0
122
+     */
123
+    public function deleteSystemValue($key);
124 124
 
125
-	/**
126
-	 * Get all keys stored for an app
127
-	 *
128
-	 * @param string $appName the appName that we stored the value under
129
-	 * @return string[] the keys stored for the app
130
-	 * @since 8.0.0
131
-	 */
132
-	public function getAppKeys($appName);
125
+    /**
126
+     * Get all keys stored for an app
127
+     *
128
+     * @param string $appName the appName that we stored the value under
129
+     * @return string[] the keys stored for the app
130
+     * @since 8.0.0
131
+     */
132
+    public function getAppKeys($appName);
133 133
 
134
-	/**
135
-	 * Writes a new app wide value
136
-	 *
137
-	 * @param string $appName the appName that we want to store the value under
138
-	 * @param string|float|int $key the key of the value, under which will be saved
139
-	 * @param string $value the value that should be stored
140
-	 * @return void
141
-	 * @since 6.0.0
142
-	 */
143
-	public function setAppValue($appName, $key, $value);
134
+    /**
135
+     * Writes a new app wide value
136
+     *
137
+     * @param string $appName the appName that we want to store the value under
138
+     * @param string|float|int $key the key of the value, under which will be saved
139
+     * @param string $value the value that should be stored
140
+     * @return void
141
+     * @since 6.0.0
142
+     */
143
+    public function setAppValue($appName, $key, $value);
144 144
 
145
-	/**
146
-	 * Looks up an app wide defined value
147
-	 *
148
-	 * @param string $appName the appName that we stored the value under
149
-	 * @param string $key the key of the value, under which it was saved
150
-	 * @param string $default the default value to be returned if the value isn't set
151
-	 * @return string the saved value
152
-	 * @since 6.0.0 - parameter $default was added in 7.0.0
153
-	 */
154
-	public function getAppValue($appName, $key, $default = '');
145
+    /**
146
+     * Looks up an app wide defined value
147
+     *
148
+     * @param string $appName the appName that we stored the value under
149
+     * @param string $key the key of the value, under which it was saved
150
+     * @param string $default the default value to be returned if the value isn't set
151
+     * @return string the saved value
152
+     * @since 6.0.0 - parameter $default was added in 7.0.0
153
+     */
154
+    public function getAppValue($appName, $key, $default = '');
155 155
 
156
-	/**
157
-	 * Delete an app wide defined value
158
-	 *
159
-	 * @param string $appName the appName that we stored the value under
160
-	 * @param string $key the key of the value, under which it was saved
161
-	 * @since 8.0.0
162
-	 */
163
-	public function deleteAppValue($appName, $key);
156
+    /**
157
+     * Delete an app wide defined value
158
+     *
159
+     * @param string $appName the appName that we stored the value under
160
+     * @param string $key the key of the value, under which it was saved
161
+     * @since 8.0.0
162
+     */
163
+    public function deleteAppValue($appName, $key);
164 164
 
165
-	/**
166
-	 * Removes all keys in appconfig belonging to the app
167
-	 *
168
-	 * @param string $appName the appName the configs are stored under
169
-	 * @since 8.0.0
170
-	 */
171
-	public function deleteAppValues($appName);
165
+    /**
166
+     * Removes all keys in appconfig belonging to the app
167
+     *
168
+     * @param string $appName the appName the configs are stored under
169
+     * @since 8.0.0
170
+     */
171
+    public function deleteAppValues($appName);
172 172
 
173 173
 
174
-	/**
175
-	 * Set a user defined value
176
-	 *
177
-	 * @param string $userId the userId of the user that we want to store the value under
178
-	 * @param string $appName the appName that we want to store the value under
179
-	 * @param string $key the key under which the value is being stored
180
-	 * @param string $value the value that you want to store
181
-	 * @param string $preCondition only update if the config value was previously the value passed as $preCondition
182
-	 * @throws \OCP\PreConditionNotMetException if a precondition is specified and is not met
183
-	 * @throws \UnexpectedValueException when trying to store an unexpected value
184
-	 * @since 6.0.0 - parameter $precondition was added in 8.0.0
185
-	 */
186
-	public function setUserValue($userId, $appName, $key, $value, $preCondition = null);
174
+    /**
175
+     * Set a user defined value
176
+     *
177
+     * @param string $userId the userId of the user that we want to store the value under
178
+     * @param string $appName the appName that we want to store the value under
179
+     * @param string $key the key under which the value is being stored
180
+     * @param string $value the value that you want to store
181
+     * @param string $preCondition only update if the config value was previously the value passed as $preCondition
182
+     * @throws \OCP\PreConditionNotMetException if a precondition is specified and is not met
183
+     * @throws \UnexpectedValueException when trying to store an unexpected value
184
+     * @since 6.0.0 - parameter $precondition was added in 8.0.0
185
+     */
186
+    public function setUserValue($userId, $appName, $key, $value, $preCondition = null);
187 187
 
188
-	/**
189
-	 * Shortcut for getting a user defined value
190
-	 *
191
-	 * @param string $userId the userId of the user that we want to store the value under
192
-	 * @param string $appName the appName that we stored the value under
193
-	 * @param string $key the key under which the value is being stored
194
-	 * @param mixed $default the default value to be returned if the value isn't set
195
-	 * @return string
196
-	 * @since 6.0.0 - parameter $default was added in 7.0.0
197
-	 */
198
-	public function getUserValue($userId, $appName, $key, $default = '');
188
+    /**
189
+     * Shortcut for getting a user defined value
190
+     *
191
+     * @param string $userId the userId of the user that we want to store the value under
192
+     * @param string $appName the appName that we stored the value under
193
+     * @param string $key the key under which the value is being stored
194
+     * @param mixed $default the default value to be returned if the value isn't set
195
+     * @return string
196
+     * @since 6.0.0 - parameter $default was added in 7.0.0
197
+     */
198
+    public function getUserValue($userId, $appName, $key, $default = '');
199 199
 
200
-	/**
201
-	 * Fetches a mapped list of userId -> value, for a specified app and key and a list of user IDs.
202
-	 *
203
-	 * @param string $appName app to get the value for
204
-	 * @param string $key the key to get the value for
205
-	 * @param array $userIds the user IDs to fetch the values for
206
-	 * @return array Mapped values: userId => value
207
-	 * @since 8.0.0
208
-	 */
209
-	public function getUserValueForUsers($appName, $key, $userIds);
200
+    /**
201
+     * Fetches a mapped list of userId -> value, for a specified app and key and a list of user IDs.
202
+     *
203
+     * @param string $appName app to get the value for
204
+     * @param string $key the key to get the value for
205
+     * @param array $userIds the user IDs to fetch the values for
206
+     * @return array Mapped values: userId => value
207
+     * @since 8.0.0
208
+     */
209
+    public function getUserValueForUsers($appName, $key, $userIds);
210 210
 
211
-	/**
212
-	 * Get the keys of all stored by an app for the user
213
-	 *
214
-	 * @param string $userId the userId of the user that we want to store the value under
215
-	 * @param string $appName the appName that we stored the value under
216
-	 * @return string[]
217
-	 * @since 8.0.0
218
-	 */
219
-	public function getUserKeys($userId, $appName);
211
+    /**
212
+     * Get the keys of all stored by an app for the user
213
+     *
214
+     * @param string $userId the userId of the user that we want to store the value under
215
+     * @param string $appName the appName that we stored the value under
216
+     * @return string[]
217
+     * @since 8.0.0
218
+     */
219
+    public function getUserKeys($userId, $appName);
220 220
 
221
-	/**
222
-	 * Delete a user value
223
-	 *
224
-	 * @param string $userId the userId of the user that we want to store the value under
225
-	 * @param string $appName the appName that we stored the value under
226
-	 * @param string $key the key under which the value is being stored
227
-	 * @since 8.0.0
228
-	 */
229
-	public function deleteUserValue($userId, $appName, $key);
221
+    /**
222
+     * Delete a user value
223
+     *
224
+     * @param string $userId the userId of the user that we want to store the value under
225
+     * @param string $appName the appName that we stored the value under
226
+     * @param string $key the key under which the value is being stored
227
+     * @since 8.0.0
228
+     */
229
+    public function deleteUserValue($userId, $appName, $key);
230 230
 
231
-	/**
232
-	 * Delete all user values
233
-	 *
234
-	 * @param string $userId the userId of the user that we want to remove all values from
235
-	 * @since 8.0.0
236
-	 */
237
-	public function deleteAllUserValues($userId);
231
+    /**
232
+     * Delete all user values
233
+     *
234
+     * @param string $userId the userId of the user that we want to remove all values from
235
+     * @since 8.0.0
236
+     */
237
+    public function deleteAllUserValues($userId);
238 238
 
239
-	/**
240
-	 * Delete all user related values of one app
241
-	 *
242
-	 * @param string $appName the appName of the app that we want to remove all values from
243
-	 * @since 8.0.0
244
-	 */
245
-	public function deleteAppFromAllUsers($appName);
239
+    /**
240
+     * Delete all user related values of one app
241
+     *
242
+     * @param string $appName the appName of the app that we want to remove all values from
243
+     * @since 8.0.0
244
+     */
245
+    public function deleteAppFromAllUsers($appName);
246 246
 
247
-	/**
248
-	 * Determines the users that have the given value set for a specific app-key-pair
249
-	 *
250
-	 * @param string $appName the app to get the user for
251
-	 * @param string $key the key to get the user for
252
-	 * @param string $value the value to get the user for
253
-	 * @return array of user IDs
254
-	 * @since 8.0.0
255
-	 */
256
-	public function getUsersForUserValue($appName, $key, $value);
247
+    /**
248
+     * Determines the users that have the given value set for a specific app-key-pair
249
+     *
250
+     * @param string $appName the app to get the user for
251
+     * @param string $key the key to get the user for
252
+     * @param string $value the value to get the user for
253
+     * @return array of user IDs
254
+     * @since 8.0.0
255
+     */
256
+    public function getUsersForUserValue($appName, $key, $value);
257 257
 }
Please login to merge, or discard this patch.