2012-12-15 19:44:46 -05:00
|
|
|
|
<?php
|
2025-06-30 09:04:05 -04:00
|
|
|
|
|
2012-12-15 19:44:46 -05:00
|
|
|
|
/**
|
2024-06-06 13:48:28 -04:00
|
|
|
|
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
|
|
|
|
|
|
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
|
|
|
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
2013-01-28 15:25:19 -05:00
|
|
|
|
*/
|
2016-05-02 09:16:20 -04:00
|
|
|
|
namespace OCA\Files_Sharing;
|
2014-03-28 10:26:15 -04:00
|
|
|
|
|
2023-08-16 06:34:18 -04:00
|
|
|
|
use OC\Files\Cache\CacheDependencies;
|
2017-05-24 07:56:09 -04:00
|
|
|
|
use OC\Files\Cache\FailedCache;
|
2016-01-22 07:01:37 -05:00
|
|
|
|
use OC\Files\Cache\Wrapper\CacheJail;
|
2021-05-05 12:09:53 -04:00
|
|
|
|
use OC\Files\Search\SearchBinaryOperator;
|
|
|
|
|
|
use OC\Files\Search\SearchComparison;
|
2017-11-10 11:02:35 -05:00
|
|
|
|
use OC\Files\Storage\Wrapper\Jail;
|
2022-04-21 10:31:19 -04:00
|
|
|
|
use OC\User\DisplayNameCache;
|
2023-08-16 06:34:18 -04:00
|
|
|
|
use OCP\Files\Cache\ICache;
|
2015-12-02 08:59:13 -05:00
|
|
|
|
use OCP\Files\Cache\ICacheEntry;
|
2021-05-05 12:09:53 -04:00
|
|
|
|
use OCP\Files\Search\ISearchBinaryOperator;
|
|
|
|
|
|
use OCP\Files\Search\ISearchComparison;
|
|
|
|
|
|
use OCP\Files\Search\ISearchOperator;
|
2018-09-26 04:43:40 -04:00
|
|
|
|
use OCP\Files\StorageNotAvailableException;
|
2023-08-17 13:43:32 -04:00
|
|
|
|
use OCP\Share\IShare;
|
2012-12-15 19:44:46 -05:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Metadata cache for shared files
|
|
|
|
|
|
*
|
|
|
|
|
|
* don't use this class directly if you need to get metadata, use \OC\Files\Filesystem::getFileInfo instead
|
|
|
|
|
|
*/
|
2016-05-02 09:16:20 -04:00
|
|
|
|
class Cache extends CacheJail {
|
2022-04-21 10:31:19 -04:00
|
|
|
|
private bool $rootUnchanged = true;
|
|
|
|
|
|
private ?string $ownerDisplayName = null;
|
2022-04-22 04:01:35 -04:00
|
|
|
|
private $numericId;
|
2022-04-21 10:31:19 -04:00
|
|
|
|
private DisplayNameCache $displayNameCache;
|
2017-03-27 08:05:01 -04:00
|
|
|
|
|
2012-12-15 19:44:46 -05:00
|
|
|
|
/**
|
2022-04-21 10:31:19 -04:00
|
|
|
|
* @param SharedStorage $storage
|
2012-12-15 19:44:46 -05:00
|
|
|
|
*/
|
2023-08-17 13:43:32 -04:00
|
|
|
|
public function __construct(
|
2024-10-18 06:04:22 -04:00
|
|
|
|
private $storage,
|
|
|
|
|
|
private ICacheEntry $sourceRootInfo,
|
2023-08-16 06:34:18 -04:00
|
|
|
|
CacheDependencies $dependencies,
|
2024-10-18 06:04:22 -04:00
|
|
|
|
private IShare $share,
|
2023-08-17 13:43:32 -04:00
|
|
|
|
) {
|
2024-10-18 06:04:22 -04:00
|
|
|
|
$this->numericId = $this->sourceRootInfo->getStorageId();
|
2023-08-16 06:34:18 -04:00
|
|
|
|
$this->displayNameCache = $dependencies->getDisplayNameCache();
|
2017-11-10 11:02:35 -05:00
|
|
|
|
|
2016-01-22 07:01:37 -05:00
|
|
|
|
parent::__construct(
|
2016-11-17 08:18:08 -05:00
|
|
|
|
null,
|
2023-08-16 06:34:18 -04:00
|
|
|
|
'',
|
|
|
|
|
|
$dependencies,
|
2016-01-22 07:01:37 -05:00
|
|
|
|
);
|
2012-12-15 19:44:46 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
2017-12-04 09:16:39 -05:00
|
|
|
|
protected function getRoot() {
|
2019-09-04 03:28:58 -04:00
|
|
|
|
if ($this->root === '') {
|
2017-12-04 09:16:39 -05:00
|
|
|
|
$absoluteRoot = $this->sourceRootInfo->getPath();
|
|
|
|
|
|
|
|
|
|
|
|
// the sourceRootInfo path is the absolute path of the folder in the "real" storage
|
|
|
|
|
|
// in the case where a folder is shared from a Jail we need to ensure that the share Jail
|
2022-07-28 07:11:38 -04:00
|
|
|
|
// has its root set relative to the source Jail
|
2017-12-04 09:16:39 -05:00
|
|
|
|
$currentStorage = $this->storage->getSourceStorage();
|
|
|
|
|
|
if ($currentStorage->instanceOfStorage(Jail::class)) {
|
|
|
|
|
|
/** @var Jail $currentStorage */
|
|
|
|
|
|
$absoluteRoot = $currentStorage->getJailedPath($absoluteRoot);
|
|
|
|
|
|
}
|
2025-01-26 08:56:17 -05:00
|
|
|
|
$this->root = $absoluteRoot ?? '';
|
2017-12-04 09:16:39 -05:00
|
|
|
|
}
|
|
|
|
|
|
return $this->root;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-12 12:33:26 -04:00
|
|
|
|
public function getGetUnjailedRoot(): string {
|
2021-01-25 11:38:34 -05:00
|
|
|
|
return $this->sourceRootInfo->getPath();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-16 06:34:18 -04:00
|
|
|
|
public function getCache(): ICache {
|
2016-11-17 08:18:08 -05:00
|
|
|
|
if (is_null($this->cache)) {
|
2017-05-24 07:56:09 -04:00
|
|
|
|
$sourceStorage = $this->storage->getSourceStorage();
|
|
|
|
|
|
if ($sourceStorage) {
|
|
|
|
|
|
$this->cache = $sourceStorage->getCache();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// don't set $this->cache here since sourceStorage will be set later
|
|
|
|
|
|
return new FailedCache();
|
|
|
|
|
|
}
|
2016-11-17 08:18:08 -05:00
|
|
|
|
}
|
|
|
|
|
|
return $this->cache;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-03-23 15:10:43 -04:00
|
|
|
|
public function getNumericStorageId() {
|
|
|
|
|
|
if (isset($this->numericId)) {
|
|
|
|
|
|
return $this->numericId;
|
|
|
|
|
|
} else {
|
2022-10-17 06:40:35 -04:00
|
|
|
|
return -1;
|
2017-03-23 15:10:43 -04:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-11-17 05:48:29 -05:00
|
|
|
|
public function get($file) {
|
|
|
|
|
|
if ($this->rootUnchanged && ($file === '' || $file === $this->sourceRootInfo->getId())) {
|
2017-12-04 09:16:39 -05:00
|
|
|
|
return $this->formatCacheEntry(clone $this->sourceRootInfo, '');
|
2016-11-17 05:48:29 -05:00
|
|
|
|
}
|
|
|
|
|
|
return parent::get($file);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function update($id, array $data) {
|
|
|
|
|
|
$this->rootUnchanged = false;
|
|
|
|
|
|
parent::update($id, $data);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function insert($file, array $data) {
|
|
|
|
|
|
$this->rootUnchanged = false;
|
|
|
|
|
|
return parent::insert($file, $data);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public function remove($file) {
|
|
|
|
|
|
$this->rootUnchanged = false;
|
|
|
|
|
|
parent::remove($file);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-10 06:40:31 -04:00
|
|
|
|
public function moveFromCache(ICache $sourceCache, $sourcePath, $targetPath) {
|
2016-11-17 05:48:29 -05:00
|
|
|
|
$this->rootUnchanged = false;
|
|
|
|
|
|
return parent::moveFromCache($sourceCache, $sourcePath, $targetPath);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-12-04 09:16:39 -05:00
|
|
|
|
protected function formatCacheEntry($entry, $path = null) {
|
|
|
|
|
|
if (is_null($path)) {
|
2019-09-04 03:28:58 -04:00
|
|
|
|
$path = $entry['path'] ?? '';
|
2017-12-04 09:16:39 -05:00
|
|
|
|
$entry['path'] = $this->getJailedPath($path);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$entry['path'] = $path;
|
|
|
|
|
|
}
|
2018-09-26 04:43:40 -04:00
|
|
|
|
|
|
|
|
|
|
try {
|
2020-09-09 07:48:48 -04:00
|
|
|
|
if (isset($entry['permissions'])) {
|
2023-08-17 13:43:32 -04:00
|
|
|
|
$entry['permissions'] &= $this->share->getPermissions();
|
2020-09-09 07:48:48 -04:00
|
|
|
|
} else {
|
|
|
|
|
|
$entry['permissions'] = $this->storage->getPermissions($entry['path']);
|
|
|
|
|
|
}
|
2023-09-19 04:54:48 -04:00
|
|
|
|
|
|
|
|
|
|
if ($this->share->getNodeId() === $entry['fileid']) {
|
|
|
|
|
|
$entry['name'] = basename($this->share->getTarget());
|
|
|
|
|
|
}
|
2018-09-26 04:43:40 -04:00
|
|
|
|
} catch (StorageNotAvailableException $e) {
|
|
|
|
|
|
// thrown by FailedStorage e.g. when the sharer does not exist anymore
|
|
|
|
|
|
// (IDE may say the exception is never thrown – false negative)
|
|
|
|
|
|
$sharePermissions = 0;
|
|
|
|
|
|
}
|
2023-08-17 13:43:32 -04:00
|
|
|
|
$entry['uid_owner'] = $this->share->getShareOwner();
|
2016-11-18 05:21:45 -05:00
|
|
|
|
$entry['displayname_owner'] = $this->getOwnerDisplayName();
|
2016-01-22 07:01:37 -05:00
|
|
|
|
if ($path === '') {
|
|
|
|
|
|
$entry['is_share_mount_point'] = true;
|
2012-12-15 19:44:46 -05:00
|
|
|
|
}
|
2016-01-22 07:01:37 -05:00
|
|
|
|
return $entry;
|
2012-12-15 19:44:46 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-11-18 05:21:45 -05:00
|
|
|
|
private function getOwnerDisplayName() {
|
|
|
|
|
|
if (!$this->ownerDisplayName) {
|
2023-08-17 13:43:32 -04:00
|
|
|
|
$uid = $this->share->getShareOwner();
|
2022-08-16 08:10:05 -04:00
|
|
|
|
$this->ownerDisplayName = $this->displayNameCache->getDisplayName($uid) ?? $uid;
|
2016-11-18 05:21:45 -05:00
|
|
|
|
}
|
|
|
|
|
|
return $this->ownerDisplayName;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2012-12-15 19:44:46 -05:00
|
|
|
|
/**
|
|
|
|
|
|
* remove all entries for files that are stored on the storage from the cache
|
|
|
|
|
|
*/
|
|
|
|
|
|
public function clear() {
|
|
|
|
|
|
// Not a valid action for Shared Cache
|
|
|
|
|
|
}
|
2020-11-19 03:14:29 -05:00
|
|
|
|
|
2021-05-05 12:09:53 -04:00
|
|
|
|
public function getQueryFilterForStorage(): ISearchOperator {
|
2022-08-17 05:58:57 -04:00
|
|
|
|
$storageFilter = \OC\Files\Cache\Cache::getQueryFilterForStorage();
|
|
|
|
|
|
|
2021-05-04 13:06:02 -04:00
|
|
|
|
// Do the normal jail behavior for non files
|
2020-11-19 03:14:29 -05:00
|
|
|
|
if ($this->storage->getItemType() !== 'file') {
|
2022-08-17 05:58:57 -04:00
|
|
|
|
return $this->addJailFilterQuery($storageFilter);
|
2020-11-19 03:14:29 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-05-04 13:06:02 -04:00
|
|
|
|
// for single file shares we don't need to do the LIKE
|
2021-05-05 12:09:53 -04:00
|
|
|
|
return new SearchBinaryOperator(
|
|
|
|
|
|
ISearchBinaryOperator::OPERATOR_AND,
|
|
|
|
|
|
[
|
2022-08-17 05:58:57 -04:00
|
|
|
|
$storageFilter,
|
2021-05-05 12:09:53 -04:00
|
|
|
|
new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'path', $this->getGetUnjailedRoot()),
|
|
|
|
|
|
]
|
2021-05-04 13:06:02 -04:00
|
|
|
|
);
|
2020-11-19 03:14:29 -05:00
|
|
|
|
}
|
2022-08-17 07:49:21 -04:00
|
|
|
|
|
|
|
|
|
|
public function getCacheEntryFromSearchResult(ICacheEntry $rawEntry): ?ICacheEntry {
|
|
|
|
|
|
if ($rawEntry->getStorageId() === $this->getNumericStorageId()) {
|
|
|
|
|
|
return parent::getCacheEntryFromSearchResult($rawEntry);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-01-22 13:24:45 -05:00
|
|
|
|
|
|
|
|
|
|
public function markRootChanged(): void {
|
|
|
|
|
|
$this->rootUnchanged = false;
|
|
|
|
|
|
}
|
2013-08-18 05:02:08 -04:00
|
|
|
|
}
|