summaryrefslogtreecommitdiffstats
path: root/lib/private
diff options
context:
space:
mode:
Diffstat (limited to 'lib/private')
-rw-r--r--lib/private/AppFramework/DependencyInjection/DIContainer.php14
-rw-r--r--lib/private/AppFramework/Http/Request.php1
-rw-r--r--lib/private/AppFramework/Middleware/OCSMiddleware.php62
-rw-r--r--lib/private/CapabilitiesManager.php21
-rw-r--r--lib/private/Comments/Comment.php6
-rw-r--r--lib/private/Installer.php6
-rw-r--r--lib/private/Notification/Manager.php2
-rw-r--r--lib/private/Server.php30
-rw-r--r--lib/private/Settings/Admin/Additional.php88
-rw-r--r--lib/private/Settings/Admin/Encryption.php91
-rw-r--r--lib/private/Settings/Admin/Logging.php86
-rw-r--r--lib/private/Settings/Admin/Server.php149
-rw-r--r--lib/private/Settings/Admin/Sharing.php90
-rw-r--r--lib/private/Settings/Admin/TipsTricks.php71
-rw-r--r--lib/private/Settings/Manager.php431
-rw-r--r--lib/private/Settings/RemoveOrphaned.php91
-rw-r--r--lib/private/Settings/Section.php77
-rw-r--r--lib/private/User/Backend.php4
-rw-r--r--lib/private/User/Database.php16
-rw-r--r--lib/private/User/Manager.php6
-rw-r--r--lib/private/User/Session.php8
-rw-r--r--lib/private/User/User.php26
-rw-r--r--lib/private/legacy/app.php26
-rw-r--r--lib/private/legacy/util.php16
24 files changed, 1370 insertions, 48 deletions
diff --git a/lib/private/AppFramework/DependencyInjection/DIContainer.php b/lib/private/AppFramework/DependencyInjection/DIContainer.php
index 66ca59d26e2..20351d1321c 100644
--- a/lib/private/AppFramework/DependencyInjection/DIContainer.php
+++ b/lib/private/AppFramework/DependencyInjection/DIContainer.php
@@ -124,6 +124,10 @@ class DIContainer extends SimpleContainer implements IAppContainer {
return $this->getServer()->getDateTimeZone();
});
+ $this->registerService('OCP\\IDateTimeFormatter', function($c) {
+ return $this->getServer()->getDateTimeFormatter();
+ });
+
$this->registerService('OCP\\IDb', function($c) {
return $this->getServer()->getDb();
});
@@ -148,6 +152,10 @@ class DIContainer extends SimpleContainer implements IAppContainer {
return $this->getServer()->getMountProviderCollection();
});
+ $this->registerService('OCP\\Files\\Config\\IUserMountCache', function($c) {
+ return $this->getServer()->getUserMountCache();
+ });
+
$this->registerService('OCP\\Files\\IRootFolder', function($c) {
return $this->getServer()->getRootFolder();
});
@@ -306,6 +314,10 @@ class DIContainer extends SimpleContainer implements IAppContainer {
return $c->query('ServerContainer')->getWebRoot();
});
+ $this->registerService('OCP\Encryption\IManager', function ($c) {
+ return $this->getServer()->getEncryptionManager();
+ });
+
/**
* App Framework APIs
@@ -396,6 +408,7 @@ class DIContainer extends SimpleContainer implements IAppContainer {
$this->registerService('MiddlewareDispatcher', function($c) use (&$middleWares) {
$dispatcher = new MiddlewareDispatcher();
$dispatcher->registerMiddleware($c['CORSMiddleware']);
+ $dispatcher->registerMiddleware($c['OCSMiddleware']);
$dispatcher->registerMiddleware($c['SecurityMiddleware']);
$dispatcher->registerMiddleWare($c['TwoFactorMiddleware']);
@@ -404,7 +417,6 @@ class DIContainer extends SimpleContainer implements IAppContainer {
}
$dispatcher->registerMiddleware($c['SessionMiddleware']);
- $dispatcher->registerMiddleware($c['OCSMiddleware']);
return $dispatcher;
});
diff --git a/lib/private/AppFramework/Http/Request.php b/lib/private/AppFramework/Http/Request.php
index 8fb19f2d9b2..2139ad05c2e 100644
--- a/lib/private/AppFramework/Http/Request.php
+++ b/lib/private/AppFramework/Http/Request.php
@@ -56,7 +56,6 @@ use OCP\Security\ISecureRandom;
class Request implements \ArrayAccess, \Countable, IRequest {
const USER_AGENT_IE = '/(MSIE)|(Trident)/';
- const USER_AGENT_IE_8 = '/MSIE 8.0/';
// Microsoft Edge User Agent from https://msdn.microsoft.com/en-us/library/hh869301(v=vs.85).aspx
const USER_AGENT_MS_EDGE = '/^Mozilla\/5\.0 \([^)]+\) AppleWebKit\/[0-9.]+ \(KHTML, like Gecko\) Chrome\/[0-9.]+ (Mobile Safari|Safari)\/[0-9.]+ Edge\/[0-9.]+$/';
// Firefox User Agent from https://developer.mozilla.org/en-US/docs/Web/HTTP/Gecko_user_agent_string_reference
diff --git a/lib/private/AppFramework/Middleware/OCSMiddleware.php b/lib/private/AppFramework/Middleware/OCSMiddleware.php
index e07d100d8ac..68445bbcc51 100644
--- a/lib/private/AppFramework/Middleware/OCSMiddleware.php
+++ b/lib/private/AppFramework/Middleware/OCSMiddleware.php
@@ -23,8 +23,14 @@
namespace OC\AppFramework\Middleware;
use OC\AppFramework\Http;
+use OCP\API;
+use OCP\AppFramework\Http\DataResponse;
+use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Http\OCSResponse;
+use OCP\AppFramework\Http\Response;
use OCP\AppFramework\OCS\OCSException;
+use OCP\AppFramework\OCS\OCSForbiddenException;
+use OCP\AppFramework\OCS\OCSNotFoundException;
use OCP\AppFramework\OCSController;
use OCP\IRequest;
use OCP\AppFramework\Middleware;
@@ -54,12 +60,35 @@ class OCSMiddleware extends Middleware {
$code = $exception->getCode();
if ($code === 0) {
- $code = Http::STATUS_INTERNAL_SERVER_ERROR;
+ $code = API::RESPOND_UNKNOWN_ERROR;
}
+
+ // Build the response
$response = new OCSResponse($format, $code, $exception->getMessage());
+ // Forbidden always sets 401 (even on v1.php)
+ if ($exception instanceof OCSForbiddenException || $code === API::RESPOND_UNAUTHORISED) {
+ $response->setStatus(Http::STATUS_UNAUTHORIZED);
+ }
+
+ // On v2.php we set actual HTTP error codes
if (substr_compare($this->request->getScriptName(), '/ocs/v2.php', -strlen('/ocs/v2.php')) === 0) {
- $response->setStatus($code);
+ if ($code === API::RESPOND_NOT_FOUND) {
+ $response->setStatus(Http::STATUS_NOT_FOUND);
+ } else if ($code === API::RESPOND_SERVER_ERROR) {
+ $response->setStatus(Http::STATUS_INTERNAL_SERVER_ERROR);
+ } else if ($code === API::RESPOND_UNKNOWN_ERROR) {
+ $response->setStatus(Http::STATUS_INTERNAL_SERVER_ERROR);
+ } else if ($code === API::RESPOND_UNAUTHORISED) {
+ // Already set
+ }
+ // 4xx and 5xx codes are forwarded as is.
+ else if ($code >= 400 && $code < 600) {
+ $response->setStatus($code);
+ } else {
+ // All other codes get a bad request
+ $response->setStatus(Http::STATUS_BAD_REQUEST);
+ }
}
return $response;
}
@@ -69,6 +98,35 @@ class OCSMiddleware extends Middleware {
/**
* @param \OCP\AppFramework\Controller $controller
+ * @param string $methodName
+ * @param Response $response
+ * @return \OCP\AppFramework\Http\Response
+ */
+ public function afterController($controller, $methodName, Response $response) {
+ /*
+ * If a different middleware has detected that a request unauthorized or forbidden
+ * we need to catch the response and convert it to a proper OCS response.
+ */
+ if ($controller instanceof OCSController && !($response instanceof OCSResponse)) {
+ if ($response->getStatus() === Http::STATUS_UNAUTHORIZED ||
+ $response->getStatus() === Http::STATUS_FORBIDDEN) {
+ $format = $this->getFormat($controller);
+
+ $message = '';
+ if ($response instanceof JSONResponse) {
+ /** @var DataResponse $response */
+ $message = $response->getData()['message'];
+ }
+ $response = new OCSResponse($format, \OCP\API::RESPOND_UNAUTHORISED, $message);
+ $response->setStatus(Http::STATUS_UNAUTHORIZED);
+ }
+ }
+
+ return $response;
+ }
+
+ /**
+ * @param \OCP\AppFramework\Controller $controller
* @return string
*/
private function getFormat($controller) {
diff --git a/lib/private/CapabilitiesManager.php b/lib/private/CapabilitiesManager.php
index 99a37d652a1..159fa97c708 100644
--- a/lib/private/CapabilitiesManager.php
+++ b/lib/private/CapabilitiesManager.php
@@ -22,15 +22,22 @@
namespace OC;
+use OCP\AppFramework\QueryException;
use OCP\Capabilities\ICapability;
+use OCP\ILogger;
class CapabilitiesManager {
- /**
- * @var \Closure[]
- */
+ /** @var \Closure[] */
private $capabilities = array();
+ /** @var ILogger */
+ private $logger;
+
+ public function __construct(ILogger $logger) {
+ $this->logger = $logger;
+ }
+
/**
* Get an array of al the capabilities that are registered at this manager
*
@@ -40,7 +47,13 @@ class CapabilitiesManager {
public function getCapabilities() {
$capabilities = [];
foreach($this->capabilities as $capability) {
- $c = $capability();
+ try {
+ $c = $capability();
+ } catch (QueryException $e) {
+ $this->logger->error('CapabilitiesManager: {message}', ['app' => 'core', 'message' => $e->getMessage()]);
+ continue;
+ }
+
if ($c instanceof ICapability) {
$capabilities = array_replace_recursive($capabilities, $c->getCapabilities());
} else {
diff --git a/lib/private/Comments/Comment.php b/lib/private/Comments/Comment.php
index d640c606f8e..f6f0801c683 100644
--- a/lib/private/Comments/Comment.php
+++ b/lib/private/Comments/Comment.php
@@ -47,8 +47,8 @@ class Comment implements IComment {
/**
* Comment constructor.
*
- * @param [] $data optional, array with keys according to column names from
- * the comments database scheme
+ * @param array $data optional, array with keys according to column names from
+ * the comments database scheme
*/
public function __construct(array $data = null) {
if(is_array($data)) {
@@ -358,7 +358,7 @@ class Comment implements IComment {
* sets the comment data based on an array with keys as taken from the
* database.
*
- * @param [] $data
+ * @param array $data
* @return IComment
*/
protected function fromArray($data) {
diff --git a/lib/private/Installer.php b/lib/private/Installer.php
index eed97e18d94..3d8a923417a 100644
--- a/lib/private/Installer.php
+++ b/lib/private/Installer.php
@@ -593,6 +593,12 @@ class Installer {
OC_App::setAppTypes($info['id']);
+ if(isset($info['settings']) && is_array($info['settings'])) {
+ // requires that autoloading was registered for the app,
+ // as happens before running the install.php some lines above
+ \OC::$server->getSettingsManager()->setupSettings($info['settings']);
+ }
+
return $info['id'];
}
diff --git a/lib/private/Notification/Manager.php b/lib/private/Notification/Manager.php
index 240cb1e11ff..a079561f5c9 100644
--- a/lib/private/Notification/Manager.php
+++ b/lib/private/Notification/Manager.php
@@ -33,7 +33,7 @@ class Manager implements IManager {
/** @var IApp[] */
protected $apps;
- /** @var INotifier */
+ /** @var INotifier[] */
protected $notifiers;
/** @var array[] */
diff --git a/lib/private/Server.php b/lib/private/Server.php
index d5808d7f17c..44fc605826c 100644
--- a/lib/private/Server.php
+++ b/lib/private/Server.php
@@ -82,7 +82,7 @@ use OC\Security\SecureRandom;
use OC\Security\TrustedDomainHelper;
use OC\Session\CryptoWrapper;
use OC\Tagging\TagMapper;
-use OCA\Theming\Template;
+use OCA\Theming\ThemingDefaults;
use OCP\IL10N;
use OCP\IServerContainer;
use OCP\Security\IContentSecurityPolicyManager;
@@ -629,7 +629,7 @@ class Server extends ServerContainer implements IServerContainer {
return new Manager();
});
$this->registerService('CapabilitiesManager', function (Server $c) {
- $manager = new \OC\CapabilitiesManager();
+ $manager = new \OC\CapabilitiesManager($c->getLogger());
$manager->registerCapability(function () use ($c) {
return new \OC\OCS\CoreCapabilities($c->getConfig());
});
@@ -651,7 +651,7 @@ class Server extends ServerContainer implements IServerContainer {
}
if ($classExists && $this->getConfig()->getSystemValue('installed', false) && $this->getAppManager()->isInstalled('theming')) {
- return new Template(
+ return new ThemingDefaults(
$this->getConfig(),
$this->getL10N('theming'),
$this->getURLGenerator(),
@@ -722,6 +722,18 @@ class Server extends ServerContainer implements IServerContainer {
return $manager;
});
+ $this->registerService('SettingsManager', function(Server $c) {
+ $manager = new \OC\Settings\Manager(
+ $c->getLogger(),
+ $c->getDatabaseConnection(),
+ $c->getL10N('core'),
+ $c->getConfig(),
+ $c->getEncryptionManager(),
+ $c->getUserManager(),
+ $c->getLockingProvider()
+ );
+ return $manager;
+ });
}
/**
@@ -1277,6 +1289,11 @@ class Server extends ServerContainer implements IServerContainer {
return $this->query('MountManager');
}
+ /** @return \OCP\Files\Config\IUserMountCache */
+ function getUserMountCache() {
+ return $this->query('UserMountCache');
+ }
+
/**
* Get the MimeTypeDetector
*
@@ -1425,4 +1442,11 @@ class Server extends ServerContainer implements IServerContainer {
public function getLDAPProvider() {
return $this->query('LDAPProvider');
}
+
+ /**
+ * @return \OCP\Settings\IManager
+ */
+ public function getSettingsManager() {
+ return $this->query('SettingsManager');
+ }
}
diff --git a/lib/private/Settings/Admin/Additional.php b/lib/private/Settings/Admin/Additional.php
new file mode 100644
index 00000000000..d133e4737a7
--- /dev/null
+++ b/lib/private/Settings/Admin/Additional.php
@@ -0,0 +1,88 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Settings\Admin;
+
+use Doctrine\DBAL\Connection;
+use Doctrine\DBAL\DBALException;
+use Doctrine\DBAL\Platforms\SqlitePlatform;
+use OC\Lock\DBLockingProvider;
+use OC\Lock\NoopLockingProvider;
+use OCP\AppFramework\Http\TemplateResponse;
+use OCP\IConfig;
+use OCP\IDBConnection;
+use OCP\IL10N;
+use OCP\Lock\ILockingProvider;
+use OCP\Settings\ISettings;
+
+class Additional implements ISettings {
+ /** @var IConfig */
+ private $config;
+
+ /**
+ * @param IConfig $config
+ */
+ public function __construct(IConfig $config) {
+ $this->config = $config;
+ }
+
+ /**
+ * @return TemplateResponse
+ */
+ public function getForm() {
+ $parameters = [
+ // Mail
+ 'sendmail_is_available' => (bool) \OC_Helper::findBinaryPath('sendmail'),
+ 'mail_domain' => $this->config->getSystemValue('mail_domain', ''),
+ 'mail_from_address' => $this->config->getSystemValue('mail_from_address', ''),
+ 'mail_smtpmode' => $this->config->getSystemValue('mail_smtpmode', ''),
+ 'mail_smtpsecure' => $this->config->getSystemValue('mail_smtpsecure', ''),
+ 'mail_smtphost' => $this->config->getSystemValue('mail_smtphost', ''),
+ 'mail_smtpport' => $this->config->getSystemValue('mail_smtpport', ''),
+ 'mail_smtpauthtype' => $this->config->getSystemValue('mail_smtpauthtype', ''),
+ 'mail_smtpauth' => $this->config->getSystemValue('mail_smtpauth', false),
+ 'mail_smtpname' => $this->config->getSystemValue('mail_smtpname', ''),
+ 'mail_smtppassword' => $this->config->getSystemValue('mail_smtppassword', ''),
+ ];
+
+ return new TemplateResponse('settings', 'admin/additional-mail', $parameters, '');
+ }
+
+ /**
+ * @return string the section ID, e.g. 'sharing'
+ */
+ public function getSection() {
+ return 'additional';
+ }
+
+ /**
+ * @return int whether the form should be rather on the top or bottom of
+ * the admin section. The forms are arranged in ascending order of the
+ * priority values. It is required to return a value between 0 and 100.
+ *
+ * E.g.: 70
+ */
+ public function getPriority() {
+ return 0;
+ }
+}
diff --git a/lib/private/Settings/Admin/Encryption.php b/lib/private/Settings/Admin/Encryption.php
new file mode 100644
index 00000000000..6e93407f1a3
--- /dev/null
+++ b/lib/private/Settings/Admin/Encryption.php
@@ -0,0 +1,91 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Settings\Admin;
+
+use OC\Encryption\Manager;
+use OCP\AppFramework\Http\TemplateResponse;
+use OCP\IUserManager;
+use OCP\Settings\ISettings;
+
+class Encryption implements ISettings {
+ /** @var Manager */
+ private $manager;
+
+ /** @var IUserManager */
+ private $userManager;
+
+ /**
+ * @param Manager $manager
+ * @param IUserManager $userManager
+ */
+ public function __construct(Manager $manager, IUserManager $userManager) {
+ $this->manager = $manager;
+ $this->userManager = $userManager;
+ }
+
+ /**
+ * @return TemplateResponse
+ */
+ public function getForm() {
+ $encryptionModules = $this->manager->getEncryptionModules();
+ $defaultEncryptionModuleId = $this->manager->getDefaultEncryptionModuleId();
+ $encryptionModuleList = [];
+ foreach ($encryptionModules as $module) {
+ $encryptionModuleList[$module['id']]['displayName'] = $module['displayName'];
+ $encryptionModuleList[$module['id']]['default'] = false;
+ if ($module['id'] === $defaultEncryptionModuleId) {
+ $encryptionModuleList[$module['id']]['default'] = true;
+ }
+ }
+
+ $parameters = [
+ // Encryption API
+ 'encryptionEnabled' => $this->manager->isEnabled(),
+ 'encryptionReady' => $this->manager->isReady(),
+ 'externalBackendsEnabled' => count($this->userManager->getBackends()) > 1,
+ // Modules
+ 'encryptionModules' => $encryptionModuleList,
+ ];
+
+ return new TemplateResponse('settings', 'admin/encryption', $parameters, '');
+ }
+
+ /**
+ * @return string the section ID, e.g. 'sharing'
+ */
+ public function getSection() {
+ return 'encryption';
+ }
+
+ /**
+ * @return int whether the form should be rather on the top or bottom of
+ * the admin section. The forms are arranged in ascending order of the
+ * priority values. It is required to return a value between 0 and 100.
+ *
+ * E.g.: 70
+ */
+ public function getPriority() {
+ return 0;
+ }
+}
diff --git a/lib/private/Settings/Admin/Logging.php b/lib/private/Settings/Admin/Logging.php
new file mode 100644
index 00000000000..407248ac4b1
--- /dev/null
+++ b/lib/private/Settings/Admin/Logging.php
@@ -0,0 +1,86 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Settings\Admin;
+
+use OC\Log\File as LogFile;
+use OCP\AppFramework\Http\TemplateResponse;
+use OCP\IConfig;
+use OCP\Settings\ISettings;
+
+class Logging implements ISettings {
+ /** @var IConfig */
+ private $config;
+
+ /**
+ * @param IConfig $config
+ */
+ public function __construct(IConfig $config) {
+ $this->config = $config;
+ }
+
+ /**
+ * @return TemplateResponse
+ */
+ public function getForm() {
+ $logType = $this->config->getSystemValue('log_type', 'file');
+ $showLog = ($logType === 'file' || $logType === 'owncloud');
+
+ $numEntriesToLoad = 5;
+ $entries = LogFile::getEntries($numEntriesToLoad + 1);
+ $entriesRemaining = count($entries) > $numEntriesToLoad;
+ $entries = array_slice($entries, 0, $numEntriesToLoad);
+
+ $logFileExists = file_exists(LogFile::getLogFilePath()) ;
+ $logFileSize = $logFileExists ? filesize(LogFile::getLogFilePath()) : 0;
+
+ $parameters = [
+ 'loglevel' => $this->config->getSystemValue('loglevel', 2),
+ 'entries' => $entries,
+ 'entriesremain' => $entriesRemaining,
+ 'doesLogFileExist' => $logFileExists,
+ 'logFileSize' => $logFileSize,
+ 'showLog' => $showLog,
+ ];
+
+ return new TemplateResponse('settings', 'admin/logging', $parameters, '');
+ }
+
+ /**
+ * @return string the section ID, e.g. 'sharing'
+ */
+ public function getSection() {
+ return 'logging';
+ }
+
+ /**
+ * @return int whether the form should be rather on the top or bottom of
+ * the admin section. The forms are arranged in ascending order of the
+ * priority values. It is required to return a value between 0 and 100.
+ *
+ * E.g.: 70
+ */
+ public function getPriority() {
+ return 0;
+ }
+}
diff --git a/lib/private/Settings/Admin/Server.php b/lib/private/Settings/Admin/Server.php
new file mode 100644
index 00000000000..6b381ab48ed
--- /dev/null
+++ b/lib/private/Settings/Admin/Server.php
@@ -0,0 +1,149 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Settings\Admin;
+
+use Doctrine\DBAL\Connection;
+use Doctrine\DBAL\DBALException;
+use Doctrine\DBAL\Platforms\SqlitePlatform;
+use OC\Lock\DBLockingProvider;
+use OC\Lock\NoopLockingProvider;
+use OCP\AppFramework\Http\TemplateResponse;
+use OCP\IConfig;
+use OCP\IDBConnection;
+use OCP\IL10N;
+use OCP\Lock\ILockingProvider;
+use OCP\Settings\ISettings;
+
+class Server implements ISettings {
+ /** @var IDBConnection|Connection */
+ private $db;
+ /** @var IConfig */
+ private $config;
+ /** @var ILockingProvider */
+ private $lockingProvider;
+ /** @var IL10N */
+ private $l;
+
+ /**
+ * @param IDBConnection $db
+ * @param IConfig $config
+ * @param ILockingProvider $lockingProvider
+ * @param IL10N $l
+ */
+ public function __construct(IDBConnection $db,
+ IConfig $config,
+ ILockingProvider $lockingProvider,
+ IL10N $l) {
+ $this->db = $db;
+ $this->config = $config;
+ $this->lockingProvider = $lockingProvider;
+ $this->l = $l;
+ }
+
+ /**
+ * @return TemplateResponse
+ */
+ public function getForm() {
+ try {
+ if ($this->db->getDatabasePlatform() instanceof SqlitePlatform) {
+ $invalidTransactionIsolationLevel = false;
+ } else {
+ $invalidTransactionIsolationLevel = $this->db->getTransactionIsolation() !== Connection::TRANSACTION_READ_COMMITTED;
+ }
+ } catch (DBALException $e) {
+ // ignore
+ $invalidTransactionIsolationLevel = false;
+ }
+
+ $envPath = getenv('PATH');
+
+ // warn if outdated version of a memcache module is used
+ $caches = [
+ 'apcu' => ['name' => $this->l->t('APCu'), 'version' => '4.0.6'],
+ 'redis' => ['name' => $this->l->t('Redis'), 'version' => '2.2.5'],
+ ];
+ $outdatedCaches = [];
+ foreach ($caches as $php_module => $data) {
+ $isOutdated = extension_loaded($php_module) && version_compare(phpversion($php_module), $data['version'], '<');
+ if ($isOutdated) {
+ $outdatedCaches[$php_module] = $data;
+ }
+ }
+
+ if ($this->lockingProvider instanceof NoopLockingProvider) {
+ $fileLockingType = 'none';
+ } else if ($this->lockingProvider instanceof DBLockingProvider) {
+ $fileLockingType = 'db';
+ } else {
+ $fileLockingType = 'cache';
+ }
+
+ // If the current web root is non-empty but the web root from the config is,
+ // and system cron is used, the URL generator fails to build valid URLs.
+ $shouldSuggestOverwriteCliUrl = $this->config->getAppValue('core', 'backgroundjobs_mode', 'ajax') === 'cron'
+ && \OC::$WEBROOT && \OC::$WEBROOT !== '/'
+ && !$this->config->getSystemValue('overwrite.cli.url', '');
+ $suggestedOverwriteCliUrl = ($shouldSuggestOverwriteCliUrl) ? \OC::$WEBROOT : '';
+
+ $parameters = [
+ // Diagnosis
+ 'readOnlyConfigEnabled' => \OC_Helper::isReadOnlyConfigEnabled(),
+ 'isLocaleWorking' => \OC_Util::isSetLocaleWorking(),
+ 'isAnnotationsWorking' => \OC_Util::isAnnotationsWorking(),
+ 'checkForWorkingWellKnownSetup' => $this->config->getSystemValue('check_for_working_wellknown_setup', true),
+ 'has_fileinfo' => \OC_Util::fileInfoLoaded(),
+ 'invalidTransactionIsolationLevel' => $invalidTransactionIsolationLevel,
+ 'getenvServerNotWorking' => empty($envPath),
+ 'OutdatedCacheWarning' => $outdatedCaches,
+ 'fileLockingType' => $fileLockingType,
+ 'suggestedOverwriteCliUrl' => $suggestedOverwriteCliUrl,
+
+ // Background jobs
+ 'backgroundjobs_mode' => $this->config->getAppValue('core', 'backgroundjobs_mode', 'ajax'),
+ 'cron_log' => $this->config->getSystemValue('cron_log', true),
+ 'lastcron' => $this->config->getAppValue('core', 'lastcron', false),
+ 'cronErrors' => $this->config->getAppValue('core', 'cronErrors'),
+ ];
+
+ return new TemplateResponse('settings', 'admin/server', $parameters, '');
+ }
+
+ /**
+ * @return string the section ID, e.g. 'sharing'
+ */
+ public function getSection() {
+ return 'server';
+ }
+
+ /**
+ * @return int whether the form should be rather on the top or bottom of
+ * the admin section. The forms are arranged in ascending order of the
+ * priority values. It is required to return a value between 0 and 100.
+ *
+ * E.g.: 70
+ */
+ public function getPriority() {
+ return 0;
+ }
+}
diff --git a/lib/private/Settings/Admin/Sharing.php b/lib/private/Settings/Admin/Sharing.php
new file mode 100644
index 00000000000..8d3ddc9b3b5
--- /dev/null
+++ b/lib/private/Settings/Admin/Sharing.php
@@ -0,0 +1,90 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Settings\Admin;
+
+use OC\Share\Share;
+use OCP\AppFramework\Http\TemplateResponse;
+use OCP\IConfig;
+use OCP\Settings\ISettings;
+use OCP\Util;
+
+class Sharing implements ISettings {
+ /** @var IConfig */
+ private $config;
+
+ /**
+ * @param IConfig $config
+ */
+ public function __construct(IConfig $config) {
+ $this->config = $config;
+ }
+
+ /**
+ * @return TemplateResponse
+ */
+ public function getForm() {
+ $excludedGroups = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', '');
+ $excludeGroupsList = !is_null(json_decode($excludedGroups))
+ ? implode('|', json_decode($excludedGroups, true)) : '';
+
+ $parameters = [
+ // Built-In Sharing
+ 'allowGroupSharing' => $this->config->getAppValue('core', 'shareapi_allow_group_sharing', 'yes'),
+ 'allowLinks' => $this->config->getAppValue('core', 'shareapi_allow_links', 'yes'),
+ 'allowMailNotification' => $this->config->getAppValue('core', 'shareapi_allow_mail_notification', 'no'),
+ 'allowPublicMailNotification' => $this->config->getAppValue('core', 'shareapi_allow_public_notification', 'no'),
+ 'allowPublicUpload' => $this->config->getAppValue('core', 'shareapi_allow_public_upload', 'yes'),
+ 'allowResharing' => $this->config->getAppValue('core', 'shareapi_allow_resharing', 'yes'),
+ 'allowShareDialogUserEnumeration' => $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes'),
+ 'enforceLinkPassword' => Util::isPublicLinkPasswordRequired(),
+ 'onlyShareWithGroupMembers' => Share::shareWithGroupMembersOnly(),
+ 'shareAPIEnabled' => $this->config->getAppValue('core', 'shareapi_enabled', 'yes'),
+ 'shareDefaultExpireDateSet' => $this->config->getAppValue('core', 'shareapi_default_expire_date', 'no'),
+ 'shareExpireAfterNDays' => $this->config->getAppValue('core', 'shareapi_expire_after_n_days', '7'),
+ 'shareEnforceExpireDate' => $this->config->getAppValue('core', 'shareapi_enforce_expire_date', 'no'),
+ 'shareExcludeGroups' => $this->config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes' ? true : false,
+ 'shareExcludedGroupsList' => $excludeGroupsList,
+ ];
+
+ return new TemplateResponse('settings', 'admin/sharing', $parameters, '');
+ }
+
+ /**
+ * @return string the section ID, e.g. 'sharing'
+ */
+ public function getSection() {
+ return 'sharing';
+ }
+
+ /**
+ * @return int whether the form should be rather on the top or bottom of
+ * the admin section. The forms are arranged in ascending order of the
+ * priority values. It is required to return a value between 0 and 100.
+ *
+ * E.g.: 70
+ */
+ public function getPriority() {
+ return 0;
+ }
+}
diff --git a/lib/private/Settings/Admin/TipsTricks.php b/lib/private/Settings/Admin/TipsTricks.php
new file mode 100644
index 00000000000..fd0fd595844
--- /dev/null
+++ b/lib/private/Settings/Admin/TipsTricks.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Settings\Admin;
+
+use OCP\AppFramework\Http\TemplateResponse;
+use OCP\IConfig;
+use OCP\Settings\ISettings;
+
+class TipsTricks implements ISettings {
+ /** @var IConfig */
+ private $config;
+
+ /**
+ * @param IConfig $config
+ */
+ public function __construct(IConfig $config) {
+ $this->config = $config;
+ }
+
+ /**
+ * @return TemplateResponse
+ */
+ public function getForm() {
+ $databaseOverload = (strpos($this->config->getSystemValue('dbtype'), 'sqlite') !== false);
+
+ $parameters = [
+ 'databaseOverload' => $databaseOverload,
+ ];
+
+ return new TemplateResponse('settings', 'admin/tipstricks', $parameters, '');
+ }
+
+ /**
+ * @return string the section ID, e.g. 'sharing'
+ */
+ public function getSection() {
+ return 'tips-tricks';
+ }
+
+ /**
+ * @return int whether the form should be rather on the top or bottom of
+ * the admin section. The forms are arranged in ascending order of the
+ * priority values. It is required to return a value between 0 and 100.
+ *
+ * E.g.: 70
+ */
+ public function getPriority() {
+ return 0;
+ }
+}
diff --git a/lib/private/Settings/Manager.php b/lib/private/Settings/Manager.php
new file mode 100644
index 00000000000..7574695d709
--- /dev/null
+++ b/lib/private/Settings/Manager.php
@@ -0,0 +1,431 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Settings;
+
+use OCP\AppFramework\QueryException;
+use OCP\Encryption\IManager as EncryptionManager;
+use OCP\IConfig;
+use OCP\IDBConnection;
+use OCP\IL10N;
+use OCP\ILogger;
+use OCP\IUserManager;
+use OCP\Lock\ILockingProvider;
+use OCP\Settings\ISettings;
+use OCP\Settings\IManager;
+use OCP\Settings\ISection;
+
+class Manager implements IManager {
+ const TABLE_ADMIN_SETTINGS = 'admin_settings';
+ const TABLE_ADMIN_SECTIONS = 'admin_sections';
+
+ /** @var ILogger */
+ private $log;
+ /** @var IDBConnection */
+ private $dbc;
+ /** @var IL10N */
+ private $l;
+ /** @var IConfig */
+ private $config;
+ /** @var EncryptionManager */
+ private $encryptionManager;
+ /** @var IUserManager */
+ private $userManager;
+ /** @var ILockingProvider */
+ private $lockingProvider;
+
+ /**
+ * @param ILogger $log
+ * @param IDBConnection $dbc
+ * @param IL10N $l
+ * @param IConfig $config
+ * @param EncryptionManager $encryptionManager
+ * @param IUserManager $userManager
+ * @param ILockingProvider $lockingProvider
+ */
+ public function __construct(
+ ILogger $log,
+ IDBConnection $dbc,
+ IL10N $l,
+ IConfig $config,
+ EncryptionManager $encryptionManager,
+ IUserManager $userManager,
+ ILockingProvider $lockingProvider
+ ) {
+ $this->log = $log;
+ $this->dbc = $dbc;
+ $this->l = $l;
+ $this->config = $config;
+ $this->encryptionManager = $encryptionManager;
+ $this->userManager = $userManager;
+ $this->lockingProvider = $lockingProvider;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function setupSettings(array $settings) {
+ if(isset($settings[IManager::KEY_ADMIN_SECTION])) {
+ $this->setupAdminSection($settings[IManager::KEY_ADMIN_SECTION]);
+ }
+ if(isset($settings[IManager::KEY_ADMIN_SETTINGS])) {
+ $this->setupAdminSettings($settings[IManager::KEY_ADMIN_SETTINGS]);
+ }
+ }
+
+ /**
+ * attempts to remove an apps section and/or settings entry. A listener is
+ * added centrally making sure that this method is called ones an app was
+ * disabled.
+ *
+ * @param string $appId
+ * @since 9.1.0
+ */
+ public function onAppDisabled($appId) {
+ $appInfo = \OC_App::getAppInfo($appId); // hello static legacy
+
+ if(isset($appInfo['settings'][IManager::KEY_ADMIN_SECTION])) {
+ $this->remove(self::TABLE_ADMIN_SECTIONS, $appInfo['settings'][IManager::KEY_ADMIN_SECTION]);
+ }
+ if(isset($settings['settings'][IManager::KEY_ADMIN_SETTINGS])) {
+ $this->remove(self::TABLE_ADMIN_SETTINGS, $appInfo['settings'][IManager::KEY_ADMIN_SETTINGS]);
+ }
+ }
+
+ public function checkForOrphanedClassNames() {
+ $tables = [ self::TABLE_ADMIN_SECTIONS, self::TABLE_ADMIN_SETTINGS ];
+ foreach ($tables as $table) {
+ $classes = $this->getClasses($table);
+ foreach($classes as $className) {
+ try {
+ \OC::$server->query($className);
+ } catch (QueryException $e) {
+ $this->remove($table, $className);
+ }
+ }
+ }
+ }
+
+ /**
+ * returns the registerd classes in the given table
+ *
+ * @param $table
+ * @return string[]
+ */
+ private function getClasses($table) {
+ $q = $this->dbc->getQueryBuilder();
+ $resultStatement = $q->select('class')
+ ->from($table)
+ ->execute();
+ $data = $resultStatement->fetchAll();
+ $resultStatement->closeCursor();
+
+ return array_map(function($row) { return $row['class']; }, $data);
+ }
+
+ /**
+ * @param string $sectionClassName
+ */
+ private function setupAdminSection($sectionClassName) {
+ if(!class_exists($sectionClassName)) {
+ $this->log->debug('Could not find admin section class ' . $sectionClassName);
+ return;
+ }
+ try {
+ $section = $this->query($sectionClassName);
+ } catch (QueryException $e) {
+ // cancel
+ return;
+ }
+
+ if(!$section instanceof ISection) {
+ $this->log->error(
+ 'Admin section instance must implement \OCP\ISection. Invalid class: {class}',
+ ['class' => $sectionClassName]
+ );
+ return;
+ }
+ if(!$this->hasAdminSection(get_class($section))) {
+ $this->addAdminSection($section);
+ } else {
+ $this->updateAdminSection($section);
+ }
+ }
+
+ private function addAdminSection(ISection $section) {
+ $this->add(self::TABLE_ADMIN_SECTIONS, [
+ 'id' => $section->getID(),
+ 'class' => get_class($section),
+ 'priority' => $section->getPriority(),
+ ]);
+ }
+
+ private function addAdminSettings(ISettings $settings) {
+ $this->add(self::TABLE_ADMIN_SETTINGS, [
+ 'class' => get_class($settings),
+ 'section' => $settings->getSection(),
+ 'priority' => $settings->getPriority(),
+ ]);
+ }
+
+ /**
+ * @param string $table
+ * @param array $values
+ */
+ private function add($table, array $values) {
+ $query = $this->dbc->getQueryBuilder();
+ $values = array_map(function($value) use ($query) {
+ return $query->createNamedParameter($value);
+ }, $values);
+ $query->insert($table)->values($values);
+ $query->execute();
+ }
+
+ private function updateAdminSettings(ISettings $settings) {
+ $this->update(
+ self::TABLE_ADMIN_SETTINGS,
+ 'class',
+ get_class($settings),
+ [
+ 'section' => $settings->getSection(),
+ 'priority' => $settings->getPriority(),
+ ]
+ );
+ }
+
+ private function updateAdminSection(ISection $section) {
+ $this->update(
+ self::TABLE_ADMIN_SECTIONS,
+ 'class',
+ get_class($section),
+ [
+ 'id' => $section->getID(),
+ 'priority' => $section->getPriority(),
+ ]
+ );
+ }
+
+ private function update($table, $idCol, $id, $values) {
+ $query = $this->dbc->getQueryBuilder();
+ $query->update($table);
+ foreach($values as $key => $value) {
+ $query->set($key, $query->createNamedParameter($value));
+ }
+ $query
+ ->where($query->expr()->eq($idCol, $query->createParameter($idCol)))
+ ->setParameter($idCol, $id)
+ ->execute();
+ }
+
+ /**
+ * @param string $className
+ * @return bool
+ */
+ private function hasAdminSection($className) {
+ return $this->has(self::TABLE_ADMIN_SECTIONS, $className);
+ }
+
+ /**
+ * @param string $className
+ * @return bool
+ */
+ private function hasAdminSettings($className) {
+ return $this->has(self::TABLE_ADMIN_SETTINGS, $className);
+ }
+
+ /**
+ * @param string $table
+ * @param string $className
+ * @return bool
+ */
+ private function has($table, $className) {
+ $query = $this->dbc->getQueryBuilder();
+ $query->select('class')
+ ->from($table)
+ ->where($query->expr()->eq('class', $query->createNamedParameter($className)))
+ ->setMaxResults(1);
+
+ $result = $query->execute();
+ $row = $result->fetch();
+ $result->closeCursor();
+
+ return (bool) $row;
+ }
+
+ /**
+ * deletes an settings or admin entry from the given table
+ *
+ * @param $table
+ * @param $className
+ */
+ private function remove($table, $className) {
+ $query = $this->dbc->getQueryBuilder();
+ $query->delete($table)
+ ->where($query->expr()->eq('class', $query->createNamedParameter($className)));
+
+ $query->execute();
+ }
+
+ private function setupAdminSettings($settingsClassName) {
+ if(!class_exists($settingsClassName)) {
+ $this->log->debug('Could not find admin section class ' . $settingsClassName);
+ return;
+ }
+
+ try {
+ /** @var ISettings $settings */
+ $settings = $this->query($settingsClassName);
+ } catch (QueryException $e) {
+ // cancel
+ return;
+ }
+
+ if(!$settings instanceof ISettings) {
+ $this->log->error(
+ 'Admin section instance must implement \OCP\ISection. Invalid class: {class}',
+ ['class' => $settingsClassName]
+ );
+ return;
+ }
+ if(!$this->hasAdminSettings(get_class($settings))) {
+ $this->addAdminSettings($settings);
+ } else {
+ $this->updateAdminSettings($settings);
+ }
+ }
+
+ private function query($className) {
+ try {
+ return \OC::$server->query($className);
+ } catch (QueryException $e) {
+ $this->log->logException($e);
+ throw $e;
+ }
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getAdminSections() {
+ $query = $this->dbc->getQueryBuilder();
+ $query->select(['class', 'priority'])
+ ->from(self::TABLE_ADMIN_SECTIONS);
+
+ // built-in sections
+ $sections = [
+ 0 => [new Section('server', $this->l->t('Server settings'), 0)],
+ 5 => [new Section('sharing', $this->l->t('Sharing'), 0)],
+ 45 => [new Section('encryption', $this->l->t('Encryption'), 0)],
+ 90 => [new Section('logging', $this->l->t('Logging'), 0)],
+ 98 => [new Section('additional', $this->l->t('Additional settings'), 0)],
+ 99 => [new Section('tips-tricks', $this->l->t('Tips & tricks'), 0)],
+ ];
+
+ $result = $query->execute();
+ while($row = $result->fetch()) {
+ if(!isset($sections[$row['priority']])) {
+ $sections[$row['priority']] = [];
+ }
+ try {
+ $sections[$row['priority']][] = $this->query($row['class']);
+ } catch (QueryException $e) {
+ // skip
+ }
+ }
+ $result->closeCursor();
+
+ ksort($sections);
+ return $sections;
+ }
+
+ private function getBuiltInAdminSettings($section) {
+ $forms = [];
+ try {
+ if($section === 'server') {
+ /** @var ISettings $form */
+ $form = new Admin\Server($this->dbc, $this->config, $this->lockingProvider, $this->l);
+ $forms[$form->getPriority()] = [$form];
+ }
+ if($section === 'encryption') {
+ /** @var ISettings $form */
+ $form = new Admin\Encryption($this->encryptionManager, $this->userManager);
+ $forms[$form->getPriority()] = [$form];
+ }
+ if($section === 'sharing') {
+ /** @var ISettings $form */
+ $form = new Admin\Sharing($this->config);
+ $forms[$form->getPriority()] = [$form];
+ }
+ if($section === 'logging') {
+ /** @var ISettings $form */
+ $form = new Admin\Logging($this->config);
+ $forms[$form->getPriority()] = [$form];
+ }
+ if($section === 'additional') {
+ /** @var ISettings $form */
+ $form = new Admin\Additional($this->config);
+ $forms[$form->getPriority()] = [$form];
+ }
+ if($section === 'tips-tricks') {
+ /** @var ISettings $form */
+ $form = new Admin\TipsTricks($this->config);
+ $forms[$form->getPriority()] = [$form];
+ }
+ } catch (QueryException $e) {
+ // skip
+ }
+ return $forms;
+ }
+
+ private function getAdminSettingsFromDB($section, &$settings) {
+ $query = $this->dbc->getQueryBuilder();
+ $query->select(['class', 'priority'])
+ ->from(self::TABLE_ADMIN_SETTINGS)
+ ->where($query->expr()->eq('section', $this->dbc->getQueryBuilder()->createParameter('section')))
+ ->setParameter('section', $section);
+
+ $result = $query->execute();
+ while($row = $result->fetch()) {
+ if(!isset($settings[$row['priority']])) {
+ $settings[$row['priority']] = [];
+ }
+ try {
+ $settings[$row['priority']][] = $this->query($row['class']);
+ } catch (QueryException $e) {
+ // skip
+ }
+ }
+ $result->closeCursor();
+
+ ksort($settings);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getAdminSettings($section) {
+ $settings = $this->getBuiltInAdminSettings($section);
+ $this->getAdminSettingsFromDB($section, $settings);
+ return $settings;
+ }
+}
diff --git a/lib/private/Settings/RemoveOrphaned.php b/lib/private/Settings/RemoveOrphaned.php
new file mode 100644
index 00000000000..fbee95c8879
--- /dev/null
+++ b/lib/private/Settings/RemoveOrphaned.php
@@ -0,0 +1,91 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Settings;
+
+use OC\BackgroundJob\JobList;
+use OC\BackgroundJob\TimedJob;
+use OC\NeedsUpdateException;
+use OCP\BackgroundJob\IJobList;
+use OCP\ILogger;
+
+/**
+ * Class RemoveOrphaned
+ *
+ * @package OC\Settings
+ */
+class RemoveOrphaned extends TimedJob {
+
+ /** @var IJobList */
+ private $jobList;
+
+ /** @var ILogger */
+ private $logger;
+
+ /** @var Manager */
+ private $manager;
+
+ public function __construct(Manager $manager = null) {
+ if($manager !== null) {
+ $this->manager = $manager;
+ } else {
+ // fix DI for Jobs
+ $this->manager = \OC::$server->getSettingsManager();
+ }
+ }
+
+ /**
+ * run the job, then remove it from the job list
+ *
+ * @param JobList $jobList
+ * @param ILogger $logger
+ */
+ public function execute($jobList, ILogger $logger = null) {
+ // add an interval of 15 mins
+ $this->setInterval(15*60);
+
+ $this->jobList = $jobList;
+ $this->logger = $logger;
+ parent::execute($jobList, $logger);
+ }
+
+ /**
+ * @param array $argument
+ * @throws \Exception
+ * @throws \OC\NeedsUpdateException
+ */
+ protected function run($argument) {
+ try {
+ \OC_App::loadApps();
+ } catch (NeedsUpdateException $ex) {
+ // only run when apps are up to date
+ return;
+ }
+
+ $this->manager->checkForOrphanedClassNames();
+
+ // remove the job once executed successfully
+ $this->jobList->remove($this);
+ }
+
+}
diff --git a/lib/private/Settings/Section.php b/lib/private/Settings/Section.php
new file mode 100644
index 00000000000..b3cf242279f
--- /dev/null
+++ b/lib/private/Settings/Section.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Settings;
+
+use OCP\Settings\ISection;
+
+class Section implements ISection {
+ /** @var string */
+ private $id;
+ /** @var string */
+ private $name;
+ /** @var int */
+ private $priority;
+
+ /**
+ * @param string $id
+ * @param string $name
+ * @param int $priority
+ */
+ public function __construct($id, $name, $priority) {
+ $this->id = $id;
+ $this->name = $name;
+ $this->priority = $priority;
+ }
+
+ /**
+ * returns the ID of the section. It is supposed to be a lower case string,
+ * e.g. 'ldap'
+ *
+ * @returns string
+ */
+ public function getID() {
+ return $this->id;
+ }
+
+ /**
+ * returns the translated name as it should be displayed, e.g. 'LDAP / AD
+ * integration'. Use the L10N service to translate it.
+ *
+ * @return string
+ */
+ public function getName() {
+ return $this->name;
+ }
+
+ /**
+ * @return int whether the form should be rather on the top or bottom of
+ * the settings navigation. The sections are arranged in ascending order of
+ * the priority values. It is required to return a value between 0 and 99.
+ *
+ * E.g.: 70
+ */
+ public function getPriority() {
+ return $this->priority;
+ }
+}
diff --git a/lib/private/User/Backend.php b/lib/private/User/Backend.php
index da86a4b0534..374ec5876e1 100644
--- a/lib/private/User/Backend.php
+++ b/lib/private/User/Backend.php
@@ -22,11 +22,13 @@
namespace OC\User;
+use \OCP\UserInterface;
+
/**
* Abstract base class for user management. Provides methods for querying backend
* capabilities.
*/
-abstract class Backend implements \OCP\UserInterface {
+abstract class Backend implements UserInterface {
/**
* error code for functions not provided by the user backend
*/
diff --git a/lib/private/User/Database.php b/lib/private/User/Database.php
index e2cbebab2e4..eba7beffeae 100644
--- a/lib/private/User/Database.php
+++ b/lib/private/User/Database.php
@@ -53,19 +53,25 @@
namespace OC\User;
use OC\Cache\CappedMemoryCache;
+use OCP\IUserBackend;
+use OCP\Util;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\GenericEvent;
/**
* Class for user management in a SQL Database (e.g. MySQL, SQLite)
*/
-class Database extends \OC\User\Backend implements \OCP\IUserBackend {
+class Database extends Backend implements IUserBackend {
/** @var CappedMemoryCache */
private $cache;
+
/** @var EventDispatcher */
private $eventDispatcher;
+
/**
- * OC_User_Database constructor.
+ * \OC\User\Database constructor.
+ *
+ * @param EventDispatcher $eventDispatcher
*/
public function __construct($eventDispatcher = null) {
$this->cache = new CappedMemoryCache();
@@ -233,7 +239,7 @@ class Database extends \OC\User\Backend implements \OCP\IUserBackend {
$result = $query->execute(array($uid));
if ($result === false) {
- \OCP\Util::writeLog('core', \OC_DB::getErrorMessage(), \OCP\Util::ERROR);
+ Util::writeLog('core', \OC_DB::getErrorMessage(), Util::ERROR);
return false;
}
@@ -310,7 +316,7 @@ class Database extends \OC\User\Backend implements \OCP\IUserBackend {
$query = \OC_DB::prepare('SELECT COUNT(*) FROM `*PREFIX*users`');
$result = $query->execute();
if ($result === false) {
- \OCP\Util::writeLog('core', \OC_DB::getErrorMessage(), \OCP\Util::ERROR);
+ Util::writeLog('core', \OC_DB::getErrorMessage(), Util::ERROR);
return false;
}
return $result->fetchOne();
@@ -345,7 +351,7 @@ class Database extends \OC\User\Backend implements \OCP\IUserBackend {
$backends = \OC::$server->getUserManager()->getBackends();
foreach ($backends as $backend) {
- if ($backend instanceof \OC\User\Database) {
+ if ($backend instanceof Database) {
/** @var \OC\User\Database $backend */
$uid = $backend->loginName2UserName($param['uid']);
if ($uid !== false) {
diff --git a/lib/private/User/Manager.php b/lib/private/User/Manager.php
index eb2f1ce1da3..f41468d4926 100644
--- a/lib/private/User/Manager.php
+++ b/lib/private/User/Manager.php
@@ -187,7 +187,7 @@ class Manager extends PublicEmitter implements IUserManager {
$password = str_replace("\0", '', $password);
foreach ($this->backends as $backend) {
- if ($backend->implementsActions(\OC\User\Backend::CHECK_PASSWORD)) {
+ if ($backend->implementsActions(Backend::CHECK_PASSWORD)) {
$uid = $backend->checkPassword($loginName, $password);
if ($uid !== false) {
return $this->getUserObject($uid, $backend);
@@ -291,7 +291,7 @@ class Manager extends PublicEmitter implements IUserManager {
$this->emit('\OC\User', 'preCreateUser', array($uid, $password));
foreach ($this->backends as $backend) {
- if ($backend->implementsActions(\OC\User\Backend::CREATE_USER)) {
+ if ($backend->implementsActions(Backend::CREATE_USER)) {
$backend->createUser($uid, $password);
$user = $this->getUserObject($uid, $backend);
$this->emit('\OC\User', 'postCreateUser', array($user, $password));
@@ -309,7 +309,7 @@ class Manager extends PublicEmitter implements IUserManager {
public function countUsers() {
$userCountStatistics = array();
foreach ($this->backends as $backend) {
- if ($backend->implementsActions(\OC\User\Backend::COUNT_USERS)) {
+ if ($backend->implementsActions(Backend::COUNT_USERS)) {
$backendUsers = $backend->countUsers();
if($backendUsers !== false) {
if($backend instanceof IUserBackend) {
diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php
index 3db6cd1a11a..3b357b69bcf 100644
--- a/lib/private/User/Session.php
+++ b/lib/private/User/Session.php
@@ -167,7 +167,7 @@ class Session implements IUserSession, Emitter {
/**
* set the currently active user
*
- * @param User|null $user
+ * @param IUser|null $user
*/
public function setUser($user) {
if (is_null($user)) {
@@ -287,10 +287,8 @@ class Session implements IUserSession, Emitter {
$this->session->regenerateId();
if ($this->validateToken($password, $uid)) {
return $this->loginWithToken($password);
- } else {
- return $this->loginWithPassword($uid, $password);
}
- return false;
+ return $this->loginWithPassword($uid, $password);
}
/**
@@ -464,7 +462,6 @@ class Session implements IUserSession, Emitter {
$message = \OC::$server->getL10N('lib')->t('User disabled');
throw new LoginException($message);
}
- return false;
}
/**
@@ -652,6 +649,7 @@ class Session implements IUserSession, Emitter {
/**
* Tries to login the user with auth token header
*
+ * @param IRequest $request
* @todo check remember me cookie
* @return boolean
*/
diff --git a/lib/private/User/User.php b/lib/private/User/User.php
index 4d403535bf3..94ac8c13621 100644
--- a/lib/private/User/User.php
+++ b/lib/private/User/User.php
@@ -30,6 +30,7 @@
namespace OC\User;
+use OC\Files\Cache\Storage;
use OC\Hooks\Emitter;
use OC_Helper;
use OCP\IAvatarManager;
@@ -38,6 +39,7 @@ use OCP\IURLGenerator;
use OCP\IUser;
use OCP\IConfig;
use OCP\UserInterface;
+use \OCP\IUserBackend;
class User implements IUser {
/** @var string $uid */
@@ -111,7 +113,7 @@ class User implements IUser {
public function getDisplayName() {
if (!isset($this->displayName)) {
$displayName = '';
- if ($this->backend and $this->backend->implementsActions(\OC\User\Backend::GET_DISPLAYNAME)) {
+ if ($this->backend and $this->backend->implementsActions(Backend::GET_DISPLAYNAME)) {
// get display name and strip whitespace from the beginning and end of it
$backendDisplayName = $this->backend->getDisplayName($this->uid);
if (is_string($backendDisplayName)) {
@@ -136,7 +138,7 @@ class User implements IUser {
*/
public function setDisplayName($displayName) {
$displayName = trim($displayName);
- if ($this->backend->implementsActions(\OC\User\Backend::SET_DISPLAYNAME) && !empty($displayName)) {
+ if ($this->backend->implementsActions(Backend::SET_DISPLAYNAME) && !empty($displayName)) {
$result = $this->backend->setDisplayName($this->uid, $displayName);
if ($result) {
$this->displayName = $displayName;
@@ -198,17 +200,17 @@ class User implements IUser {
// FIXME: Feels like an hack - suggestions?
// We have to delete the user from all groups
- foreach (\OC_Group::getUserGroups($this->uid) as $i) {
- \OC_Group::removeFromGroup($this->uid, $i);
+ foreach (\OC::$server->getGroupManager()->getUserGroupIds($this) as $groupId) {
+ \OC_Group::removeFromGroup($this->uid, $groupId);
}
// Delete the user's keys in preferences
\OC::$server->getConfig()->deleteAllUserValues($this->uid);
// Delete user files in /data/
- \OC_Helper::rmdirr(\OC_User::getHome($this->uid));
+ \OC_Helper::rmdirr($this->getHome());
// Delete the users entry in the storage table
- \OC\Files\Cache\Storage::remove('home::' . $this->uid);
+ Storage::remove('home::' . $this->uid);
\OC::$server->getCommentsManager()->deleteReferencesOfActor('users', $this->uid);
\OC::$server->getCommentsManager()->deleteReadMarksFromUser($this);
@@ -231,7 +233,7 @@ class User implements IUser {
if ($this->emitter) {
$this->emitter->emit('\OC\User', 'preSetPassword', array($this, $password, $recoveryPassword));
}
- if ($this->backend->implementsActions(\OC\User\Backend::SET_PASSWORD)) {
+ if ($this->backend->implementsActions(Backend::SET_PASSWORD)) {
$result = $this->backend->setPassword($this->uid, $password);
if ($this->emitter) {
$this->emitter->emit('\OC\User', 'postSetPassword', array($this, $password, $recoveryPassword));
@@ -249,7 +251,7 @@ class User implements IUser {
*/
public function getHome() {
if (!$this->home) {
- if ($this->backend->implementsActions(\OC\User\Backend::GET_HOME) and $home = $this->backend->getHome($this->uid)) {
+ if ($this->backend->implementsActions(Backend::GET_HOME) and $home = $this->backend->getHome($this->uid)) {
$this->home = $home;
} elseif ($this->config) {
$this->home = $this->config->getSystemValue('datadirectory') . '/' . $this->uid;
@@ -266,7 +268,7 @@ class User implements IUser {
* @return string
*/
public function getBackendClassName() {
- if($this->backend instanceof \OCP\IUserBackend) {
+ if($this->backend instanceof IUserBackend) {
return $this->backend->getBackendName();
}
return get_class($this->backend);
@@ -278,7 +280,7 @@ class User implements IUser {
* @return bool
*/
public function canChangeAvatar() {
- if ($this->backend->implementsActions(\OC\User\Backend::PROVIDE_AVATAR)) {
+ if ($this->backend->implementsActions(Backend::PROVIDE_AVATAR)) {
return $this->backend->canChangeAvatar($this->uid);
}
return true;
@@ -290,7 +292,7 @@ class User implements IUser {
* @return bool
*/
public function canChangePassword() {
- return $this->backend->implementsActions(\OC\User\Backend::SET_PASSWORD);
+ return $this->backend->implementsActions(Backend::SET_PASSWORD);
}
/**
@@ -302,7 +304,7 @@ class User implements IUser {
if ($this->config->getSystemValue('allow_user_to_change_display_name') === false) {
return false;
}
- return $this->backend->implementsActions(\OC\User\Backend::SET_DISPLAYNAME);
+ return $this->backend->implementsActions(Backend::SET_DISPLAYNAME);
}
/**
diff --git a/lib/private/legacy/app.php b/lib/private/legacy/app.php
index 2d5e5ba1932..ceb36449bf0 100644
--- a/lib/private/legacy/app.php
+++ b/lib/private/legacy/app.php
@@ -51,6 +51,7 @@ use OC\App\Platform;
use OC\Installer;
use OC\OCSClient;
use OC\Repair;
+use OCP\App\ManagerEvent;
/**
* This class manages the apps. It allows them to register and integrate in the
@@ -345,6 +346,13 @@ class OC_App {
} else {
$appManager->enableApp($app);
}
+
+ $info = self::getAppInfo($app);
+ if(isset($info['settings']) && is_array($info['settings'])) {
+ $appPath = self::getAppPath($app);
+ self::registerAutoloading($app, $appPath);
+ \OC::$server->getSettingsManager()->setupSettings($info['settings']);
+ }
}
/**
@@ -471,7 +479,7 @@ class OC_App {
$settings[] = array(
"id" => "admin",
"order" => 1000,
- "href" => $urlGenerator->linkToRoute('settings_admin'),
+ "href" => $urlGenerator->linkToRoute('settings.AdminSettings.index'),
"name" => $l->t("Admin"),
"icon" => $urlGenerator->imagePath("settings", "admin.svg")
);
@@ -1162,6 +1170,13 @@ class OC_App {
if (isset($appData['id'])) {
$config->setAppValue($app, 'ocsid', $appData['id']);
}
+
+ if(isset($info['settings']) && is_array($info['settings'])) {
+ $appPath = self::getAppPath($app);
+ self::registerAutoloading($app, $appPath);
+ \OC::$server->getSettingsManager()->setupSettings($info['settings']);
+ }
+
\OC_Hook::emit('OC_App', 'post_enable', array('app' => $app));
} else {
if(empty($appName) ) {
@@ -1199,6 +1214,11 @@ class OC_App {
include $appPath . '/appinfo/update.php';
}
self::setupBackgroundJobs($appData['background-jobs']);
+ if(isset($appData['settings']) && is_array($appData['settings'])) {
+ $appPath = self::getAppPath($appId);
+ self::registerAutoloading($appId, $appPath);
+ \OC::$server->getSettingsManager()->setupSettings($appData['settings']);
+ }
//set remote/public handlers
if (array_key_exists('ocsid', $appData)) {
@@ -1218,6 +1238,10 @@ class OC_App {
$version = \OC_App::getAppVersion($appId);
\OC::$server->getAppConfig()->setValue($appId, 'installed_version', $version);
+ \OC::$server->getEventDispatcher()->dispatch(ManagerEvent::EVENT_APP_UPDATE, new ManagerEvent(
+ ManagerEvent::EVENT_APP_UPDATE, $appId
+ ));
+
return true;
}
diff --git a/lib/private/legacy/util.php b/lib/private/legacy/util.php
index 83274f82792..a975da39271 100644
--- a/lib/private/legacy/util.php
+++ b/lib/private/legacy/util.php
@@ -165,6 +165,7 @@ class OC_Util {
// install storage availability wrapper, before most other wrappers
\OC\Files\Filesystem::addStorageWrapper('oc_availability', function ($mountPoint, $storage) {
+ /** @var \OCP\Files\Storage $storage */
if (!$storage->instanceOfStorage('\OC\Files\Storage\Shared') && !$storage->isLocal()) {
return new \OC\Files\Storage\Wrapper\Availability(['storage' => $storage]);
}
@@ -172,7 +173,7 @@ class OC_Util {
});
\OC\Files\Filesystem::addStorageWrapper('oc_encoding', function ($mountPoint, \OCP\Files\Storage $storage, \OCP\Files\Mount\IMountPoint $mount) {
- if ($mount->getOption('encoding_compatibility', true) && !$storage->instanceOfStorage('\OC\Files\Storage\Shared') && !$storage->isLocal()) {
+ if ($mount->getOption('encoding_compatibility', false) && !$storage->instanceOfStorage('\OC\Files\Storage\Shared') && !$storage->isLocal()) {
return new \OC\Files\Storage\Wrapper\Encoding(['storage' => $storage]);
}
return $storage;
@@ -290,16 +291,19 @@ class OC_Util {
/**
* Get the quota of a user
*
- * @param string $user
+ * @param string $userId
* @return int Quota bytes
*/
- public static function getUserQuota($user) {
- $userQuota = \OC::$server->getUserManager()->get($user)->getQuota();
+ public static function getUserQuota($userId) {
+ $user = \OC::$server->getUserManager()->get($userId);
+ if (is_null($user)) {
+ return \OCP\Files\FileInfo::SPACE_UNLIMITED;
+ }
+ $userQuota = $user->getQuota();
if($userQuota === 'none') {
return \OCP\Files\FileInfo::SPACE_UNLIMITED;
- }else{
- return OC_Helper::computerFileSize($userQuota);
}
+ return OC_Helper::computerFileSize($userQuota);
}
/**