aboutsummaryrefslogtreecommitdiffstats
path: root/lib/private
diff options
context:
space:
mode:
Diffstat (limited to 'lib/private')
-rw-r--r--lib/private/Calendar/Manager.php17
-rw-r--r--lib/private/Federation/CloudIdManager.php79
-rw-r--r--lib/private/Files/SetupManager.php8
-rw-r--r--lib/private/Files/Storage/Wrapper/Quota.php71
-rw-r--r--lib/private/Files/Stream/HashWrapper.php11
-rw-r--r--lib/private/NavigationManager.php2
-rw-r--r--lib/private/Repair/MoveUpdaterStepFile.php4
-rw-r--r--lib/private/Server.php8
-rw-r--r--lib/private/Settings/Manager.php7
-rw-r--r--lib/private/User/Database.php4
-rw-r--r--lib/private/User/Session.php8
-rw-r--r--lib/private/User/User.php8
12 files changed, 189 insertions, 38 deletions
diff --git a/lib/private/Calendar/Manager.php b/lib/private/Calendar/Manager.php
index f0b8e9fd50d..550ba36dd6b 100644
--- a/lib/private/Calendar/Manager.php
+++ b/lib/private/Calendar/Manager.php
@@ -330,12 +330,27 @@ class Manager implements IManager {
// to the email address in the ORGANIZER.
// We don't want to accept a CANCEL request from just anyone
$organizer = substr($vEvent->{'ORGANIZER'}->getValue(), 7);
- if (strcasecmp($sender, $organizer) !== 0 && strcasecmp($replyTo, $organizer) !== 0) {
+ $isNotOrganizer = ($replyTo !== null) ? (strcasecmp($sender, $organizer) !== 0 && strcasecmp($replyTo, $organizer) !== 0) : (strcasecmp($sender, $organizer) !== 0);
+ if ($isNotOrganizer) {
$this->logger->warning('Sender must be the ORGANIZER of this event');
return false;
}
+ //check if the event is in the future
+ /** @var DateTime $eventTime */
+ $eventTime = $vEvent->{'DTSTART'};
+ if ($eventTime->getDateTime()->getTimeStamp() < $this->timeFactory->getTime()) { // this might cause issues with recurrences
+ $this->logger->warning('Only events in the future are processed');
+ return false;
+ }
+
+ // Check if we have a calendar to work with
$calendars = $this->getCalendarsForPrincipal($principalUri);
+ if (empty($calendars)) {
+ $this->logger->warning('Could not find any calendars for principal ' . $principalUri);
+ return false;
+ }
+
$found = null;
// if the attendee has been found in at least one calendar event with the UID of the iMIP event
// we process it.
diff --git a/lib/private/Federation/CloudIdManager.php b/lib/private/Federation/CloudIdManager.php
index 77bb9437ba2..e4e42cb1293 100644
--- a/lib/private/Federation/CloudIdManager.php
+++ b/lib/private/Federation/CloudIdManager.php
@@ -30,11 +30,17 @@ declare(strict_types=1);
*/
namespace OC\Federation;
+use OCA\DAV\Events\CardUpdatedEvent;
use OCP\Contacts\IManager;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventDispatcher;
use OCP\Federation\ICloudId;
use OCP\Federation\ICloudIdManager;
+use OCP\ICache;
+use OCP\ICacheFactory;
use OCP\IURLGenerator;
use OCP\IUserManager;
+use OCP\User\Events\UserChangedEvent;
class CloudIdManager implements ICloudIdManager {
/** @var IManager */
@@ -43,11 +49,48 @@ class CloudIdManager implements ICloudIdManager {
private $urlGenerator;
/** @var IUserManager */
private $userManager;
-
- public function __construct(IManager $contactsManager, IURLGenerator $urlGenerator, IUserManager $userManager) {
+ private ICache $memCache;
+ /** @var array[] */
+ private array $cache = [];
+
+ public function __construct(
+ IManager $contactsManager,
+ IURLGenerator $urlGenerator,
+ IUserManager $userManager,
+ ICacheFactory $cacheFactory,
+ IEventDispatcher $eventDispatcher
+ ) {
$this->contactsManager = $contactsManager;
$this->urlGenerator = $urlGenerator;
$this->userManager = $userManager;
+ $this->memCache = $cacheFactory->createDistributed('cloud_id_');
+ $eventDispatcher->addListener(UserChangedEvent::class, [$this, 'handleUserEvent']);
+ $eventDispatcher->addListener(CardUpdatedEvent::class, [$this, 'handleCardEvent']);
+ }
+
+ public function handleUserEvent(Event $event): void {
+ if ($event instanceof UserChangedEvent && $event->getFeature() === 'displayName') {
+ $userId = $event->getUser()->getUID();
+ $key = $userId . '@local';
+ unset($this->cache[$key]);
+ $this->memCache->remove($key);
+ }
+ }
+
+ public function handleCardEvent(Event $event): void {
+ if ($event instanceof CardUpdatedEvent) {
+ $data = $event->getCardData()['carddata'];
+ foreach (explode("\r\n", $data) as $line) {
+ if (strpos($line, "CLOUD;") === 0) {
+ $parts = explode(':', $line, 2);
+ if (isset($parts[1])) {
+ $key = $parts[1];
+ unset($this->cache[$key]);
+ $this->memCache->remove($key);
+ }
+ }
+ }
+ }
}
/**
@@ -120,18 +163,42 @@ class CloudIdManager implements ICloudIdManager {
* @return CloudId
*/
public function getCloudId(string $user, ?string $remote): ICloudId {
- if ($remote === null) {
+ $isLocal = $remote === null;
+ if ($isLocal) {
$remote = rtrim($this->removeProtocolFromUrl($this->urlGenerator->getAbsoluteURL('/')), '/');
$fixedRemote = $this->fixRemoteURL($remote);
- $localUser = $this->userManager->get($user);
- $displayName = !is_null($localUser) ? $localUser->getDisplayName() : '';
+ $host = $fixedRemote;
} else {
- // TODO check what the correct url is for remote (asking the remote)
+ // note that for remote id's we don't strip the protocol for the remote we use to construct the CloudId
+ // this way if a user has an explicit non-https cloud id this will be preserved
+ // we do still use the version without protocol for looking up the display name
$fixedRemote = $this->fixRemoteURL($remote);
$host = $this->removeProtocolFromUrl($fixedRemote);
+ }
+
+ $key = $user . '@' . ($isLocal ? 'local' : $host);
+ $cached = $this->cache[$key] ?? $this->memCache->get($key);
+ if ($cached) {
+ $this->cache[$key] = $cached; // put items from memcache into local cache
+ return new CloudId($cached['id'], $cached['user'], $cached['remote'], $cached['displayName']);
+ }
+
+ if ($isLocal) {
+ $localUser = $this->userManager->get($user);
+ $displayName = $localUser ? $localUser->getDisplayName() : '';
+ } else {
$displayName = $this->getDisplayNameFromContact($user . '@' . $host);
}
$id = $user . '@' . $remote;
+
+ $data = [
+ 'id' => $id,
+ 'user' => $user,
+ 'remote' => $fixedRemote,
+ 'displayName' => $displayName,
+ ];
+ $this->cache[$key] = $data;
+ $this->memCache->set($key, $data, 15 * 60);
return new CloudId($id, $user, $fixedRemote, $displayName);
}
diff --git a/lib/private/Files/SetupManager.php b/lib/private/Files/SetupManager.php
index 5782a5a72a6..d52a291cd99 100644
--- a/lib/private/Files/SetupManager.php
+++ b/lib/private/Files/SetupManager.php
@@ -172,10 +172,10 @@ class SetupManager {
*/
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']);
- }
+ $user = $storage->getUser();
+ return new Quota(['storage' => $storage, 'quotaCallback' => function () use ($user) {
+ return OC_Util::getUserQuota($user);
+ }, 'root' => 'files']);
}
}
diff --git a/lib/private/Files/Storage/Wrapper/Quota.php b/lib/private/Files/Storage/Wrapper/Quota.php
index 4cd0a5e0b4a..8b129472eb0 100644
--- a/lib/private/Files/Storage/Wrapper/Quota.php
+++ b/lib/private/Files/Storage/Wrapper/Quota.php
@@ -33,40 +33,47 @@
namespace OC\Files\Storage\Wrapper;
use OC\Files\Filesystem;
+use OC\SystemConfig;
use OCP\Files\Cache\ICacheEntry;
+use OCP\Files\FileInfo;
use OCP\Files\Storage\IStorage;
class Quota extends Wrapper {
-
- /**
- * @var int $quota
- */
- protected $quota;
-
- /**
- * @var string $sizeRoot
- */
- protected $sizeRoot;
-
- private $config;
+ /** @var callable|null */
+ protected $quotaCallback;
+ protected ?int $quota;
+ protected string $sizeRoot;
+ private SystemConfig $config;
/**
* @param array $parameters
*/
public function __construct($parameters) {
parent::__construct($parameters);
- $this->quota = $parameters['quota'];
- $this->sizeRoot = isset($parameters['root']) ? $parameters['root'] : '';
- $this->config = \OC::$server->getSystemConfig();
+ $this->quota = $parameters['quota'] ?? null;
+ $this->quotaCallback = $parameters['quotaCallback'] ?? null;
+ $this->sizeRoot = $parameters['root'] ?? '';
+ $this->config = \OC::$server->get(SystemConfig::class);
}
/**
* @return int quota value
*/
- public function getQuota() {
+ public function getQuota(): int {
+ if ($this->quota === null) {
+ $quotaCallback = $this->quotaCallback;
+ if ($quotaCallback === null) {
+ throw new \Exception("No quota or quota callback provider");
+ }
+ $this->quota = $quotaCallback();
+ }
return $this->quota;
}
+ private function hasQuota(): bool {
+ return $this->getQuota() !== FileInfo::SPACE_UNLIMITED;
+ }
+
/**
* @param string $path
* @param \OC\Files\Storage\Storage $storage
@@ -100,7 +107,10 @@ class Quota extends Wrapper {
* @return int|bool
*/
public function free_space($path) {
- if ($this->quota < 0 || strpos($path, 'cache') === 0 || strpos($path, 'uploads') === 0) {
+ if (!$this->hasQuota()) {
+ return $this->storage->free_space($path);
+ }
+ if ($this->getQuota() < 0 || strpos($path, 'cache') === 0 || strpos($path, 'uploads') === 0) {
return $this->storage->free_space($path);
} else {
$used = $this->getSize($this->sizeRoot);
@@ -108,7 +118,7 @@ class Quota extends Wrapper {
return \OCP\Files\FileInfo::SPACE_NOT_COMPUTED;
} else {
$free = $this->storage->free_space($path);
- $quotaFree = max($this->quota - $used, 0);
+ $quotaFree = max($this->getQuota() - $used, 0);
// if free space is known
if ($free >= 0) {
$free = min($free, $quotaFree);
@@ -128,6 +138,9 @@ class Quota extends Wrapper {
* @return int|false
*/
public function file_put_contents($path, $data) {
+ if (!$this->hasQuota()) {
+ return $this->storage->file_put_contents($path, $data);
+ }
$free = $this->free_space($path);
if ($free < 0 or strlen($data) < $free) {
return $this->storage->file_put_contents($path, $data);
@@ -144,6 +157,9 @@ class Quota extends Wrapper {
* @return bool
*/
public function copy($source, $target) {
+ if (!$this->hasQuota()) {
+ return $this->storage->copy($source, $target);
+ }
$free = $this->free_space($target);
if ($free < 0 or $this->getSize($source) < $free) {
return $this->storage->copy($source, $target);
@@ -160,6 +176,9 @@ class Quota extends Wrapper {
* @return resource|bool
*/
public function fopen($path, $mode) {
+ if (!$this->hasQuota()) {
+ return $this->storage->fopen($path, $mode);
+ }
$source = $this->storage->fopen($path, $mode);
// don't apply quota for part files
@@ -202,6 +221,9 @@ class Quota extends Wrapper {
* @return bool
*/
public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
+ if (!$this->hasQuota()) {
+ return $this->storage->copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
+ }
$free = $this->free_space($targetInternalPath);
if ($free < 0 or $this->getSize($sourceInternalPath, $sourceStorage) < $free) {
return $this->storage->copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
@@ -217,6 +239,9 @@ class Quota extends Wrapper {
* @return bool
*/
public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
+ if (!$this->hasQuota()) {
+ return $this->storage->moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
+ }
$free = $this->free_space($targetInternalPath);
if ($free < 0 or $this->getSize($sourceInternalPath, $sourceStorage) < $free) {
return $this->storage->moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
@@ -226,8 +251,11 @@ class Quota extends Wrapper {
}
public function mkdir($path) {
+ if (!$this->hasQuota()) {
+ return $this->storage->mkdir($path);
+ }
$free = $this->free_space($path);
- if ($this->shouldApplyQuota($path) && $free === 0.0) {
+ if ($this->shouldApplyQuota($path) && $free == 0) {
return false;
}
@@ -235,8 +263,11 @@ class Quota extends Wrapper {
}
public function touch($path, $mtime = null) {
+ if (!$this->hasQuota()) {
+ return $this->storage->touch($path, $mtime);
+ }
$free = $this->free_space($path);
- if ($free === 0.0) {
+ if ($free == 0) {
return false;
}
diff --git a/lib/private/Files/Stream/HashWrapper.php b/lib/private/Files/Stream/HashWrapper.php
index fd9bb3cdd0b..4060d74de7d 100644
--- a/lib/private/Files/Stream/HashWrapper.php
+++ b/lib/private/Files/Stream/HashWrapper.php
@@ -67,7 +67,16 @@ class HashWrapper extends Wrapper {
public function stream_close() {
if (is_callable($this->callback)) {
- call_user_func($this->callback, hash_final($this->hash));
+ // if the stream is closed as a result of the end-of-request GC, the hash context might be cleaned up before this stream
+ if ($this->hash instanceof \HashContext) {
+ try {
+ $hash = @hash_final($this->hash);
+ if ($hash) {
+ call_user_func($this->callback, $hash);
+ }
+ } catch (\Throwable $e) {
+ }
+ }
// prevent further calls by potential PHP 7 GC ghosts
$this->callback = null;
}
diff --git a/lib/private/NavigationManager.php b/lib/private/NavigationManager.php
index bbf28d2c142..7fd76850816 100644
--- a/lib/private/NavigationManager.php
+++ b/lib/private/NavigationManager.php
@@ -228,7 +228,7 @@ class NavigationManager implements INavigationManager {
'id' => 'admin_settings',
'order' => 3,
'href' => $this->urlGenerator->linkToRoute('settings.AdminSettings.index', ['section' => 'overview']),
- 'name' => $l->t('Admin settings'),
+ 'name' => $l->t('Administration settings'),
'icon' => $this->urlGenerator->imagePath('settings', 'admin.svg'),
]);
} else {
diff --git a/lib/private/Repair/MoveUpdaterStepFile.php b/lib/private/Repair/MoveUpdaterStepFile.php
index bc7430d7a7f..020510804d7 100644
--- a/lib/private/Repair/MoveUpdaterStepFile.php
+++ b/lib/private/Repair/MoveUpdaterStepFile.php
@@ -43,14 +43,14 @@ class MoveUpdaterStepFile implements IRepairStep {
}
public function run(IOutput $output) {
- $dataDir = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data');
+ $updateDir = $this->config->getSystemValue('updatedirectory') ?? $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data');
$instanceId = $this->config->getSystemValue('instanceid', null);
if (!is_string($instanceId) || empty($instanceId)) {
return;
}
- $updaterFolderPath = $dataDir . '/updater-' . $instanceId;
+ $updaterFolderPath = $updateDir . '/updater-' . $instanceId;
$stepFile = $updaterFolderPath . '/.step';
if (file_exists($stepFile)) {
$output->info('.step file exists');
diff --git a/lib/private/Server.php b/lib/private/Server.php
index f18ac7b6534..c1a50cfcaff 100644
--- a/lib/private/Server.php
+++ b/lib/private/Server.php
@@ -1365,7 +1365,13 @@ class Server extends ServerContainer implements IServerContainer {
});
$this->registerService(ICloudIdManager::class, function (ContainerInterface $c) {
- return new CloudIdManager($c->get(\OCP\Contacts\IManager::class), $c->get(IURLGenerator::class), $c->get(IUserManager::class));
+ return new CloudIdManager(
+ $c->get(\OCP\Contacts\IManager::class),
+ $c->get(IURLGenerator::class),
+ $c->get(IUserManager::class),
+ $c->get(ICacheFactory::class),
+ $c->get(IEventDispatcher::class),
+ );
});
$this->registerAlias(\OCP\GlobalScale\IConfig::class, \OC\GlobalScale\Config::class);
diff --git a/lib/private/Settings/Manager.php b/lib/private/Settings/Manager.php
index 05a286e4758..44f1df09c15 100644
--- a/lib/private/Settings/Manager.php
+++ b/lib/private/Settings/Manager.php
@@ -150,6 +150,13 @@ class Manager implements IManager {
return $this->sections[$type];
}
+ public function getSection(string $type, string $sectionId): ?IIconSection {
+ if (isset($this->sections[$type]) && isset($this->sections[$type][$sectionId])) {
+ return $this->sections[$type][$sectionId];
+ }
+ return null;
+ }
+
protected function isKnownDuplicateSectionId(string $sectionID): bool {
return in_array($sectionID, [
'connected-accounts',
diff --git a/lib/private/User/Database.php b/lib/private/User/Database.php
index 0b38f04bfe3..f106c2e8b6d 100644
--- a/lib/private/User/Database.php
+++ b/lib/private/User/Database.php
@@ -212,11 +212,13 @@ class Database extends ABackend implements
* @param string $displayName The new display name
* @return bool
*
+ * @throws \InvalidArgumentException
+ *
* Change the display name of a user
*/
public function setDisplayName(string $uid, string $displayName): bool {
if (mb_strlen($displayName) > 64) {
- return false;
+ throw new \InvalidArgumentException('Invalid displayname');
}
$this->fixDI();
diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php
index 626ddca2dad..65a213d4bf8 100644
--- a/lib/private/User/Session.php
+++ b/lib/private/User/Session.php
@@ -865,6 +865,10 @@ class Session implements IUserSession, Emitter {
$tokens = $this->config->getUserKeys($uid, 'login_token');
// test cookies token against stored tokens
if (!in_array($currentToken, $tokens, true)) {
+ $this->logger->error('Tried to log in {uid} but could not verify token', [
+ 'app' => 'core',
+ 'uid' => $uid,
+ ]);
return false;
}
// replace successfully used token with a new one
@@ -876,6 +880,10 @@ class Session implements IUserSession, Emitter {
$sessionId = $this->session->getId();
$token = $this->tokenProvider->renewSessionToken($oldSessionId, $sessionId);
} catch (SessionNotAvailableException $ex) {
+ $this->logger->warning('Could not renew session token for {uid} because the session is unavailable', [
+ 'app' => 'core',
+ 'uid' => $uid,
+ ]);
return false;
} catch (InvalidTokenException $ex) {
$this->logger->warning('Renewing session token failed', ['app' => 'core']);
diff --git a/lib/private/User/User.php b/lib/private/User/User.php
index 7f7d6273e30..f5d93dcd680 100644
--- a/lib/private/User/User.php
+++ b/lib/private/User/User.php
@@ -154,6 +154,9 @@ class User implements IUser {
*
* @param string $displayName
* @return bool
+ *
+ * @since 25.0.0 Throw InvalidArgumentException
+ * @throws \InvalidArgumentException
*/
public function setDisplayName($displayName) {
$displayName = trim($displayName);
@@ -196,7 +199,7 @@ class User implements IUser {
$this->setPrimaryEMailAddress('');
}
- if ($oldMailAddress !== $mailAddress) {
+ if ($oldMailAddress !== strtolower($mailAddress)) {
$this->triggerChange('eMailAddress', $mailAddress, $oldMailAddress);
}
}
@@ -556,6 +559,9 @@ class User implements IUser {
public function getCloudId() {
$uid = $this->getUID();
$server = $this->urlGenerator->getAbsoluteURL('/');
+ if (substr($server, -10) === '/index.php') {
+ $server = substr($server, 0, -10);
+ }
$server = rtrim($this->removeProtocolFromUrl($server), '/');
return $uid . '@' . $server;
}