diff options
Diffstat (limited to 'lib/private')
21 files changed, 379 insertions, 736 deletions
diff --git a/lib/private/Activity/LegacyFilter.php b/lib/private/Activity/LegacyFilter.php deleted file mode 100644 index 9beffc1f3a7..00000000000 --- a/lib/private/Activity/LegacyFilter.php +++ /dev/null @@ -1,110 +0,0 @@ -<?php -/** - * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> - * - * @author Joas Schilling <coding@schilljs.com> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -namespace OC\Activity; - -use OCP\Activity\IFilter; -use OCP\Activity\IManager; - -class LegacyFilter implements IFilter { - - /** @var IManager */ - protected $manager; - /** @var string */ - protected $identifier; - /** @var string */ - protected $name; - /** @var bool */ - protected $isTopFilter; - - /** - * LegacySetting constructor. - * - * @param IManager $manager - * @param string $identifier - * @param string $name - * @param bool $isTopFilter - */ - public function __construct(IManager $manager, - $identifier, - $name, - $isTopFilter) { - $this->manager = $manager; - $this->identifier = $identifier; - $this->name = $name; - $this->isTopFilter = $isTopFilter; - } - - /** - * @return string Lowercase a-z and underscore only identifier - * @since 11.0.0 - */ - public function getIdentifier() { - return $this->identifier; - } - - /** - * @return string A translated string - * @since 11.0.0 - */ - public function getName() { - return $this->name; - } - - /** - * @return int whether the filter should be rather on the top or bottom of - * the admin section. The filters are arranged in ascending order of the - * priority values. It is required to return a value between 0 and 100. - * @since 11.0.0 - */ - public function getPriority() { - return $this->isTopFilter ? 40 : 50; - } - - /** - * @return string Full URL to an icon, empty string when none is given - * @since 11.0.0 - */ - public function getIcon() { - // Old API was CSS class, so we can not use this... - return ''; - } - - /** - * @param string[] $types - * @return string[] An array of allowed apps from which activities should be displayed - * @since 11.0.0 - */ - public function filterTypes(array $types) { - return $this->manager->filterNotificationTypes($types, $this->getIdentifier()); - } - - /** - * @return string[] An array of allowed apps from which activities should be displayed - * @since 11.0.0 - */ - public function allowedApps() { - return []; - } -} - diff --git a/lib/private/Activity/LegacySetting.php b/lib/private/Activity/LegacySetting.php deleted file mode 100644 index 7d08533aef5..00000000000 --- a/lib/private/Activity/LegacySetting.php +++ /dev/null @@ -1,125 +0,0 @@ -<?php -/** - * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> - * - * @author Joas Schilling <coding@schilljs.com> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -namespace OC\Activity; - -use OCP\Activity\ISetting; - -class LegacySetting implements ISetting { - - /** @var string */ - protected $identifier; - /** @var string */ - protected $name; - /** @var bool */ - protected $canChangeStream; - /** @var bool */ - protected $isDefaultEnabledStream; - /** @var bool */ - protected $canChangeMail; - /** @var bool */ - protected $isDefaultEnabledMail; - - /** - * LegacySetting constructor. - * - * @param string $identifier - * @param string $name - * @param bool $canChangeStream - * @param bool $isDefaultEnabledStream - * @param bool $canChangeMail - * @param bool $isDefaultEnabledMail - */ - public function __construct($identifier, - $name, - $canChangeStream, - $isDefaultEnabledStream, - $canChangeMail, - $isDefaultEnabledMail) { - $this->identifier = $identifier; - $this->name = $name; - $this->canChangeStream = $canChangeStream; - $this->isDefaultEnabledStream = $isDefaultEnabledStream; - $this->canChangeMail = $canChangeMail; - $this->isDefaultEnabledMail = $isDefaultEnabledMail; - } - - /** - * @return string Lowercase a-z and underscore only identifier - * @since 11.0.0 - */ - public function getIdentifier() { - return $this->identifier; - } - - /** - * @return string A translated string - * @since 11.0.0 - */ - public function getName() { - return $this->name; - } - - /** - * @return int whether the filter should be rather on the top or bottom of - * the admin section. The filters are arranged in ascending order of the - * priority values. It is required to return a value between 0 and 100. - * @since 11.0.0 - */ - public function getPriority() { - return 70; - } - - /** - * @return bool True when the option can be changed for the stream - * @since 11.0.0 - */ - public function canChangeStream() { - return $this->canChangeStream; - } - - /** - * @return bool True when the option can be changed for the stream - * @since 11.0.0 - */ - public function isDefaultEnabledStream() { - return $this->isDefaultEnabledStream; - } - - /** - * @return bool True when the option can be changed for the mail - * @since 11.0.0 - */ - public function canChangeMail() { - return $this->canChangeMail; - } - - /** - * @return bool True when the option can be changed for the stream - * @since 11.0.0 - */ - public function isDefaultEnabledMail() { - return $this->isDefaultEnabledMail; - } -} - diff --git a/lib/private/Activity/Manager.php b/lib/private/Activity/Manager.php index 9e70b6f465a..3381c23e31c 100644 --- a/lib/private/Activity/Manager.php +++ b/lib/private/Activity/Manager.php @@ -28,7 +28,6 @@ namespace OC\Activity; use OCP\Activity\IConsumer; use OCP\Activity\IEvent; -use OCP\Activity\IExtension; use OCP\Activity\IFilter; use OCP\Activity\IManager; use OCP\Activity\IProvider; @@ -64,14 +63,6 @@ class Manager implements IManager { /** @var string */ protected $currentUserId; - /** - * constructor of the controller - * - * @param IRequest $request - * @param IUserSession $session - * @param IConfig $config - * @param IValidator $validator - */ public function __construct(IRequest $request, IUserSession $session, IConfig $config, @@ -88,29 +79,10 @@ class Manager implements IManager { /** @var IConsumer[] */ private $consumers = array(); - /** @var \Closure[] */ - private $extensionsClosures = array(); - - /** @var IExtension[] */ - private $extensions = array(); - - /** @var array list of filters "name" => "is valid" */ - protected $validFilters = array( - 'all' => true, - 'by' => true, - 'self' => true, - ); - - /** @var array list of type icons "type" => "css class" */ - protected $typeIcons = array(); - - /** @var array list of special parameters "app" => ["text" => ["parameter" => "type"]] */ - protected $specialParameters = array(); - /** * @return \OCP\Activity\IConsumer[] */ - protected function getConsumers() { + protected function getConsumers(): array { if (!empty($this->consumers)) { return $this->consumers; } @@ -129,27 +101,6 @@ class Manager implements IManager { } /** - * @return \OCP\Activity\IExtension[] - */ - protected function getExtensions() { - if (!empty($this->extensions)) { - return $this->extensions; - } - - $this->extensions = []; - foreach($this->extensionsClosures as $extension) { - $e = $extension(); - if ($e instanceof IExtension) { - $this->extensions[] = $e; - } else { - throw new \InvalidArgumentException('The given extension does not implement the \OCP\Activity\IExtension interface'); - } - } - - return $this->extensions; - } - - /** * Generates a new IEvent object * * Make sure to call at least the following methods before sending it to the @@ -161,7 +112,7 @@ class Manager implements IManager { * * @return IEvent */ - public function generateEvent() { + public function generateEvent(): IEvent { return new Event($this->validator); } @@ -177,7 +128,7 @@ class Manager implements IManager { * @param IEvent $event * @throws \BadMethodCallException if required values have not been set */ - public function publish(IEvent $event) { + public function publish(IEvent $event): void { if ($event->getAuthor() === '') { if ($this->session->getUser() instanceof IUser) { $event->setAuthor($this->session->getUser()->getUID()); @@ -205,38 +156,22 @@ class Manager implements IManager { * * @param \Closure $callable */ - public function registerConsumer(\Closure $callable) { + public function registerConsumer(\Closure $callable): void { $this->consumersClosures[] = $callable; $this->consumers = []; } - /** - * In order to improve lazy loading a closure can be registered which will be called in case - * activity consumers are actually requested - * - * $callable has to return an instance of OCA\Activity\IExtension - * - * @param \Closure $callable - */ - public function registerExtension(\Closure $callable) { - $this->extensionsClosures[] = $callable; - $this->extensions = []; - } - /** @var string[] */ protected $filterClasses = []; /** @var IFilter[] */ protected $filters = []; - /** @var bool */ - protected $loadedLegacyFilters = false; - /** * @param string $filter Class must implement OCA\Activity\IFilter * @return void */ - public function registerFilter($filter) { + public function registerFilter(string $filter): void { $this->filterClasses[$filter] = false; } @@ -244,24 +179,7 @@ class Manager implements IManager { * @return IFilter[] * @throws \InvalidArgumentException */ - public function getFilters() { - if (!$this->loadedLegacyFilters) { - $legacyFilters = $this->getNavigation(); - - foreach ($legacyFilters['top'] as $filter => $data) { - $this->filters[$filter] = new LegacyFilter( - $this, $filter, $data['name'], true - ); - } - - foreach ($legacyFilters['apps'] as $filter => $data) { - $this->filters[$filter] = new LegacyFilter( - $this, $filter, $data['name'], false - ); - } - $this->loadedLegacyFilters = true; - } - + public function getFilters(): array { foreach ($this->filterClasses as $class => $false) { /** @var IFilter $filter */ $filter = \OC::$server->query($class); @@ -283,7 +201,7 @@ class Manager implements IManager { * @throws \InvalidArgumentException when the filter was not found * @since 11.0.0 */ - public function getFilterById($id) { + public function getFilterById(string $id): IFilter { $filters = $this->getFilters(); if (isset($filters[$id])) { @@ -303,7 +221,7 @@ class Manager implements IManager { * @param string $provider Class must implement OCA\Activity\IProvider * @return void */ - public function registerProvider($provider) { + public function registerProvider(string $provider): void { $this->providerClasses[$provider] = false; } @@ -311,7 +229,7 @@ class Manager implements IManager { * @return IProvider[] * @throws \InvalidArgumentException */ - public function getProviders() { + public function getProviders(): array { foreach ($this->providerClasses as $class => $false) { /** @var IProvider $provider */ $provider = \OC::$server->query($class); @@ -333,14 +251,11 @@ class Manager implements IManager { /** @var ISetting[] */ protected $settings = []; - /** @var bool */ - protected $loadedLegacyTypes = false; - /** * @param string $setting Class must implement OCA\Activity\ISetting * @return void */ - public function registerSetting($setting) { + public function registerSetting(string $setting): void { $this->settingsClasses[$setting] = false; } @@ -348,32 +263,7 @@ class Manager implements IManager { * @return ISetting[] * @throws \InvalidArgumentException */ - public function getSettings() { - if (!$this->loadedLegacyTypes) { - $l = \OC::$server->getL10N('core'); - $legacyTypes = $this->getNotificationTypes($l->getLanguageCode()); - $streamTypes = $this->getDefaultTypes(IExtension::METHOD_STREAM); - $mailTypes = $this->getDefaultTypes(IExtension::METHOD_MAIL); - foreach ($legacyTypes as $type => $data) { - if (is_string($data)) { - $desc = $data; - $canChangeStream = true; - $canChangeMail = true; - } else { - $desc = $data['desc']; - $canChangeStream = in_array(IExtension::METHOD_STREAM, $data['methods']); - $canChangeMail = in_array(IExtension::METHOD_MAIL, $data['methods']); - } - - $this->settings[$type] = new LegacySetting( - $type, $desc, - $canChangeStream, in_array($type, $streamTypes), - $canChangeMail, in_array($type, $mailTypes) - ); - } - $this->loadedLegacyTypes = true; - } - + public function getSettings(): array { foreach ($this->settingsClasses as $class => $false) { /** @var ISetting $setting */ $setting = \OC::$server->query($class); @@ -395,7 +285,7 @@ class Manager implements IManager { * @throws \InvalidArgumentException when the setting was not found * @since 11.0.0 */ - public function getSettingById($id) { + public function getSettingById(string $id): ISetting { $settings = $this->getSettings(); if (isset($settings[$id])) { @@ -405,127 +295,46 @@ class Manager implements IManager { throw new \InvalidArgumentException('Requested setting does not exist'); } - /** - * @param string $type - * @return string - */ - public function getTypeIcon($type) { - if (isset($this->typeIcons[$type])) { - return $this->typeIcons[$type]; - } - - foreach ($this->getExtensions() as $c) { - $icon = $c->getTypeIcon($type); - if (is_string($icon)) { - $this->typeIcons[$type] = $icon; - return $icon; - } - } - - $this->typeIcons[$type] = ''; - return ''; - } /** * @param string $type - * @param string $id + * @param int $id */ - public function setFormattingObject($type, $id) { + public function setFormattingObject(string $type, int $id): void { $this->formattingObjectType = $type; - $this->formattingObjectId = (string) $id; + $this->formattingObjectId = $id; } /** * @return bool */ - public function isFormattingFilteredObject() { + public function isFormattingFilteredObject(): bool { return $this->formattingObjectType !== null && $this->formattingObjectId !== null && $this->formattingObjectType === $this->request->getParam('object_type') - && $this->formattingObjectId === $this->request->getParam('object_id'); + && $this->formattingObjectId === (int) $this->request->getParam('object_id'); } /** * @param bool $status Set to true, when parsing events should not use SVG icons */ - public function setRequirePNG($status) { + public function setRequirePNG(bool $status): void { $this->requirePNG = $status; } /** * @return bool */ - public function getRequirePNG() { + public function getRequirePNG(): bool { return $this->requirePNG; } /** - * @param string $app - * @param string $text - * @param array $params - * @param boolean $stripPath - * @param boolean $highlightParams - * @param string $languageCode - * @return string|false - */ - public function translate($app, $text, $params, $stripPath, $highlightParams, $languageCode) { - foreach ($this->getExtensions() as $c) { - $translation = $c->translate($app, $text, $params, $stripPath, $highlightParams, $languageCode); - if (is_string($translation)) { - return $translation; - } - } - - return false; - } - - /** - * @param string $app - * @param string $text - * @return array|false - */ - public function getSpecialParameterList($app, $text) { - if (isset($this->specialParameters[$app][$text])) { - return $this->specialParameters[$app][$text]; - } - - if (!isset($this->specialParameters[$app])) { - $this->specialParameters[$app] = array(); - } - - foreach ($this->getExtensions() as $c) { - $specialParameter = $c->getSpecialParameterList($app, $text); - if (is_array($specialParameter)) { - $this->specialParameters[$app][$text] = $specialParameter; - return $specialParameter; - } - } - - $this->specialParameters[$app][$text] = false; - return false; - } - - /** - * @param array $activity - * @return integer|false - */ - public function getGroupParameter($activity) { - foreach ($this->getExtensions() as $c) { - $parameter = $c->getGroupParameter($activity); - if ($parameter !== false) { - return $parameter; - } - } - - return false; - } - - /** * Set the user we need to use * * @param string|null $currentUserId * @throws \UnexpectedValueException If the user is invalid */ - public function setCurrentUserId($currentUserId) { + public function setCurrentUserId(string $currentUserId = null): void { if (!is_string($currentUserId) && $currentUserId !== null) { throw new \UnexpectedValueException('The given current user is invalid'); } @@ -540,14 +349,16 @@ class Manager implements IManager { * @return string * @throws \UnexpectedValueException If the token is invalid, does not exist or is not unique */ - public function getCurrentUserId() { + public function getCurrentUserId(): string { if ($this->currentUserId !== null) { return $this->currentUserId; - } else if (!$this->session->isLoggedIn()) { + } + + if (!$this->session->isLoggedIn()) { return $this->getUserFromToken(); - } else { - return $this->session->getUser()->getUID(); } + + return $this->session->getUser()->getUID(); } /** @@ -556,7 +367,7 @@ class Manager implements IManager { * @return string * @throws \UnexpectedValueException If the token is invalid, does not exist or is not unique */ - protected function getUserFromToken() { + protected function getUserFromToken(): string { $token = (string) $this->request->getParam('token', ''); if (strlen($token) !== 30) { throw new \UnexpectedValueException('The token is invalid'); @@ -573,130 +384,4 @@ class Manager implements IManager { return array_shift($users); } - /** - * @return array - * @deprecated 11.0.0 - Use getFilters() instead - */ - public function getNavigation() { - $entries = array( - 'apps' => array(), - 'top' => array(), - ); - foreach ($this->getExtensions() as $c) { - $additionalEntries = $c->getNavigation(); - if (is_array($additionalEntries)) { - $entries['apps'] = array_merge($entries['apps'], $additionalEntries['apps']); - $entries['top'] = array_merge($entries['top'], $additionalEntries['top']); - } - } - - return $entries; - } - - /** - * @param string $filterValue - * @return boolean - * @deprecated 11.0.0 - Use getFilterById() instead - */ - public function isFilterValid($filterValue) { - if (isset($this->validFilters[$filterValue])) { - return $this->validFilters[$filterValue]; - } - - foreach ($this->getExtensions() as $c) { - if ($c->isFilterValid($filterValue) === true) { - $this->validFilters[$filterValue] = true; - return true; - } - } - - $this->validFilters[$filterValue] = false; - return false; - } - - /** - * @param array $types - * @param string $filter - * @return array - * @deprecated 11.0.0 - Use getFilterById()->filterTypes() instead - */ - public function filterNotificationTypes($types, $filter) { - if (!$this->isFilterValid($filter)) { - return $types; - } - - foreach ($this->getExtensions() as $c) { - $result = $c->filterNotificationTypes($types, $filter); - if (is_array($result)) { - $types = $result; - } - } - return $types; - } - - /** - * @param string $filter - * @return array - * @deprecated 11.0.0 - Use getFilterById() instead - */ - public function getQueryForFilter($filter) { - if (!$this->isFilterValid($filter)) { - return [null, null]; - } - - $conditions = array(); - $parameters = array(); - - foreach ($this->getExtensions() as $c) { - $result = $c->getQueryForFilter($filter); - if (is_array($result)) { - list($condition, $parameter) = $result; - if ($condition && is_array($parameter)) { - $conditions[] = $condition; - $parameters = array_merge($parameters, $parameter); - } - } - } - - if (empty($conditions)) { - return array(null, null); - } - - return array(' and ((' . implode(') or (', $conditions) . '))', $parameters); - } - - /** - * Will return additional notification types as specified by other apps - * - * @param string $languageCode - * @return array - * @deprecated 11.0.0 - Use getSettings() instead - */ - public function getNotificationTypes($languageCode) { - $notificationTypes = $sharingNotificationTypes = []; - foreach ($this->getExtensions() as $c) { - $result = $c->getNotificationTypes($languageCode); - if (is_array($result)) { - $notificationTypes = array_merge($notificationTypes, $result); - } - } - - return array_merge($sharingNotificationTypes, $notificationTypes); - } - - /** - * @param string $method - * @return array - * @deprecated 11.0.0 - Use getSettings()->isDefaulEnabled<method>() instead - */ - public function getDefaultTypes($method) { - $defaultTypes = array(); - foreach ($this->getExtensions() as $c) { - $types = $c->getDefaultTypes($method); - if (is_array($types)) { - $defaultTypes = array_merge($types, $defaultTypes); - } - } - return $defaultTypes; - } } diff --git a/lib/private/AppFramework/DependencyInjection/DIContainer.php b/lib/private/AppFramework/DependencyInjection/DIContainer.php index 38857af0d39..de25f8fe4d3 100644 --- a/lib/private/AppFramework/DependencyInjection/DIContainer.php +++ b/lib/private/AppFramework/DependencyInjection/DIContainer.php @@ -261,6 +261,9 @@ class DIContainer extends SimpleContainer implements IAppContainer { $c->query(\OCP\IConfig::class) ) ); + $dispatcher->registerMiddleware( + $c->query(\OC\AppFramework\Middleware\AdditionalScriptsMiddleware::class) + ); foreach($this->middleWares as $middleWare) { $dispatcher->registerMiddleware($c[$middleWare]); diff --git a/lib/private/AppFramework/Middleware/AdditionalScriptsMiddleware.php b/lib/private/AppFramework/Middleware/AdditionalScriptsMiddleware.php new file mode 100644 index 00000000000..de1a02026bf --- /dev/null +++ b/lib/private/AppFramework/Middleware/AdditionalScriptsMiddleware.php @@ -0,0 +1,56 @@ +<?php +declare(strict_types=1); +/** + * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.nl> + * + * @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\AppFramework\Middleware; + +use OCP\AppFramework\Http\Response; +use OCP\AppFramework\Http\TemplateResponse; +use OCP\AppFramework\Middleware; +use OCP\IUserSession; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; + +class AdditionalScriptsMiddleware extends Middleware { + /** @var EventDispatcherInterface */ + private $dispatcher; + /** @var IUserSession */ + private $userSession; + + public function __construct(EventDispatcherInterface $dispatcher, IUserSession $userSession) { + $this->dispatcher = $dispatcher; + $this->userSession = $userSession; + } + + public function afterController($controller, $methodName, Response $response): Response { + if ($response instanceof TemplateResponse) { + $this->dispatcher->dispatch(TemplateResponse::EVENT_LOAD_ADDITIONAL_SCRIPTS); + + if ($this->userSession->isLoggedIn()) { + $this->dispatcher->dispatch(TemplateResponse::EVENT_LOAD_ADDITIONAL_SCRIPTS_LOGGEDIN); + } + } + + return $response; + } + +} diff --git a/lib/private/AppFramework/Routing/RouteConfig.php b/lib/private/AppFramework/Routing/RouteConfig.php index 70208725f46..0477f4dc209 100644 --- a/lib/private/AppFramework/Routing/RouteConfig.php +++ b/lib/private/AppFramework/Routing/RouteConfig.php @@ -1,4 +1,5 @@ <?php +declare(strict_types=1); /** * @copyright Copyright (c) 2016, ownCloud, Inc. * @@ -79,47 +80,42 @@ class RouteConfig { * OCS routes go into a different collection */ $oldCollection = $this->router->getCurrentCollection(); - $this->router->useCollection($oldCollection.'.ocs'); + $this->router->useCollection($oldCollection . '.ocs'); // parse ocs simple routes $this->processOCS($this->routes); + // parse ocs simple routes + $this->processOCSResources($this->routes); + $this->router->useCollection($oldCollection); } - private function processOCS(array $routes) { - $ocsRoutes = isset($routes['ocs']) ? $routes['ocs'] : []; + private function processOCS(array $routes): void { + $ocsRoutes = $routes['ocs'] ?? []; foreach ($ocsRoutes as $ocsRoute) { $name = $ocsRoute['name']; - $postfix = ''; - - if (isset($ocsRoute['postfix'])) { - $postfix = $ocsRoute['postfix']; - } - - if (isset($ocsRoute['root'])) { - $root = $ocsRoute['root']; - } else { - $root = '/apps/'.$this->appName; - } + $postfix = $ocsRoute['postfix'] ?? ''; + $root = $ocsRoute['root'] ?? '/apps/' . $this->appName; $url = $root . $ocsRoute['url']; - $verb = isset($ocsRoute['verb']) ? strtoupper($ocsRoute['verb']) : 'GET'; + $verb = strtoupper($ocsRoute['verb'] ?? 'GET'); $split = explode('#', $name, 2); - if (count($split) != 2) { + if (count($split) !== 2) { throw new \UnexpectedValueException('Invalid route name'); } - $controller = $split[0]; - $action = $split[1]; + list($controller, $action) = $split; $controllerName = $this->buildControllerName($controller); $actionName = $this->buildActionName($action); + $routeName = 'ocs.' . $this->appName . '.' . $controller . '.' . $action . $postfix; + // register the route $handler = new RouteActionHandler($this->container, $controllerName, $actionName); - $router = $this->router->create('ocs.'.$this->appName.'.'.$controller.'.'.$action . $postfix, $url) + $router = $this->router->create($routeName, $url) ->method($verb) ->action($handler); @@ -142,33 +138,29 @@ class RouteConfig { * @param array $routes * @throws \UnexpectedValueException */ - private function processSimpleRoutes($routes) - { - $simpleRoutes = isset($routes['routes']) ? $routes['routes'] : array(); + private function processSimpleRoutes(array $routes): void { + $simpleRoutes = $routes['routes'] ?? []; foreach ($simpleRoutes as $simpleRoute) { $name = $simpleRoute['name']; - $postfix = ''; - - if (isset($simpleRoute['postfix'])) { - $postfix = $simpleRoute['postfix']; - } + $postfix = $simpleRoute['postfix'] ?? ''; $url = $simpleRoute['url']; - $verb = isset($simpleRoute['verb']) ? strtoupper($simpleRoute['verb']) : 'GET'; + $verb = strtoupper($simpleRoute['verb'] ?? 'GET'); $split = explode('#', $name, 2); - if (count($split) != 2) { + if (count($split) !== 2) { throw new \UnexpectedValueException('Invalid route name'); } - $controller = $split[0]; - $action = $split[1]; + list($controller, $action) = $split; $controllerName = $this->buildControllerName($controller); $actionName = $this->buildActionName($action); + $routeName = $this->appName . '.' . $controller . '.' . $action . $postfix; + // register the route $handler = new RouteActionHandler($this->container, $controllerName, $actionName); - $router = $this->router->create($this->appName.'.'.$controller.'.'.$action . $postfix, $url) + $router = $this->router->create($routeName, $url) ->method($verb) ->action($handler); @@ -187,41 +179,90 @@ class RouteConfig { } /** + * For a given name and url restful OCS routes are created: + * - index + * - show + * - create + * - update + * - destroy + * + * @param array $routes + */ + private function processOCSResources(array $routes): void { + // declaration of all restful actions + $actions = [ + ['name' => 'index', 'verb' => 'GET', 'on-collection' => true], + ['name' => 'show', 'verb' => 'GET'], + ['name' => 'create', 'verb' => 'POST', 'on-collection' => true], + ['name' => 'update', 'verb' => 'PUT'], + ['name' => 'destroy', 'verb' => 'DELETE'], + ]; + + $resources = $routes['ocs-resources'] ?? []; + foreach ($resources as $resource => $config) { + $root = $config['root'] ?? '/apps/' . $this->appName; + + // the url parameter used as id to the resource + foreach($actions as $action) { + $url = $root . $config['url']; + $method = $action['name']; + $verb = strtoupper($action['verb'] ?? 'GET'); + $collectionAction = $action['on-collection'] ?? false; + if (!$collectionAction) { + $url .= '/{id}'; + } + if (isset($action['url-postfix'])) { + $url .= '/' . $action['url-postfix']; + } + + $controller = $resource; + + $controllerName = $this->buildControllerName($controller); + $actionName = $this->buildActionName($method); + + $routeName = 'ocs.' . $this->appName . '.' . strtolower($resource) . '.' . strtolower($method); + + $this->router->create($routeName, $url)->method($verb)->action( + new RouteActionHandler($this->container, $controllerName, $actionName) + ); + } + } + } + + /** * For a given name and url restful routes are created: * - index * - show - * - new * - create * - update * - destroy * * @param array $routes */ - private function processResources($routes) - { + private function processResources(array $routes): void { // declaration of all restful actions - $actions = array( - array('name' => 'index', 'verb' => 'GET', 'on-collection' => true), - array('name' => 'show', 'verb' => 'GET'), - array('name' => 'create', 'verb' => 'POST', 'on-collection' => true), - array('name' => 'update', 'verb' => 'PUT'), - array('name' => 'destroy', 'verb' => 'DELETE'), - ); - - $resources = isset($routes['resources']) ? $routes['resources'] : array(); + $actions = [ + ['name' => 'index', 'verb' => 'GET', 'on-collection' => true], + ['name' => 'show', 'verb' => 'GET'], + ['name' => 'create', 'verb' => 'POST', 'on-collection' => true], + ['name' => 'update', 'verb' => 'PUT'], + ['name' => 'destroy', 'verb' => 'DELETE'], + ]; + + $resources = $routes['resources'] ?? []; foreach ($resources as $resource => $config) { // the url parameter used as id to the resource foreach($actions as $action) { $url = $config['url']; $method = $action['name']; - $verb = isset($action['verb']) ? strtoupper($action['verb']) : 'GET'; - $collectionAction = isset($action['on-collection']) ? $action['on-collection'] : false; + $verb = strtoupper($action['verb'] ?? 'GET'); + $collectionAction = $action['on-collection'] ?? false; if (!$collectionAction) { - $url = $url . '/{id}'; + $url .= '/{id}'; } if (isset($action['url-postfix'])) { - $url = $url . '/' . $action['url-postfix']; + $url .= '/' . $action['url-postfix']; } $controller = $resource; @@ -243,8 +284,7 @@ class RouteConfig { * @param string $controller * @return string */ - private function buildControllerName($controller) - { + private function buildControllerName(string $controller): string { if (!isset($this->controllerNameCache[$controller])) { $this->controllerNameCache[$controller] = $this->underScoreToCamelCase(ucfirst($controller)) . 'Controller'; } @@ -256,7 +296,7 @@ class RouteConfig { * @param string $action * @return string */ - private function buildActionName($action) { + private function buildActionName(string $action): string { return $this->underScoreToCamelCase($action); } @@ -265,12 +305,12 @@ class RouteConfig { * @param string $str * @return string */ - private function underScoreToCamelCase($str) { - $pattern = "/_[a-z]?/"; + private function underScoreToCamelCase(string $str): string { + $pattern = '/_[a-z]?/'; return preg_replace_callback( $pattern, function ($matches) { - return strtoupper(ltrim($matches[0], "_")); + return strtoupper(ltrim($matches[0], '_')); }, $str); } diff --git a/lib/private/Authentication/TwoFactorAuth/Manager.php b/lib/private/Authentication/TwoFactorAuth/Manager.php index 56fca8a745c..ef95184aba7 100644 --- a/lib/private/Authentication/TwoFactorAuth/Manager.php +++ b/lib/private/Authentication/TwoFactorAuth/Manager.php @@ -31,6 +31,7 @@ use function array_diff; use function array_filter; use BadMethodCallException; use Exception; +use OC\Authentication\Exceptions\ExpiredTokenException; use OC\Authentication\Exceptions\InvalidTokenException; use OC\Authentication\Token\IProvider as TokenProvider; use OCP\Activity\IManager; @@ -364,4 +365,12 @@ class Manager { $this->config->setUserValue($user->getUID(), 'login_token_2fa', $token->getId(), $this->timeFactory->getTime()); } + public function clearTwoFactorPending(string $userId) { + $tokensNeeding2FA = $this->config->getUserKeys($userId, 'login_token_2fa'); + + foreach ($tokensNeeding2FA as $tokenId) { + $this->tokenProvider->invalidateTokenById($userId, $tokenId); + } + } + } diff --git a/lib/private/Config.php b/lib/private/Config.php index c881e485006..f462bebaf58 100644 --- a/lib/private/Config.php +++ b/lib/private/Config.php @@ -265,10 +265,8 @@ class Config { flock($filePointer, LOCK_UN); fclose($filePointer); - // Try invalidating the opcache just for the file we wrote... - if (!\OC_Util::deleteFromOpcodeCache($this->configFilePath)) { - // But if that doesn't work, clear the whole cache. - \OC_Util::clearOpcodeCache(); + if (function_exists('opcache_invalidate')) { + @opcache_invalidate($this->configFilePath, true); } } } diff --git a/lib/private/ContactsManager.php b/lib/private/ContactsManager.php index 6a83a718d41..e279997e634 100644 --- a/lib/private/ContactsManager.php +++ b/lib/private/ContactsManager.php @@ -119,7 +119,12 @@ namespace OC { } /** + * Return a list of the user's addressbooks display names + * ! The addressBook displayName are not unique, please use getUserAddressBooks + * * @return array + * @since 6.0.0 + * @deprecated 16.0.0 - Use `$this->getUserAddressBooks()` instead */ public function getAddressBooks() { $this->loadAddressBooks(); @@ -132,6 +137,17 @@ namespace OC { } /** + * Return a list of the user's addressbooks + * + * @return IAddressBook[] + * @since 16.0.0 + */ + public function getUserAddressBooks(): Array { + $this->loadAddressBooks(); + return $this->addressBooks; + } + + /** * removes all registered address book instances */ public function clear() { diff --git a/lib/private/Files/ObjectStore/S3ObjectTrait.php b/lib/private/Files/ObjectStore/S3ObjectTrait.php index a1110d87c8f..0b55c319ea8 100644 --- a/lib/private/Files/ObjectStore/S3ObjectTrait.php +++ b/lib/private/Files/ObjectStore/S3ObjectTrait.php @@ -23,6 +23,7 @@ namespace OC\Files\ObjectStore; +use Aws\S3\MultipartUploader; use Aws\S3\S3Client; const S3_UPLOAD_PART_SIZE = 524288000; // 500MB @@ -72,10 +73,12 @@ trait S3ObjectTrait { * @since 7.0.0 */ function writeObject($urn, $stream) { - $this->getConnection()->upload($this->bucket, $urn, $stream, 'private', [ - 'mup_threshold' => S3_UPLOAD_PART_SIZE, + $uploader = new MultipartUploader($this->getConnection(), $stream, [ + 'bucket' => $this->bucket, + 'key' => $urn, 'part_size' => S3_UPLOAD_PART_SIZE ]); + $uploader->upload(); } /** diff --git a/lib/private/Files/View.php b/lib/private/Files/View.php index 21df67cf557..6066aed411f 100644 --- a/lib/private/Files/View.php +++ b/lib/private/Files/View.php @@ -1137,7 +1137,13 @@ class View { list($storage, $internalPath) = Filesystem::resolvePath($absolutePath . $postFix); if ($run and $storage) { if (in_array('write', $hooks) || in_array('delete', $hooks)) { - $this->changeLock($path, ILockingProvider::LOCK_EXCLUSIVE); + try { + $this->changeLock($path, ILockingProvider::LOCK_EXCLUSIVE); + } catch (LockedException $e) { + // release the shared lock we acquired before quiting + $this->unlockFile($path, ILockingProvider::LOCK_SHARED); + throw $e; + } } try { if (!is_null($extraParam)) { diff --git a/lib/private/InitialStateService.php b/lib/private/InitialStateService.php new file mode 100644 index 00000000000..6db264bb981 --- /dev/null +++ b/lib/private/InitialStateService.php @@ -0,0 +1,90 @@ +<?php +declare(strict_types=1); +/** + * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl> + * + * @author Roeland Jago Douma <roeland@famdouma.nl> + * + * @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; + +use Closure; +use OCP\IInitialStateService; +use OCP\ILogger; + +class InitialStateService implements IInitialStateService { + + /** @var ILogger */ + private $logger; + + /** @var string[][] */ + private $states = []; + + /** @var Closure[][] */ + private $lazyStates = []; + + public function __construct(ILogger $logger) { + $this->logger = $logger; + } + + public function provideInitialState(string $appName, string $key, $data): void { + // Scalars and JsonSerializable are fine + if (is_scalar($data) || $data instanceof \JsonSerializable || is_array($data)) { + if (!isset($this->states[$appName])) { + $this->states[$appName] = []; + } + $this->states[$appName][$key] = json_encode($data); + return; + } + + $this->logger->warning('Invalid data provided to provideInitialState by ' . $appName); + } + + public function provideLazyInitialState(string $appName, string $key, Closure $closure): void { + if (!isset($this->lazyStates[$appName])) { + $this->lazyStates[$appName] = []; + } + $this->lazyStates[$appName][$key] = $closure; + } + + /** + * Invoke all callbacks to populate the `states` property + */ + private function invokeLazyStateCallbacks(): void { + foreach ($this->lazyStates as $app => $lazyStates) { + foreach ($lazyStates as $key => $lazyState) { + $this->provideInitialState($app, $key, $lazyState()); + } + } + $this->lazyStates = []; + } + + public function getInitialStates(): array { + $this->invokeLazyStateCallbacks(); + + $appStates = []; + foreach ($this->states as $app => $states) { + foreach ($states as $key => $value) { + $appStates["$app-$key"] = $value; + } + } + return $appStates; + } + +} diff --git a/lib/private/Preview/TXT.php b/lib/private/Preview/TXT.php index a5efb73010c..2bb121775d6 100644 --- a/lib/private/Preview/TXT.php +++ b/lib/private/Preview/TXT.php @@ -60,8 +60,9 @@ class TXT extends Provider { $lines = preg_split("/\r\n|\n|\r/", $content); - $fontSize = $maxX ? (int) ((5 / 32) * $maxX) : 5; //5px - $lineSize = ceil($fontSize * 1.25); + // Define text size of text file preview + $fontSize = $maxX ? (int) ((2 / 32) * $maxX) : 5; //5px + $lineSize = ceil($fontSize * 1.5); $image = imagecreate($maxX, $maxY); imagecolorallocate($image, 255, 255, 255); diff --git a/lib/private/Server.php b/lib/private/Server.php index 03d115fe022..86d304af5ef 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -141,8 +141,10 @@ use OCP\Files\NotFoundException; use OCP\Files\Storage\IStorageFactory; use OCP\FullTextSearch\IFullTextSearchManager; use OCP\GlobalScale\IConfig; +use OCP\Group\ISubAdmin; use OCP\ICacheFactory; use OCP\IDBConnection; +use OCP\IInitialStateService; use OCP\IL10N; use OCP\IServerContainer; use OCP\ITempManager; @@ -413,9 +415,9 @@ class Server extends ServerContainer implements IServerContainer { $userSession->listen('\OC\User', 'preLogin', function ($uid, $password) { \OC_Hook::emit('OC_User', 'pre_login', array('run' => true, 'uid' => $uid, 'password' => $password)); }); - $userSession->listen('\OC\User', 'postLogin', function ($user, $password) { + $userSession->listen('\OC\User', 'postLogin', function ($user, $password, $isTokenLogin) { /** @var $user \OC\User\User */ - \OC_Hook::emit('OC_User', 'post_login', array('run' => true, 'uid' => $user->getUID(), 'password' => $password)); + \OC_Hook::emit('OC_User', 'post_login', array('run' => true, 'uid' => $user->getUID(), 'password' => $password, 'isTokenLogin' => $isTokenLogin)); }); $userSession->listen('\OC\User', 'postRememberedLogin', function ($user, $password) { /** @var $user \OC\User\User */ @@ -1201,6 +1203,10 @@ class Server extends ServerContainer implements IServerContainer { ); }); + $this->registerAlias(ISubAdmin::class, SubAdmin::class); + + $this->registerAlias(IInitialStateService::class, InitialStateService::class); + $this->connectDispatcher(); } diff --git a/lib/private/Settings/Personal/PersonalInfo.php b/lib/private/Settings/Personal/PersonalInfo.php index 8c1c8cb19b8..98991ce6d40 100644 --- a/lib/private/Settings/Personal/PersonalInfo.php +++ b/lib/private/Settings/Personal/PersonalInfo.php @@ -227,7 +227,7 @@ class PersonalInfo implements ISettings { $uid = $user->getUID(); - $userLocaleString = $this->config->getUserValue($uid, 'core', 'locale', 'en_US'); + $userLocaleString = $this->config->getUserValue($uid, 'core', 'locale', $this->l10nFactory->findLocale()); $userLang = $this->config->getUserValue($uid, 'core', 'lang', $this->l10nFactory->findLanguage()); diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php index e76269f9d86..b04f1acbd87 100644 --- a/lib/private/Share20/Manager.php +++ b/lib/private/Share20/Manager.php @@ -692,15 +692,15 @@ class Manager implements IManager { $emailAddress, $share->getExpirationDate() ); - $this->logger->debug('Send share notification to ' . $emailAddress . ' for share with ID ' . $share->getId(), ['app' => 'share']); + $this->logger->debug('Sent share notification to ' . $emailAddress . ' for share with ID ' . $share->getId(), ['app' => 'share']); } else { - $this->logger->debug('Share notification not send to ' . $share->getSharedWith() . ' because email address is not set.', ['app' => 'share']); + $this->logger->debug('Share notification not sent to ' . $share->getSharedWith() . ' because email address is not set.', ['app' => 'share']); } } else { - $this->logger->debug('Share notification not send to ' . $share->getSharedWith() . ' because user could not be found.', ['app' => 'share']); + $this->logger->debug('Share notification not sent to ' . $share->getSharedWith() . ' because user could not be found.', ['app' => 'share']); } } else { - $this->logger->debug('Share notification not send because mailsend is false.', ['app' => 'share']); + $this->logger->debug('Share notification not sent because mailsend is false.', ['app' => 'share']); } } @@ -708,13 +708,16 @@ class Manager implements IManager { } /** + * Send mail notifications + * + * This method will catch and log mail transmission errors + * * @param IL10N $l Language of the recipient * @param string $filename file/folder name * @param string $link link to the file/folder * @param string $initiator user ID of share sender * @param string $shareWith email address of share receiver * @param \DateTime|null $expiration - * @throws \Exception If mail couldn't be sent */ protected function sendMailNotification(IL10N $l, $filename, @@ -773,7 +776,15 @@ class Manager implements IManager { } $message->useTemplate($emailTemplate); - $this->mailer->send($message); + try { + $failedRecipients = $this->mailer->send($message); + if(!empty($failedRecipients)) { + $this->logger->error('Share notification mail could not be sent to: ' . implode(', ', $failedRecipients)); + return; + } + } catch (\Exception $e) { + $this->logger->logException($e, ['message' => 'Share notification mail could not be sent']); + } } /** diff --git a/lib/private/SubAdmin.php b/lib/private/SubAdmin.php index 44d79d8994e..f79a0b1ae5a 100644 --- a/lib/private/SubAdmin.php +++ b/lib/private/SubAdmin.php @@ -29,13 +29,14 @@ namespace OC; use OC\Hooks\PublicEmitter; +use OCP\Group\ISubAdmin; use OCP\IUser; use OCP\IUserManager; use OCP\IGroup; use OCP\IGroupManager; use OCP\IDBConnection; -class SubAdmin extends PublicEmitter { +class SubAdmin extends PublicEmitter implements ISubAdmin { /** @var IUserManager */ private $userManager; @@ -70,9 +71,8 @@ class SubAdmin extends PublicEmitter { * add a SubAdmin * @param IUser $user user to be SubAdmin * @param IGroup $group group $user becomes subadmin of - * @return bool */ - public function createSubAdmin(IUser $user, IGroup $group) { + public function createSubAdmin(IUser $user, IGroup $group): void { $qb = $this->dbConn->getQueryBuilder(); $qb->insert('group_admin') @@ -84,16 +84,14 @@ class SubAdmin extends PublicEmitter { $this->emit('\OC\SubAdmin', 'postCreateSubAdmin', [$user, $group]); \OC_Hook::emit("OC_SubAdmin", "post_createSubAdmin", ["gid" => $group->getGID()]); - return true; } /** * delete a SubAdmin * @param IUser $user the user that is the SubAdmin * @param IGroup $group the group - * @return bool */ - public function deleteSubAdmin(IUser $user, IGroup $group) { + public function deleteSubAdmin(IUser $user, IGroup $group): void { $qb = $this->dbConn->getQueryBuilder(); $qb->delete('group_admin') @@ -103,7 +101,6 @@ class SubAdmin extends PublicEmitter { $this->emit('\OC\SubAdmin', 'postDeleteSubAdmin', [$user, $group]); \OC_Hook::emit("OC_SubAdmin", "post_deleteSubAdmin", ["gid" => $group->getGID()]); - return true; } /** @@ -111,7 +108,7 @@ class SubAdmin extends PublicEmitter { * @param IUser $user the SubAdmin * @return IGroup[] */ - public function getSubAdminsGroups(IUser $user) { + public function getSubAdminsGroups(IUser $user): array { $qb = $this->dbConn->getQueryBuilder(); $result = $qb->select('gid') @@ -136,7 +133,7 @@ class SubAdmin extends PublicEmitter { * @param IUser $user * @return array ['displayName' => displayname] */ - public function getSubAdminsGroupsName(IUser $user) { + public function getSubAdminsGroupsName(IUser $user): array { return array_map(function($group) { return array('displayName' => $group->getDisplayName()); }, $this->getSubAdminsGroups($user)); @@ -147,7 +144,7 @@ class SubAdmin extends PublicEmitter { * @param IGroup $group the group * @return IUser[] */ - public function getGroupsSubAdmins(IGroup $group) { + public function getGroupsSubAdmins(IGroup $group): array { $qb = $this->dbConn->getQueryBuilder(); $result = $qb->select('uid') @@ -171,7 +168,7 @@ class SubAdmin extends PublicEmitter { * get all SubAdmins * @return array */ - public function getAllSubAdmins() { + public function getAllSubAdmins(): array { $qb = $this->dbConn->getQueryBuilder(); $result = $qb->select('*') @@ -200,7 +197,7 @@ class SubAdmin extends PublicEmitter { * @param IGroup $group * @return bool */ - public function isSubAdminOfGroup(IUser $user, IGroup $group) { + public function isSubAdminOfGroup(IUser $user, IGroup $group): bool { $qb = $this->dbConn->getQueryBuilder(); /* @@ -224,7 +221,7 @@ class SubAdmin extends PublicEmitter { * @param IUser $user * @return bool */ - public function isSubAdmin(IUser $user) { + public function isSubAdmin(IUser $user): bool { // Check if the user is already an admin if ($this->groupManager->isAdmin($user->getUID())) { return true; @@ -250,7 +247,7 @@ class SubAdmin extends PublicEmitter { * @param IUser $user * @return bool */ - public function isUserAccessible($subadmin, $user) { + public function isUserAccessible(IUser $subadmin, IUser $user): bool { if(!$this->isSubAdmin($subadmin)) { return false; } @@ -269,30 +266,24 @@ class SubAdmin extends PublicEmitter { /** * delete all SubAdmins by $user * @param IUser $user - * @return boolean */ - private function post_deleteUser($user) { + private function post_deleteUser(IUser $user) { $qb = $this->dbConn->getQueryBuilder(); $qb->delete('group_admin') ->where($qb->expr()->eq('uid', $qb->createNamedParameter($user->getUID()))) ->execute(); - - return true; } /** * delete all SubAdmins by $group * @param IGroup $group - * @return boolean */ - private function post_deleteGroup($group) { + private function post_deleteGroup(IGroup $group) { $qb = $this->dbConn->getQueryBuilder(); $qb->delete('group_admin') ->where($qb->expr()->eq('gid', $qb->createNamedParameter($group->getGID()))) ->execute(); - - return true; } } diff --git a/lib/private/TemplateLayout.php b/lib/private/TemplateLayout.php index 284f14c5db4..e4a2724de67 100644 --- a/lib/private/TemplateLayout.php +++ b/lib/private/TemplateLayout.php @@ -220,6 +220,10 @@ class TemplateLayout extends \OC_Template { } } + + /** @var InitialStateService $initialState */ + $initialState = \OC::$server->query(InitialStateService::class); + $this->assign('initialStates', $initialState->getInitialStates()); } /** diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php index a69aed3910b..45f9cbc260f 100644 --- a/lib/private/User/Session.php +++ b/lib/private/User/Session.php @@ -360,7 +360,8 @@ class Session implements IUserSession, Emitter { $this->setUser($user); $this->setLoginName($loginDetails['loginName']); - if(isset($loginDetails['token']) && $loginDetails['token'] instanceof IToken) { + $isToken = isset($loginDetails['token']) && $loginDetails['token'] instanceof IToken; + if ($isToken) { $this->setToken($loginDetails['token']->getId()); $this->lockdownManager->setToken($loginDetails['token']); $firstTimeLogin = false; @@ -368,7 +369,11 @@ class Session implements IUserSession, Emitter { $this->setToken(null); $firstTimeLogin = $user->updateLastLoginTimestamp(); } - $this->manager->emit('\OC\User', 'postLogin', [$user, $loginDetails['password']]); + $this->manager->emit('\OC\User', 'postLogin', [ + $user, + $loginDetails['password'], + $isToken, + ]); if($this->isLoggedIn()) { $this->prepareUserLogin($firstTimeLogin, $regenerateSessionId); return true; diff --git a/lib/private/legacy/user.php b/lib/private/legacy/user.php index e006a59771a..3d4dc5cc982 100644 --- a/lib/private/legacy/user.php +++ b/lib/private/legacy/user.php @@ -269,12 +269,8 @@ class OC_User { return $backend->getLogoutUrl(); } - $logoutUrl = $urlGenerator->linkToRouteAbsolute( - 'core.login.logout', - [ - 'requesttoken' => \OCP\Util::callRegister(), - ] - ); + $logoutUrl = $urlGenerator->linkToRouteAbsolute('core.login.logout'); + $logoutUrl .= '?requesttoken=' . urlencode(\OCP\Util::callRegister()); return $logoutUrl; } diff --git a/lib/private/legacy/util.php b/lib/private/legacy/util.php index a94ced8bb1f..9bada5bb733 100644 --- a/lib/private/legacy/util.php +++ b/lib/private/legacy/util.php @@ -43,6 +43,7 @@ * @author Victor Dubiniuk <dubiniuk@owncloud.com> * @author Vincent Petry <pvince81@owncloud.com> * @author Volkan Gezer <volkangezer@gmail.com> + * @author Robert Dailey <rcdailey@gmail.com> * * @license AGPL-3.0 * @@ -789,13 +790,20 @@ class OC_Util { ]; } } else if (!is_writable($CONFIG_DATADIRECTORY) or !is_readable($CONFIG_DATADIRECTORY)) { - //common hint for all file permissions error messages - $permissionsHint = $l->t('Permissions can usually be fixed by giving the webserver write access to the root directory. See %s.', - [$urlGenerator->linkToDocs('admin-dir_permissions')]); - $errors[] = [ - 'error' => 'Your data directory is not writable', - 'hint' => $permissionsHint - ]; + // is_writable doesn't work for NFS mounts, so try to write a file and check if it exists. + $testFile = sprintf('%s/%s.tmp', $CONFIG_DATADIRECTORY, uniqid('data_dir_writability_test_')); + $handle = fopen($testFile, 'w'); + if (!$handle || fwrite($handle, 'Test write operation') === FALSE) { + $permissionsHint = $l->t('Permissions can usually be fixed by giving the webserver write access to the root directory. See %s.', + [$urlGenerator->linkToDocs('admin-dir_permissions')]); + $errors[] = [ + 'error' => 'Your data directory is not writable', + 'hint' => $permissionsHint + ]; + } else { + fclose($handle); + unlink($testFile); + } } else { $errors = array_merge($errors, self::checkDataDirectoryPermissions($CONFIG_DATADIRECTORY)); } @@ -1324,56 +1332,6 @@ class OC_Util { } /** - * Clear a single file from the opcode cache - * This is useful for writing to the config file - * in case the opcode cache does not re-validate files - * Returns true if successful, false if unsuccessful: - * caller should fall back on clearing the entire cache - * with clearOpcodeCache() if unsuccessful - * - * @param string $path the path of the file to clear from the cache - * @return bool true if underlying function returns true, otherwise false - */ - public static function deleteFromOpcodeCache($path) { - $ret = false; - if ($path) { - // APC >= 3.1.1 - if (function_exists('apc_delete_file')) { - $ret = @apc_delete_file($path); - } - // Zend OpCache >= 7.0.0, PHP >= 5.5.0 - if (function_exists('opcache_invalidate')) { - $ret = @opcache_invalidate($path); - } - } - return $ret; - } - - /** - * Clear the opcode cache if one exists - * This is necessary for writing to the config file - * in case the opcode cache does not re-validate files - * - * @return void - * @suppress PhanDeprecatedFunction - * @suppress PhanUndeclaredConstant - */ - public static function clearOpcodeCache() { - // APC - if (function_exists('apc_clear_cache')) { - apc_clear_cache(); - } - // Zend Opcache - if (function_exists('accelerator_reset')) { - accelerator_reset(); - } - // Opcache (PHP >= 5.5) - if (function_exists('opcache_reset')) { - @opcache_reset(); - } - } - - /** * Normalize a unicode string * * @param string $value a not normalized string |