diff options
Diffstat (limited to 'lib/private')
-rw-r--r-- | lib/private/App/InfoParser.php | 51 | ||||
-rw-r--r-- | lib/private/AppFramework/App.php | 21 | ||||
-rw-r--r-- | lib/private/AppFramework/DependencyInjection/DIContainer.php | 5 | ||||
-rw-r--r-- | lib/private/Console/Application.php | 25 | ||||
-rw-r--r-- | lib/private/Files/Config/CachedMountInfo.php | 18 | ||||
-rw-r--r-- | lib/private/Files/Config/LazyStorageMountInfo.php | 9 | ||||
-rw-r--r-- | lib/private/Files/Config/UserMountCache.php | 30 | ||||
-rw-r--r-- | lib/private/Files/Node/Folder.php | 62 | ||||
-rw-r--r-- | lib/private/Files/Node/Root.php | 14 | ||||
-rw-r--r-- | lib/private/Installer.php | 2 | ||||
-rw-r--r-- | lib/private/L10N/Factory.php | 30 | ||||
-rw-r--r-- | lib/private/Log.php | 2 | ||||
-rw-r--r-- | lib/private/Notification/Notification.php | 32 | ||||
-rw-r--r-- | lib/private/Server.php | 4 | ||||
-rw-r--r-- | lib/private/Share20/DefaultShareProvider.php | 79 | ||||
-rw-r--r-- | lib/private/Share20/Manager.php | 3 | ||||
-rw-r--r-- | lib/private/Share20/Share.php | 2 | ||||
-rw-r--r-- | lib/private/User/Database.php | 9 | ||||
-rw-r--r-- | lib/private/User/Session.php | 2 | ||||
-rw-r--r-- | lib/private/legacy/app.php | 17 | ||||
-rw-r--r-- | lib/private/legacy/helper.php | 26 |
21 files changed, 287 insertions, 156 deletions
diff --git a/lib/private/App/InfoParser.php b/lib/private/App/InfoParser.php index e975ad6f096..44f495534c9 100644 --- a/lib/private/App/InfoParser.php +++ b/lib/private/App/InfoParser.php @@ -1,6 +1,7 @@ <?php /** * @copyright Copyright (c) 2016, ownCloud, Inc. + * @copyright Copyright (c) 2016, Lukas Reschke <lukas@statuscode.ch> * * @author Andreas Fischer <bantu@owncloud.com> * @author Christoph Wurst <christoph@owncloud.com> @@ -26,18 +27,17 @@ namespace OC\App; -use OCP\IURLGenerator; +use OCP\ICache; class InfoParser { - - /** @var IURLGenerator */ - private $urlGenerator; + /** @var \OCP\ICache|null */ + private $cache; /** - * @param IURLGenerator $urlGenerator + * @param ICache|null $cache */ - public function __construct(IURLGenerator $urlGenerator) { - $this->urlGenerator = $urlGenerator; + public function __construct(ICache $cache = null) { + $this->cache = $cache; } /** @@ -49,18 +49,28 @@ class InfoParser { return null; } + if(!is_null($this->cache)) { + $fileCacheKey = $file . filemtime($file); + if ($cachedValue = $this->cache->get($fileCacheKey)) { + return json_decode($cachedValue, true); + } + } + libxml_use_internal_errors(true); $loadEntities = libxml_disable_entity_loader(false); $xml = simplexml_load_file($file); + libxml_disable_entity_loader($loadEntities); - if ($xml == false) { + if ($xml === false) { libxml_clear_errors(); return null; } $array = $this->xmlToArray($xml); + if (is_null($array)) { return null; } + if (!array_key_exists('info', $array)) { $array['info'] = []; } @@ -97,18 +107,10 @@ class InfoParser { if (!array_key_exists('two-factor-providers', $array)) { $array['two-factor-providers'] = []; } - - if (array_key_exists('documentation', $array) && is_array($array['documentation'])) { - foreach ($array['documentation'] as $key => $url) { - // If it is not an absolute URL we assume it is a key - // i.e. admin-ldap will get converted to go.php?to=admin-ldap - if (!$this->isHTTPURL($url)) { - $url = $this->urlGenerator->linkToDocs($url); - } - - $array['documentation'][$key] = $url; - } + if (!array_key_exists('commands', $array)) { + $array['commands'] = []; } + if (array_key_exists('types', $array)) { if (is_array($array['types'])) { foreach ($array['types'] as $type => $v) { @@ -139,6 +141,13 @@ class InfoParser { if (isset($array['background-jobs']['job']) && is_array($array['background-jobs']['job'])) { $array['background-jobs'] = $array['background-jobs']['job']; } + if (isset($array['commands']['command']) && is_array($array['commands']['command'])) { + $array['commands'] = $array['commands']['command']; + } + + if(!is_null($this->cache)) { + $this->cache->set($fileCacheKey, json_encode($array)); + } return $array; } @@ -193,8 +202,4 @@ class InfoParser { return $array; } - - private function isHTTPURL($url) { - return stripos($url, 'https://') === 0 || stripos($url, 'http://') === 0; - } } diff --git a/lib/private/AppFramework/App.php b/lib/private/AppFramework/App.php index 427a850f396..e15e4a797ea 100644 --- a/lib/private/AppFramework/App.php +++ b/lib/private/AppFramework/App.php @@ -59,24 +59,11 @@ class App { return $topNamespace . self::$nameSpaceCache[$appId]; } - // first try to parse the app's appinfo/info.xml <namespace> tag - $appPath = OC_App::getAppPath($appId); - if ($appPath !== false) { - $filePath = "$appPath/appinfo/info.xml"; - if (is_file($filePath)) { - $loadEntities = libxml_disable_entity_loader(false); - $xml = @simplexml_load_file($filePath); - libxml_disable_entity_loader($loadEntities); - if ($xml) { - $result = $xml->xpath('/info/namespace'); - if ($result && count($result) > 0) { - self::$nameSpaceCache[$appId] = trim((string) $result[0]); - // take first namespace result - return $topNamespace . self::$nameSpaceCache[$appId]; - } - } - } + $appInfo = \OC_App::getAppInfo($appId); + if (isset($appInfo['namespace'])) { + return $topNamespace . trim($appInfo['namespace']); } + // if the tag is not found, fall back to uppercasing the first letter self::$nameSpaceCache[$appId] = ucfirst($appId); return $topNamespace . self::$nameSpaceCache[$appId]; diff --git a/lib/private/AppFramework/DependencyInjection/DIContainer.php b/lib/private/AppFramework/DependencyInjection/DIContainer.php index 3f2212a7f24..21d5eaa9503 100644 --- a/lib/private/AppFramework/DependencyInjection/DIContainer.php +++ b/lib/private/AppFramework/DependencyInjection/DIContainer.php @@ -47,7 +47,7 @@ use OC\Core\Middleware\TwoFactorMiddleware; use OCP\AppFramework\IApi; use OCP\AppFramework\IAppContainer; use OCP\Files\IAppData; - +use OCP\Files\Mount\IMountManager; class DIContainer extends SimpleContainer implements IAppContainer { @@ -313,6 +313,9 @@ class DIContainer extends SimpleContainer implements IAppContainer { $this->registerService('OCP\\AppFramework\\IAppContainer', function ($c) { return $c; }); + $this->registerService(IMountManager::class, function () { + return $this->getServer()->getMountManager(); + }); // commonly used attributes $this->registerService('UserId', function ($c) { diff --git a/lib/private/Console/Application.php b/lib/private/Console/Application.php index 3033d7beb86..299b23714b6 100644 --- a/lib/private/Console/Application.php +++ b/lib/private/Console/Application.php @@ -27,12 +27,11 @@ namespace OC\Console; use OC_App; +use OCP\AppFramework\QueryException; use OCP\Console\ConsoleEvent; -use OCP\Defaults; use OCP\IConfig; use OCP\IRequest; use Symfony\Component\Console\Application as SymfonyApplication; -use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; @@ -103,6 +102,12 @@ class Application { if($appPath === false) { continue; } + // load commands using info.xml + $info = \OC_App::getAppInfo($app); + if (isset($info['commands'])) { + $this->loadCommandsFromInfoXml($info['commands']); + } + // load from register_command.php \OC_App::registerAutoloading($app, $appPath); $file = $appPath . '/appinfo/register_command.php'; if (file_exists($file)) { @@ -149,4 +154,20 @@ class Application { )); return $this->application->run($input, $output); } + + private function loadCommandsFromInfoXml($commands) { + foreach ($commands as $command) { + try { + $c = \OC::$server->query($command); + } catch (QueryException $e) { + if (class_exists($command)) { + $c = new $command(); + } else { + throw new \Exception("Console command '$command' is unknown and could not be loaded"); + } + } + + $this->application->add($c); + } + } } diff --git a/lib/private/Files/Config/CachedMountInfo.php b/lib/private/Files/Config/CachedMountInfo.php index 74812b3ed8c..c4132a34431 100644 --- a/lib/private/Files/Config/CachedMountInfo.php +++ b/lib/private/Files/Config/CachedMountInfo.php @@ -54,6 +54,11 @@ class CachedMountInfo implements ICachedMountInfo { protected $mountId; /** + * @var string + */ + protected $rootInternalPath; + + /** * CachedMountInfo constructor. * * @param IUser $user @@ -61,13 +66,15 @@ class CachedMountInfo implements ICachedMountInfo { * @param int $rootId * @param string $mountPoint * @param int|null $mountId + * @param string $rootInternalPath */ - public function __construct(IUser $user, $storageId, $rootId, $mountPoint, $mountId = null) { + public function __construct(IUser $user, $storageId, $rootId, $mountPoint, $mountId = null, $rootInternalPath = '') { $this->user = $user; $this->storageId = $storageId; $this->rootId = $rootId; $this->mountPoint = $mountPoint; $this->mountId = $mountId; + $this->rootInternalPath = $rootInternalPath; } /** @@ -122,4 +129,13 @@ class CachedMountInfo implements ICachedMountInfo { public function getMountId() { return $this->mountId; } + + /** + * Get the internal path (within the storage) of the root of the mount + * + * @return string + */ + public function getRootInternalPath() { + return $this->rootInternalPath; + } } diff --git a/lib/private/Files/Config/LazyStorageMountInfo.php b/lib/private/Files/Config/LazyStorageMountInfo.php index 4df813d57d0..40d463c5103 100644 --- a/lib/private/Files/Config/LazyStorageMountInfo.php +++ b/lib/private/Files/Config/LazyStorageMountInfo.php @@ -76,4 +76,13 @@ class LazyStorageMountInfo extends CachedMountInfo { public function getMountId() { return $this->mount->getMountId(); } + + /** + * Get the internal path (within the storage) of the root of the mount + * + * @return string + */ + public function getRootInternalPath() { + return $this->mount->getInternalPath($this->mount->getMountPoint()); + } } diff --git a/lib/private/Files/Config/UserMountCache.php b/lib/private/Files/Config/UserMountCache.php index bd8343fa440..e9e142d0d4b 100644 --- a/lib/private/Files/Config/UserMountCache.php +++ b/lib/private/Files/Config/UserMountCache.php @@ -31,6 +31,7 @@ use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\Files\Config\ICachedMountInfo; use OCP\Files\Config\IUserMountCache; use OCP\Files\Mount\IMountPoint; +use OCP\Files\Node; use OCP\Files\NotFoundException; use OCP\ICache; use OCP\IDBConnection; @@ -187,7 +188,7 @@ class UserMountCache implements IUserMountCache { private function dbRowToMountInfo(array $row) { $user = $this->userManager->get($row['user_id']); - return new CachedMountInfo($user, (int)$row['storage_id'], (int)$row['root_id'], $row['mount_point'], $row['mount_id']); + return new CachedMountInfo($user, (int)$row['storage_id'], (int)$row['root_id'], $row['mount_point'], $row['mount_id'], isset($row['path'])? $row['path']:''); } /** @@ -197,8 +198,9 @@ class UserMountCache implements IUserMountCache { public function getMountsForUser(IUser $user) { if (!isset($this->mountsForUsers[$user->getUID()])) { $builder = $this->connection->getQueryBuilder(); - $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id') - ->from('mounts') + $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path') + ->from('mounts', 'm') + ->innerJoin('m', 'filecache', 'f', $builder->expr()->eq('m.root_id', 'f.fileid')) ->where($builder->expr()->eq('user_id', $builder->createPositionalParameter($user->getUID()))); $rows = $query->execute()->fetchAll(); @@ -214,8 +216,9 @@ class UserMountCache implements IUserMountCache { */ public function getMountsForStorageId($numericStorageId) { $builder = $this->connection->getQueryBuilder(); - $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id') - ->from('mounts') + $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path') + ->from('mounts', 'm') + ->innerJoin('m', 'filecache', 'f' , $builder->expr()->eq('m.root_id', 'f.fileid')) ->where($builder->expr()->eq('storage_id', $builder->createPositionalParameter($numericStorageId, IQueryBuilder::PARAM_INT))); $rows = $query->execute()->fetchAll(); @@ -229,8 +232,9 @@ class UserMountCache implements IUserMountCache { */ public function getMountsForRootId($rootFileId) { $builder = $this->connection->getQueryBuilder(); - $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id') - ->from('mounts') + $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path') + ->from('mounts', 'm') + ->innerJoin('m', 'filecache', 'f', $builder->expr()->eq('m.root_id', 'f.fileid')) ->where($builder->expr()->eq('root_id', $builder->createPositionalParameter($rootFileId, IQueryBuilder::PARAM_INT))); $rows = $query->execute()->fetchAll(); @@ -246,7 +250,7 @@ class UserMountCache implements IUserMountCache { private function getCacheInfoFromFileId($fileId) { if (!isset($this->cacheInfoCache[$fileId])) { $builder = $this->connection->getQueryBuilder(); - $query = $builder->select('storage', 'path') + $query = $builder->select('storage', 'path', 'mimetype') ->from('filecache') ->where($builder->expr()->eq('fileid', $builder->createNamedParameter($fileId, IQueryBuilder::PARAM_INT))); @@ -254,7 +258,8 @@ class UserMountCache implements IUserMountCache { if (is_array($row)) { $this->cacheInfoCache[$fileId] = [ (int)$row['storage'], - $row['path'] + $row['path'], + (int)$row['mimetype'] ]; } else { throw new NotFoundException('File with id "' . $fileId . '" not found'); @@ -281,15 +286,10 @@ class UserMountCache implements IUserMountCache { if ($fileId === $mount->getRootId()) { return true; } - try { - list(, $internalMountPath) = $this->getCacheInfoFromFileId($mount->getRootId()); - } catch (NotFoundException $e) { - return false; - } + $internalMountPath = $mount->getRootInternalPath(); return $internalMountPath === '' || substr($internalPath, 0, strlen($internalMountPath) + 1) === $internalMountPath . '/'; }); - } /** diff --git a/lib/private/Files/Node/Folder.php b/lib/private/Files/Node/Folder.php index e67e4817e2a..353b89068cb 100644 --- a/lib/private/Files/Node/Folder.php +++ b/lib/private/Files/Node/Folder.php @@ -28,6 +28,7 @@ namespace OC\Files\Node; use OC\DB\QueryBuilder\Literal; use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\Files\Config\ICachedMountInfo; use OCP\Files\FileInfo; use OCP\Files\Mount\IMountPoint; use OCP\Files\NotFoundException; @@ -83,7 +84,7 @@ class Folder extends Node implements \OCP\Files\Folder { public function getDirectoryListing() { $folderContent = $this->view->getDirectoryContent($this->path); - return array_map(function(FileInfo $info) { + return array_map(function (FileInfo $info) { if ($info->getMimetype() === 'httpd/unix-directory') { return new Folder($this->root, $this->view, $info->getPath(), $info); } else { @@ -253,7 +254,7 @@ class Folder extends Node implements \OCP\Files\Folder { } } - return array_map(function(FileInfo $file) { + return array_map(function (FileInfo $file) { return $this->createNode($file->getPath(), $file); }, $files); } @@ -263,29 +264,48 @@ class Folder extends Node implements \OCP\Files\Folder { * @return \OC\Files\Node\Node[] */ public function getById($id) { + $mountCache = $this->root->getUserMountCache(); + $mountsContainingFile = $mountCache->getMountsForFileId((int)$id); $mounts = $this->root->getMountsIn($this->path); $mounts[] = $this->root->getMount($this->path); - // reverse the array so we start with the storage this view is in - // which is the most likely to contain the file we're looking for - $mounts = array_reverse($mounts); + /** @var IMountPoint[] $folderMounts */ + $folderMounts = array_combine(array_map(function (IMountPoint $mountPoint) { + return $mountPoint->getMountPoint(); + }, $mounts), $mounts); + + /** @var ICachedMountInfo[] $mountsContainingFile */ + $mountsContainingFile = array_values(array_filter($mountsContainingFile, function (ICachedMountInfo $cachedMountInfo) use ($folderMounts) { + return isset($folderMounts[$cachedMountInfo->getMountPoint()]); + })); - $nodes = array(); - foreach ($mounts as $mount) { - /** - * @var \OC\Files\Mount\MountPoint $mount - */ - if ($mount->getStorage()) { - $cache = $mount->getStorage()->getCache(); - $internalPath = $cache->getPathById($id); - if (is_string($internalPath)) { - $fullPath = $mount->getMountPoint() . $internalPath; - if (!is_null($path = $this->getRelativePath($fullPath))) { - $nodes[] = $this->get($path); - } - } - } + if (count($mountsContainingFile) === 0) { + return []; } - return $nodes; + + // we only need to get the cache info once, since all mounts we found point to the same storage + + $mount = $folderMounts[$mountsContainingFile[0]->getMountPoint()]; + $cacheEntry = $mount->getStorage()->getCache()->get((int)$id); + if (!$cacheEntry) { + return []; + } + // cache jails will hide the "true" internal path + $internalPath = ltrim($mountsContainingFile[0]->getRootInternalPath() . '/' . $cacheEntry->getPath(), '/'); + + $nodes = array_map(function (ICachedMountInfo $cachedMountInfo) use ($cacheEntry, $folderMounts, $internalPath) { + $mount = $folderMounts[$cachedMountInfo->getMountPoint()]; + $pathRelativeToMount = substr($internalPath, strlen($cachedMountInfo->getRootInternalPath())); + $pathRelativeToMount = ltrim($pathRelativeToMount, '/'); + $absolutePath = $cachedMountInfo->getMountPoint() . $pathRelativeToMount; + return $this->root->createNode($absolutePath, new \OC\Files\FileInfo( + $absolutePath, $mount->getStorage(), $cacheEntry->getPath(), $cacheEntry, $mount, + \OC::$server->getUserManager()->get($mount->getStorage()->getOwner($pathRelativeToMount)) + )); + }, $mountsContainingFile); + + return array_filter($nodes, function (Node $node) { + return $this->getRelativePath($node->getPath()); + }); } public function getFreeSpace() { diff --git a/lib/private/Files/Node/Root.php b/lib/private/Files/Node/Root.php index 007847fb513..0cda2c8b822 100644 --- a/lib/private/Files/Node/Root.php +++ b/lib/private/Files/Node/Root.php @@ -31,6 +31,7 @@ namespace OC\Files\Node; use OC\Cache\CappedMemoryCache; use OC\Files\Mount\Manager; use OC\Files\Mount\MountPoint; +use OCP\Files\Config\IUserMountCache; use OCP\Files\NotFoundException; use OCP\Files\NotPermittedException; use OC\Hooks\PublicEmitter; @@ -75,16 +76,23 @@ class Root extends Folder implements IRootFolder { private $userFolderCache; /** + * @var IUserMountCache + */ + private $userMountCache; + + /** * @param \OC\Files\Mount\Manager $manager * @param \OC\Files\View $view * @param \OC\User\User|null $user + * @param IUserMountCache $userMountCache */ - public function __construct($manager, $view, $user) { + public function __construct($manager, $view, $user, IUserMountCache $userMountCache) { parent::__construct($this, $view, ''); $this->mountManager = $manager; $this->user = $user; $this->emitter = new PublicEmitter(); $this->userFolderCache = new CappedMemoryCache(); + $this->userMountCache = $userMountCache; } /** @@ -361,4 +369,8 @@ class Root extends Folder implements IRootFolder { public function clearCache() { $this->userFolderCache = new CappedMemoryCache(); } + + public function getUserMountCache() { + return $this->userMountCache; + } } diff --git a/lib/private/Installer.php b/lib/private/Installer.php index 3d8a923417a..009df790585 100644 --- a/lib/private/Installer.php +++ b/lib/private/Installer.php @@ -614,7 +614,7 @@ class Installer { } $codeChecker = new CodeChecker(new PrivateCheck(new EmptyCheck())); - $errors = $codeChecker->analyseFolder($folder); + $errors = $codeChecker->analyseFolder(basename($folder), $folder); return empty($errors); } diff --git a/lib/private/L10N/Factory.php b/lib/private/L10N/Factory.php index 91233a0c4a7..8aad395065c 100644 --- a/lib/private/L10N/Factory.php +++ b/lib/private/L10N/Factory.php @@ -2,6 +2,7 @@ /** * @copyright Copyright (c) 2016, ownCloud, Inc. * @copyright 2016 Roeland Jago Douma <roeland@famdouma.nl> + * @copyright 2016 Lukas Reschke <lukas@statuscode.ch> * * @author Bart Visscher <bartv@thisnet.nl> * @author Joas Schilling <coding@schilljs.com> @@ -288,6 +289,27 @@ class Factory implements IFactory { } /** + * Checks if $sub is a subdirectory of $parent + * + * @param string $sub + * @param string $parent + * @return bool + */ + private function isSubDirectory($sub, $parent) { + // Check whether $sub contains no ".." + if(strpos($sub, '..') !== false) { + return false; + } + + // Check whether $sub is a subdirectory of $parent + if (strpos($sub, $parent) === 0) { + return true; + } + + return false; + } + + /** * Get a list of language files that should be loaded * * @param string $app @@ -302,10 +324,10 @@ class Factory implements IFactory { $i18nDir = $this->findL10nDir($app); $transFile = strip_tags($i18nDir) . strip_tags($lang) . '.json'; - if ((\OC_Helper::isSubDirectory($transFile, $this->serverRoot . '/core/l10n/') - || \OC_Helper::isSubDirectory($transFile, $this->serverRoot . '/lib/l10n/') - || \OC_Helper::isSubDirectory($transFile, $this->serverRoot . '/settings/l10n/') - || \OC_Helper::isSubDirectory($transFile, \OC_App::getAppPath($app) . '/l10n/') + if (($this->isSubDirectory($transFile, $this->serverRoot . '/core/l10n/') + || $this->isSubDirectory($transFile, $this->serverRoot . '/lib/l10n/') + || $this->isSubDirectory($transFile, $this->serverRoot . '/settings/l10n/') + || $this->isSubDirectory($transFile, \OC_App::getAppPath($app) . '/l10n/') ) && file_exists($transFile)) { // load the translations file diff --git a/lib/private/Log.php b/lib/private/Log.php index b76cb4f8c28..ef1b70d3cb9 100644 --- a/lib/private/Log.php +++ b/lib/private/Log.php @@ -277,7 +277,7 @@ class Log implements ILogger { $request = \OC::$server->getRequest(); // if token is found in the request change set the log condition to satisfied - if($request && hash_equals($logCondition['shared_secret'], $request->getParam('log_secret'))) { + if($request && hash_equals($logCondition['shared_secret'], $request->getParam('log_secret', ''))) { $this->logConditionSatisfied = true; } } diff --git a/lib/private/Notification/Notification.php b/lib/private/Notification/Notification.php index 9b5877a3058..7bf4b9a74cf 100644 --- a/lib/private/Notification/Notification.php +++ b/lib/private/Notification/Notification.php @@ -242,7 +242,7 @@ class Notification implements INotification { /** * @param string $subject * @return $this - * @throws \InvalidArgumentException if the subject are invalid + * @throws \InvalidArgumentException if the subject is invalid * @since 8.2.0 */ public function setParsedSubject($subject) { @@ -300,7 +300,7 @@ class Notification implements INotification { /** * @param string $message * @return $this - * @throws \InvalidArgumentException if the message are invalid + * @throws \InvalidArgumentException if the message is invalid * @since 8.2.0 */ public function setParsedMessage($message) { @@ -322,7 +322,7 @@ class Notification implements INotification { /** * @param string $link * @return $this - * @throws \InvalidArgumentException if the link are invalid + * @throws \InvalidArgumentException if the link is invalid * @since 8.2.0 */ public function setLink($link) { @@ -342,6 +342,28 @@ class Notification implements INotification { } /** + * @param string $icon + * @return $this + * @throws \InvalidArgumentException if the icon is invalid + * @since 9.2.0 + */ + public function setIcon($icon) { + if (!is_string($icon) || $icon === '' || isset($icon[4000])) { + throw new \InvalidArgumentException('The given icon is invalid'); + } + $this->icon = $icon; + return $this; + } + + /** + * @return string + * @since 9.2.0 + */ + public function getIcon() { + return $this->icon; + } + + /** * @return IAction * @since 8.2.0 */ @@ -352,7 +374,7 @@ class Notification implements INotification { /** * @param IAction $action * @return $this - * @throws \InvalidArgumentException if the action are invalid + * @throws \InvalidArgumentException if the action is invalid * @since 8.2.0 */ public function addAction(IAction $action) { @@ -383,7 +405,7 @@ class Notification implements INotification { /** * @param IAction $action * @return $this - * @throws \InvalidArgumentException if the action are invalid + * @throws \InvalidArgumentException if the action is invalid * @since 8.2.0 */ public function addParsedAction(IAction $action) { diff --git a/lib/private/Server.php b/lib/private/Server.php index b49e94b554e..291714b23d1 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -175,10 +175,10 @@ class Server extends ServerContainer implements IServerContainer { $this->registerService('SystemTagObjectMapper', function (Server $c) { return $c->query('SystemTagManagerFactory')->getObjectMapper(); }); - $this->registerService('RootFolder', function () { + $this->registerService('RootFolder', function (Server $c) { $manager = \OC\Files\Filesystem::getMountManager(null); $view = new View(); - $root = new Root($manager, $view, null); + $root = new Root($manager, $view, null, $c->getUserMountCache()); $connector = new HookConnector($root, $view); $connector->viewToNode(); return $root; diff --git a/lib/private/Share20/DefaultShareProvider.php b/lib/private/Share20/DefaultShareProvider.php index d6afcf99912..56b9d5b1ee8 100644 --- a/lib/private/Share20/DefaultShareProvider.php +++ b/lib/private/Share20/DefaultShareProvider.php @@ -543,7 +543,7 @@ class DefaultShareProvider implements IShareProvider { // If the recipient is set for a group share resolve to that user if ($recipientId !== null && $share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { - $share = $this->resolveGroupShare($share, $recipientId); + $share = $this->resolveGroupShares([$share], $recipientId)[0]; } return $share; @@ -709,11 +709,8 @@ class DefaultShareProvider implements IShareProvider { /* * Resolve all group shares to user specific shares - * TODO: Optmize this! */ - foreach($shares2 as $share) { - $shares[] = $this->resolveGroupShare($share, $userId); - } + $shares = $this->resolveGroupShares($shares2, $userId); } else { throw new BackendError('Invalid backend'); } @@ -802,37 +799,59 @@ class DefaultShareProvider implements IShareProvider { } /** - * Resolve a group share to a user specific share - * Thus if the user moved their group share make sure this is properly reflected here. - * - * @param \OCP\Share\IShare $share - * @param string $userId - * @return Share Returns the updated share if one was found else return the original share. + * @param Share[] $shares + * @param $userId + * @return Share[] The updates shares if no update is found for a share return the original */ - private function resolveGroupShare(\OCP\Share\IShare $share, $userId) { - $qb = $this->dbConn->getQueryBuilder(); + private function resolveGroupShares($shares, $userId) { + $result = []; - $stmt = $qb->select('*') - ->from('share') - ->where($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId()))) - ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(self::SHARE_TYPE_USERGROUP))) - ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId))) - ->andWhere($qb->expr()->orX( - $qb->expr()->eq('item_type', $qb->createNamedParameter('file')), - $qb->expr()->eq('item_type', $qb->createNamedParameter('folder')) - )) - ->setMaxResults(1) - ->execute(); + $start = 0; + while(true) { + /** @var Share[] $shareSlice */ + $shareSlice = array_slice($shares, $start, 100); + $start += 100; + + if ($shareSlice === []) { + break; + } + + /** @var int[] $ids */ + $ids = []; + /** @var Share[] $shareMap */ + $shareMap = []; + + foreach ($shareSlice as $share) { + $ids[] = (int)$share->getId(); + $shareMap[$share->getId()] = $share; + } - $data = $stmt->fetch(); - $stmt->closeCursor(); + $qb = $this->dbConn->getQueryBuilder(); + + $query = $qb->select('*') + ->from('share') + ->where($qb->expr()->in('parent', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY))) + ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId))) + ->andWhere($qb->expr()->orX( + $qb->expr()->eq('item_type', $qb->createNamedParameter('file')), + $qb->expr()->eq('item_type', $qb->createNamedParameter('folder')) + )); - if ($data !== false) { - $share->setPermissions((int)$data['permissions']); - $share->setTarget($data['file_target']); + $stmt = $query->execute(); + + while($data = $stmt->fetch()) { + $shareMap[$data['parent']]->setPermissions((int)$data['permissions']); + $shareMap[$data['parent']]->setTarget($data['file_target']); + } + + $stmt->closeCursor(); + + foreach ($shareMap as $share) { + $result[] = $share; + } } - return $share; + return $result; } /** diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php index b4fe69a83e2..22cf5a3f65a 100644 --- a/lib/private/Share20/Manager.php +++ b/lib/private/Share20/Manager.php @@ -614,8 +614,11 @@ class Manager implements IManager { throw new \Exception($error); } + $oldShare = $share; $provider = $this->factory->getProviderForType($share->getShareType()); $share = $provider->create($share); + //reuse the node we already have + $share->setNode($oldShare->getNode()); // Post share hook $postHookData = [ diff --git a/lib/private/Share20/Share.php b/lib/private/Share20/Share.php index c565809c078..e3e8482f4e1 100644 --- a/lib/private/Share20/Share.php +++ b/lib/private/Share20/Share.php @@ -160,7 +160,7 @@ class Share implements \OCP\Share\IShare { $nodes = $userFolder->getById($this->fileId); if (empty($nodes)) { - throw new NotFoundException(); + throw new NotFoundException('Node for share not found, fileid: ' . $this->fileId); } $this->node = $nodes[0]; diff --git a/lib/private/User/Database.php b/lib/private/User/Database.php index eba7beffeae..28cb3302858 100644 --- a/lib/private/User/Database.php +++ b/lib/private/User/Database.php @@ -94,6 +94,9 @@ class Database extends Backend implements IUserBackend { $query = \OC_DB::prepare('INSERT INTO `*PREFIX*users` ( `uid`, `password` ) VALUES( ?, ? )'); $result = $query->execute(array($uid, \OC::$server->getHasher()->hash($password))); + // Clear cache + unset($this->cache[$uid]); + return $result ? true : false; } @@ -234,7 +237,7 @@ class Database extends Backend implements IUserBackend { * @return boolean */ private function loadUser($uid) { - if (empty($this->cache[$uid])) { + if (!isset($this->cache[$uid])) { $query = \OC_DB::prepare('SELECT `uid`, `displayname` FROM `*PREFIX*users` WHERE LOWER(`uid`) = LOWER(?)'); $result = $query->execute(array($uid)); @@ -243,6 +246,8 @@ class Database extends Backend implements IUserBackend { return false; } + $this->cache[$uid] = false; + while ($row = $result->fetchRow()) { $this->cache[$uid]['uid'] = $row['uid']; $this->cache[$uid]['displayname'] = $row['displayname']; @@ -284,7 +289,7 @@ class Database extends Backend implements IUserBackend { */ public function userExists($uid) { $this->loadUser($uid); - return !empty($this->cache[$uid]); + return $this->cache[$uid] !== false; } /** diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php index dec959820f8..4b56609ccfc 100644 --- a/lib/private/User/Session.php +++ b/lib/private/User/Session.php @@ -597,7 +597,6 @@ class Session implements IUserSession, Emitter { } $dbToken->setLastCheck($now); - $this->tokenProvider->updateToken($dbToken); return true; } @@ -608,7 +607,6 @@ class Session implements IUserSession, Emitter { return false; } $dbToken->setLastCheck($now); - $this->tokenProvider->updateToken($dbToken); return true; } diff --git a/lib/private/legacy/app.php b/lib/private/legacy/app.php index c3d2d1d6ad4..5e05884f5c0 100644 --- a/lib/private/legacy/app.php +++ b/lib/private/legacy/app.php @@ -47,6 +47,7 @@ * */ use OC\App\DependencyAnalyzer; +use OC\App\InfoParser; use OC\App\Platform; use OC\Installer; use OC\OCSClient; @@ -681,7 +682,7 @@ class OC_App { $file = $appPath . '/appinfo/info.xml'; } - $parser = new \OC\App\InfoParser(\OC::$server->getURLGenerator()); + $parser = new InfoParser(\OC::$server->getMemCacheFactory()->create('core.appinfo')); $data = $parser->parse($file); if (is_array($data)) { @@ -847,6 +848,7 @@ class OC_App { $blacklist = \OC::$server->getAppManager()->getAlwaysEnabledApps(); $appList = array(); $langCode = \OC::$server->getL10N('core')->getLanguageCode(); + $urlGenerator = \OC::$server->getURLGenerator(); foreach ($installedApps as $app) { if (array_search($app, $blacklist) === false) { @@ -900,6 +902,19 @@ class OC_App { } } } + // fix documentation + if (isset($info['documentation']) && is_array($info['documentation'])) { + foreach ($info['documentation'] as $key => $url) { + // If it is not an absolute URL we assume it is a key + // i.e. admin-ldap will get converted to go.php?to=admin-ldap + if (stripos($url, 'https://') !== 0 && stripos($url, 'http://') !== 0) { + $url = $urlGenerator->linkToDocs($url); + } + + $info['documentation'][$key] = $url; + } + } + $info['version'] = OC_App::getAppVersion($app); $appList[] = $info; } diff --git a/lib/private/legacy/helper.php b/lib/private/legacy/helper.php index b19e58a9e6c..0b9477dacd4 100644 --- a/lib/private/legacy/helper.php +++ b/lib/private/legacy/helper.php @@ -378,32 +378,6 @@ class OC_Helper { } /** - * Checks if $sub is a subdirectory of $parent - * - * @param string $sub - * @param string $parent - * @return bool - */ - public static function isSubDirectory($sub, $parent) { - $realpathSub = realpath($sub); - $realpathParent = realpath($parent); - - // realpath() may return false in case the directory does not exist - // since we can not be sure how different PHP versions may behave here - // we do an additional check whether realpath returned false - if($realpathSub === false || $realpathParent === false) { - return false; - } - - // Check whether $sub is a subdirectory of $parent - if (strpos($realpathSub, $realpathParent) === 0) { - return true; - } - - return false; - } - - /** * Returns an array with all keys from input lowercased or uppercased. Numbered indices are left as is. * * @param array $input The array to work on |