summaryrefslogtreecommitdiffstats
path: root/lib/private
diff options
context:
space:
mode:
Diffstat (limited to 'lib/private')
-rw-r--r--lib/private/Accounts/Account.php33
-rw-r--r--lib/private/Accounts/AccountManager.php5
-rw-r--r--lib/private/App/AppStore/Fetcher/AppFetcher.php8
-rw-r--r--lib/private/AppConfig.php67
-rw-r--r--lib/private/AppFramework/Bootstrap/Coordinator.php10
-rw-r--r--lib/private/AppFramework/DependencyInjection/DIContainer.php4
-rw-r--r--lib/private/AppFramework/Http/Dispatcher.php11
-rw-r--r--lib/private/Archive/Archive.php77
-rw-r--r--lib/private/Archive/TAR.php113
-rw-r--r--lib/private/Archive/ZIP.php102
-rw-r--r--lib/private/Authentication/Token/PublicKeyTokenProvider.php5
-rw-r--r--lib/private/Avatar/AvatarManager.php3
-rw-r--r--lib/private/BackgroundJob/Job.php3
-rw-r--r--lib/private/BackgroundJob/JobList.php22
-rw-r--r--lib/private/BackgroundJob/Legacy/QueuedJob.php3
-rw-r--r--lib/private/BackgroundJob/Legacy/RegularJob.php3
-rw-r--r--lib/private/BackgroundJob/QueuedJob.php2
-rw-r--r--lib/private/BackgroundJob/TimedJob.php2
-rw-r--r--lib/private/Cache/CappedMemoryCache.php28
-rw-r--r--lib/private/Comments/Manager.php9
-rw-r--r--lib/private/Contacts/ContactsMenu/ContactsStore.php20
-rw-r--r--lib/private/Contacts/ContactsMenu/Providers/ProfileProvider.php18
-rw-r--r--lib/private/DB/Connection.php24
-rw-r--r--lib/private/DB/MigrationService.php2
-rw-r--r--lib/private/Diagnostics/Event.php4
-rw-r--r--lib/private/Diagnostics/EventLogger.php66
-rw-r--r--lib/private/Files/Cache/Scanner.php5
-rw-r--r--lib/private/Files/Cache/Storage.php7
-rw-r--r--lib/private/Files/Config/CachedMountFileInfo.php20
-rw-r--r--lib/private/Files/Config/CachedMountInfo.php70
-rw-r--r--lib/private/Files/Config/LazyStorageMountInfo.php20
-rw-r--r--lib/private/Files/Config/MountProviderCollection.php16
-rw-r--r--lib/private/Files/Config/UserMountCache.php34
-rw-r--r--lib/private/Files/Filesystem.php157
-rw-r--r--lib/private/Files/Mount/CacheMountProvider.php4
-rw-r--r--lib/private/Files/Mount/LocalHomeMountProvider.php2
-rw-r--r--lib/private/Files/Mount/Manager.php59
-rw-r--r--lib/private/Files/Mount/MountPoint.php25
-rw-r--r--lib/private/Files/Mount/ObjectHomeMountProvider.php2
-rw-r--r--lib/private/Files/Mount/ObjectStorePreviewCacheMountProvider.php10
-rw-r--r--lib/private/Files/Mount/RootMountProvider.php103
-rw-r--r--lib/private/Files/Node/LazyFolder.php2
-rw-r--r--lib/private/Files/Node/Root.php73
-rw-r--r--lib/private/Files/ObjectStore/S3.php1
-rw-r--r--lib/private/Files/ObjectStore/S3ConnectionTrait.php13
-rw-r--r--lib/private/Files/ObjectStore/S3ObjectTrait.php2
-rw-r--r--lib/private/Files/SetupManager.php294
-rw-r--r--lib/private/Files/SetupManagerFactory.php79
-rw-r--r--lib/private/Files/SimpleFS/NewSimpleFile.php11
-rw-r--r--lib/private/Files/SimpleFS/SimpleFile.php7
-rw-r--r--lib/private/Files/Storage/Common.php7
-rw-r--r--lib/private/Files/Storage/Local.php18
-rw-r--r--lib/private/Files/View.php23
-rw-r--r--lib/private/Group/MetaData.php34
-rw-r--r--lib/private/Log.php10
-rw-r--r--lib/private/Preview/Bitmap.php21
-rw-r--r--lib/private/Preview/Bundled.php6
-rw-r--r--lib/private/Preview/HEIC.php23
-rw-r--r--lib/private/Preview/Krita.php4
-rw-r--r--lib/private/Preview/Movie.php24
-rw-r--r--lib/private/Preview/OpenDocument.php2
-rw-r--r--lib/private/Preview/ProviderV2.php17
-rw-r--r--lib/private/Profile/ProfileManager.php24
-rw-r--r--lib/private/Profile/TProfileHelper.php15
-rw-r--r--lib/private/RedisFactory.php12
-rw-r--r--lib/private/Security/CSP/ContentSecurityPolicy.php7
-rw-r--r--lib/private/Security/CertificateManager.php18
-rw-r--r--lib/private/Server.php25
-rw-r--r--lib/private/Support/Subscription/Registry.php2
-rw-r--r--lib/private/SystemConfig.php11
-rw-r--r--lib/private/Template/JSResourceLocator.php2
-rw-r--r--lib/private/User/Database.php31
-rw-r--r--lib/private/User/Session.php8
-rw-r--r--lib/private/User/User.php20
-rw-r--r--lib/private/UserStatus/ISettableProvider.php11
-rw-r--r--lib/private/UserStatus/Manager.php8
-rw-r--r--lib/private/legacy/OC_App.php5
-rw-r--r--lib/private/legacy/OC_Util.php254
78 files changed, 1417 insertions, 885 deletions
diff --git a/lib/private/Accounts/Account.php b/lib/private/Accounts/Account.php
index 540d15cd4b9..d3287b219d0 100644
--- a/lib/private/Accounts/Account.php
+++ b/lib/private/Accounts/Account.php
@@ -72,6 +72,28 @@ class Account implements IAccount {
});
}
+ public function setAllPropertiesFromJson(array $properties): IAccount {
+ foreach ($properties as $propertyName => $propertyObject) {
+ if ($this->isCollection($propertyName)) {
+ $collection = new AccountPropertyCollection($propertyName);
+ /** @var array<int, IAccountProperty> $collectionProperties */
+ $collectionProperties = [];
+ /** @var array<int, array<string, string>> $propertyObject */
+ foreach ($propertyObject as ['value' => $value, 'scope' => $scope, 'verified' => $verified, 'verificationData' => $verificationData]) {
+ $collectionProperties[] = new AccountProperty($collection->getName(), $value, $scope, $verified, $verificationData);
+ }
+ $collection->setProperties($collectionProperties);
+ $this->setPropertyCollection($collection);
+ } else {
+ /** @var array<string, string> $propertyObject */
+ ['value' => $value, 'scope' => $scope, 'verified' => $verified, 'verificationData' => $verificationData] = $propertyObject;
+ $this->setProperty($propertyName, $value, $scope, $verified, $verificationData);
+ }
+ }
+
+ return $this;
+ }
+
public function getAllProperties(): Generator {
foreach ($this->properties as $propertyObject) {
if ($propertyObject instanceof IAccountProperty) {
@@ -104,9 +126,16 @@ class Account implements IAccount {
return $result;
}
- /** @return IAccountPropertyCollection[]|IAccountProperty[] */
+ /** @return array<string, IAccountProperty|array<int, IAccountProperty>> */
public function jsonSerialize(): array {
- return $this->properties;
+ $properties = $this->properties;
+ foreach ($properties as $propertyName => $propertyObject) {
+ if ($propertyObject instanceof IAccountPropertyCollection) {
+ // Override collection serialization to discard duplicate name
+ $properties[$propertyName] = $propertyObject->jsonSerialize()[$propertyName];
+ }
+ }
+ return $properties;
}
public function getUser(): IUser {
diff --git a/lib/private/Accounts/AccountManager.php b/lib/private/Accounts/AccountManager.php
index 7f855c07d46..127adc9ef38 100644
--- a/lib/private/Accounts/AccountManager.php
+++ b/lib/private/Accounts/AccountManager.php
@@ -40,6 +40,7 @@ use libphonenumber\NumberParseException;
use libphonenumber\PhoneNumber;
use libphonenumber\PhoneNumberFormat;
use libphonenumber\PhoneNumberUtil;
+use OC\Profile\TProfileHelper;
use OCA\Settings\BackgroundJobs\VerifyUserData;
use OCP\Accounts\IAccount;
use OCP\Accounts\IAccountManager;
@@ -79,6 +80,8 @@ use function json_last_error;
class AccountManager implements IAccountManager {
use TAccountsHelper;
+ use TProfileHelper;
+
/** @var IDBConnection database connection */
private $connection;
@@ -722,7 +725,7 @@ class AccountManager implements IAccountManager {
[
'name' => self::PROPERTY_PROFILE_ENABLED,
- 'value' => '1',
+ 'value' => $this->isProfileEnabledByDefault($this->config) ? '1' : '0',
],
];
}
diff --git a/lib/private/App/AppStore/Fetcher/AppFetcher.php b/lib/private/App/AppStore/Fetcher/AppFetcher.php
index 6c201978e1f..579f350b5bb 100644
--- a/lib/private/App/AppStore/Fetcher/AppFetcher.php
+++ b/lib/private/App/AppStore/Fetcher/AppFetcher.php
@@ -90,8 +90,8 @@ class AppFetcher extends Fetcher {
return [];
}
- $allowPreReleases = $allowUnstable || $this->getChannel() === 'beta' || $this->getChannel() === 'daily';
- $allowNightly = $allowUnstable || $this->getChannel() === 'daily';
+ $allowPreReleases = $allowUnstable || $this->getChannel() === 'beta' || $this->getChannel() === 'daily' || $this->getChannel() === 'git';
+ $allowNightly = $allowUnstable || $this->getChannel() === 'daily' || $this->getChannel() === 'git';
foreach ($response['data'] as $dataKey => $app) {
$releases = [];
@@ -183,7 +183,9 @@ class AppFetcher extends Fetcher {
public function get($allowUnstable = false) {
- $apps = parent::get($allowUnstable);
+ $allowPreReleases = $allowUnstable || $this->getChannel() === 'beta' || $this->getChannel() === 'daily' || $this->getChannel() === 'git';
+
+ $apps = parent::get($allowPreReleases);
$allowList = $this->config->getSystemValue('appsallowlist');
// If the admin specified a allow list, filter apps from the appstore
diff --git a/lib/private/AppConfig.php b/lib/private/AppConfig.php
index e2d6d49a845..1324d7f3056 100644
--- a/lib/private/AppConfig.php
+++ b/lib/private/AppConfig.php
@@ -45,17 +45,84 @@ class AppConfig implements IAppConfig {
/** @var array[] */
protected $sensitiveValues = [
+ 'circles' => [
+ '/^local_gskey$/',
+ ],
'external' => [
'/^sites$/',
],
+ 'integration_discourse' => [
+ '/^private_key$/',
+ '/^public_key$/',
+ ],
+ 'integration_dropbox' => [
+ '/^client_id$/',
+ '/^client_secret$/',
+ ],
+ 'integration_github' => [
+ '/^client_id$/',
+ '/^client_secret$/',
+ ],
+ 'integration_gitlab' => [
+ '/^client_id$/',
+ '/^client_secret$/',
+ '/^oauth_instance_url$/',
+ ],
+ 'integration_google' => [
+ '/^client_id$/',
+ '/^client_secret$/',
+ ],
+ 'integration_jira' => [
+ '/^client_id$/',
+ '/^client_secret$/',
+ '/^forced_instance_url$/',
+ ],
+ 'integration_onedrive' => [
+ '/^client_id$/',
+ '/^client_secret$/',
+ ],
+ 'integration_openproject' => [
+ '/^client_id$/',
+ '/^client_secret$/',
+ '/^oauth_instance_url$/',
+ ],
+ 'integration_reddit' => [
+ '/^client_id$/',
+ '/^client_secret$/',
+ ],
+ 'integration_suitecrm' => [
+ '/^client_id$/',
+ '/^client_secret$/',
+ '/^oauth_instance_url$/',
+ ],
+ 'integration_twitter' => [
+ '/^consumer_key$/',
+ '/^consumer_secret$/',
+ '/^followed_user$/',
+ ],
+ 'integration_zammad' => [
+ '/^client_id$/',
+ '/^client_secret$/',
+ '/^oauth_instance_url$/',
+ ],
+ 'notify_push' => [
+ '/^cookie$/',
+ ],
'spreed' => [
'/^bridge_bot_password/',
'/^signaling_servers$/',
'/^signaling_ticket_secret$/',
+ '/^sip_bridge_dialin_info$/',
+ '/^sip_bridge_shared_secret$/',
'/^stun_servers$/',
'/^turn_servers$/',
'/^turn_server_secret$/',
],
+ 'support' => [
+ '/^last_response$/',
+ '/^potential_subscription_key$/',
+ '/^subscription_key$/',
+ ],
'theming' => [
'/^imprintUrl$/',
'/^privacyUrl$/',
diff --git a/lib/private/AppFramework/Bootstrap/Coordinator.php b/lib/private/AppFramework/Bootstrap/Coordinator.php
index 6e05b7fdc88..b6378830732 100644
--- a/lib/private/AppFramework/Bootstrap/Coordinator.php
+++ b/lib/private/AppFramework/Bootstrap/Coordinator.php
@@ -30,6 +30,7 @@ declare(strict_types=1);
namespace OC\AppFramework\Bootstrap;
+use OCP\Diagnostics\IEventLogger;
use function class_exists;
use function class_implements;
use function in_array;
@@ -58,6 +59,9 @@ class Coordinator {
/** @var IEventDispatcher */
private $eventDispatcher;
+ /** @var IEventLogger */
+ private $eventLogger;
+
/** @var LoggerInterface */
private $logger;
@@ -72,12 +76,14 @@ class Coordinator {
Registry $registry,
IManager $dashboardManager,
IEventDispatcher $eventListener,
+ IEventLogger $eventLogger,
LoggerInterface $logger
) {
$this->serverContainer = $container;
$this->registry = $registry;
$this->dashboardManager = $dashboardManager;
$this->eventDispatcher = $eventListener;
+ $this->eventLogger = $eventLogger;
$this->logger = $logger;
}
@@ -126,7 +132,9 @@ class Coordinator {
continue;
}
+ $this->eventLogger->start('bootstrap:register_app_' . $appId, '');
$application->register($this->registrationContext->for($appId));
+ $this->eventLogger->end('bootstrap:register_app_' . $appId);
}
} catch (Throwable $e) {
$this->logger->emergency('Error during app service registration: ' . $e->getMessage(), [
@@ -172,6 +180,7 @@ class Coordinator {
* the instance was already created for register, but any other
* (legacy) code will now do their magic via the constructor.
*/
+ $this->eventLogger->start('bootstrap:boot_app_' . $appId, '');
try {
/** @var App $application */
$application = $this->serverContainer->query($applicationClassName);
@@ -189,6 +198,7 @@ class Coordinator {
'exception' => $e,
]);
}
+ $this->eventLogger->end('bootstrap:boot_app_' . $appId);
}
public function isBootable(string $appId) {
diff --git a/lib/private/AppFramework/DependencyInjection/DIContainer.php b/lib/private/AppFramework/DependencyInjection/DIContainer.php
index 293b9e47b25..e06d5226a28 100644
--- a/lib/private/AppFramework/DependencyInjection/DIContainer.php
+++ b/lib/private/AppFramework/DependencyInjection/DIContainer.php
@@ -46,6 +46,7 @@ use OC\AppFramework\Middleware\SessionMiddleware;
use OC\AppFramework\ScopedPsrLogger;
use OC\AppFramework\Utility\SimpleContainer;
use OC\Core\Middleware\TwoFactorMiddleware;
+use OC\Diagnostics\EventLogger;
use OC\Log\PsrLoggerAdapter;
use OC\ServerContainer;
use OC\Settings\AuthorizedGroupMapper;
@@ -184,7 +185,8 @@ class DIContainer extends SimpleContainer implements IAppContainer {
$c->get(IRequest::class),
$c->get(IConfig::class),
$c->get(IDBConnection::class),
- $c->get(LoggerInterface::class)
+ $c->get(LoggerInterface::class),
+ $c->get(EventLogger::class)
);
});
diff --git a/lib/private/AppFramework/Http/Dispatcher.php b/lib/private/AppFramework/Http/Dispatcher.php
index 0f12dbda629..21d61bc95aa 100644
--- a/lib/private/AppFramework/Http/Dispatcher.php
+++ b/lib/private/AppFramework/Http/Dispatcher.php
@@ -39,6 +39,7 @@ use OC\DB\ConnectionAdapter;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\Response;
+use OCP\Diagnostics\IEventLogger;
use OCP\IConfig;
use OCP\IRequest;
use Psr\Log\LoggerInterface;
@@ -69,6 +70,9 @@ class Dispatcher {
/** @var LoggerInterface */
private $logger;
+ /** @var IEventLogger */
+ private $eventLogger;
+
/**
* @param Http $protocol the http protocol with contains all status headers
* @param MiddlewareDispatcher $middlewareDispatcher the dispatcher which
@@ -79,6 +83,7 @@ class Dispatcher {
* @param IConfig $config
* @param ConnectionAdapter $connection
* @param LoggerInterface $logger
+ * @param IEventLogger $eventLogger
*/
public function __construct(Http $protocol,
MiddlewareDispatcher $middlewareDispatcher,
@@ -86,7 +91,8 @@ class Dispatcher {
IRequest $request,
IConfig $config,
ConnectionAdapter $connection,
- LoggerInterface $logger) {
+ LoggerInterface $logger,
+ IEventLogger $eventLogger) {
$this->protocol = $protocol;
$this->middlewareDispatcher = $middlewareDispatcher;
$this->reflector = $reflector;
@@ -94,6 +100,7 @@ class Dispatcher {
$this->config = $config;
$this->connection = $connection;
$this->logger = $logger;
+ $this->eventLogger = $eventLogger;
}
@@ -214,7 +221,9 @@ class Dispatcher {
$arguments[] = $value;
}
+ $this->eventLogger->start('controller:' . get_class($controller) . '::' . $methodName, 'App framework controller execution');
$response = \call_user_func_array([$controller, $methodName], $arguments);
+ $this->eventLogger->end('controller:' . get_class($controller) . '::' . $methodName);
// format response
if ($response instanceof DataResponse || !($response instanceof Response)) {
diff --git a/lib/private/Archive/Archive.php b/lib/private/Archive/Archive.php
index 141db11f419..cef306230fd 100644
--- a/lib/private/Archive/Archive.php
+++ b/lib/private/Archive/Archive.php
@@ -30,97 +30,84 @@
namespace OC\Archive;
abstract class Archive {
- /**
- * @param $source
- */
- abstract public function __construct($source);
+ abstract public function __construct(string $source);
+
/**
* add an empty folder to the archive
- * @param string $path
- * @return bool
*/
- abstract public function addFolder($path);
+ abstract public function addFolder(string $path): bool;
+
/**
* add a file to the archive
- * @param string $path
* @param string $source either a local file or string data
- * @return bool
*/
- abstract public function addFile($path, $source = '');
+ abstract public function addFile(string $path, string $source = ''): bool;
+
/**
* rename a file or folder in the archive
- * @param string $source
- * @param string $dest
- * @return bool
*/
- abstract public function rename($source, $dest);
+ abstract public function rename(string $source, string $dest): bool;
+
/**
* get the uncompressed size of a file in the archive
- * @param string $path
- * @return int
+ * @return int|false
*/
- abstract public function filesize($path);
+ abstract public function filesize(string $path);
+
/**
* get the last modified time of a file in the archive
- * @param string $path
- * @return int
+ * @return int|false
*/
- abstract public function mtime($path);
+ abstract public function mtime(string $path);
+
/**
* get the files in a folder
* @param string $path
* @return array
*/
- abstract public function getFolder($path);
+ abstract public function getFolder(string $path): array;
+
/**
* get all files in the archive
- * @return array
*/
- abstract public function getFiles();
+ abstract public function getFiles(): array;
+
/**
* get the content of a file
- * @param string $path
- * @return string
+ * @return string|false
*/
- abstract public function getFile($path);
+ abstract public function getFile(string $path);
+
/**
* extract a single file from the archive
- * @param string $path
- * @param string $dest
- * @return bool
*/
- abstract public function extractFile($path, $dest);
+ abstract public function extractFile(string $path, string $dest): bool;
+
/**
* extract the archive
- * @param string $dest
- * @return bool
*/
- abstract public function extract($dest);
+ abstract public function extract(string $dest): bool;
+
/**
* check if a file or folder exists in the archive
- * @param string $path
- * @return bool
*/
- abstract public function fileExists($path);
+ abstract public function fileExists(string $path): bool;
+
/**
* remove a file or folder from the archive
- * @param string $path
- * @return bool
*/
- abstract public function remove($path);
+ abstract public function remove(string $path): bool;
+
/**
* get a file handler
- * @param string $path
- * @param string $mode
* @return bool|resource
*/
- abstract public function getStream($path, $mode);
+ abstract public function getStream(string $path, string $mode);
+
/**
* add a folder and all its content
- * @param string $path
- * @param string $source
*/
- public function addRecursive($path, $source) {
+ public function addRecursive(string $path, string $source): void {
$dh = opendir($source);
if (is_resource($dh)) {
$this->addFolder($path);
diff --git a/lib/private/Archive/TAR.php b/lib/private/Archive/TAR.php
index a024ce84b2f..79c09cbe9e2 100644
--- a/lib/private/Archive/TAR.php
+++ b/lib/private/Archive/TAR.php
@@ -39,19 +39,26 @@ class TAR extends Archive {
public const GZIP = 1;
public const BZIP = 2;
- private $fileList;
- private $cachedHeaders;
+ /**
+ * @var string[]|false
+ */
+ private $fileList = false;
+ /**
+ * @var array|false
+ */
+ private $cachedHeaders = false;
/**
- * @var \Archive_Tar tar
+ * @var \Archive_Tar
*/
private $tar = null;
- private $path;
/**
- * @param string $source
+ * @var string
*/
- public function __construct($source) {
+ private $path;
+
+ public function __construct(string $source) {
$types = [null, 'gz', 'bz2'];
$this->path = $source;
$this->tar = new \Archive_Tar($source, $types[self::getTarType($source)]);
@@ -59,11 +66,8 @@ class TAR extends Archive {
/**
* try to detect the type of tar compression
- *
- * @param string $file
- * @return integer
*/
- public static function getTarType($file) {
+ public static function getTarType(string $file): int {
if (strpos($file, '.')) {
$extension = substr($file, strrpos($file, '.'));
switch ($extension) {
@@ -85,11 +89,8 @@ class TAR extends Archive {
/**
* add an empty folder to the archive
- *
- * @param string $path
- * @return bool
*/
- public function addFolder($path) {
+ public function addFolder(string $path): bool {
$tmpBase = \OC::$server->getTempManager()->getTemporaryFolder();
$path = rtrim($path, '/') . '/';
if ($this->fileExists($path)) {
@@ -113,11 +114,9 @@ class TAR extends Archive {
/**
* add a file to the archive
*
- * @param string $path
* @param string $source either a local file or string data
- * @return bool
*/
- public function addFile($path, $source = '') {
+ public function addFile(string $path, string $source = ''): bool {
if ($this->fileExists($path)) {
$this->remove($path);
}
@@ -132,12 +131,8 @@ class TAR extends Archive {
/**
* rename a file or folder in the archive
- *
- * @param string $source
- * @param string $dest
- * @return bool
*/
- public function rename($source, $dest) {
+ public function rename(string $source, string $dest): bool {
//no proper way to delete, rename entire archive, rename file and remake archive
$tmp = \OC::$server->getTempManager()->getTemporaryFolder();
$this->tar->extract($tmp);
@@ -152,10 +147,7 @@ class TAR extends Archive {
return true;
}
- /**
- * @param string $file
- */
- private function getHeader($file) {
+ private function getHeader(string $file): ?array {
if (!$this->cachedHeaders) {
$this->cachedHeaders = $this->tar->listContent();
}
@@ -174,32 +166,27 @@ class TAR extends Archive {
/**
* get the uncompressed size of a file in the archive
*
- * @param string $path
- * @return int
+ * @return int|false
*/
- public function filesize($path) {
+ public function filesize(string $path) {
$stat = $this->getHeader($path);
- return $stat['size'];
+ return $stat['size'] ?? false;
}
/**
* get the last modified time of a file in the archive
*
- * @param string $path
- * @return int
+ * @return int|false
*/
- public function mtime($path) {
+ public function mtime(string $path) {
$stat = $this->getHeader($path);
- return $stat['mtime'];
+ return $stat['mtime'] ?? false;
}
/**
* get the files in a folder
- *
- * @param string $path
- * @return array
*/
- public function getFolder($path) {
+ public function getFolder(string $path): array {
$files = $this->getFiles();
$folderContent = [];
$pathLength = strlen($path);
@@ -222,10 +209,8 @@ class TAR extends Archive {
/**
* get all files in the archive
- *
- * @return array
*/
- public function getFiles() {
+ public function getFiles(): array {
if ($this->fileList) {
return $this->fileList;
}
@@ -243,21 +228,21 @@ class TAR extends Archive {
/**
* get the content of a file
*
- * @param string $path
- * @return string
+ * @return string|false
*/
- public function getFile($path) {
- return $this->tar->extractInString($path);
+ public function getFile(string $path) {
+ $string = $this->tar->extractInString($path);
+ if (is_string($string)) {
+ return $string;
+ } else {
+ return false;
+ }
}
/**
* extract a single file from the archive
- *
- * @param string $path
- * @param string $dest
- * @return bool
*/
- public function extractFile($path, $dest) {
+ public function extractFile(string $path, string $dest): bool {
$tmp = \OC::$server->getTempManager()->getTemporaryFolder();
if (!$this->fileExists($path)) {
return false;
@@ -276,21 +261,15 @@ class TAR extends Archive {
/**
* extract the archive
- *
- * @param string $dest
- * @return bool
*/
- public function extract($dest) {
+ public function extract(string $dest): bool {
return $this->tar->extract($dest);
}
/**
* check if a file or folder exists in the archive
- *
- * @param string $path
- * @return bool
*/
- public function fileExists($path) {
+ public function fileExists(string $path): bool {
$files = $this->getFiles();
if ((array_search($path, $files) !== false) or (array_search($path . '/', $files) !== false)) {
return true;
@@ -312,11 +291,8 @@ class TAR extends Archive {
/**
* remove a file or folder from the archive
- *
- * @param string $path
- * @return bool
*/
- public function remove($path) {
+ public function remove(string $path): bool {
if (!$this->fileExists($path)) {
return false;
}
@@ -336,13 +312,12 @@ class TAR extends Archive {
/**
* get a file handler
*
- * @param string $path
- * @param string $mode
* @return bool|resource
*/
- public function getStream($path, $mode) {
- if (strrpos($path, '.') !== false) {
- $ext = substr($path, strrpos($path, '.'));
+ public function getStream(string $path, string $mode) {
+ $lastPoint = strrpos($path, '.');
+ if ($lastPoint !== false) {
+ $ext = substr($path, $lastPoint);
} else {
$ext = '';
}
@@ -365,7 +340,7 @@ class TAR extends Archive {
/**
* write back temporary files
*/
- public function writeBack($tmpFile, $path) {
+ public function writeBack(string $tmpFile, string $path): void {
$this->addFile($path, $tmpFile);
unlink($tmpFile);
}
@@ -373,7 +348,7 @@ class TAR extends Archive {
/**
* reopen the archive to ensure everything is written
*/
- private function reopen() {
+ private function reopen(): void {
if ($this->tar) {
$this->tar->_close();
$this->tar = null;
diff --git a/lib/private/Archive/ZIP.php b/lib/private/Archive/ZIP.php
index e058d476021..ca9a046ab83 100644
--- a/lib/private/Archive/ZIP.php
+++ b/lib/private/Archive/ZIP.php
@@ -32,41 +32,42 @@
namespace OC\Archive;
use Icewind\Streams\CallbackWrapper;
-use OCP\ILogger;
+use Psr\Log\LoggerInterface;
class ZIP extends Archive {
/**
* @var \ZipArchive zip
*/
- private $zip = null;
- private $path;
+ private $zip;
/**
- * @param string $source
+ * @var string
*/
- public function __construct($source) {
+ private $path;
+
+ public function __construct(string $source) {
$this->path = $source;
$this->zip = new \ZipArchive();
if ($this->zip->open($source, \ZipArchive::CREATE)) {
} else {
- \OCP\Util::writeLog('files_archive', 'Error while opening archive '.$source, ILogger::WARN);
+ \OC::$server->get(LoggerInterface::class)->warning('Error while opening archive '.$source, ['app' => 'files_archive']);
}
}
+
/**
* add an empty folder to the archive
* @param string $path
* @return bool
*/
- public function addFolder($path) {
+ public function addFolder(string $path): bool {
return $this->zip->addEmptyDir($path);
}
+
/**
* add a file to the archive
- * @param string $path
* @param string $source either a local file or string data
- * @return bool
*/
- public function addFile($path, $source = '') {
+ public function addFile(string $path, string $source = ''): bool {
if ($source and $source[0] == '/' and file_exists($source)) {
$result = $this->zip->addFile($source, $path);
} else {
@@ -78,40 +79,37 @@ class ZIP extends Archive {
}
return $result;
}
+
/**
* rename a file or folder in the archive
- * @param string $source
- * @param string $dest
- * @return boolean|null
*/
- public function rename($source, $dest) {
+ public function rename(string $source, string $dest): bool {
$source = $this->stripPath($source);
$dest = $this->stripPath($dest);
- $this->zip->renameName($source, $dest);
+ return $this->zip->renameName($source, $dest);
}
+
/**
* get the uncompressed size of a file in the archive
- * @param string $path
- * @return int
+ * @return int|false
*/
- public function filesize($path) {
+ public function filesize(string $path) {
$stat = $this->zip->statName($path);
- return $stat['size'];
+ return $stat['size'] ?? false;
}
+
/**
* get the last modified time of a file in the archive
- * @param string $path
- * @return int
+ * @return int|false
*/
- public function mtime($path) {
+ public function mtime(string $path) {
return filemtime($this->path);
}
+
/**
* get the files in a folder
- * @param string $path
- * @return array
*/
- public function getFolder($path) {
+ public function getFolder(string $path): array {
$files = $this->getFiles();
$folderContent = [];
$pathLength = strlen($path);
@@ -124,11 +122,11 @@ class ZIP extends Archive {
}
return $folderContent;
}
+
/**
* get all files in the archive
- * @return array
*/
- public function getFiles() {
+ public function getFiles(): array {
$fileCount = $this->zip->numFiles;
$files = [];
for ($i = 0;$i < $fileCount;$i++) {
@@ -136,67 +134,65 @@ class ZIP extends Archive {
}
return $files;
}
+
/**
* get the content of a file
- * @param string $path
- * @return string
+ * @return string|false
*/
- public function getFile($path) {
+ public function getFile(string $path) {
return $this->zip->getFromName($path);
}
+
/**
* extract a single file from the archive
- * @param string $path
- * @param string $dest
- * @return boolean|null
*/
- public function extractFile($path, $dest) {
+ public function extractFile(string $path, string $dest): bool {
$fp = $this->zip->getStream($path);
- file_put_contents($dest, $fp);
+ if ($fp === false) {
+ return false;
+ }
+ return file_put_contents($dest, $fp) !== false;
}
+
/**
* extract the archive
- * @param string $dest
- * @return bool
*/
- public function extract($dest) {
+ public function extract(string $dest): bool {
return $this->zip->extractTo($dest);
}
+
/**
* check if a file or folder exists in the archive
- * @param string $path
- * @return bool
*/
- public function fileExists($path) {
+ public function fileExists(string $path): bool {
return ($this->zip->locateName($path) !== false) or ($this->zip->locateName($path.'/') !== false);
}
+
/**
* remove a file or folder from the archive
- * @param string $path
- * @return bool
*/
- public function remove($path) {
+ public function remove(string $path): bool {
if ($this->fileExists($path.'/')) {
return $this->zip->deleteName($path.'/');
} else {
return $this->zip->deleteName($path);
}
}
+
/**
* get a file handler
- * @param string $path
- * @param string $mode
* @return bool|resource
*/
- public function getStream($path, $mode) {
+ public function getStream(string $path, string $mode) {
if ($mode == 'r' or $mode == 'rb') {
return $this->zip->getStream($path);
} else {
//since we can't directly get a writable stream,
//make a temp copy of the file and put it back
//in the archive when the stream is closed
- if (strrpos($path, '.') !== false) {
- $ext = substr($path, strrpos($path, '.'));
+ $lastPoint = strrpos($path, '.');
+ if ($lastPoint !== false) {
+ $ext = substr($path, $lastPoint);
} else {
$ext = '';
}
@@ -214,16 +210,12 @@ class ZIP extends Archive {
/**
* write back temporary files
*/
- public function writeBack($tmpFile, $path) {
+ public function writeBack(string $tmpFile, string $path): void {
$this->addFile($path, $tmpFile);
unlink($tmpFile);
}
- /**
- * @param string $path
- * @return string
- */
- private function stripPath($path) {
+ private function stripPath(string $path): string {
if (!$path || $path[0] == '/') {
return substr($path, 1);
} else {
diff --git a/lib/private/Authentication/Token/PublicKeyTokenProvider.php b/lib/private/Authentication/Token/PublicKeyTokenProvider.php
index 04781457a7a..d2ee47cf380 100644
--- a/lib/private/Authentication/Token/PublicKeyTokenProvider.php
+++ b/lib/private/Authentication/Token/PublicKeyTokenProvider.php
@@ -97,12 +97,17 @@ class PublicKeyTokenProvider implements IProvider {
$tokenHash = $this->hashToken($tokenId);
if (isset($this->cache[$tokenHash])) {
+ if ($this->cache[$tokenHash] instanceof DoesNotExistException) {
+ $ex = $this->cache[$tokenHash];
+ throw new InvalidTokenException("Token does not exist: " . $ex->getMessage(), 0, $ex);
+ }
$token = $this->cache[$tokenHash];
} else {
try {
$token = $this->mapper->getToken($this->hashToken($tokenId));
$this->cache[$token->getToken()] = $token;
} catch (DoesNotExistException $ex) {
+ $this->cache[$tokenHash] = $ex;
throw new InvalidTokenException("Token does not exist: " . $ex->getMessage(), 0, $ex);
}
}
diff --git a/lib/private/Avatar/AvatarManager.php b/lib/private/Avatar/AvatarManager.php
index c3afd8094c7..77138085dc9 100644
--- a/lib/private/Avatar/AvatarManager.php
+++ b/lib/private/Avatar/AvatarManager.php
@@ -43,6 +43,7 @@ use OCP\Accounts\PropertyDoesNotExistException;
use OCP\Files\IAppData;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
+use OCP\Files\StorageNotAvailableException;
use OCP\IAvatar;
use OCP\IAvatarManager;
use OCP\IConfig;
@@ -173,7 +174,7 @@ class AvatarManager implements IAvatarManager {
$folder->delete();
} catch (NotFoundException $e) {
$this->logger->debug("No cache for the user $userId. Ignoring avatar deletion");
- } catch (NotPermittedException $e) {
+ } catch (NotPermittedException | StorageNotAvailableException $e) {
$this->logger->error("Unable to delete user avatars for $userId. gnoring avatar deletion");
} catch (NoUserException $e) {
$this->logger->debug("User $userId not found. gnoring avatar deletion");
diff --git a/lib/private/BackgroundJob/Job.php b/lib/private/BackgroundJob/Job.php
index 6f85e3382ed..399ff05134e 100644
--- a/lib/private/BackgroundJob/Job.php
+++ b/lib/private/BackgroundJob/Job.php
@@ -29,6 +29,9 @@ use OCP\BackgroundJob\IJob;
use OCP\BackgroundJob\IJobList;
use OCP\ILogger;
+/**
+ * @deprecated internal class, use \OCP\BackgroundJob\Job
+ */
abstract class Job implements IJob {
/** @var int */
protected $id;
diff --git a/lib/private/BackgroundJob/JobList.php b/lib/private/BackgroundJob/JobList.php
index 16dfa7b58a6..21af79c4686 100644
--- a/lib/private/BackgroundJob/JobList.php
+++ b/lib/private/BackgroundJob/JobList.php
@@ -29,6 +29,7 @@
*/
namespace OC\BackgroundJob;
+use Doctrine\DBAL\Platforms\MySQLPlatform;
use OCP\AppFramework\QueryException;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\AutoloadNotAllowedException;
@@ -111,10 +112,25 @@ class JobList implements IJobList {
$query->delete('jobs')
->where($query->expr()->eq('class', $query->createNamedParameter($class)));
if (!is_null($argument)) {
- $argument = json_encode($argument);
- $query->andWhere($query->expr()->eq('argument', $query->createNamedParameter($argument)));
+ $argumentJson = json_encode($argument);
+ $query->andWhere($query->expr()->eq('argument_hash', $query->createNamedParameter(md5($argumentJson))));
+ }
+
+ // Add galera safe delete chunking if using mysql
+ // Stops us hitting wsrep_max_ws_rows when large row counts are deleted
+ if ($this->connection->getDatabasePlatform() instanceof MySQLPlatform) {
+ // Then use chunked delete
+ $max = IQueryBuilder::MAX_ROW_DELETION;
+
+ $query->setMaxResults($max);
+
+ do {
+ $deleted = $query->execute();
+ } while ($deleted === $max);
+ } else {
+ // Dont use chunked delete - let the DB handle the large row count natively
+ $query->execute();
}
- $query->execute();
}
/**
diff --git a/lib/private/BackgroundJob/Legacy/QueuedJob.php b/lib/private/BackgroundJob/Legacy/QueuedJob.php
index d68fd217fdd..fd001738d4f 100644
--- a/lib/private/BackgroundJob/Legacy/QueuedJob.php
+++ b/lib/private/BackgroundJob/Legacy/QueuedJob.php
@@ -23,6 +23,9 @@
*/
namespace OC\BackgroundJob\Legacy;
+/**
+ * @deprecated internal class, use \OCP\BackgroundJob\QueuedJob
+ */
class QueuedJob extends \OC\BackgroundJob\QueuedJob {
public function run($argument) {
$class = $argument['klass'];
diff --git a/lib/private/BackgroundJob/Legacy/RegularJob.php b/lib/private/BackgroundJob/Legacy/RegularJob.php
index e3286536c9a..0f337a35eb0 100644
--- a/lib/private/BackgroundJob/Legacy/RegularJob.php
+++ b/lib/private/BackgroundJob/Legacy/RegularJob.php
@@ -24,6 +24,9 @@ namespace OC\BackgroundJob\Legacy;
use OCP\AutoloadNotAllowedException;
+/**
+ * @deprecated internal class, use \OCP\BackgroundJob\QueuedJob
+ */
class RegularJob extends \OC\BackgroundJob\Job {
public function run($argument) {
try {
diff --git a/lib/private/BackgroundJob/QueuedJob.php b/lib/private/BackgroundJob/QueuedJob.php
index 176227e73db..28d86481e62 100644
--- a/lib/private/BackgroundJob/QueuedJob.php
+++ b/lib/private/BackgroundJob/QueuedJob.php
@@ -32,6 +32,8 @@ use OCP\ILogger;
* create a background job that is to be executed once
*
* @package OC\BackgroundJob
+ *
+ * @deprecated internal class, use \OCP\BackgroundJob\QueuedJob
*/
abstract class QueuedJob extends Job {
/**
diff --git a/lib/private/BackgroundJob/TimedJob.php b/lib/private/BackgroundJob/TimedJob.php
index 62b9bab7ccc..0f0951e1aec 100644
--- a/lib/private/BackgroundJob/TimedJob.php
+++ b/lib/private/BackgroundJob/TimedJob.php
@@ -34,6 +34,8 @@ use OCP\ILogger;
* create a background job that is to be executed at an interval
*
* @package OC\BackgroundJob
+ *
+ * @deprecated internal class, use \OCP\BackgroundJob\TimedJob
*/
abstract class TimedJob extends Job {
protected $interval = 0;
diff --git a/lib/private/Cache/CappedMemoryCache.php b/lib/private/Cache/CappedMemoryCache.php
index 584a53f0ff2..9260bf1f6b3 100644
--- a/lib/private/Cache/CappedMemoryCache.php
+++ b/lib/private/Cache/CappedMemoryCache.php
@@ -27,30 +27,42 @@ use OCP\ICache;
* In-memory cache with a capacity limit to keep memory usage in check
*
* Uses a simple FIFO expiry mechanism
+ * @template T
*/
class CappedMemoryCache implements ICache, \ArrayAccess {
private $capacity;
+ /** @var T[] */
private $cache = [];
public function __construct($capacity = 512) {
$this->capacity = $capacity;
}
- public function hasKey($key) {
+ public function hasKey($key): bool {
return isset($this->cache[$key]);
}
+ /**
+ * @return ?T
+ */
public function get($key) {
- return isset($this->cache[$key]) ? $this->cache[$key] : null;
+ return $this->cache[$key] ?? null;
}
- public function set($key, $value, $ttl = 0) {
+ /**
+ * @param string $key
+ * @param T $value
+ * @param int $ttl
+ * @return bool
+ */
+ public function set($key, $value, $ttl = 0): bool {
if (is_null($key)) {
$this->cache[] = $value;
} else {
$this->cache[$key] = $value;
}
$this->garbageCollect();
+ return true;
}
public function remove($key) {
@@ -68,13 +80,18 @@ class CappedMemoryCache implements ICache, \ArrayAccess {
}
/**
- * @return mixed
+ * @return T
*/
#[\ReturnTypeWillChange]
public function &offsetGet($offset) {
return $this->cache[$offset];
}
+ /**
+ * @param string $key
+ * @param T $value
+ * @return void
+ */
public function offsetSet($offset, $value): void {
$this->set($offset, $value);
}
@@ -83,6 +100,9 @@ class CappedMemoryCache implements ICache, \ArrayAccess {
$this->remove($offset);
}
+ /**
+ * @return T[]
+ */
public function getData() {
return $this->cache;
}
diff --git a/lib/private/Comments/Manager.php b/lib/private/Comments/Manager.php
index 7c312b18f7d..384187accf3 100644
--- a/lib/private/Comments/Manager.php
+++ b/lib/private/Comments/Manager.php
@@ -611,13 +611,16 @@ class Manager implements ICommentsManager {
$query->select('*')
->from('comments')
- ->where($query->expr()->iLike('message', $query->createNamedParameter(
- '%' . $this->dbConn->escapeLikeParameter($search). '%'
- )))
->orderBy('creation_timestamp', 'DESC')
->addOrderBy('id', 'DESC')
->setMaxResults($limit);
+ if ($search !== '') {
+ $query->where($query->expr()->iLike('message', $query->createNamedParameter(
+ '%' . $this->dbConn->escapeLikeParameter($search). '%'
+ )));
+ }
+
if ($objectType !== '') {
$query->andWhere($query->expr()->eq('object_type', $query->createNamedParameter($objectType)));
}
diff --git a/lib/private/Contacts/ContactsMenu/ContactsStore.php b/lib/private/Contacts/ContactsMenu/ContactsStore.php
index a27c2ae455a..5b7a942a244 100644
--- a/lib/private/Contacts/ContactsMenu/ContactsStore.php
+++ b/lib/private/Contacts/ContactsMenu/ContactsStore.php
@@ -32,7 +32,7 @@
namespace OC\Contacts\ContactsMenu;
use OC\KnownUser\KnownUserService;
-use OCP\Accounts\IAccountManager;
+use OC\Profile\ProfileManager;
use OCP\Contacts\ContactsMenu\IContactsStore;
use OCP\Contacts\ContactsMenu\IEntry;
use OCP\Contacts\IManager;
@@ -44,10 +44,6 @@ use OCP\IUserManager;
use OCP\L10N\IFactory as IL10NFactory;
class ContactsStore implements IContactsStore {
- use \OC\Profile\TProfileHelper;
-
- /** @var IAccountManager */
- private $accountManager;
/** @var IManager */
private $contactsManager;
@@ -55,6 +51,9 @@ class ContactsStore implements IContactsStore {
/** @var IConfig */
private $config;
+ /** @var ProfileManager */
+ private $profileManager;
+
/** @var IUserManager */
private $userManager;
@@ -71,18 +70,18 @@ class ContactsStore implements IContactsStore {
private $l10nFactory;
public function __construct(
- IAccountManager $accountManager,
IManager $contactsManager,
IConfig $config,
+ ProfileManager $profileManager,
IUserManager $userManager,
IURLGenerator $urlGenerator,
IGroupManager $groupManager,
KnownUserService $knownUserService,
IL10NFactory $l10nFactory
) {
- $this->accountManager = $accountManager;
$this->contactsManager = $contactsManager;
$this->config = $config;
+ $this->profileManager = $profileManager;
$this->userManager = $userManager;
$this->urlGenerator = $urlGenerator;
$this->groupManager = $groupManager;
@@ -335,10 +334,9 @@ class ContactsStore implements IContactsStore {
// Provide profile parameters for core/src/OC/contactsmenu/contact.handlebars template
if (isset($contact['UID']) && isset($contact['FN'])) {
$targetUserId = $contact['UID'];
- $user = $this->userManager->get($targetUserId);
- if (!empty($user)) {
- $account = $this->accountManager->getAccount($user);
- if ($this->isProfileEnabled($account)) {
+ $targetUser = $this->userManager->get($targetUserId);
+ if (!empty($targetUser)) {
+ if ($this->profileManager->isProfileEnabled($targetUser)) {
$entry->setProfileTitle($this->l10nFactory->get('lib')->t('View profile'));
$entry->setProfileUrl($this->urlGenerator->linkToRouteAbsolute('core.ProfilePage.index', ['targetUserId' => $targetUserId]));
}
diff --git a/lib/private/Contacts/ContactsMenu/Providers/ProfileProvider.php b/lib/private/Contacts/ContactsMenu/Providers/ProfileProvider.php
index 15d24fc7773..e654319c3fa 100644
--- a/lib/private/Contacts/ContactsMenu/Providers/ProfileProvider.php
+++ b/lib/private/Contacts/ContactsMenu/Providers/ProfileProvider.php
@@ -24,7 +24,7 @@
namespace OC\Contacts\ContactsMenu\Providers;
-use OCP\Accounts\IAccountManager;
+use OC\Profile\ProfileManager;
use OCP\Contacts\ContactsMenu\IActionFactory;
use OCP\Contacts\ContactsMenu\IEntry;
use OCP\Contacts\ContactsMenu\IProvider;
@@ -33,14 +33,13 @@ use OCP\IUserManager;
use OCP\L10N\IFactory as IL10NFactory;
class ProfileProvider implements IProvider {
- use \OC\Profile\TProfileHelper;
-
- /** @var IAccountManager */
- private $accountManager;
/** @var IActionFactory */
private $actionFactory;
+ /** @var ProfileManager */
+ private $profileManager;
+
/** @var IL10NFactory */
private $l10nFactory;
@@ -51,21 +50,21 @@ class ProfileProvider implements IProvider {
private $userManager;
/**
- * @param IAccountManager $accountManager
* @param IActionFactory $actionFactory
+ * @param ProfileManager $profileManager
* @param IL10NFactory $l10nFactory
* @param IURLGenerator $urlGenerator
* @param IUserManager $userManager
*/
public function __construct(
- IAccountManager $accountManager,
IActionFactory $actionFactory,
+ ProfileManager $profileManager,
IL10NFactory $l10nFactory,
IURLGenerator $urlGenerator,
IUserManager $userManager
) {
- $this->accountManager = $accountManager;
$this->actionFactory = $actionFactory;
+ $this->profileManager = $profileManager;
$this->l10nFactory = $l10nFactory;
$this->urlGenerator = $urlGenerator;
$this->userManager = $userManager;
@@ -78,8 +77,7 @@ class ProfileProvider implements IProvider {
$targetUserId = $entry->getProperty('UID');
$targetUser = $this->userManager->get($targetUserId);
if (!empty($targetUser)) {
- $account = $this->accountManager->getAccount($targetUser);
- if ($this->isProfileEnabled($account)) {
+ if ($this->profileManager->isProfileEnabled($targetUser)) {
$iconUrl = $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'actions/profile.svg'));
$profileActionText = $this->l10nFactory->get('lib')->t('View profile');
$profileUrl = $this->urlGenerator->linkToRouteAbsolute('core.ProfilePage.index', ['targetUserId' => $targetUserId]);
diff --git a/lib/private/DB/Connection.php b/lib/private/DB/Connection.php
index b8d1a747fa2..e32c530c19e 100644
--- a/lib/private/DB/Connection.php
+++ b/lib/private/DB/Connection.php
@@ -81,7 +81,17 @@ class Connection extends \Doctrine\DBAL\Connection {
*/
public function connect() {
try {
- return parent::connect();
+ if ($this->_conn) {
+ return parent::connect();
+ }
+
+ // Only trigger the event logger for the initial connect call
+ $eventLogger = \OC::$server->getEventLogger();
+ $eventLogger->start('connect:db', 'db connection opened');
+ $status = parent::connect();
+ $eventLogger->end('connect:db');
+
+ return $status;
} catch (Exception $e) {
// throw a new exception to prevent leaking info from the stacktrace
throw new Exception('Failed to connect to the database: ' . $e->getMessage(), $e->getCode());
@@ -538,12 +548,20 @@ class Connection extends \Doctrine\DBAL\Connection {
* Migrate the database to the given schema
*
* @param Schema $toSchema
+ * @param bool $dryRun If true, will return the sql queries instead of running them.
*
* @throws Exception
+ *
+ * @return string|null Returns a string only if $dryRun is true.
*/
- public function migrateToSchema(Schema $toSchema) {
+ public function migrateToSchema(Schema $toSchema, bool $dryRun = false) {
$migrator = $this->getMigrator();
- $migrator->migrate($toSchema);
+
+ if ($dryRun) {
+ return $migrator->generateChangeScript($toSchema);
+ } else {
+ $migrator->migrate($toSchema);
+ }
}
private function getMigrator() {
diff --git a/lib/private/DB/MigrationService.php b/lib/private/DB/MigrationService.php
index 6ad74a58591..e7361cb4cab 100644
--- a/lib/private/DB/MigrationService.php
+++ b/lib/private/DB/MigrationService.php
@@ -634,6 +634,8 @@ class MigrationService {
if ($isUsingDefaultName && \strlen($table->getName()) - $prefixLength >= 23) {
throw new \InvalidArgumentException('Primary index name on "' . $table->getName() . '" is too long.');
}
+ } elseif (!$primaryKey instanceof Index) {
+ throw new \InvalidArgumentException('Table "' . $table->getName() . '" has no primary key and therefor will not behave sane in clustered setups.');
}
}
diff --git a/lib/private/Diagnostics/Event.php b/lib/private/Diagnostics/Event.php
index 95b737155dc..0c3aa6ae29c 100644
--- a/lib/private/Diagnostics/Event.php
+++ b/lib/private/Diagnostics/Event.php
@@ -100,4 +100,8 @@ class Event implements IEvent {
}
return $this->end - $this->start;
}
+
+ public function __toString() {
+ return $this->getId() . ' ' . $this->getDescription() . ' ' . $this->getDuration();
+ }
}
diff --git a/lib/private/Diagnostics/EventLogger.php b/lib/private/Diagnostics/EventLogger.php
index 4f3343ec625..35cef0be3f5 100644
--- a/lib/private/Diagnostics/EventLogger.php
+++ b/lib/private/Diagnostics/EventLogger.php
@@ -24,25 +24,59 @@
*/
namespace OC\Diagnostics;
+use OC\Log;
+use OC\SystemConfig;
+use OCP\Diagnostics\IEvent;
use OCP\Diagnostics\IEventLogger;
+use Psr\Log\LoggerInterface;
class EventLogger implements IEventLogger {
- /**
- * @var \OC\Diagnostics\Event[]
- */
+
+ /** @var Event[] */
private $events = [];
-
+
+ /** @var SystemConfig */
+ private $config;
+
+ /** @var LoggerInterface */
+ private $logger;
+
+ /** @var Log */
+ private $internalLogger;
+
/**
* @var bool - Module needs to be activated by some app
*/
private $activated = false;
+ public function __construct(SystemConfig $config, LoggerInterface $logger, Log $internalLogger) {
+ $this->config = $config;
+ $this->logger = $logger;
+ $this->internalLogger = $internalLogger;
+
+ if ($this->isLoggingActivated()) {
+ $this->activate();
+ }
+ }
+
+ public function isLoggingActivated(): bool {
+ $systemValue = (bool)$this->config->getValue('diagnostics.logging', false);
+
+ if ($systemValue && $this->config->getValue('debug', false)) {
+ return true;
+ }
+
+ $isDebugLevel = $this->internalLogger->getLogLevel([]) === Log::DEBUG;
+ return $systemValue && $isDebugLevel;
+ }
+
/**
* @inheritdoc
*/
- public function start($id, $description) {
+ public function start($id, $description = '') {
if ($this->activated) {
$this->events[$id] = new Event($id, $description, microtime(true));
+ $this->writeLog($this->events[$id]);
}
}
@@ -53,6 +87,7 @@ class EventLogger implements IEventLogger {
if ($this->activated && isset($this->events[$id])) {
$timing = $this->events[$id];
$timing->end(microtime(true));
+ $this->writeLog($timing);
}
}
@@ -63,6 +98,7 @@ class EventLogger implements IEventLogger {
if ($this->activated) {
$this->events[$id] = new Event($id, $description, $start);
$this->events[$id]->end($end);
+ $this->writeLog($this->events[$id]);
}
}
@@ -72,11 +108,29 @@ class EventLogger implements IEventLogger {
public function getEvents() {
return $this->events;
}
-
+
/**
* @inheritdoc
*/
public function activate() {
$this->activated = true;
}
+
+ private function writeLog(IEvent $event) {
+ if ($this->activated) {
+ if ($event->getEnd() === null) {
+ return;
+ }
+ $duration = $event->getDuration();
+ $timeInMs = round($duration * 1000, 4);
+
+ $loggingMinimum = (int)$this->config->getValue('diagnostics.logging.threshold', 0);
+ if ($loggingMinimum > 0 && $timeInMs < $loggingMinimum) {
+ return;
+ }
+
+ $message = microtime() . ' - ' . $event->getId() . ': ' . $timeInMs . ' (' . $event->getDescription() . ')';
+ $this->logger->debug($message, ['app' => 'diagnostics']);
+ }
+ }
}
diff --git a/lib/private/Files/Cache/Scanner.php b/lib/private/Files/Cache/Scanner.php
index bd8db2c8a12..af412dd129b 100644
--- a/lib/private/Files/Cache/Scanner.php
+++ b/lib/private/Files/Cache/Scanner.php
@@ -36,7 +36,6 @@
namespace OC\Files\Cache;
use Doctrine\DBAL\Exception;
-use OC\Files\Filesystem;
use OC\Files\Storage\Wrapper\Jail;
use OC\Files\Storage\Wrapper\Encoding;
use OC\Hooks\BasicEmitter;
@@ -140,8 +139,8 @@ class Scanner extends BasicEmitter implements IScanner {
return null;
}
}
- // only proceed if $file is not a partial file nor a blacklisted file
- if (!self::isPartialFile($file) and !Filesystem::isFileBlacklisted($file)) {
+ // only proceed if $file is not a partial file, blacklist is handled by the storage
+ if (!self::isPartialFile($file)) {
//acquire a lock
if ($lock) {
diff --git a/lib/private/Files/Cache/Storage.php b/lib/private/Files/Cache/Storage.php
index 33785607ef7..2de2c2f84d7 100644
--- a/lib/private/Files/Cache/Storage.php
+++ b/lib/private/Files/Cache/Storage.php
@@ -158,7 +158,7 @@ class Storage {
}
/**
- * @return array|null [ available, last_checked ]
+ * @return array [ available, last_checked ]
*/
public function getAvailability() {
if ($row = self::getStorageById($this->storageId)) {
@@ -167,7 +167,10 @@ class Storage {
'last_checked' => $row['last_checked']
];
} else {
- return null;
+ return [
+ 'available' => true,
+ 'last_checked' => time(),
+ ];
}
}
diff --git a/lib/private/Files/Config/CachedMountFileInfo.php b/lib/private/Files/Config/CachedMountFileInfo.php
index 7fdc26f7d53..11a9a505808 100644
--- a/lib/private/Files/Config/CachedMountFileInfo.php
+++ b/lib/private/Files/Config/CachedMountFileInfo.php
@@ -27,15 +27,23 @@ use OCP\Files\Config\ICachedMountFileInfo;
use OCP\IUser;
class CachedMountFileInfo extends CachedMountInfo implements ICachedMountFileInfo {
- /** @var string */
- private $internalPath;
+ private string $internalPath;
- public function __construct(IUser $user, $storageId, $rootId, $mountPoint, $mountId, $rootInternalPath, $internalPath) {
- parent::__construct($user, $storageId, $rootId, $mountPoint, $mountId, $rootInternalPath);
+ public function __construct(
+ IUser $user,
+ int $storageId,
+ int $rootId,
+ string $mountPoint,
+ ?int $mountId,
+ string $mountProvider,
+ string $rootInternalPath,
+ string $internalPath
+ ) {
+ parent::__construct($user, $storageId, $rootId, $mountPoint, $mountProvider, $mountId, $rootInternalPath);
$this->internalPath = $internalPath;
}
- public function getInternalPath() {
+ public function getInternalPath(): string {
if ($this->getRootInternalPath()) {
return substr($this->internalPath, strlen($this->getRootInternalPath()) + 1);
} else {
@@ -43,7 +51,7 @@ class CachedMountFileInfo extends CachedMountInfo implements ICachedMountFileInf
}
}
- public function getPath() {
+ public function getPath(): string {
return $this->getMountPoint() . $this->getInternalPath();
}
}
diff --git a/lib/private/Files/Config/CachedMountInfo.php b/lib/private/Files/Config/CachedMountInfo.php
index e7e10cfe2af..43c9fae63ec 100644
--- a/lib/private/Files/Config/CachedMountInfo.php
+++ b/lib/private/Files/Config/CachedMountInfo.php
@@ -28,35 +28,13 @@ use OCP\Files\Node;
use OCP\IUser;
class CachedMountInfo implements ICachedMountInfo {
- /**
- * @var IUser
- */
- protected $user;
-
- /**
- * @var int
- */
- protected $storageId;
-
- /**
- * @var int
- */
- protected $rootId;
-
- /**
- * @var string
- */
- protected $mountPoint;
-
- /**
- * @var int|null
- */
- protected $mountId;
-
- /**
- * @var string
- */
- protected $rootInternalPath;
+ protected IUser $user;
+ protected int $storageId;
+ protected int $rootId;
+ protected string $mountPoint;
+ protected ?int $mountId;
+ protected string $rootInternalPath;
+ protected string $mountProvider;
/**
* CachedMountInfo constructor.
@@ -68,40 +46,52 @@ class CachedMountInfo implements ICachedMountInfo {
* @param int|null $mountId
* @param string $rootInternalPath
*/
- public function __construct(IUser $user, $storageId, $rootId, $mountPoint, $mountId = null, $rootInternalPath = '') {
+ public function __construct(
+ IUser $user,
+ int $storageId,
+ int $rootId,
+ string $mountPoint,
+ string $mountProvider,
+ int $mountId = null,
+ string $rootInternalPath = ''
+ ) {
$this->user = $user;
$this->storageId = $storageId;
$this->rootId = $rootId;
$this->mountPoint = $mountPoint;
$this->mountId = $mountId;
$this->rootInternalPath = $rootInternalPath;
+ if (strlen($mountProvider) > 128) {
+ throw new \Exception("Mount provider $mountProvider name exceeds the limit of 128 characters");
+ }
+ $this->mountProvider = $mountProvider;
}
/**
* @return IUser
*/
- public function getUser() {
+ public function getUser(): IUser {
return $this->user;
}
/**
* @return int the numeric storage id of the mount
*/
- public function getStorageId() {
+ public function getStorageId(): int {
return $this->storageId;
}
/**
* @return int the fileid of the root of the mount
*/
- public function getRootId() {
+ public function getRootId(): int {
return $this->rootId;
}
/**
- * @return Node the root node of the mount
+ * @return Node|null the root node of the mount
*/
- public function getMountPointNode() {
+ public function getMountPointNode(): ?Node {
// TODO injection etc
Filesystem::initMountPoints($this->getUser()->getUID());
$userNode = \OC::$server->getUserFolder($this->getUser()->getUID());
@@ -116,7 +106,7 @@ class CachedMountInfo implements ICachedMountInfo {
/**
* @return string the mount point of the mount for the user
*/
- public function getMountPoint() {
+ public function getMountPoint(): string {
return $this->mountPoint;
}
@@ -126,7 +116,7 @@ class CachedMountInfo implements ICachedMountInfo {
* @return int|null mount id or null if not applicable
* @since 9.1.0
*/
- public function getMountId() {
+ public function getMountId(): ?int {
return $this->mountId;
}
@@ -135,7 +125,11 @@ class CachedMountInfo implements ICachedMountInfo {
*
* @return string
*/
- public function getRootInternalPath() {
+ public function getRootInternalPath(): string {
return $this->rootInternalPath;
}
+
+ public function getMountProvider(): string {
+ return $this->mountProvider;
+ }
}
diff --git a/lib/private/Files/Config/LazyStorageMountInfo.php b/lib/private/Files/Config/LazyStorageMountInfo.php
index bfd632c5f6e..78055a2cdb8 100644
--- a/lib/private/Files/Config/LazyStorageMountInfo.php
+++ b/lib/private/Files/Config/LazyStorageMountInfo.php
@@ -25,8 +25,7 @@ use OCP\Files\Mount\IMountPoint;
use OCP\IUser;
class LazyStorageMountInfo extends CachedMountInfo {
- /** @var IMountPoint */
- private $mount;
+ private IMountPoint $mount;
/**
* CachedMountInfo constructor.
@@ -37,12 +36,15 @@ class LazyStorageMountInfo extends CachedMountInfo {
public function __construct(IUser $user, IMountPoint $mount) {
$this->user = $user;
$this->mount = $mount;
+ $this->rootId = 0;
+ $this->storageId = 0;
+ $this->mountPoint = '';
}
/**
* @return int the numeric storage id of the mount
*/
- public function getStorageId() {
+ public function getStorageId(): int {
if (!$this->storageId) {
$this->storageId = $this->mount->getNumericStorageId();
}
@@ -52,7 +54,7 @@ class LazyStorageMountInfo extends CachedMountInfo {
/**
* @return int the fileid of the root of the mount
*/
- public function getRootId() {
+ public function getRootId(): int {
if (!$this->rootId) {
$this->rootId = $this->mount->getStorageRootId();
}
@@ -62,14 +64,14 @@ class LazyStorageMountInfo extends CachedMountInfo {
/**
* @return string the mount point of the mount for the user
*/
- public function getMountPoint() {
+ public function getMountPoint(): string {
if (!$this->mountPoint) {
$this->mountPoint = $this->mount->getMountPoint();
}
return parent::getMountPoint();
}
- public function getMountId() {
+ public function getMountId(): ?int {
return $this->mount->getMountId();
}
@@ -78,7 +80,11 @@ class LazyStorageMountInfo extends CachedMountInfo {
*
* @return string
*/
- public function getRootInternalPath() {
+ public function getRootInternalPath(): string {
return $this->mount->getInternalPath($this->mount->getMountPoint());
}
+
+ public function getMountProvider(): string {
+ return $this->mount->getMountProvider();
+ }
}
diff --git a/lib/private/Files/Config/MountProviderCollection.php b/lib/private/Files/Config/MountProviderCollection.php
index ba70e29ab8d..cd8a2a2e29f 100644
--- a/lib/private/Files/Config/MountProviderCollection.php
+++ b/lib/private/Files/Config/MountProviderCollection.php
@@ -184,16 +184,6 @@ class MountProviderCollection implements IMountProviderCollection, Emitter {
}
/**
- * Cache mounts for user
- *
- * @param IUser $user
- * @param IMountPoint[] $mountPoints
- */
- public function registerMounts(IUser $user, array $mountPoints) {
- $this->mountCache->registerMounts($user, $mountPoints);
- }
-
- /**
* Get the mount cache which can be used to search for mounts without setting up the filesystem
*
* @return IUserMountCache
@@ -222,4 +212,10 @@ class MountProviderCollection implements IMountProviderCollection, Emitter {
}, []);
return $mounts;
}
+
+ public function clearProviders() {
+ $this->providers = [];
+ $this->homeProviders = [];
+ $this->rootProviders = [];
+ }
}
diff --git a/lib/private/Files/Config/UserMountCache.php b/lib/private/Files/Config/UserMountCache.php
index 71eb918a58c..dc2640361e7 100644
--- a/lib/private/Files/Config/UserMountCache.php
+++ b/lib/private/Files/Config/UserMountCache.php
@@ -164,7 +164,8 @@ class UserMountCache implements IUserMountCache {
if (
$newMount->getMountPoint() !== $cachedMount->getMountPoint() ||
$newMount->getStorageId() !== $cachedMount->getStorageId() ||
- $newMount->getMountId() !== $cachedMount->getMountId()
+ $newMount->getMountId() !== $cachedMount->getMountId() ||
+ $newMount->getMountProvider() !== $cachedMount->getMountProvider()
) {
$changed[] = $newMount;
}
@@ -180,7 +181,8 @@ class UserMountCache implements IUserMountCache {
'root_id' => $mount->getRootId(),
'user_id' => $mount->getUser()->getUID(),
'mount_point' => $mount->getMountPoint(),
- 'mount_id' => $mount->getMountId()
+ 'mount_id' => $mount->getMountId(),
+ 'mount_provider_class' => $mount->getMountProvider(),
], ['root_id', 'user_id']);
} else {
// in some cases this is legitimate, like orphaned shares
@@ -195,6 +197,7 @@ class UserMountCache implements IUserMountCache {
->set('storage_id', $builder->createNamedParameter($mount->getStorageId()))
->set('mount_point', $builder->createNamedParameter($mount->getMountPoint()))
->set('mount_id', $builder->createNamedParameter($mount->getMountId(), IQueryBuilder::PARAM_INT))
+ ->set('mount_provider_class', $builder->createNamedParameter($mount->getMountProvider()))
->where($builder->expr()->eq('user_id', $builder->createNamedParameter($mount->getUser()->getUID())))
->andWhere($builder->expr()->eq('root_id', $builder->createNamedParameter($mount->getRootId(), IQueryBuilder::PARAM_INT)));
@@ -219,7 +222,15 @@ class UserMountCache implements IUserMountCache {
if (!is_null($mount_id)) {
$mount_id = (int)$mount_id;
}
- return new CachedMountInfo($user, (int)$row['storage_id'], (int)$row['root_id'], $row['mount_point'], $mount_id, isset($row['path']) ? $row['path'] : '');
+ return new CachedMountInfo(
+ $user,
+ (int)$row['storage_id'],
+ (int)$row['root_id'],
+ $row['mount_point'],
+ $row['mount_provider_class'] ?? '',
+ $mount_id,
+ isset($row['path']) ? $row['path'] : '',
+ );
}
/**
@@ -229,7 +240,7 @@ 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', 'f.path')
+ $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path', 'mount_provider_class')
->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())));
@@ -250,7 +261,7 @@ class UserMountCache implements IUserMountCache {
*/
public function getMountsForStorageId($numericStorageId, $user = null) {
$builder = $this->connection->getQueryBuilder();
- $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path')
+ $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path', 'mount_provider_class')
->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)));
@@ -272,7 +283,7 @@ 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', 'f.path')
+ $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path', 'mount_provider_class')
->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)));
@@ -286,10 +297,10 @@ class UserMountCache implements IUserMountCache {
/**
* @param $fileId
- * @return array
+ * @return array{int, string, int}
* @throws \OCP\Files\NotFoundException
*/
- private function getCacheInfoFromFileId($fileId) {
+ private function getCacheInfoFromFileId($fileId): array {
if (!isset($this->cacheInfoCache[$fileId])) {
$builder = $this->connection->getQueryBuilder();
$query = $builder->select('storage', 'path', 'mimetype')
@@ -303,7 +314,7 @@ class UserMountCache implements IUserMountCache {
if (is_array($row)) {
$this->cacheInfoCache[$fileId] = [
(int)$row['storage'],
- $row['path'],
+ (string)$row['path'],
(int)$row['mimetype']
];
} else {
@@ -326,7 +337,7 @@ class UserMountCache implements IUserMountCache {
return [];
}
$builder = $this->connection->getQueryBuilder();
- $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path')
+ $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path', 'mount_provider_class')
->from('mounts', 'm')
->innerJoin('m', 'filecache', 'f', $builder->expr()->eq('m.root_id', 'f.fileid'))
->where($builder->expr()->eq('storage_id', $builder->createPositionalParameter($storageId, IQueryBuilder::PARAM_INT)));
@@ -343,7 +354,7 @@ class UserMountCache implements IUserMountCache {
if ($fileId === (int)$row['root_id']) {
return true;
}
- $internalMountPath = isset($row['path']) ? $row['path'] : '';
+ $internalMountPath = $row['path'] ?? '';
return $internalMountPath === '' || substr($internalPath, 0, strlen($internalMountPath) + 1) === $internalMountPath . '/';
});
@@ -356,6 +367,7 @@ class UserMountCache implements IUserMountCache {
$mount->getRootId(),
$mount->getMountPoint(),
$mount->getMountId(),
+ $mount->getMountProvider(),
$mount->getRootInternalPath(),
$internalPath
);
diff --git a/lib/private/Files/Filesystem.php b/lib/private/Files/Filesystem.php
index e439b746bf6..9db9252037f 100644
--- a/lib/private/Files/Filesystem.php
+++ b/lib/private/Files/Filesystem.php
@@ -38,13 +38,12 @@
namespace OC\Files;
use OC\Cache\CappedMemoryCache;
-use OC\Files\Config\MountProviderCollection;
use OC\Files\Mount\MountPoint;
-use OC\Lockdown\Filesystem\NullStorage;
-use OCP\Files\Config\IMountProvider;
+use OC\User\NoUserException;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\Files\Events\Node\FilesystemTornDownEvent;
use OCP\Files\NotFoundException;
use OCP\Files\Storage\IStorageFactory;
-use OCP\ILogger;
use OCP\IUser;
use OCP\IUserManager;
@@ -67,6 +66,9 @@ class Filesystem {
private static $listeningForProviders = false;
+ /** @var string[]|null */
+ private static $blacklist = null;
+
/**
* classname which used for hooks handling
* used as signalclass in OC_Hooks::emit()
@@ -259,11 +261,7 @@ class Filesystem {
\OC_Util::setupFS();
}
$mount = self::$mounts->find($path);
- if ($mount) {
- return $mount->getMountPoint();
- } else {
- return '';
- }
+ return $mount->getMountPoint();
}
/**
@@ -319,11 +317,7 @@ class Filesystem {
*/
public static function resolvePath($path) {
$mount = self::getMountManager()->find($path);
- if ($mount) {
- return [$mount->getStorage(), rtrim($mount->getInternalPath($path), '/')];
- } else {
- return [null, null];
- }
+ return [$mount->getStorage(), rtrim($mount->getInternalPath($path), '/')];
}
public static function init($user, $root) {
@@ -332,6 +326,13 @@ class Filesystem {
}
self::getLoader();
self::$defaultInstance = new View($root);
+ /** @var IEventDispatcher $eventDispatcher */
+ $eventDispatcher = \OC::$server->get(IEventDispatcher::class);
+ $eventDispatcher->addListener(FilesystemTornDownEvent::class, function () {
+ self::$defaultInstance = null;
+ self::$usersSetup = [];
+ self::$loaded = false;
+ });
if (!self::$mounts) {
self::$mounts = \OC::$server->getMountManager();
@@ -358,106 +359,16 @@ class Filesystem {
* @throws \OC\User\NoUserException if the user is not available
*/
public static function initMountPoints($user = '') {
- $userManager = \OC::$server->getUserManager();
- if (is_string($user)) {
- if ($user === '') {
- $user = \OC_User::getUser();
- }
-
- $userObject = $userManager->get($user);
- } elseif ($user instanceof IUser) {
- $userObject = $user;
- $user = $userObject->getUID();
+ /** @var IUserManager $userManager */
+ $userManager = \OC::$server->get(IUserManager::class);
+
+ $userObject = ($user instanceof IUser) ? $user : $userManager->get($user);
+ if ($userObject) {
+ /** @var SetupManager $setupManager */
+ $setupManager = \OC::$server->get(SetupManager::class);
+ $setupManager->setupForUser($userObject);
} else {
- $userObject = null;
- }
-
- if ($userObject === null || $user === false || $user === '') {
- throw new \OC\User\NoUserException('Attempted to initialize mount points for null user and no user in session');
- }
-
- if (isset(self::$usersSetup[$user])) {
- return;
- }
-
- self::$usersSetup[$user] = true;
-
- if (is_null($userObject)) {
- \OCP\Util::writeLog('files', ' Backends provided no user object for ' . $user, ILogger::ERROR);
- // reset flag, this will make it possible to rethrow the exception if called again
- unset(self::$usersSetup[$user]);
- throw new \OC\User\NoUserException('Backends provided no user object for ' . $user);
- }
-
- $realUid = $userObject->getUID();
- // workaround in case of different casings
- if ($user !== $realUid) {
- $stack = json_encode(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 50));
- \OCP\Util::writeLog('files', 'initMountPoints() called with wrong user casing. This could be a bug. Expected: "' . $realUid . '" got "' . $user . '". Stack: ' . $stack, ILogger::WARN);
- $user = $realUid;
-
- // again with the correct casing
- if (isset(self::$usersSetup[$user])) {
- return;
- }
-
- self::$usersSetup[$user] = true;
- }
-
- if (\OC::$server->getLockdownManager()->canAccessFilesystem()) {
- /** @var \OC\Files\Config\MountProviderCollection $mountConfigManager */
- $mountConfigManager = \OC::$server->getMountProviderCollection();
-
- // home mounts are handled seperate since we need to ensure this is mounted before we call the other mount providers
- $homeMount = $mountConfigManager->getHomeMountForUser($userObject);
- self::getMountManager()->addMount($homeMount);
-
- if ($homeMount->getStorageRootId() === -1) {
- $homeMount->getStorage()->mkdir('');
- $homeMount->getStorage()->getScanner()->scan('');
- }
-
- \OC\Files\Filesystem::getStorage($user);
-
- // Chance to mount for other storages
- if ($userObject) {
- $mounts = $mountConfigManager->addMountForUser($userObject, self::getMountManager());
- $mounts[] = $homeMount;
- $mountConfigManager->registerMounts($userObject, $mounts);
- }
-
- self::listenForNewMountProviders($mountConfigManager, $userManager);
- } else {
- self::getMountManager()->addMount(new MountPoint(
- new NullStorage([]),
- '/' . $user
- ));
- self::getMountManager()->addMount(new MountPoint(
- new NullStorage([]),
- '/' . $user . '/files'
- ));
- }
- \OC_Hook::emit('OC_Filesystem', 'post_initMountPoints', ['user' => $user]);
- }
-
- /**
- * Get mounts from mount providers that are registered after setup
- *
- * @param MountProviderCollection $mountConfigManager
- * @param IUserManager $userManager
- */
- private static function listenForNewMountProviders(MountProviderCollection $mountConfigManager, IUserManager $userManager) {
- if (!self::$listeningForProviders) {
- self::$listeningForProviders = true;
- $mountConfigManager->listen('\OC\Files\Config', 'registerMountProvider', function (IMountProvider $provider) use ($userManager) {
- foreach (Filesystem::$usersSetup as $user => $setup) {
- $userObject = $userManager->get($user);
- if ($userObject) {
- $mounts = $provider->getMountsForUser($userObject, Filesystem::getLoader());
- array_walk($mounts, [self::$mounts, 'addMount']);
- }
- }
- });
+ throw new NoUserException();
}
}
@@ -474,8 +385,7 @@ class Filesystem {
* tear down the filesystem, removing all storage providers
*/
public static function tearDown() {
- self::clearMounts();
- self::$defaultInstance = null;
+ \OC_Util::tearDownFS();
}
/**
@@ -493,16 +403,6 @@ class Filesystem {
}
/**
- * clear all mounts and storage backends
- */
- public static function clearMounts() {
- if (self::$mounts) {
- self::$usersSetup = [];
- self::$mounts->clear();
- }
- }
-
- /**
* mount an \OC\Files\Storage\Storage in our virtual filesystem
*
* @param \OC\Files\Storage\Storage|string $class
@@ -595,9 +495,12 @@ class Filesystem {
public static function isFileBlacklisted($filename) {
$filename = self::normalizePath($filename);
- $blacklist = \OC::$server->getConfig()->getSystemValue('blacklisted_files', ['.htaccess']);
+ if (self::$blacklist === null) {
+ self::$blacklist = \OC::$server->getConfig()->getSystemValue('blacklisted_files', ['.htaccess']);
+ }
+
$filename = strtolower(basename($filename));
- return in_array($filename, $blacklist);
+ return in_array($filename, self::$blacklist);
}
/**
diff --git a/lib/private/Files/Mount/CacheMountProvider.php b/lib/private/Files/Mount/CacheMountProvider.php
index 16ecefb0dac..90dfa0b05f3 100644
--- a/lib/private/Files/Mount/CacheMountProvider.php
+++ b/lib/private/Files/Mount/CacheMountProvider.php
@@ -61,8 +61,8 @@ class CacheMountProvider implements IMountProvider {
}
return [
- new MountPoint('\OC\Files\Storage\Local', '/' . $user->getUID() . '/cache', ['datadir' => $cacheDir, $loader]),
- new MountPoint('\OC\Files\Storage\Local', '/' . $user->getUID() . '/uploads', ['datadir' => $cacheDir . '/uploads', $loader])
+ new MountPoint('\OC\Files\Storage\Local', '/' . $user->getUID() . '/cache', ['datadir' => $cacheDir], $loader, null, null, self::class),
+ new MountPoint('\OC\Files\Storage\Local', '/' . $user->getUID() . '/uploads', ['datadir' => $cacheDir . '/uploads'], $loader, null, null, self::class)
];
} else {
return [];
diff --git a/lib/private/Files/Mount/LocalHomeMountProvider.php b/lib/private/Files/Mount/LocalHomeMountProvider.php
index c7b2296c4a8..25a67fc1574 100644
--- a/lib/private/Files/Mount/LocalHomeMountProvider.php
+++ b/lib/private/Files/Mount/LocalHomeMountProvider.php
@@ -38,6 +38,6 @@ class LocalHomeMountProvider implements IHomeMountProvider {
*/
public function getHomeMountForUser(IUser $user, IStorageFactory $loader) {
$arguments = ['user' => $user];
- return new MountPoint('\OC\Files\Storage\Home', '/' . $user->getUID(), $arguments, $loader);
+ return new MountPoint('\OC\Files\Storage\Home', '/' . $user->getUID(), $arguments, $loader, null, null, self::class);
}
}
diff --git a/lib/private/Files/Mount/Manager.php b/lib/private/Files/Mount/Manager.php
index 8c6f1acceec..66832690363 100644
--- a/lib/private/Files/Mount/Manager.php
+++ b/lib/private/Files/Mount/Manager.php
@@ -26,26 +26,30 @@ declare(strict_types=1);
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
+
namespace OC\Files\Mount;
use OC\Cache\CappedMemoryCache;
use OC\Files\Filesystem;
+use OC\Files\SetupManager;
+use OC\Files\SetupManagerFactory;
use OCP\Files\Mount\IMountManager;
use OCP\Files\Mount\IMountPoint;
+use OCP\Files\NotFoundException;
class Manager implements IMountManager {
/** @var MountPoint[] */
- private $mounts = [];
-
- /** @var CappedMemoryCache */
- private $pathCache;
-
- /** @var CappedMemoryCache */
- private $inPathCache;
-
- public function __construct() {
+ private array $mounts = [];
+ /** @var CappedMemoryCache<IMountPoint> */
+ private CappedMemoryCache $pathCache;
+ /** @var CappedMemoryCache<IMountPoint[]> */
+ private CappedMemoryCache $inPathCache;
+ private SetupManager $setupManager;
+
+ public function __construct(SetupManagerFactory $setupManagerFactory) {
$this->pathCache = new CappedMemoryCache();
$this->inPathCache = new CappedMemoryCache();
+ $this->setupManager = $setupManagerFactory->create($this);
}
/**
@@ -81,23 +85,14 @@ class Manager implements IMountManager {
$this->inPathCache->clear();
}
- private function setupForFind(string $path) {
- if (strpos($path, '/appdata_' . \OC_Util::getInstanceId()) === 0) {
- // for appdata, we only setup the root bits, not the user bits
- \OC_Util::setupRootFS();
- } else {
- \OC_Util::setupFS();
- }
- }
-
/**
* Find the mount for $path
*
* @param string $path
- * @return MountPoint|null
+ * @return IMountPoint
*/
- public function find(string $path) {
- $this->setupForFind($path);
+ public function find(string $path): IMountPoint {
+ $this->setupManager->setupForPath($path);
$path = Filesystem::normalizePath($path);
if (isset($this->pathCache[$path])) {
@@ -110,10 +105,8 @@ class Manager implements IMountManager {
if (isset($this->mounts[$mountPoint])) {
$this->pathCache[$path] = $this->mounts[$mountPoint];
return $this->mounts[$mountPoint];
- }
-
- if ($current === '') {
- return null;
+ } elseif ($current === '') {
+ break;
}
$current = dirname($current);
@@ -121,16 +114,18 @@ class Manager implements IMountManager {
$current = '';
}
}
+
+ throw new NotFoundException("No mount for path " . $path . " existing mounts: " . implode(",", array_keys($this->mounts)));
}
/**
* Find all mounts in $path
*
* @param string $path
- * @return MountPoint[]
+ * @return IMountPoint[]
*/
public function findIn(string $path): array {
- $this->setupForFind($path);
+ $this->setupManager->setupForPath($path);
$path = $this->formatPath($path);
if (isset($this->inPathCache[$path])) {
@@ -160,7 +155,7 @@ class Manager implements IMountManager {
* Find mounts by storage id
*
* @param string $id
- * @return MountPoint[]
+ * @return IMountPoint[]
*/
public function findByStorageId(string $id): array {
\OC_Util::setupFS();
@@ -177,7 +172,7 @@ class Manager implements IMountManager {
}
/**
- * @return MountPoint[]
+ * @return IMountPoint[]
*/
public function getAll(): array {
return $this->mounts;
@@ -187,7 +182,7 @@ class Manager implements IMountManager {
* Find mounts by numeric storage id
*
* @param int $id
- * @return MountPoint[]
+ * @return IMountPoint[]
*/
public function findByNumericId(int $id): array {
$storageId = \OC\Files\Cache\Storage::getStorageId($id);
@@ -205,4 +200,8 @@ class Manager implements IMountManager {
}
return $path;
}
+
+ public function getSetupManager(): SetupManager {
+ return $this->setupManager;
+ }
}
diff --git a/lib/private/Files/Mount/MountPoint.php b/lib/private/Files/Mount/MountPoint.php
index 368be0a917e..d598355dbae 100644
--- a/lib/private/Files/Mount/MountPoint.php
+++ b/lib/private/Files/Mount/MountPoint.php
@@ -34,6 +34,7 @@ use OC\Files\Filesystem;
use OC\Files\Storage\Storage;
use OC\Files\Storage\StorageFactory;
use OCP\Files\Mount\IMountPoint;
+use OCP\Files\Storage\IStorageFactory;
use OCP\ILogger;
class MountPoint implements IMountPoint {
@@ -76,6 +77,9 @@ class MountPoint implements IMountPoint {
/** @var int|null */
protected $mountId;
+ /** @var string */
+ protected $mountProvider;
+
/**
* @param string|\OC\Files\Storage\Storage $storage
* @param string $mountpoint
@@ -83,9 +87,18 @@ class MountPoint implements IMountPoint {
* @param \OCP\Files\Storage\IStorageFactory $loader
* @param array $mountOptions mount specific options
* @param int|null $mountId
+ * @param string|null $mountProvider
* @throws \Exception
*/
- public function __construct($storage, $mountpoint, $arguments = null, $loader = null, $mountOptions = null, $mountId = null) {
+ public function __construct(
+ $storage,
+ string $mountpoint,
+ array $arguments = null,
+ IStorageFactory $loader = null,
+ array $mountOptions = null,
+ int $mountId = null,
+ string $mountProvider = null
+ ) {
if (is_null($arguments)) {
$arguments = [];
}
@@ -113,6 +126,12 @@ class MountPoint implements IMountPoint {
$this->class = $storage;
$this->arguments = $arguments;
}
+ if ($mountProvider) {
+ if (strlen($mountProvider) > 128) {
+ throw new \Exception("Mount provider $mountProvider name exceeds the limit of 128 characters");
+ }
+ }
+ $this->mountProvider = $mountProvider ?? '';
}
/**
@@ -286,4 +305,8 @@ class MountPoint implements IMountPoint {
public function getMountType() {
return '';
}
+
+ public function getMountProvider(): string {
+ return $this->mountProvider;
+ }
}
diff --git a/lib/private/Files/Mount/ObjectHomeMountProvider.php b/lib/private/Files/Mount/ObjectHomeMountProvider.php
index 972d3893e66..6a8a7d1f2fb 100644
--- a/lib/private/Files/Mount/ObjectHomeMountProvider.php
+++ b/lib/private/Files/Mount/ObjectHomeMountProvider.php
@@ -65,7 +65,7 @@ class ObjectHomeMountProvider implements IHomeMountProvider {
return null;
}
- return new MountPoint('\OC\Files\ObjectStore\HomeObjectStoreStorage', '/' . $user->getUID(), $config['arguments'], $loader);
+ return new MountPoint('\OC\Files\ObjectStore\HomeObjectStoreStorage', '/' . $user->getUID(), $config['arguments'], $loader, null, null, self::class);
}
/**
diff --git a/lib/private/Files/Mount/ObjectStorePreviewCacheMountProvider.php b/lib/private/Files/Mount/ObjectStorePreviewCacheMountProvider.php
index 2830e37ded3..0043503f2cd 100644
--- a/lib/private/Files/Mount/ObjectStorePreviewCacheMountProvider.php
+++ b/lib/private/Files/Mount/ObjectStorePreviewCacheMountProvider.php
@@ -69,7 +69,10 @@ class ObjectStorePreviewCacheMountProvider implements IRootMountProvider {
AppdataPreviewObjectStoreStorage::class,
'/appdata_' . $instanceId . '/preview/' . $parent . '/' . $child,
$this->getMultiBucketObjectStore($i),
- $loader
+ $loader,
+ null,
+ null,
+ self::class
);
$i++;
}
@@ -87,7 +90,10 @@ class ObjectStorePreviewCacheMountProvider implements IRootMountProvider {
$fakeRootStorageJail,
'/appdata_' . $instanceId . '/preview/old-multibucket',
null,
- $loader
+ $loader,
+ null,
+ null,
+ self::class
);
return $mountPoints;
diff --git a/lib/private/Files/Mount/RootMountProvider.php b/lib/private/Files/Mount/RootMountProvider.php
new file mode 100644
index 00000000000..b301fc6dd14
--- /dev/null
+++ b/lib/private/Files/Mount/RootMountProvider.php
@@ -0,0 +1,103 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2022 Robin Appelman <robin@icewind.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\Files\Mount;
+
+use OC;
+use OC\Files\ObjectStore\ObjectStoreStorage;
+use OC\Files\Storage\LocalRootStorage;
+use OC_App;
+use OCP\Files\Config\IRootMountProvider;
+use OCP\Files\Storage\IStorageFactory;
+use OCP\IConfig;
+use Psr\Log\LoggerInterface;
+
+class RootMountProvider implements IRootMountProvider {
+ private IConfig $config;
+ private LoggerInterface $logger;
+
+ public function __construct(IConfig $config, LoggerInterface $logger) {
+ $this->config = $config;
+ $this->logger = $logger;
+ }
+
+ public function getRootMounts(IStorageFactory $loader): array {
+ $objectStore = $this->config->getSystemValue('objectstore', null);
+ $objectStoreMultiBucket = $this->config->getSystemValue('objectstore_multibucket', null);
+
+ if ($objectStoreMultiBucket) {
+ return [$this->getMultiBucketStoreRootMount($loader, $objectStoreMultiBucket)];
+ } elseif ($objectStore) {
+ return [$this->getObjectStoreRootMount($loader, $objectStore)];
+ } else {
+ return [$this->getLocalRootMount($loader)];
+ }
+ }
+
+ private function validateObjectStoreConfig(array &$config) {
+ if (empty($config['class'])) {
+ $this->logger->error('No class given for objectstore', ['app' => 'files']);
+ }
+ if (!isset($config['arguments'])) {
+ $config['arguments'] = [];
+ }
+
+ // instantiate object store implementation
+ $name = $config['class'];
+ if (strpos($name, 'OCA\\') === 0 && substr_count($name, '\\') >= 2) {
+ $segments = explode('\\', $name);
+ OC_App::loadApp(strtolower($segments[1]));
+ }
+ }
+
+ private function getLocalRootMount(IStorageFactory $loader): MountPoint {
+ $configDataDirectory = $this->config->getSystemValue("datadirectory", OC::$SERVERROOT . "/data");
+ return new MountPoint(LocalRootStorage::class, '/', ['datadir' => $configDataDirectory], $loader, null, null, self::class);
+ }
+
+ private function getObjectStoreRootMount(IStorageFactory $loader, array $config): MountPoint {
+ $this->validateObjectStoreConfig($config);
+
+ $config['arguments']['objectstore'] = new $config['class']($config['arguments']);
+ // mount with plain / root object store implementation
+ $config['class'] = ObjectStoreStorage::class;
+
+ return new MountPoint($config['class'], '/', $config['arguments'], $loader, null, null, self::class);
+ }
+
+ private function getMultiBucketStoreRootMount(IStorageFactory $loader, array $config): MountPoint {
+ $this->validateObjectStoreConfig($config);
+
+ if (!isset($config['arguments']['bucket'])) {
+ $config['arguments']['bucket'] = '';
+ }
+ // put the root FS always in first bucket for multibucket configuration
+ $config['arguments']['bucket'] .= '0';
+
+ $config['arguments']['objectstore'] = new $config['class']($config['arguments']);
+ // mount with plain / root object store implementation
+ $config['class'] = ObjectStoreStorage::class;
+
+ return new MountPoint($config['class'], '/', $config['arguments'], $loader, null, null, self::class);
+ }
+}
diff --git a/lib/private/Files/Node/LazyFolder.php b/lib/private/Files/Node/LazyFolder.php
index 55421257886..bfdaeeccff7 100644
--- a/lib/private/Files/Node/LazyFolder.php
+++ b/lib/private/Files/Node/LazyFolder.php
@@ -38,7 +38,7 @@ class LazyFolder implements \OCP\Files\Folder {
private $folderClosure;
/** @var LazyFolder | null */
- private $folder = null;
+ protected $folder = null;
/**
* LazyFolder constructor.
diff --git a/lib/private/Files/Node/Root.php b/lib/private/Files/Node/Root.php
index 4a86207f25a..88ac4a31d34 100644
--- a/lib/private/Files/Node/Root.php
+++ b/lib/private/Files/Node/Root.php
@@ -29,18 +29,23 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
+
namespace OC\Files\Node;
use OC\Cache\CappedMemoryCache;
use OC\Files\Mount\Manager;
use OC\Files\Mount\MountPoint;
+use OC\Files\View;
use OC\Hooks\PublicEmitter;
use OC\User\NoUserException;
+use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Config\IUserMountCache;
+use OCP\Files\Events\Node\FilesystemTornDownEvent;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\ILogger;
+use OCP\IUser;
use OCP\IUserManager;
/**
@@ -63,35 +68,32 @@ use OCP\IUserManager;
* @package OC\Files\Node
*/
class Root extends Folder implements IRootFolder {
- /** @var Manager */
- private $mountManager;
- /** @var PublicEmitter */
- private $emitter;
- /** @var null|\OC\User\User */
- private $user;
- /** @var CappedMemoryCache */
- private $userFolderCache;
- /** @var IUserMountCache */
- private $userMountCache;
- /** @var ILogger */
- private $logger;
- /** @var IUserManager */
- private $userManager;
+ private Manager $mountManager;
+ private PublicEmitter $emitter;
+ private ?IUser $user;
+ private CappedMemoryCache $userFolderCache;
+ private IUserMountCache $userMountCache;
+ private ILogger $logger;
+ private IUserManager $userManager;
+ private IEventDispatcher $eventDispatcher;
/**
- * @param \OC\Files\Mount\Manager $manager
- * @param \OC\Files\View $view
- * @param \OC\User\User|null $user
+ * @param Manager $manager
+ * @param View $view
+ * @param IUser|null $user
* @param IUserMountCache $userMountCache
* @param ILogger $logger
* @param IUserManager $userManager
*/
- public function __construct($manager,
- $view,
- $user,
- IUserMountCache $userMountCache,
- ILogger $logger,
- IUserManager $userManager) {
+ public function __construct(
+ $manager,
+ $view,
+ $user,
+ IUserMountCache $userMountCache,
+ ILogger $logger,
+ IUserManager $userManager,
+ IEventDispatcher $eventDispatcher
+ ) {
parent::__construct($this, $view, '');
$this->mountManager = $manager;
$this->user = $user;
@@ -100,6 +102,9 @@ class Root extends Folder implements IRootFolder {
$this->userMountCache = $userMountCache;
$this->logger = $logger;
$this->userManager = $userManager;
+ $eventDispatcher->addListener(FilesystemTornDownEvent::class, function () {
+ $this->userFolderCache = new CappedMemoryCache();
+ });
}
/**
@@ -189,9 +194,9 @@ class Root extends Folder implements IRootFolder {
/**
* @param string $path
- * @throws \OCP\Files\NotFoundException
- * @throws \OCP\Files\NotPermittedException
* @return Node
+ * @throws \OCP\Files\NotPermittedException
+ * @throws \OCP\Files\NotFoundException
*/
public function get($path) {
$path = $this->normalizePath($path);
@@ -212,8 +217,8 @@ class Root extends Folder implements IRootFolder {
/**
* @param string $targetPath
- * @throws \OCP\Files\NotPermittedException
* @return \OC\Files\Node\Node
+ * @throws \OCP\Files\NotPermittedException
*/
public function rename($targetPath) {
throw new NotPermittedException();
@@ -225,8 +230,8 @@ class Root extends Folder implements IRootFolder {
/**
* @param string $targetPath
- * @throws \OCP\Files\NotPermittedException
* @return \OC\Files\Node\Node
+ * @throws \OCP\Files\NotPermittedException
*/
public function copy($targetPath) {
throw new NotPermittedException();
@@ -266,21 +271,21 @@ class Root extends Folder implements IRootFolder {
* @return int
*/
public function getId() {
- return null;
+ return 0;
}
/**
* @return array
*/
public function stat() {
- return null;
+ return [];
}
/**
* @return int
*/
public function getMTime() {
- return null;
+ return 0;
}
/**
@@ -288,14 +293,14 @@ class Root extends Folder implements IRootFolder {
* @return int
*/
public function getSize($includeMounts = true) {
- return null;
+ return 0;
}
/**
* @return string
*/
public function getEtag() {
- return null;
+ return '';
}
/**
@@ -392,10 +397,6 @@ class Root extends Folder implements IRootFolder {
return $this->userFolderCache->get($userId);
}
- public function clearCache() {
- $this->userFolderCache = new CappedMemoryCache();
- }
-
public function getUserMountCache() {
return $this->userMountCache;
}
diff --git a/lib/private/Files/ObjectStore/S3.php b/lib/private/Files/ObjectStore/S3.php
index 074f3a1df91..6492145fb63 100644
--- a/lib/private/Files/ObjectStore/S3.php
+++ b/lib/private/Files/ObjectStore/S3.php
@@ -30,6 +30,7 @@ class S3 implements IObjectStore {
use S3ObjectTrait;
public function __construct($parameters) {
+ $parameters['primary_storage'] = true;
$this->parseParams($parameters);
}
diff --git a/lib/private/Files/ObjectStore/S3ConnectionTrait.php b/lib/private/Files/ObjectStore/S3ConnectionTrait.php
index b72b0ebee53..d6f42c455b4 100644
--- a/lib/private/Files/ObjectStore/S3ConnectionTrait.php
+++ b/lib/private/Files/ObjectStore/S3ConnectionTrait.php
@@ -38,6 +38,7 @@ use Aws\S3\Exception\S3Exception;
use Aws\S3\S3Client;
use GuzzleHttp\Promise;
use GuzzleHttp\Promise\RejectedPromise;
+use OCP\ICertificateManager;
use OCP\ILogger;
trait S3ConnectionTrait {
@@ -120,6 +121,15 @@ trait S3ConnectionTrait {
)
);
+ // since we store the certificate bundles on the primary storage, we can't get the bundle while setting up the primary storage
+ if (!isset($this->params['primary_storage'])) {
+ /** @var ICertificateManager $certManager */
+ $certManager = \OC::$server->get(ICertificateManager::class);
+ $certPath = $certManager->getAbsoluteBundlePath();
+ } else {
+ $certPath = \OC::$SERVERROOT . '/resources/config/ca-bundle.crt';
+ }
+
$options = [
'version' => isset($this->params['version']) ? $this->params['version'] : 'latest',
'credentials' => $provider,
@@ -129,9 +139,10 @@ trait S3ConnectionTrait {
'signature_provider' => \Aws\or_chain([self::class, 'legacySignatureProvider'], ClientResolver::_default_signature_provider()),
'csm' => false,
'use_arn_region' => false,
+ 'http' => ['verify' => $certPath],
];
if ($this->getProxy()) {
- $options['http'] = [ 'proxy' => $this->getProxy() ];
+ $options['http']['proxy'] = $this->getProxy();
}
if (isset($this->params['legacy_auth']) && $this->params['legacy_auth']) {
$options['signature_version'] = 'v2';
diff --git a/lib/private/Files/ObjectStore/S3ObjectTrait.php b/lib/private/Files/ObjectStore/S3ObjectTrait.php
index 769901acc79..4e54a26e98a 100644
--- a/lib/private/Files/ObjectStore/S3ObjectTrait.php
+++ b/lib/private/Files/ObjectStore/S3ObjectTrait.php
@@ -126,7 +126,7 @@ trait S3ObjectTrait {
if ($e->getState()->isInitiated() && (array_key_exists('UploadId', $uploadInfo))) {
$this->getConnection()->abortMultipartUpload($uploadInfo);
}
- throw $e;
+ throw new \OCA\DAV\Connector\Sabre\Exception\BadGateway("Error while uploading to S3 bucket", 0, $e);
}
}
diff --git a/lib/private/Files/SetupManager.php b/lib/private/Files/SetupManager.php
new file mode 100644
index 00000000000..9726fbef428
--- /dev/null
+++ b/lib/private/Files/SetupManager.php
@@ -0,0 +1,294 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2022 Robin Appelman <robin@icewind.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\Files;
+
+use OC\Files\Config\MountProviderCollection;
+use OC\Files\Mount\MountPoint;
+use OC\Files\ObjectStore\HomeObjectStoreStorage;
+use OC\Files\Storage\Common;
+use OC\Files\Storage\Home;
+use OC\Files\Storage\Storage;
+use OC\Files\Storage\Wrapper\Availability;
+use OC\Files\Storage\Wrapper\Encoding;
+use OC\Files\Storage\Wrapper\PermissionsMask;
+use OC\Files\Storage\Wrapper\Quota;
+use OC\Lockdown\Filesystem\NullStorage;
+use OC_App;
+use OC_Hook;
+use OC_Util;
+use OCP\Constants;
+use OCP\Diagnostics\IEventLogger;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\Files\Config\IMountProvider;
+use OCP\Files\Config\IUserMountCache;
+use OCP\Files\Events\Node\FilesystemTornDownEvent;
+use OCP\Files\Mount\IMountManager;
+use OCP\Files\Mount\IMountPoint;
+use OCP\Files\Storage\IStorage;
+use OCP\IUser;
+use OCP\IUserManager;
+use OCP\IUserSession;
+use OCP\Lockdown\ILockdownManager;
+
+class SetupManager {
+ private bool $rootSetup = false;
+ private IEventLogger $eventLogger;
+ private MountProviderCollection $mountProviderCollection;
+ private IMountManager $mountManager;
+ private IUserManager $userManager;
+ private array $setupUsers = [];
+ private IEventDispatcher $eventDispatcher;
+ private IUserMountCache $userMountCache;
+ private ILockdownManager $lockdownManager;
+ private IUserSession $userSession;
+ private bool $listeningForProviders;
+
+ public function __construct(
+ IEventLogger $eventLogger,
+ MountProviderCollection $mountProviderCollection,
+ IMountManager $mountManager,
+ IUserManager $userManager,
+ IEventDispatcher $eventDispatcher,
+ IUserMountCache $userMountCache,
+ ILockdownManager $lockdownManager,
+ IUserSession $userSession
+ ) {
+ $this->eventLogger = $eventLogger;
+ $this->mountProviderCollection = $mountProviderCollection;
+ $this->mountManager = $mountManager;
+ $this->userManager = $userManager;
+ $this->eventDispatcher = $eventDispatcher;
+ $this->userMountCache = $userMountCache;
+ $this->lockdownManager = $lockdownManager;
+ $this->userSession = $userSession;
+ $this->listeningForProviders = false;
+ }
+
+ private function setupBuiltinWrappers() {
+ Filesystem::addStorageWrapper('mount_options', function ($mountPoint, IStorage $storage, IMountPoint $mount) {
+ if ($storage->instanceOfStorage(Common::class)) {
+ $storage->setMountOptions($mount->getOptions());
+ }
+ return $storage;
+ });
+
+ Filesystem::addStorageWrapper('enable_sharing', function ($mountPoint, IStorage $storage, IMountPoint $mount) {
+ if (!$mount->getOption('enable_sharing', true)) {
+ return new PermissionsMask([
+ 'storage' => $storage,
+ 'mask' => Constants::PERMISSION_ALL - Constants::PERMISSION_SHARE,
+ ]);
+ }
+ return $storage;
+ });
+
+ // install storage availability wrapper, before most other wrappers
+ Filesystem::addStorageWrapper('oc_availability', function ($mountPoint, IStorage $storage) {
+ if (!$storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage') && !$storage->isLocal()) {
+ return new Availability(['storage' => $storage]);
+ }
+ return $storage;
+ });
+
+ Filesystem::addStorageWrapper('oc_encoding', function ($mountPoint, IStorage $storage, IMountPoint $mount) {
+ if ($mount->getOption('encoding_compatibility', false) && !$storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage') && !$storage->isLocal()) {
+ return new Encoding(['storage' => $storage]);
+ }
+ return $storage;
+ });
+
+ Filesystem::addStorageWrapper('oc_quota', function ($mountPoint, $storage) {
+ // set up quota for home storages, even for other users
+ // which can happen when using sharing
+
+ /**
+ * @var Storage $storage
+ */
+ if ($storage->instanceOfStorage(HomeObjectStoreStorage::class) || $storage->instanceOfStorage(Home::class)) {
+ if (is_object($storage->getUser())) {
+ $quota = OC_Util::getUserQuota($storage->getUser());
+ if ($quota !== \OCP\Files\FileInfo::SPACE_UNLIMITED) {
+ return new Quota(['storage' => $storage, 'quota' => $quota, 'root' => 'files']);
+ }
+ }
+ }
+
+ return $storage;
+ });
+
+ Filesystem::addStorageWrapper('readonly', function ($mountPoint, IStorage $storage, IMountPoint $mount) {
+ /*
+ * Do not allow any operations that modify the storage
+ */
+ if ($mount->getOption('readonly', false)) {
+ return new PermissionsMask([
+ 'storage' => $storage,
+ 'mask' => Constants::PERMISSION_ALL & ~(
+ Constants::PERMISSION_UPDATE |
+ Constants::PERMISSION_CREATE |
+ Constants::PERMISSION_DELETE
+ ),
+ ]);
+ }
+ return $storage;
+ });
+ }
+
+ /**
+ * Setup the full filesystem for the specified user
+ */
+ public function setupForUser(IUser $user): void {
+ $this->setupRoot();
+
+ if (in_array($user->getUID(), $this->setupUsers, true)) {
+ return;
+ }
+ $this->setupUsers[] = $user->getUID();
+
+ $this->eventLogger->start('setup_fs', 'Setup filesystem');
+
+ $prevLogging = Filesystem::logWarningWhenAddingStorageWrapper(false);
+
+ OC_Hook::emit('OC_Filesystem', 'preSetup', ['user' => $user->getUID()]);
+
+ Filesystem::logWarningWhenAddingStorageWrapper($prevLogging);
+
+ $userDir = '/' . $user->getUID() . '/files';
+
+ Filesystem::init($user, $userDir);
+
+ if ($this->lockdownManager->canAccessFilesystem()) {
+ // home mounts are handled separate since we need to ensure this is mounted before we call the other mount providers
+ $homeMount = $this->mountProviderCollection->getHomeMountForUser($user);
+ $this->mountManager->addMount($homeMount);
+
+ if ($homeMount->getStorageRootId() === -1) {
+ $homeMount->getStorage()->mkdir('');
+ $homeMount->getStorage()->getScanner()->scan('');
+ }
+
+ // Chance to mount for other storages
+ $mounts = $this->mountProviderCollection->addMountForUser($user, $this->mountManager);
+ $mounts[] = $homeMount;
+ $this->userMountCache->registerMounts($user, $mounts);
+
+ $this->listenForNewMountProviders();
+ } else {
+ $this->mountManager->addMount(new MountPoint(
+ new NullStorage([]),
+ '/' . $user->getUID()
+ ));
+ $this->mountManager->addMount(new MountPoint(
+ new NullStorage([]),
+ '/' . $user->getUID() . '/files'
+ ));
+ }
+ \OC_Hook::emit('OC_Filesystem', 'post_initMountPoints', ['user' => $user->getUID()]);
+
+ OC_Hook::emit('OC_Filesystem', 'setup', ['user' => $user->getUID(), 'user_dir' => $userDir]);
+
+ $this->eventLogger->end('setup_fs');
+ }
+
+ /**
+ * Set up the root filesystem
+ */
+ public function setupRoot(): void {
+ //setting up the filesystem twice can only lead to trouble
+ if ($this->rootSetup) {
+ return;
+ }
+ $this->rootSetup = true;
+
+ $this->eventLogger->start('setup_root_fs', 'Setup root filesystem');
+
+ // load all filesystem apps before, so no setup-hook gets lost
+ OC_App::loadApps(['filesystem']);
+ $prevLogging = Filesystem::logWarningWhenAddingStorageWrapper(false);
+
+ $this->setupBuiltinWrappers();
+
+ Filesystem::logWarningWhenAddingStorageWrapper($prevLogging);
+
+ $rootMounts = $this->mountProviderCollection->getRootMounts();
+ foreach ($rootMounts as $rootMountProvider) {
+ $this->mountManager->addMount($rootMountProvider);
+ }
+
+ $this->eventLogger->end('setup_root_fs');
+ }
+
+ /**
+ * Set up the filesystem for the specified path
+ */
+ public function setupForPath(string $path): void {
+ if (substr_count($path, '/') < 2) {
+ if ($user = $this->userSession->getUser()) {
+ $this->setupForUser($user);
+ } else {
+ $this->setupRoot();
+ }
+ return;
+ } elseif (strpos($path, '/appdata_' . \OC_Util::getInstanceId()) === 0 || strpos($path, '/files_external/') === 0) {
+ $this->setupRoot();
+ return;
+ } else {
+ [, $userId] = explode('/', $path);
+ }
+
+ $user = $this->userManager->get($userId);
+
+ if (!$user) {
+ $this->setupRoot();
+ return;
+ }
+
+ $this->setupForUser($user);
+ }
+
+ public function tearDown() {
+ $this->setupUsers = [];
+ $this->rootSetup = false;
+ $this->mountManager->clear();
+ $this->eventDispatcher->dispatchTyped(new FilesystemTornDownEvent());
+ }
+
+ /**
+ * Get mounts from mount providers that are registered after setup
+ */
+ private function listenForNewMountProviders() {
+ if (!$this->listeningForProviders) {
+ $this->listeningForProviders = true;
+ $this->mountProviderCollection->listen('\OC\Files\Config', 'registerMountProvider', function (IMountProvider $provider) {
+ foreach ($this->setupUsers as $userId) {
+ $user = $this->userManager->get($userId);
+ if ($user) {
+ $mounts = $provider->getMountsForUser($user, Filesystem::getLoader());
+ array_walk($mounts, [$this->mountManager, 'addMount']);
+ }
+ }
+ });
+ }
+ }
+}
diff --git a/lib/private/Files/SetupManagerFactory.php b/lib/private/Files/SetupManagerFactory.php
new file mode 100644
index 00000000000..56e70d09961
--- /dev/null
+++ b/lib/private/Files/SetupManagerFactory.php
@@ -0,0 +1,79 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2022 Robin Appelman <robin@icewind.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\Files;
+
+use OCP\Diagnostics\IEventLogger;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\Files\Config\IMountProviderCollection;
+use OCP\Files\Config\IUserMountCache;
+use OCP\Files\Mount\IMountManager;
+use OCP\IUserManager;
+use OCP\IUserSession;
+use OCP\Lockdown\ILockdownManager;
+
+class SetupManagerFactory {
+ private IEventLogger $eventLogger;
+ private IMountProviderCollection $mountProviderCollection;
+ private IUserManager $userManager;
+ private IEventDispatcher $eventDispatcher;
+ private IUserMountCache $userMountCache;
+ private ILockdownManager $lockdownManager;
+ private IUserSession $userSession;
+ private ?SetupManager $setupManager;
+
+ public function __construct(
+ IEventLogger $eventLogger,
+ IMountProviderCollection $mountProviderCollection,
+ IUserManager $userManager,
+ IEventDispatcher $eventDispatcher,
+ IUserMountCache $userMountCache,
+ ILockdownManager $lockdownManager,
+ IUserSession $userSession
+ ) {
+ $this->eventLogger = $eventLogger;
+ $this->mountProviderCollection = $mountProviderCollection;
+ $this->userManager = $userManager;
+ $this->eventDispatcher = $eventDispatcher;
+ $this->userMountCache = $userMountCache;
+ $this->lockdownManager = $lockdownManager;
+ $this->userSession = $userSession;
+ $this->setupManager = null;
+ }
+
+ public function create(IMountManager $mountManager): SetupManager {
+ if (!$this->setupManager) {
+ $this->setupManager = new SetupManager(
+ $this->eventLogger,
+ $this->mountProviderCollection,
+ $mountManager,
+ $this->userManager,
+ $this->eventDispatcher,
+ $this->userMountCache,
+ $this->lockdownManager,
+ $this->userSession,
+ );
+ }
+ return $this->setupManager;
+ }
+}
diff --git a/lib/private/Files/SimpleFS/NewSimpleFile.php b/lib/private/Files/SimpleFS/NewSimpleFile.php
index f805403fd87..76fc69ebbe7 100644
--- a/lib/private/Files/SimpleFS/NewSimpleFile.php
+++ b/lib/private/Files/SimpleFS/NewSimpleFile.php
@@ -191,6 +191,17 @@ class NewSimpleFile implements ISimpleFile {
}
/**
+ * {@inheritDoc}
+ */
+ public function getExtension(): string {
+ if ($this->file) {
+ return $this->file->getExtension();
+ } else {
+ return \pathinfo($this->name, PATHINFO_EXTENSION);
+ }
+ }
+
+ /**
* Open the file as stream for reading, resulting resource can be operated as stream like the result from php's own fopen
*
* @return resource
diff --git a/lib/private/Files/SimpleFS/SimpleFile.php b/lib/private/Files/SimpleFS/SimpleFile.php
index baf9b24e020..21a2fd92dcb 100644
--- a/lib/private/Files/SimpleFS/SimpleFile.php
+++ b/lib/private/Files/SimpleFS/SimpleFile.php
@@ -159,6 +159,13 @@ class SimpleFile implements ISimpleFile {
}
/**
+ * {@inheritDoc}
+ */
+ public function getExtension(): string {
+ return $this->file->getExtension();
+ }
+
+ /**
* Open the file as stream for reading, resulting resource can be operated as stream like the result from php's own fopen
*
* @return resource
diff --git a/lib/private/Files/Storage/Common.php b/lib/private/Files/Storage/Common.php
index 7239c58a8a1..8e7e56e6ca2 100644
--- a/lib/private/Files/Storage/Common.php
+++ b/lib/private/Files/Storage/Common.php
@@ -52,6 +52,7 @@ use OC\Files\Storage\Wrapper\Jail;
use OC\Files\Storage\Wrapper\Wrapper;
use OCP\Files\EmptyFileNameException;
use OCP\Files\FileNameTooLongException;
+use OCP\Files\ForbiddenException;
use OCP\Files\GenericFileException;
use OCP\Files\InvalidCharacterInPathException;
use OCP\Files\InvalidDirectoryException;
@@ -702,6 +703,10 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage {
* @inheritdoc
*/
public function getMetaData($path) {
+ if (Filesystem::isFileBlacklisted($path)) {
+ throw new ForbiddenException('Invalid path: ' . $path, false);
+ }
+
$permissions = $this->getPermissions($path);
if (!$permissions & \OCP\Constants::PERMISSION_READ) {
//can't read, nothing we can do
@@ -880,7 +885,7 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage {
if (is_resource($dh)) {
$basePath = rtrim($directory, '/');
while (($file = readdir($dh)) !== false) {
- if (!Filesystem::isIgnoredDir($file) && !Filesystem::isFileBlacklisted($file)) {
+ if (!Filesystem::isIgnoredDir($file)) {
$childPath = $basePath . '/' . trim($file, '/');
$metadata = $this->getMetaData($childPath);
if ($metadata !== null) {
diff --git a/lib/private/Files/Storage/Local.php b/lib/private/Files/Storage/Local.php
index 6406beaeebc..34ab9a5fc97 100644
--- a/lib/private/Files/Storage/Local.php
+++ b/lib/private/Files/Storage/Local.php
@@ -47,7 +47,9 @@ use OC\Files\Storage\Wrapper\Jail;
use OCP\Constants;
use OCP\Files\ForbiddenException;
use OCP\Files\GenericFileException;
+use OCP\Files\IMimeTypeDetector;
use OCP\Files\Storage\IStorage;
+use OCP\IConfig;
use OCP\ILogger;
/**
@@ -60,6 +62,10 @@ class Local extends \OC\Files\Storage\Common {
protected $realDataDir;
+ private IConfig $config;
+
+ private IMimeTypeDetector $mimeTypeDetector;
+
public function __construct($arguments) {
if (!isset($arguments['datadir']) || !is_string($arguments['datadir'])) {
throw new \InvalidArgumentException('No data directory set for local storage');
@@ -76,6 +82,8 @@ class Local extends \OC\Files\Storage\Common {
$this->datadir .= '/';
}
$this->dataDirLength = strlen($this->realDataDir);
+ $this->config = \OC::$server->get(IConfig::class);
+ $this->mimeTypeDetector = \OC::$server->get(IMimeTypeDetector::class);
}
public function __destruct() {
@@ -155,6 +163,9 @@ class Local extends \OC\Files\Storage\Common {
$statResult['size'] = $filesize;
$statResult[7] = $filesize;
}
+ if (is_array($statResult)) {
+ $statResult['full_path'] = $fullPath;
+ }
return $statResult;
}
@@ -181,15 +192,14 @@ class Local extends \OC\Files\Storage\Common {
}
if (!($path === '' || $path === '/')) { // deletable depends on the parents unix permissions
- $fullPath = $this->getSourcePath($path);
- $parent = dirname($fullPath);
+ $parent = dirname($stat['full_path']);
if (is_writable($parent)) {
$permissions += Constants::PERMISSION_DELETE;
}
}
$data = [];
- $data['mimetype'] = $isDir ? 'httpd/unix-directory' : \OC::$server->getMimeTypeDetector()->detectPath($path);
+ $data['mimetype'] = $isDir ? 'httpd/unix-directory' : $this->mimeTypeDetector->detectPath($path);
$data['mtime'] = $stat['mtime'];
if ($data['mtime'] === false) {
$data['mtime'] = time();
@@ -450,7 +460,7 @@ class Local extends \OC\Files\Storage\Common {
$fullPath = $this->datadir . $path;
$currentPath = $path;
- $allowSymlinks = \OC::$server->getConfig()->getSystemValue('localstorage.allowsymlinks', false);
+ $allowSymlinks = $this->config->getSystemValue('localstorage.allowsymlinks', false);
if ($allowSymlinks || $currentPath === '') {
return $fullPath;
}
diff --git a/lib/private/Files/View.php b/lib/private/Files/View.php
index 3cdc6166840..779e0611591 100644
--- a/lib/private/Files/View.php
+++ b/lib/private/Files/View.php
@@ -274,7 +274,7 @@ class View {
/**
* remove mount point
*
- * @param \OC\Files\Mount\MoveableMount $mount
+ * @param IMountPoint $mount
* @param string $path relative to data/
* @return boolean
*/
@@ -719,7 +719,7 @@ class View {
$postFix = (substr($path, -1) === '/') ? '/' : '';
$absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path));
$mount = Filesystem::getMountManager()->find($absolutePath . $postFix);
- if ($mount and $mount->getInternalPath($absolutePath) === '') {
+ if ($mount->getInternalPath($absolutePath) === '') {
return $this->removeMount($mount, $absolutePath);
}
if ($this->is_dir($path)) {
@@ -1383,10 +1383,6 @@ class View {
$path = Filesystem::normalizePath($this->fakeRoot . '/' . $path);
$mount = Filesystem::getMountManager()->find($path);
- if (!$mount) {
- \OC::$server->getLogger()->warning('Mountpoint not found for path: ' . $path);
- return false;
- }
$storage = $mount->getStorage();
$internalPath = $mount->getInternalPath($path);
if ($storage) {
@@ -1488,7 +1484,7 @@ class View {
$rootEntry = $subCache->get('');
if (!$rootEntry) {
- $subScanner = $subStorage->getScanner('');
+ $subScanner = $subStorage->getScanner();
try {
$subScanner->scanFile('');
} catch (\OCP\Files\StorageNotAvailableException $e) {
@@ -1739,12 +1735,13 @@ class View {
$manager = Filesystem::getMountManager();
$mounts = $manager->findIn($this->fakeRoot);
$mounts[] = $manager->find($this->fakeRoot);
- // reverse the array so we start with the storage this view is in
+ $mounts = array_filter($mounts);
+ // 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);
- // put non shared mounts in front of the shared mount
- // this prevent unneeded recursion into shares
+ // put non-shared mounts in front of the shared mount
+ // this prevents unneeded recursion into shares
usort($mounts, function (IMountPoint $a, IMountPoint $b) {
return $a instanceof SharedMount && (!$b instanceof SharedMount) ? 1 : -1;
});
@@ -1915,14 +1912,10 @@ class View {
* @param string $absolutePath absolute path
* @param bool $useParentMount true to return parent mount instead of whatever
* is mounted directly on the given path, false otherwise
- * @return \OC\Files\Mount\MountPoint mount point for which to apply locks
+ * @return IMountPoint mount point for which to apply locks
*/
private function getMountForLock($absolutePath, $useParentMount = false) {
- $results = [];
$mount = Filesystem::getMountManager()->find($absolutePath);
- if (!$mount) {
- return $results;
- }
if ($useParentMount) {
// find out if something is mounted directly on the path
diff --git a/lib/private/Group/MetaData.php b/lib/private/Group/MetaData.php
index fb10caa86ea..a58d7e78bfc 100644
--- a/lib/private/Group/MetaData.php
+++ b/lib/private/Group/MetaData.php
@@ -30,6 +30,7 @@
namespace OC\Group;
use OC\Group\Manager as GroupManager;
+use OCP\IGroup;
use OCP\IGroupManager;
use OCP\IUserSession;
@@ -46,25 +47,23 @@ class MetaData {
protected $metaData = [];
/** @var GroupManager */
protected $groupManager;
- /** @var bool */
- protected $sorting = false;
+ /** @var int */
+ protected $sorting = self::SORT_NONE;
/** @var IUserSession */
protected $userSession;
/**
* @param string $user the uid of the current user
* @param bool $isAdmin whether the current users is an admin
- * @param IGroupManager $groupManager
- * @param IUserSession $userSession
*/
public function __construct(
- $user,
- $isAdmin,
+ string $user,
+ bool $isAdmin,
IGroupManager $groupManager,
IUserSession $userSession
) {
$this->user = $user;
- $this->isAdmin = (bool)$isAdmin;
+ $this->isAdmin = $isAdmin;
$this->groupManager = $groupManager;
$this->userSession = $userSession;
}
@@ -77,9 +76,8 @@ class MetaData {
* @param string $groupSearch only effective when instance was created with
* isAdmin being true
* @param string $userSearch the pattern users are search for
- * @return array
*/
- public function get($groupSearch = '', $userSearch = '') {
+ public function get(string $groupSearch = '', string $userSearch = ''): array {
$key = $groupSearch . '::' . $userSearch;
if (isset($this->metaData[$key])) {
return $this->metaData[$key];
@@ -122,10 +120,8 @@ class MetaData {
/**
* sets the sort mode, see SORT_* constants for supported modes
- *
- * @param int $sortMode
*/
- public function setSorting($sortMode) {
+ public function setSorting(int $sortMode): void {
switch ($sortMode) {
case self::SORT_USERCOUNT:
case self::SORT_GROUPNAME:
@@ -144,7 +140,7 @@ class MetaData {
* @param int $sortIndex the sort key index, by reference
* @param array $data the group's meta data as returned by generateGroupMetaData()
*/
- private function addEntry(&$entries, &$sortKeys, &$sortIndex, $data) {
+ private function addEntry(array &$entries, array &$sortKeys, int &$sortIndex, array $data): void {
$entries[] = $data;
if ($this->sorting === self::SORT_USERCOUNT) {
$sortKeys[$sortIndex] = $data['usercount'];
@@ -157,11 +153,9 @@ class MetaData {
/**
* creates an array containing the group meta data
- * @param \OCP\IGroup $group
- * @param string $userSearch
* @return array with the keys 'id', 'name', 'usercount' and 'disabled'
*/
- private function generateGroupMetaData(\OCP\IGroup $group, $userSearch) {
+ private function generateGroupMetaData(IGroup $group, string $userSearch): array {
return [
'id' => $group->getGID(),
'name' => $group->getDisplayName(),
@@ -176,9 +170,8 @@ class MetaData {
* sorts the result array, if applicable
* @param array $entries the result array, by reference
* @param array $sortKeys the array containing the sort keys
- * @param return null
*/
- private function sort(&$entries, $sortKeys) {
+ private function sort(array &$entries, array $sortKeys): void {
if ($this->sorting === self::SORT_USERCOUNT) {
array_multisort($sortKeys, SORT_DESC, $entries);
} elseif ($this->sorting === self::SORT_GROUPNAME) {
@@ -188,10 +181,9 @@ class MetaData {
/**
* returns the available groups
- * @param string $search a search string
- * @return \OCP\IGroup[]
+ * @return IGroup[]
*/
- public function getGroups($search = '') {
+ public function getGroups(string $search = ''): array {
if ($this->isAdmin) {
return $this->groupManager->search($search);
} else {
diff --git a/lib/private/Log.php b/lib/private/Log.php
index edbfdea7b9d..0415967f0f0 100644
--- a/lib/private/Log.php
+++ b/lib/private/Log.php
@@ -232,7 +232,7 @@ class Log implements ILogger, IDataLogger {
}
}
- private function getLogLevel($context) {
+ public function getLogLevel($context) {
$logCondition = $this->config->getValue('log.condition', []);
/**
@@ -308,7 +308,13 @@ class Log implements ILogger, IDataLogger {
$app = $context['app'] ?? 'no app in context';
$level = $context['level'] ?? ILogger::ERROR;
- $serializer = new ExceptionSerializer($this->config);
+ // if an error is raised before the autoloader is properly setup, we can't serialize exceptions
+ try {
+ $serializer = new ExceptionSerializer($this->config);
+ } catch (\Throwable $e) {
+ $this->error("Failed to load ExceptionSerializer serializer while trying to log " . $exception->getMessage());
+ return;
+ }
$data = $serializer->serializeException($exception);
$data['CustomMessage'] = $this->interpolateMessage($context, $context['message'] ?? '--');
diff --git a/lib/private/Preview/Bitmap.php b/lib/private/Preview/Bitmap.php
index 57451da5725..3a4108664dd 100644
--- a/lib/private/Preview/Bitmap.php
+++ b/lib/private/Preview/Bitmap.php
@@ -29,7 +29,7 @@ namespace OC\Preview;
use Imagick;
use OCP\Files\File;
use OCP\IImage;
-use OCP\ILogger;
+use Psr\Log\LoggerInterface;
/**
* Creates a PNG preview using ImageMagick via the PECL extension
@@ -43,16 +43,25 @@ abstract class Bitmap extends ProviderV2 {
*/
public function getThumbnail(File $file, int $maxX, int $maxY): ?IImage {
$tmpPath = $this->getLocalFile($file);
+ if ($tmpPath === false) {
+ \OC::$server->get(LoggerInterface::class)->error(
+ 'Failed to get thumbnail for: ' . $file->getPath(),
+ ['app' => 'core']
+ );
+ return null;
+ }
// Creates \Imagick object from bitmap or vector file
try {
$bp = $this->getResizedPreview($tmpPath, $maxX, $maxY);
} catch (\Exception $e) {
- \OC::$server->getLogger()->logException($e, [
- 'message' => 'File: ' . $file->getPath() . ' Imagick says:',
- 'level' => ILogger::ERROR,
- 'app' => 'core',
- ]);
+ \OC::$server->get(LoggerInterface::class)->error(
+ 'File: ' . $file->getPath() . ' Imagick says:',
+ [
+ 'exception' => $e,
+ 'app' => 'core',
+ ]
+ );
return null;
}
diff --git a/lib/private/Preview/Bundled.php b/lib/private/Preview/Bundled.php
index f026d3259f5..063c69ba5dd 100644
--- a/lib/private/Preview/Bundled.php
+++ b/lib/private/Preview/Bundled.php
@@ -30,9 +30,11 @@ use OCP\IImage;
* Extracts a preview from files that embed them in an ZIP archive
*/
abstract class Bundled extends ProviderV2 {
- protected function extractThumbnail(File $file, $path): ?IImage {
+ protected function extractThumbnail(File $file, string $path): ?IImage {
$sourceTmp = \OC::$server->getTempManager()->getTemporaryFile();
$targetTmp = \OC::$server->getTempManager()->getTemporaryFile();
+ $this->tmpFiles[] = $sourceTmp;
+ $this->tmpFiles[] = $targetTmp;
try {
$content = $file->fopen('r');
@@ -46,7 +48,7 @@ abstract class Bundled extends ProviderV2 {
$image->fixOrientation();
return $image;
- } catch (\Exception $e) {
+ } catch (\Throwable $e) {
return null;
}
}
diff --git a/lib/private/Preview/HEIC.php b/lib/private/Preview/HEIC.php
index 6601de238a9..7ce6b93ba3b 100644
--- a/lib/private/Preview/HEIC.php
+++ b/lib/private/Preview/HEIC.php
@@ -32,7 +32,7 @@ namespace OC\Preview;
use OCP\Files\File;
use OCP\Files\FileInfo;
use OCP\IImage;
-use OCP\ILogger;
+use Psr\Log\LoggerInterface;
/**
* Creates a JPG preview using ImageMagick via the PECL extension
@@ -63,17 +63,26 @@ class HEIC extends ProviderV2 {
}
$tmpPath = $this->getLocalFile($file);
+ if ($tmpPath === false) {
+ \OC::$server->get(LoggerInterface::class)->error(
+ 'Failed to get thumbnail for: ' . $file->getPath(),
+ ['app' => 'core']
+ );
+ return null;
+ }
// Creates \Imagick object from the heic file
try {
$bp = $this->getResizedPreview($tmpPath, $maxX, $maxY);
$bp->setFormat('jpg');
} catch (\Exception $e) {
- \OC::$server->getLogger()->logException($e, [
- 'message' => 'File: ' . $file->getPath() . ' Imagick says:',
- 'level' => ILogger::ERROR,
- 'app' => 'core',
- ]);
+ \OC::$server->get(LoggerInterface::class)->error(
+ 'File: ' . $file->getPath() . ' Imagick says:',
+ [
+ 'exception' => $e,
+ 'app' => 'core',
+ ]
+ );
return null;
}
@@ -109,7 +118,7 @@ class HEIC extends ProviderV2 {
$bp->setImageFormat('jpg');
$bp = $this->resize($bp, $maxX, $maxY);
-
+
return $bp;
}
diff --git a/lib/private/Preview/Krita.php b/lib/private/Preview/Krita.php
index ec7be4b82cf..eb25db9928c 100644
--- a/lib/private/Preview/Krita.php
+++ b/lib/private/Preview/Krita.php
@@ -39,11 +39,11 @@ class Krita extends Bundled {
*/
public function getThumbnail(File $file, int $maxX, int $maxY): ?IImage {
$image = $this->extractThumbnail($file, 'mergedimage.png');
- if ($image->valid()) {
+ if (($image !== null) && $image->valid()) {
return $image;
}
$image = $this->extractThumbnail($file, 'preview.png');
- if ($image->valid()) {
+ if (($image !== null) && $image->valid()) {
return $image;
}
return null;
diff --git a/lib/private/Preview/Movie.php b/lib/private/Preview/Movie.php
index a6e424caa2a..781cbad1954 100644
--- a/lib/private/Preview/Movie.php
+++ b/lib/private/Preview/Movie.php
@@ -99,11 +99,14 @@ class Movie extends ProviderV2 {
foreach ($sizeAttempts as $size) {
$absPath = $this->getLocalFile($file, $size);
- $result = $this->generateThumbNail($maxX, $maxY, $absPath, 5);
- if ($result === null) {
- $result = $this->generateThumbNail($maxX, $maxY, $absPath, 1);
+ $result = null;
+ if (is_string($absPath)) {
+ $result = $this->generateThumbNail($maxX, $maxY, $absPath, 5);
if ($result === null) {
- $result = $this->generateThumbNail($maxX, $maxY, $absPath, 0);
+ $result = $this->generateThumbNail($maxX, $maxY, $absPath, 1);
+ if ($result === null) {
+ $result = $this->generateThumbNail($maxX, $maxY, $absPath, 0);
+ }
}
}
@@ -117,25 +120,18 @@ class Movie extends ProviderV2 {
return $result;
}
- /**
- * @param int $maxX
- * @param int $maxY
- * @param string $absPath
- * @param int $second
- * @return null|\OCP\IImage
- */
- private function generateThumbNail($maxX, $maxY, $absPath, $second): ?IImage {
+ private function generateThumbNail(int $maxX, int $maxY, string $absPath, int $second): ?IImage {
$tmpPath = \OC::$server->getTempManager()->getTemporaryFile();
$binaryType = substr(strrchr($this->binary, '/'), 1);
if ($binaryType === 'avconv') {
- $cmd = $this->binary . ' -y -ss ' . escapeshellarg($second) .
+ $cmd = $this->binary . ' -y -ss ' . escapeshellarg((string)$second) .
' -i ' . escapeshellarg($absPath) .
' -an -f mjpeg -vframes 1 -vsync 1 ' . escapeshellarg($tmpPath) .
' 2>&1';
} elseif ($binaryType === 'ffmpeg') {
- $cmd = $this->binary . ' -y -ss ' . escapeshellarg($second) .
+ $cmd = $this->binary . ' -y -ss ' . escapeshellarg((string)$second) .
' -i ' . escapeshellarg($absPath) .
' -f mjpeg -vframes 1' .
' ' . escapeshellarg($tmpPath) .
diff --git a/lib/private/Preview/OpenDocument.php b/lib/private/Preview/OpenDocument.php
index 8deb9fd0a1e..5f27e325d31 100644
--- a/lib/private/Preview/OpenDocument.php
+++ b/lib/private/Preview/OpenDocument.php
@@ -42,7 +42,7 @@ class OpenDocument extends Bundled {
*/
public function getThumbnail(File $file, int $maxX, int $maxY): ?IImage {
$image = $this->extractThumbnail($file, 'Thumbnails/thumbnail.png');
- if ($image->valid()) {
+ if (($image !== null) && $image->valid()) {
return $image;
}
return null;
diff --git a/lib/private/Preview/ProviderV2.php b/lib/private/Preview/ProviderV2.php
index 4323f149702..0cb7eb59e21 100644
--- a/lib/private/Preview/ProviderV2.php
+++ b/lib/private/Preview/ProviderV2.php
@@ -35,7 +35,7 @@ abstract class ProviderV2 implements IProviderV2 {
protected $options;
/** @var array */
- private $tmpFiles = [];
+ protected $tmpFiles = [];
/**
* Constructor
@@ -72,7 +72,7 @@ abstract class ProviderV2 implements IProviderV2 {
*/
abstract public function getThumbnail(File $file, int $maxX, int $maxY): ?IImage;
- protected function useTempFile(File $file) {
+ protected function useTempFile(File $file): bool {
return $file->isEncrypted() || !$file->getStorage()->isLocal();
}
@@ -81,9 +81,9 @@ abstract class ProviderV2 implements IProviderV2 {
*
* @param File $file
* @param int $maxSize maximum size for temporary files
- * @return string
+ * @return string|false
*/
- protected function getLocalFile(File $file, int $maxSize = null): string {
+ protected function getLocalFile(File $file, int $maxSize = null) {
if ($this->useTempFile($file)) {
$absPath = \OC::$server->getTempManager()->getTemporaryFile();
@@ -97,14 +97,19 @@ abstract class ProviderV2 implements IProviderV2 {
$this->tmpFiles[] = $absPath;
return $absPath;
} else {
- return $file->getStorage()->getLocalFile($file->getInternalPath());
+ $path = $file->getStorage()->getLocalFile($file->getInternalPath());
+ if (is_string($path)) {
+ return $path;
+ } else {
+ return false;
+ }
}
}
/**
* Clean any generated temporary files
*/
- protected function cleanTmpFiles() {
+ protected function cleanTmpFiles(): void {
foreach ($this->tmpFiles as $tmpFile) {
unlink($tmpFile);
}
diff --git a/lib/private/Profile/ProfileManager.php b/lib/private/Profile/ProfileManager.php
index c4317b294f3..edb51458c66 100644
--- a/lib/private/Profile/ProfileManager.php
+++ b/lib/private/Profile/ProfileManager.php
@@ -40,6 +40,7 @@ use OCP\Accounts\IAccountManager;
use OCP\Accounts\PropertyDoesNotExistException;
use OCP\App\IAppManager;
use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\IConfig;
use OCP\IUser;
use OCP\L10N\IFactory;
use OCP\Profile\ILinkAction;
@@ -54,6 +55,9 @@ class ProfileManager {
/** @var IAppManager */
private $appManager;
+ /** @var IConfig */
+ private $config;
+
/** @var ProfileConfigMapper */
private $configMapper;
@@ -106,6 +110,7 @@ class ProfileManager {
public function __construct(
IAccountManager $accountManager,
IAppManager $appManager,
+ IConfig $config,
ProfileConfigMapper $configMapper,
ContainerInterface $container,
KnownUserService $knownUserService,
@@ -115,6 +120,7 @@ class ProfileManager {
) {
$this->accountManager = $accountManager;
$this->appManager = $appManager;
+ $this->config = $config;
$this->configMapper = $configMapper;
$this->container = $container;
$this->knownUserService = $knownUserService;
@@ -124,6 +130,24 @@ class ProfileManager {
}
/**
+ * If no user is passed as an argument return whether profile is enabled globally in `config.php`
+ */
+ public function isProfileEnabled(?IUser $user = null): ?bool {
+ $profileEnabledGlobally = $this->config->getSystemValueBool('profile.enabled', true);
+
+ if (empty($user) || !$profileEnabledGlobally) {
+ return $profileEnabledGlobally;
+ }
+
+ $account = $this->accountManager->getAccount($user);
+ return filter_var(
+ $account->getProperty(IAccountManager::PROPERTY_PROFILE_ENABLED)->getValue(),
+ FILTER_VALIDATE_BOOLEAN,
+ FILTER_NULL_ON_FAILURE,
+ );
+ }
+
+ /**
* Register an action for the user
*/
private function registerAction(ILinkAction $action, IUser $targetUser, ?IUser $visitingUser): void {
diff --git a/lib/private/Profile/TProfileHelper.php b/lib/private/Profile/TProfileHelper.php
index 0d4b5c6286e..5b57e1c9d5c 100644
--- a/lib/private/Profile/TProfileHelper.php
+++ b/lib/private/Profile/TProfileHelper.php
@@ -3,7 +3,7 @@
declare(strict_types=1);
/**
- * @copyright 2021 Christopher Ng <chrng8@gmail.com>
+ * @copyright 2022 Christopher Ng <chrng8@gmail.com>
*
* @author Christopher Ng <chrng8@gmail.com>
*
@@ -26,19 +26,12 @@ declare(strict_types=1);
namespace OC\Profile;
-use OCP\Accounts\IAccount;
-use OCP\Accounts\IAccountManager;
+use OCP\IConfig;
trait TProfileHelper {
-
- /**
- * Returns whether the profile is enabled for the account
- *
- * @since 23.0.0
- */
- protected function isProfileEnabled(IAccount $account): ?bool {
+ protected function isProfileEnabledByDefault(IConfig $config): ?bool {
return filter_var(
- $account->getProperty(IAccountManager::PROPERTY_PROFILE_ENABLED)->getValue(),
+ $config->getAppValue('settings', 'profile_enabled_by_default', '1'),
FILTER_VALIDATE_BOOLEAN,
FILTER_NULL_ON_FAILURE,
);
diff --git a/lib/private/RedisFactory.php b/lib/private/RedisFactory.php
index 88d22cf9d13..5c38ed0807d 100644
--- a/lib/private/RedisFactory.php
+++ b/lib/private/RedisFactory.php
@@ -26,6 +26,8 @@
*/
namespace OC;
+use OCP\Diagnostics\IEventLogger;
+
class RedisFactory {
public const REDIS_MINIMAL_VERSION = '3.1.3';
public const REDIS_EXTRA_PARAMETERS_MINIMAL_VERSION = '5.3.0';
@@ -33,16 +35,18 @@ class RedisFactory {
/** @var \Redis|\RedisCluster */
private $instance;
- /** @var SystemConfig */
- private $config;
+ private SystemConfig $config;
+
+ private IEventLogger $eventLogger;
/**
* RedisFactory constructor.
*
* @param SystemConfig $config
*/
- public function __construct(SystemConfig $config) {
+ public function __construct(SystemConfig $config, IEventLogger $eventLogger) {
$this->config = $config;
+ $this->eventLogger = $eventLogger;
}
private function create() {
@@ -113,6 +117,7 @@ class RedisFactory {
$port = null;
}
+ $this->eventLogger->start('connect:redis', 'Connect to redis and send AUTH, SELECT');
// Support for older phpredis versions not supporting connectionParameters
if ($connectionParameters !== null) {
// Non-clustered redis requires connection parameters to be wrapped inside `stream`
@@ -141,6 +146,7 @@ class RedisFactory {
if (isset($config['dbindex'])) {
$this->instance->select($config['dbindex']);
}
+ $this->eventLogger->end('connect:redis');
}
}
diff --git a/lib/private/Security/CSP/ContentSecurityPolicy.php b/lib/private/Security/CSP/ContentSecurityPolicy.php
index 78517f639a7..8a72934d4c9 100644
--- a/lib/private/Security/CSP/ContentSecurityPolicy.php
+++ b/lib/private/Security/CSP/ContentSecurityPolicy.php
@@ -244,4 +244,11 @@ class ContentSecurityPolicy extends \OCP\AppFramework\Http\ContentSecurityPolicy
public function setReportTo(array $reportTo) {
$this->reportTo = $reportTo;
}
+
+ /**
+ * @param boolean $strictDynamicAllowed
+ */
+ public function setStrictDynamicAllowed(bool $strictDynamicAllowed) {
+ $this->strictDynamicAllowed = $strictDynamicAllowed;
+ }
}
diff --git a/lib/private/Security/CertificateManager.php b/lib/private/Security/CertificateManager.php
index 0c6791163c2..6f3b01e23b9 100644
--- a/lib/private/Security/CertificateManager.php
+++ b/lib/private/Security/CertificateManager.php
@@ -240,15 +240,19 @@ class CertificateManager implements ICertificateManager {
* @return string
*/
public function getAbsoluteBundlePath(): string {
- if (!$this->hasCertificates()) {
- return \OC::$SERVERROOT . '/resources/config/ca-bundle.crt';
- }
+ try {
+ if (!$this->hasCertificates()) {
+ return \OC::$SERVERROOT . '/resources/config/ca-bundle.crt';
+ }
- if ($this->needsRebundling()) {
- $this->createCertificateBundle();
- }
+ if ($this->needsRebundling()) {
+ $this->createCertificateBundle();
+ }
- return $this->view->getLocalFile($this->getCertificateBundle());
+ return $this->view->getLocalFile($this->getCertificateBundle());
+ } catch (\Exception $e) {
+ return \OC::$SERVERROOT . '/resources/config/ca-bundle.crt';
+ }
}
/**
diff --git a/lib/private/Server.php b/lib/private/Server.php
index 13bbf972abb..00afaf1d6a9 100644
--- a/lib/private/Server.php
+++ b/lib/private/Server.php
@@ -91,9 +91,11 @@ use OC\Files\Mount\CacheMountProvider;
use OC\Files\Mount\LocalHomeMountProvider;
use OC\Files\Mount\ObjectHomeMountProvider;
use OC\Files\Mount\ObjectStorePreviewCacheMountProvider;
+use OC\Files\Mount\RootMountProvider;
use OC\Files\Node\HookConnector;
use OC\Files\Node\LazyRoot;
use OC\Files\Node\Root;
+use OC\Files\SetupManager;
use OC\Files\Storage\StorageFactory;
use OC\Files\Template\TemplateManager;
use OC\Files\Type\Loader;
@@ -142,6 +144,7 @@ use OC\Share20\ProviderFactory;
use OC\Share20\ShareHelper;
use OC\SystemTag\ManagerFactory as SystemTagManagerFactory;
use OC\Tagging\TagMapper;
+use OC\Talk\Broker;
use OC\Template\JSCombiner;
use OCA\Theming\ImageManager;
use OCA\Theming\ThemingDefaults;
@@ -215,6 +218,7 @@ use OCP\L10N\IFactory;
use OCP\LDAP\ILDAPProvider;
use OCP\LDAP\ILDAPProviderFactory;
use OCP\Lock\ILockingProvider;
+use OCP\Lockdown\ILockdownManager;
use OCP\Log\ILogFactory;
use OCP\Mail\IMailer;
use OCP\Remote\Api\IApiFactory;
@@ -231,6 +235,7 @@ use OCP\Security\VerificationToken\IVerificationToken;
use OCP\Share\IShareHelper;
use OCP\SystemTag\ISystemTagManager;
use OCP\SystemTag\ISystemTagObjectMapper;
+use OCP\Talk\IBroker;
use OCP\User\Events\BeforePasswordUpdatedEvent;
use OCP\User\Events\BeforeUserCreatedEvent;
use OCP\User\Events\BeforeUserDeletedEvent;
@@ -422,7 +427,8 @@ class Server extends ServerContainer implements IServerContainer {
null,
$c->get(IUserMountCache::class),
$this->get(ILogger::class),
- $this->get(IUserManager::class)
+ $this->get(IUserManager::class),
+ $this->get(IEventDispatcher::class),
);
$previewConnector = new \OC\Preview\WatcherConnector(
@@ -718,7 +724,7 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerService('RedisFactory', function (Server $c) {
$systemConfig = $c->get(SystemConfig::class);
- return new RedisFactory($systemConfig);
+ return new RedisFactory($systemConfig, $c->getEventLogger());
});
$this->registerService(\OCP\Activity\IManager::class, function (Server $c) {
@@ -871,12 +877,7 @@ class Server extends ServerContainer implements IServerContainer {
});
$this->registerDeprecatedAlias('HttpClientService', IClientService::class);
$this->registerService(IEventLogger::class, function (ContainerInterface $c) {
- $eventLogger = new EventLogger();
- if ($c->get(SystemConfig::class)->getValue('debug', false)) {
- // In debug mode, module is being activated by default
- $eventLogger->activate();
- }
- return $eventLogger;
+ return new EventLogger($c->get(SystemConfig::class), $c->get(LoggerInterface::class), $c->get(Log::class));
});
/** @deprecated 19.0.0 */
$this->registerDeprecatedAlias('EventLogger', IEventLogger::class);
@@ -952,6 +953,7 @@ class Server extends ServerContainer implements IServerContainer {
$manager->registerProvider(new CacheMountProvider($config));
$manager->registerHomeProvider(new LocalHomeMountProvider());
$manager->registerHomeProvider(new ObjectHomeMountProvider($config));
+ $manager->registerRootProvider(new RootMountProvider($config, $c->get(LoggerInterface::class)));
$manager->registerRootProvider(new ObjectStorePreviewCacheMountProvider($logger, $config));
return $manager;
@@ -1094,6 +1096,11 @@ class Server extends ServerContainer implements IServerContainer {
/** @deprecated 19.0.0 */
$this->registerDeprecatedAlias('LockingProvider', ILockingProvider::class);
+ $this->registerAlias(ILockdownManager::class, 'LockdownManager');
+ $this->registerService(SetupManager::class, function ($c) {
+ // create the setupmanager through the mount manager to resolve the cyclic dependency
+ return $c->get(\OC\Files\Mount\Manager::class)->getSetupManager();
+ });
$this->registerAlias(IMountManager::class, \OC\Files\Mount\Manager::class);
/** @deprecated 19.0.0 */
$this->registerDeprecatedAlias('MountManager', IMountManager::class);
@@ -1395,6 +1402,8 @@ class Server extends ServerContainer implements IServerContainer {
$this->registerAlias(\OCP\UserStatus\IManager::class, \OC\UserStatus\Manager::class);
+ $this->registerAlias(IBroker::class, Broker::class);
+
$this->connectDispatcher();
}
diff --git a/lib/private/Support/Subscription/Registry.php b/lib/private/Support/Subscription/Registry.php
index 1298337acb2..ba3642d021c 100644
--- a/lib/private/Support/Subscription/Registry.php
+++ b/lib/private/Support/Subscription/Registry.php
@@ -34,6 +34,7 @@ use OCP\IGroupManager;
use OCP\IServerContainer;
use OCP\IUserManager;
use OCP\Notification\IManager;
+use OCP\User\Backend\ICountUsersBackend;
use OCP\Support\Subscription\Exception\AlreadyRegisteredException;
use OCP\Support\Subscription\IRegistry;
use OCP\Support\Subscription\ISubscription;
@@ -189,6 +190,7 @@ class Registry implements IRegistry {
$backends = $this->userManager->getBackends();
foreach ($backends as $backend) {
if ($backend->implementsActions(Backend::COUNT_USERS)) {
+ /** @var ICountUsersBackend $backend */
$backendUsers = $backend->countUsers();
if ($backendUsers !== false) {
$userCount += $backendUsers;
diff --git a/lib/private/SystemConfig.php b/lib/private/SystemConfig.php
index c435b9180b9..0bc6154fbc4 100644
--- a/lib/private/SystemConfig.php
+++ b/lib/private/SystemConfig.php
@@ -43,6 +43,10 @@ class SystemConfig {
'dbhost' => true,
'dbpassword' => true,
'dbuser' => true,
+ 'activity_dbname' => true,
+ 'activity_dbhost' => true,
+ 'activity_dbpassword' => true,
+ 'activity_dbuser' => true,
'mail_from_address' => true,
'mail_domain' => true,
'mail_smtphost' => true,
@@ -53,6 +57,13 @@ class SystemConfig {
'updater.secret' => true,
'trusted_proxies' => true,
'proxyuserpwd' => true,
+ 'sentry.dsn' => true,
+ 'sentry.public-dsn' => true,
+ 'zammad.download.secret' => true,
+ 'zammad.portal.secret' => true,
+ 'zammad.secret' => true,
+ 'github.client_id' => true,
+ 'github.client_secret' => true,
'log.condition' => [
'shared_secret' => true,
],
diff --git a/lib/private/Template/JSResourceLocator.php b/lib/private/Template/JSResourceLocator.php
index 1421e28033a..bf84e1ae958 100644
--- a/lib/private/Template/JSResourceLocator.php
+++ b/lib/private/Template/JSResourceLocator.php
@@ -74,7 +74,7 @@ class JSResourceLocator extends ResourceLocator {
|| $this->cacheAndAppendCombineJsonIfExist($this->serverroot, $script.'.json')
|| $this->appendIfExist($this->serverroot, $theme_dir.'core/'.$script.'.js')
|| $this->appendIfExist($this->serverroot, 'core/'.$script.'.js')
- || $this->appendIfExist($this->serverroot, "dist/core-$scriptName.js")
+ || (strpos($scriptName, '/') === -1 && $this->appendIfExist($this->serverroot, "dist/core-$scriptName.js"))
|| $this->cacheAndAppendCombineJsonIfExist($this->serverroot, 'core/'.$script.'.json')
) {
return;
diff --git a/lib/private/User/Database.php b/lib/private/User/Database.php
index 81094d4d8af..a9464c27085 100644
--- a/lib/private/User/Database.php
+++ b/lib/private/User/Database.php
@@ -193,7 +193,13 @@ class Database extends ABackend implements
$hasher = \OC::$server->getHasher();
$hashedPassword = $hasher->hash($password);
- return $this->updatePassword($uid, $hashedPassword);
+ $return = $this->updatePassword($uid, $hashedPassword);
+
+ if ($return) {
+ $this->cache[$uid]['password'] = $hashedPassword;
+ }
+
+ return $return;
}
return false;
@@ -329,28 +335,16 @@ class Database extends ABackend implements
* returns the user id or false
*/
public function checkPassword(string $loginName, string $password) {
- $this->fixDI();
+ $found = $this->loadUser($loginName);
- $qb = $this->dbConn->getQueryBuilder();
- $qb->select('uid', 'password')
- ->from($this->table)
- ->where(
- $qb->expr()->eq(
- 'uid_lower', $qb->createNamedParameter(mb_strtolower($loginName))
- )
- );
- $result = $qb->execute();
- $row = $result->fetch();
- $result->closeCursor();
-
- if ($row) {
- $storedHash = $row['password'];
+ if ($found && is_array($this->cache[$loginName])) {
+ $storedHash = $this->cache[$loginName]['password'];
$newHash = '';
if (\OC::$server->getHasher()->verify($password, $storedHash, $newHash)) {
if (!empty($newHash)) {
$this->updatePassword($loginName, $newHash);
}
- return (string)$row['uid'];
+ return (string)$this->cache[$loginName]['uid'];
}
}
@@ -375,7 +369,7 @@ class Database extends ABackend implements
}
$qb = $this->dbConn->getQueryBuilder();
- $qb->select('uid', 'displayname')
+ $qb->select('uid', 'displayname', 'password')
->from($this->table)
->where(
$qb->expr()->eq(
@@ -391,6 +385,7 @@ class Database extends ABackend implements
$this->cache[$uid] = [
'uid' => (string)$row['uid'],
'displayname' => (string)$row['displayname'],
+ 'password' => (string)$row['password'],
];
} else {
$this->cache[$uid] = false;
diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php
index 2973240a4a1..cd26337cd20 100644
--- a/lib/private/User/Session.php
+++ b/lib/private/User/Session.php
@@ -548,11 +548,11 @@ class Session implements IUserSession, Emitter {
\OC::$server->getCsrfTokenManager()->refreshToken();
}
- //we need to pass the user name, which may differ from login name
- $user = $this->getUser()->getUID();
- OC_Util::setupFS($user);
-
if ($firstTimeLogin) {
+ //we need to pass the user name, which may differ from login name
+ $user = $this->getUser()->getUID();
+ OC_Util::setupFS($user);
+
// TODO: lock necessary?
//trigger creation of user home and /files folder
$userFolder = \OC::$server->getUserFolder($user);
diff --git a/lib/private/User/User.php b/lib/private/User/User.php
index 5fa1272f95c..0a51622428b 100644
--- a/lib/private/User/User.php
+++ b/lib/private/User/User.php
@@ -73,7 +73,7 @@ class User implements IUser {
/** @var IEventDispatcher */
private $dispatcher;
- /** @var bool */
+ /** @var bool|null */
private $enabled;
/** @var Emitter|Manager */
@@ -82,7 +82,7 @@ class User implements IUser {
/** @var string */
private $home;
- /** @var int */
+ /** @var int|null */
private $lastLogin;
/** @var \OCP\IConfig */
@@ -104,9 +104,6 @@ class User implements IUser {
}
$this->config = $config;
$this->urlGenerator = $urlGenerator;
- $enabled = $this->config->getUserValue($uid, 'core', 'enabled', 'true');
- $this->enabled = ($enabled === 'true');
- $this->lastLogin = $this->config->getUserValue($uid, 'login', 'lastLogin', 0);
if (is_null($this->urlGenerator)) {
$this->urlGenerator = \OC::$server->getURLGenerator();
}
@@ -231,14 +228,17 @@ class User implements IUser {
* @return int
*/
public function getLastLogin() {
- return $this->lastLogin;
+ if ($this->lastLogin === null) {
+ $this->lastLogin = (int) $this->config->getUserValue($this->uid, 'login', 'lastLogin', 0);
+ }
+ return (int) $this->lastLogin;
}
/**
* updates the timestamp of the most recent login of this user
*/
public function updateLastLoginTimestamp() {
- $firstTimeLogin = ($this->lastLogin === 0);
+ $firstTimeLogin = ($this->getLastLogin() === 0);
$this->lastLogin = time();
$this->config->setUserValue(
$this->uid, 'login', 'lastLogin', $this->lastLogin);
@@ -406,7 +406,11 @@ class User implements IUser {
* @return bool
*/
public function isEnabled() {
- return $this->enabled;
+ if ($this->enabled === null) {
+ $enabled = $this->config->getUserValue($this->uid, 'core', 'enabled', 'true');
+ $this->enabled = $enabled === 'true';
+ }
+ return (bool) $this->enabled;
}
/**
diff --git a/lib/private/UserStatus/ISettableProvider.php b/lib/private/UserStatus/ISettableProvider.php
index fc0d502845e..88a107d1f86 100644
--- a/lib/private/UserStatus/ISettableProvider.php
+++ b/lib/private/UserStatus/ISettableProvider.php
@@ -52,4 +52,15 @@ interface ISettableProvider extends IProvider {
* @param string $status The expected current status.
*/
public function revertUserStatus(string $userId, string $messageId, string $status): void;
+
+ /**
+ * Revert an automatically set user status. For example after leaving a call,
+ * change back to the previously set status. If the user has already updated
+ * their status, this method does nothing.
+ *
+ * @param string[] $userIds The users for which we want to update the status.
+ * @param string $messageId The expected current messageId.
+ * @param string $status The expected current status.
+ */
+ public function revertMultipleUserStatus(array $userIds, string $messageId, string $status): void;
}
diff --git a/lib/private/UserStatus/Manager.php b/lib/private/UserStatus/Manager.php
index bca80bc5b03..c93795bea5b 100644
--- a/lib/private/UserStatus/Manager.php
+++ b/lib/private/UserStatus/Manager.php
@@ -121,4 +121,12 @@ class Manager implements IManager {
}
$this->provider->revertUserStatus($userId, $messageId, $status);
}
+
+ public function revertMultipleUserStatus(array $userIds, string $messageId, string $status): void {
+ $this->setupProvider();
+ if (!$this->provider || !($this->provider instanceof ISettableProvider)) {
+ return;
+ }
+ $this->provider->revertMultipleUserStatus($userIds, $messageId, $status);
+ }
}
diff --git a/lib/private/legacy/OC_App.php b/lib/private/legacy/OC_App.php
index 1ce3662000e..ca01e91216b 100644
--- a/lib/private/legacy/OC_App.php
+++ b/lib/private/legacy/OC_App.php
@@ -173,6 +173,7 @@ class OC_App {
$hasAppPhpFile = is_file($appPath . '/appinfo/app.php');
+ \OC::$server->getEventLogger()->start('bootstrap:load_app_' . $app, 'Load app: ' . $app);
if ($isBootable && $hasAppPhpFile) {
\OC::$server->getLogger()->error('/appinfo/app.php is not loaded when \OCP\AppFramework\Bootstrap\IBootstrap on the application class is used. Migrate everything from app.php to the Application class.', [
'app' => $app,
@@ -181,7 +182,6 @@ class OC_App {
\OC::$server->getLogger()->debug('/appinfo/app.php is deprecated, use \OCP\AppFramework\Bootstrap\IBootstrap on the application class instead.', [
'app' => $app,
]);
- \OC::$server->getEventLogger()->start('load_app_' . $app, 'Load app: ' . $app);
try {
self::requireAppFile($app);
} catch (Throwable $ex) {
@@ -201,8 +201,9 @@ class OC_App {
]);
}
}
- \OC::$server->getEventLogger()->end('load_app_' . $app);
}
+ \OC::$server->getEventLogger()->end('bootstrap:load_app_' . $app);
+
$coordinator->bootApp($app);
$info = self::getAppInfo($app);
diff --git a/lib/private/legacy/OC_Util.php b/lib/private/legacy/OC_Util.php
index 9110678537f..ceed79bc9d5 100644
--- a/lib/private/legacy/OC_Util.php
+++ b/lib/private/legacy/OC_Util.php
@@ -66,11 +66,10 @@
use bantu\IniGetWrapper\IniGetWrapper;
use OC\AppFramework\Http\Request;
-use OC\Files\Storage\LocalRootStorage;
+use OC\Files\SetupManager;
use OCP\Files\Template\ITemplateManager;
use OCP\IConfig;
use OCP\IGroupManager;
-use OCP\ILogger;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\Share\IManager;
@@ -80,9 +79,6 @@ class OC_Util {
public static $scripts = [];
public static $styles = [];
public static $headers = [];
- private static $rootMounted = false;
- private static $rootFsSetup = false;
- private static $fsSetup = false;
/** @var array Local cache of version.php */
private static $versionCache = null;
@@ -91,222 +87,6 @@ class OC_Util {
return \OC::$server->getAppManager();
}
- private static function initLocalStorageRootFS() {
- // mount local file backend as root
- $configDataDirectory = \OC::$server->getSystemConfig()->getValue("datadirectory", OC::$SERVERROOT . "/data");
- //first set up the local "root" storage
- \OC\Files\Filesystem::initMountManager();
- if (!self::$rootMounted) {
- \OC\Files\Filesystem::mount(LocalRootStorage::class, ['datadir' => $configDataDirectory], '/');
- self::$rootMounted = true;
- }
- }
-
- /**
- * mounting an object storage as the root fs will in essence remove the
- * necessity of a data folder being present.
- * TODO make home storage aware of this and use the object storage instead of local disk access
- *
- * @param array $config containing 'class' and optional 'arguments'
- * @suppress PhanDeprecatedFunction
- */
- private static function initObjectStoreRootFS($config) {
- // check misconfiguration
- if (empty($config['class'])) {
- \OCP\Util::writeLog('files', 'No class given for objectstore', ILogger::ERROR);
- }
- if (!isset($config['arguments'])) {
- $config['arguments'] = [];
- }
-
- // instantiate object store implementation
- $name = $config['class'];
- if (strpos($name, 'OCA\\') === 0 && substr_count($name, '\\') >= 2) {
- $segments = explode('\\', $name);
- OC_App::loadApp(strtolower($segments[1]));
- }
- $config['arguments']['objectstore'] = new $config['class']($config['arguments']);
- // mount with plain / root object store implementation
- $config['class'] = '\OC\Files\ObjectStore\ObjectStoreStorage';
-
- // mount object storage as root
- \OC\Files\Filesystem::initMountManager();
- if (!self::$rootMounted) {
- \OC\Files\Filesystem::mount($config['class'], $config['arguments'], '/');
- self::$rootMounted = true;
- }
- }
-
- /**
- * mounting an object storage as the root fs will in essence remove the
- * necessity of a data folder being present.
- *
- * @param array $config containing 'class' and optional 'arguments'
- * @suppress PhanDeprecatedFunction
- */
- private static function initObjectStoreMultibucketRootFS($config) {
- // check misconfiguration
- if (empty($config['class'])) {
- \OCP\Util::writeLog('files', 'No class given for objectstore', ILogger::ERROR);
- }
- if (!isset($config['arguments'])) {
- $config['arguments'] = [];
- }
-
- // instantiate object store implementation
- $name = $config['class'];
- if (strpos($name, 'OCA\\') === 0 && substr_count($name, '\\') >= 2) {
- $segments = explode('\\', $name);
- OC_App::loadApp(strtolower($segments[1]));
- }
-
- if (!isset($config['arguments']['bucket'])) {
- $config['arguments']['bucket'] = '';
- }
- // put the root FS always in first bucket for multibucket configuration
- $config['arguments']['bucket'] .= '0';
-
- $config['arguments']['objectstore'] = new $config['class']($config['arguments']);
- // mount with plain / root object store implementation
- $config['class'] = '\OC\Files\ObjectStore\ObjectStoreStorage';
-
- // mount object storage as root
- \OC\Files\Filesystem::initMountManager();
- if (!self::$rootMounted) {
- \OC\Files\Filesystem::mount($config['class'], $config['arguments'], '/');
- self::$rootMounted = true;
- }
- }
-
- /**
- * Can be set up
- *
- * @param string $user
- * @return boolean
- * @description configure the initial filesystem based on the configuration
- * @suppress PhanDeprecatedFunction
- * @suppress PhanAccessMethodInternal
- */
- public static function setupRootFS(string $user = '') {
- //setting up the filesystem twice can only lead to trouble
- if (self::$rootFsSetup) {
- return false;
- }
-
- \OC::$server->getEventLogger()->start('setup_root_fs', 'Setup root filesystem');
-
- // load all filesystem apps before, so no setup-hook gets lost
- OC_App::loadApps(['filesystem']);
-
- self::$rootFsSetup = true;
-
- \OC\Files\Filesystem::initMountManager();
-
- $prevLogging = \OC\Files\Filesystem::logWarningWhenAddingStorageWrapper(false);
- \OC\Files\Filesystem::addStorageWrapper('mount_options', function ($mountPoint, \OCP\Files\Storage $storage, \OCP\Files\Mount\IMountPoint $mount) {
- if ($storage->instanceOfStorage('\OC\Files\Storage\Common')) {
- /** @var \OC\Files\Storage\Common $storage */
- $storage->setMountOptions($mount->getOptions());
- }
- return $storage;
- });
-
- \OC\Files\Filesystem::addStorageWrapper('enable_sharing', function ($mountPoint, \OCP\Files\Storage\IStorage $storage, \OCP\Files\Mount\IMountPoint $mount) {
- if (!$mount->getOption('enable_sharing', true)) {
- return new \OC\Files\Storage\Wrapper\PermissionsMask([
- 'storage' => $storage,
- 'mask' => \OCP\Constants::PERMISSION_ALL - \OCP\Constants::PERMISSION_SHARE
- ]);
- }
- return $storage;
- });
-
- // install storage availability wrapper, before most other wrappers
- \OC\Files\Filesystem::addStorageWrapper('oc_availability', function ($mountPoint, \OCP\Files\Storage\IStorage $storage) {
- if (!$storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage') && !$storage->isLocal()) {
- return new \OC\Files\Storage\Wrapper\Availability(['storage' => $storage]);
- }
- return $storage;
- });
-
- \OC\Files\Filesystem::addStorageWrapper('oc_encoding', function ($mountPoint, \OCP\Files\Storage $storage, \OCP\Files\Mount\IMountPoint $mount) {
- if ($mount->getOption('encoding_compatibility', false) && !$storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage') && !$storage->isLocal()) {
- return new \OC\Files\Storage\Wrapper\Encoding(['storage' => $storage]);
- }
- return $storage;
- });
-
- \OC\Files\Filesystem::addStorageWrapper('oc_quota', function ($mountPoint, $storage) {
- // set up quota for home storages, even for other users
- // which can happen when using sharing
-
- /**
- * @var \OC\Files\Storage\Storage $storage
- */
- if ($storage->instanceOfStorage('\OC\Files\Storage\Home')
- || $storage->instanceOfStorage('\OC\Files\ObjectStore\HomeObjectStoreStorage')
- ) {
- /** @var \OC\Files\Storage\Home $storage */
- if (is_object($storage->getUser())) {
- $quota = OC_Util::getUserQuota($storage->getUser());
- if ($quota !== \OCP\Files\FileInfo::SPACE_UNLIMITED) {
- return new \OC\Files\Storage\Wrapper\Quota(['storage' => $storage, 'quota' => $quota, 'root' => 'files']);
- }
- }
- }
-
- return $storage;
- });
-
- \OC\Files\Filesystem::addStorageWrapper('readonly', function ($mountPoint, \OCP\Files\Storage\IStorage $storage, \OCP\Files\Mount\IMountPoint $mount) {
- /*
- * Do not allow any operations that modify the storage
- */
- if ($mount->getOption('readonly', false)) {
- return new \OC\Files\Storage\Wrapper\PermissionsMask([
- 'storage' => $storage,
- 'mask' => \OCP\Constants::PERMISSION_ALL & ~(
- \OCP\Constants::PERMISSION_UPDATE |
- \OCP\Constants::PERMISSION_CREATE |
- \OCP\Constants::PERMISSION_DELETE
- ),
- ]);
- }
- return $storage;
- });
-
- OC_Hook::emit('OC_Filesystem', 'preSetup', ['user' => $user]);
-
- \OC\Files\Filesystem::logWarningWhenAddingStorageWrapper($prevLogging);
-
- //check if we are using an object storage
- $objectStore = \OC::$server->getSystemConfig()->getValue('objectstore', null);
- $objectStoreMultibucket = \OC::$server->getSystemConfig()->getValue('objectstore_multibucket', null);
-
- // use the same order as in ObjectHomeMountProvider
- if (isset($objectStoreMultibucket)) {
- self::initObjectStoreMultibucketRootFS($objectStoreMultibucket);
- } elseif (isset($objectStore)) {
- self::initObjectStoreRootFS($objectStore);
- } else {
- self::initLocalStorageRootFS();
- }
-
- /** @var \OCP\Files\Config\IMountProviderCollection $mountProviderCollection */
- $mountProviderCollection = \OC::$server->query(\OCP\Files\Config\IMountProviderCollection::class);
- $rootMountProviders = $mountProviderCollection->getRootMounts();
-
- /** @var \OC\Files\Mount\Manager $mountManager */
- $mountManager = \OC\Files\Filesystem::getMountManager();
- foreach ($rootMountProviders as $rootMountProvider) {
- $mountManager->addMount($rootMountProvider);
- }
-
- \OC::$server->getEventLogger()->end('setup_root_fs');
-
- return true;
- }
-
/**
* Setup the file system
*
@@ -317,14 +97,6 @@ class OC_Util {
* @suppress PhanAccessMethodInternal
*/
public static function setupFS(?string $user = '') {
- self::setupRootFS($user ?? '');
-
- if (self::$fsSetup) {
- return false;
- }
-
- \OC::$server->getEventLogger()->start('setup_fs', 'Setup filesystem');
-
// If we are not forced to load a specific user we load the one that is logged in
if ($user === '') {
$userObject = \OC::$server->get(\OCP\IUserSession::class)->getUser();
@@ -332,18 +104,14 @@ class OC_Util {
$userObject = \OC::$server->get(\OCP\IUserManager::class)->get($user);
}
- //if we aren't logged in, or the user doesn't exist, there is no use to set up the filesystem
- if ($userObject) {
- self::$fsSetup = true;
-
- $userDir = '/' . $userObject->getUID() . '/files';
-
- //jail the user into his "home" directory
- \OC\Files\Filesystem::init($userObject, $userDir);
+ /** @var SetupManager $setupManager */
+ $setupManager = \OC::$server->get(SetupManager::class);
- OC_Hook::emit('OC_Filesystem', 'setup', ['user' => $userObject->getUID(), 'user_dir' => $userDir]);
+ if ($userObject) {
+ $setupManager->setupForUser($userObject);
+ } else {
+ $setupManager->setupRoot();
}
- \OC::$server->getEventLogger()->end('setup_fs');
return true;
}
@@ -497,11 +265,9 @@ class OC_Util {
* @suppress PhanUndeclaredMethod
*/
public static function tearDownFS() {
- \OC\Files\Filesystem::tearDown();
- \OC::$server->getRootFolder()->clearCache();
- self::$fsSetup = false;
- self::$rootFsSetup = false;
- self::$rootMounted = false;
+ /** @var SetupManager $setupManager */
+ $setupManager = \OC::$server->get(SetupManager::class);
+ $setupManager->tearDown();
}
/**