mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-21 12:35:52 +03:00
properly compute if a folder is top level or child extern mounted
asks new permission to server to be able to know if a folder is a top level mounted folder should allow detecting the top level folders from external storages or group folders should also make the client reliably detect that it is handling a child folder inside a group folder and be allowed to rename such folders Signed-off-by: Matthieu Gallien <matthieu.gallien@nextcloud.com>
This commit is contained in:
parent
b6ff0c5abb
commit
55034f7e43
16 changed files with 114 additions and 26 deletions
|
@ -13,6 +13,10 @@ set(NEXTCLOUD_SERVER_VERSION_SECURE_FILEDROP_MIN_SUPPORTED_MAJOR 26)
|
||||||
set(NEXTCLOUD_SERVER_VERSION_SECURE_FILEDROP_MIN_SUPPORTED_MINOR 0)
|
set(NEXTCLOUD_SERVER_VERSION_SECURE_FILEDROP_MIN_SUPPORTED_MINOR 0)
|
||||||
set(NEXTCLOUD_SERVER_VERSION_SECURE_FILEDROP_MIN_SUPPORTED_PATCH 0)
|
set(NEXTCLOUD_SERVER_VERSION_SECURE_FILEDROP_MIN_SUPPORTED_PATCH 0)
|
||||||
|
|
||||||
|
set(NEXTCLOUD_SERVER_VERSION_MOUNT_ROOT_PROPERTY_SUPPORTED_MAJOR 28)
|
||||||
|
set(NEXTCLOUD_SERVER_VERSION_MOUNT_ROOT_PROPERTY_SUPPORTED_MINOR 0)
|
||||||
|
set(NEXTCLOUD_SERVER_VERSION_MOUNT_ROOT_PROPERTY_SUPPORTED_PATCH 3)
|
||||||
|
|
||||||
if ( NOT DEFINED MIRALL_VERSION_SUFFIX )
|
if ( NOT DEFINED MIRALL_VERSION_SUFFIX )
|
||||||
set( MIRALL_VERSION_SUFFIX "git") #e.g. beta1, beta2, rc1
|
set( MIRALL_VERSION_SUFFIX "git") #e.g. beta1, beta2, rc1
|
||||||
endif( NOT DEFINED MIRALL_VERSION_SUFFIX )
|
endif( NOT DEFINED MIRALL_VERSION_SUFFIX )
|
||||||
|
|
|
@ -17,10 +17,15 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "remotepermissions.h"
|
#include "remotepermissions.h"
|
||||||
|
|
||||||
|
#include <QLoggingCategory>
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
namespace OCC {
|
namespace OCC {
|
||||||
|
|
||||||
|
Q_LOGGING_CATEGORY(lcRemotePermissions, "nextcloud.sync.remotepermissions", QtInfoMsg)
|
||||||
|
|
||||||
static const char letters[] = " WDNVCKRSMm";
|
static const char letters[] = " WDNVCKRSMm";
|
||||||
|
|
||||||
|
|
||||||
|
@ -68,11 +73,43 @@ RemotePermissions RemotePermissions::fromDbValue(const QByteArray &value)
|
||||||
return perm;
|
return perm;
|
||||||
}
|
}
|
||||||
|
|
||||||
RemotePermissions RemotePermissions::fromServerString(const QString &value)
|
template <typename T>
|
||||||
|
RemotePermissions RemotePermissions::internalFromServerString(const QString &value,
|
||||||
|
const T&otherProperties,
|
||||||
|
MountedPermissionAlgorithm algorithm)
|
||||||
{
|
{
|
||||||
RemotePermissions perm;
|
RemotePermissions perm;
|
||||||
perm.fromArray(value.utf16());
|
perm.fromArray(value.utf16());
|
||||||
|
|
||||||
|
if (algorithm == MountedPermissionAlgorithm::WildGuessMountedSubProperty) {
|
||||||
|
return perm;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((otherProperties.contains(QStringLiteral("is-mount-root")) && otherProperties.value(QStringLiteral("is-mount-root")) == QStringLiteral("false") && perm.hasPermission(RemotePermissions::IsMounted)) ||
|
||||||
|
(!otherProperties.contains(QStringLiteral("is-mount-root")) && perm.hasPermission(RemotePermissions::IsMounted))) {
|
||||||
|
/* All the entries in a external storage have 'M' in their permission. However, for all
|
||||||
|
purposes in the desktop client, we only need to know about the mount points.
|
||||||
|
So replace the 'M' by a 'm' for every sub entries in an external storage */
|
||||||
|
perm.unsetPermission(RemotePermissions::IsMounted);
|
||||||
|
perm.setPermission(RemotePermissions::IsMountedSub);
|
||||||
|
qCInfo(lcRemotePermissions()) << otherProperties.value(QStringLiteral("permissions")) << "replacing M permissions by m for subfolders inside a group folder";
|
||||||
|
}
|
||||||
|
|
||||||
return perm;
|
return perm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RemotePermissions RemotePermissions::fromServerString(const QString &value,
|
||||||
|
MountedPermissionAlgorithm algorithm,
|
||||||
|
const QMap<QString, QString> &otherProperties)
|
||||||
|
{
|
||||||
|
return internalFromServerString(value, otherProperties, algorithm);
|
||||||
|
}
|
||||||
|
|
||||||
|
RemotePermissions RemotePermissions::fromServerString(const QString &value,
|
||||||
|
MountedPermissionAlgorithm algorithm,
|
||||||
|
const QVariantMap &otherProperties)
|
||||||
|
{
|
||||||
|
return internalFromServerString(value, otherProperties, algorithm);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace OCC
|
} // namespace OCC
|
||||||
|
|
|
@ -59,6 +59,11 @@ public:
|
||||||
PermissionsCount = IsMountedSub
|
PermissionsCount = IsMountedSub
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class MountedPermissionAlgorithm {
|
||||||
|
UseMountRootProperty,
|
||||||
|
WildGuessMountedSubProperty,
|
||||||
|
};
|
||||||
|
|
||||||
/// null permissions
|
/// null permissions
|
||||||
RemotePermissions() = default;
|
RemotePermissions() = default;
|
||||||
|
|
||||||
|
@ -72,7 +77,14 @@ public:
|
||||||
static RemotePermissions fromDbValue(const QByteArray &);
|
static RemotePermissions fromDbValue(const QByteArray &);
|
||||||
|
|
||||||
/// read a permissions string received from the server, never null
|
/// read a permissions string received from the server, never null
|
||||||
static RemotePermissions fromServerString(const QString &);
|
static RemotePermissions fromServerString(const QString &value,
|
||||||
|
MountedPermissionAlgorithm algorithm = MountedPermissionAlgorithm::WildGuessMountedSubProperty,
|
||||||
|
const QMap<QString, QString> &otherProperties = {});
|
||||||
|
|
||||||
|
/// read a permissions string received from the server, never null
|
||||||
|
static RemotePermissions fromServerString(const QString &value,
|
||||||
|
MountedPermissionAlgorithm algorithm,
|
||||||
|
const QVariantMap &otherProperties = {});
|
||||||
|
|
||||||
[[nodiscard]] bool hasPermission(Permissions p) const
|
[[nodiscard]] bool hasPermission(Permissions p) const
|
||||||
{
|
{
|
||||||
|
@ -101,6 +113,13 @@ public:
|
||||||
{
|
{
|
||||||
return dbg << p.toString();
|
return dbg << p.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static RemotePermissions internalFromServerString(const QString &value,
|
||||||
|
const T&otherProperties,
|
||||||
|
MountedPermissionAlgorithm algorithm);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -213,7 +213,8 @@ void EditLocallyJob::fetchRemoteFileParentInfo()
|
||||||
QByteArrayLiteral("http://owncloud.org/ns:size"),
|
QByteArrayLiteral("http://owncloud.org/ns:size"),
|
||||||
QByteArrayLiteral("http://owncloud.org/ns:id"),
|
QByteArrayLiteral("http://owncloud.org/ns:id"),
|
||||||
QByteArrayLiteral("http://owncloud.org/ns:permissions"),
|
QByteArrayLiteral("http://owncloud.org/ns:permissions"),
|
||||||
QByteArrayLiteral("http://owncloud.org/ns:checksums")};
|
QByteArrayLiteral("http://owncloud.org/ns:checksums"),
|
||||||
|
QByteArrayLiteral("http://nextcloud.org/ns:is-mount-root")};
|
||||||
|
|
||||||
job->setProperties(props);
|
job->setProperties(props);
|
||||||
connect(job, &LsColJob::directoryListingIterated, this, &EditLocallyJob::slotDirectoryListingIterated);
|
connect(job, &LsColJob::directoryListingIterated, this, &EditLocallyJob::slotDirectoryListingIterated);
|
||||||
|
@ -545,7 +546,9 @@ void EditLocallyJob::slotDirectoryListingIterated(const QString &name, const QMa
|
||||||
const auto cleanName = nameWithoutDavPath.startsWith(remoteFolderPathWithoutLeadingSlash)
|
const auto cleanName = nameWithoutDavPath.startsWith(remoteFolderPathWithoutLeadingSlash)
|
||||||
? nameWithoutDavPath.mid(remoteFolderPathWithoutLeadingSlash.size()) : nameWithoutDavPath;
|
? nameWithoutDavPath.mid(remoteFolderPathWithoutLeadingSlash.size()) : nameWithoutDavPath;
|
||||||
disconnect(job, &LsColJob::directoryListingIterated, this, &EditLocallyJob::slotDirectoryListingIterated);
|
disconnect(job, &LsColJob::directoryListingIterated, this, &EditLocallyJob::slotDirectoryListingIterated);
|
||||||
_fileParentItem = SyncFileItem::fromProperties(cleanName, properties);
|
_fileParentItem = SyncFileItem::fromProperties(cleanName,
|
||||||
|
properties,
|
||||||
|
_accountState->account()->serverHasMountRootProperty() ? RemotePermissions::MountedPermissionAlgorithm::UseMountRootProperty : RemotePermissions::MountedPermissionAlgorithm::WildGuessMountedSubProperty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -616,6 +616,7 @@ void FolderStatusModel::fetchMore(const QModelIndex &parent)
|
||||||
auto props = QList<QByteArray>() << "resourcetype"
|
auto props = QList<QByteArray>() << "resourcetype"
|
||||||
<< "http://owncloud.org/ns:size"
|
<< "http://owncloud.org/ns:size"
|
||||||
<< "http://owncloud.org/ns:permissions"
|
<< "http://owncloud.org/ns:permissions"
|
||||||
|
<< "http://nextcloud.org/ns:is-mount-root"
|
||||||
<< "http://owncloud.org/ns:fileid";
|
<< "http://owncloud.org/ns:fileid";
|
||||||
if (_accountState->account()->capabilities().clientSideEncryptionAvailable()) {
|
if (_accountState->account()->capabilities().clientSideEncryptionAvailable()) {
|
||||||
props << "http://nextcloud.org/ns:is-encrypted";
|
props << "http://nextcloud.org/ns:is-encrypted";
|
||||||
|
|
|
@ -117,7 +117,7 @@ InvalidFilenameDialog::~InvalidFilenameDialog() = default;
|
||||||
void InvalidFilenameDialog::checkIfAllowedToRename()
|
void InvalidFilenameDialog::checkIfAllowedToRename()
|
||||||
{
|
{
|
||||||
const auto propfindJob = new PropfindJob(_account, QDir::cleanPath(_folder->remotePath() + _originalFileName));
|
const auto propfindJob = new PropfindJob(_account, QDir::cleanPath(_folder->remotePath() + _originalFileName));
|
||||||
propfindJob->setProperties({ "http://owncloud.org/ns:permissions" });
|
propfindJob->setProperties({"http://owncloud.org/ns:permissions", "http://nextcloud.org/ns:is-mount-root"});
|
||||||
connect(propfindJob, &PropfindJob::result, this, &InvalidFilenameDialog::onPropfindPermissionSuccess);
|
connect(propfindJob, &PropfindJob::result, this, &InvalidFilenameDialog::onPropfindPermissionSuccess);
|
||||||
connect(propfindJob, &PropfindJob::finishedWithError, this, &InvalidFilenameDialog::onPropfindPermissionError);
|
connect(propfindJob, &PropfindJob::finishedWithError, this, &InvalidFilenameDialog::onPropfindPermissionError);
|
||||||
propfindJob->start();
|
propfindJob->start();
|
||||||
|
|
|
@ -169,7 +169,7 @@ void ShellExtensionsServer::processCustomStateRequest(QLocalSocket *socket, cons
|
||||||
}));
|
}));
|
||||||
|
|
||||||
auto *const lsColJob = new LsColJob(folder->accountState()->account(), QDir::cleanPath(folder->remotePath() + lsColJobPath));
|
auto *const lsColJob = new LsColJob(folder->accountState()->account(), QDir::cleanPath(folder->remotePath() + lsColJobPath));
|
||||||
lsColJob->setProperties({QByteArrayLiteral("http://owncloud.org/ns:share-types"), QByteArrayLiteral("http://owncloud.org/ns:permissions")});
|
lsColJob->setProperties({QByteArrayLiteral("http://owncloud.org/ns:share-types"), QByteArrayLiteral("http://owncloud.org/ns:permissions"), QByteArrayLiteral("http://nextcloud.org/ns:is-mount-root")});
|
||||||
|
|
||||||
const auto folderAlias = customStateRequestInfo.folderAlias;
|
const auto folderAlias = customStateRequestInfo.folderAlias;
|
||||||
|
|
||||||
|
|
|
@ -731,6 +731,17 @@ int Account::serverVersionInt() const
|
||||||
components.value(2).toInt());
|
components.value(2).toInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Account::serverHasMountRootProperty() const
|
||||||
|
{
|
||||||
|
if (serverVersionInt() == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return serverVersionInt() >= Account::makeServerVersion(NEXTCLOUD_SERVER_VERSION_MOUNT_ROOT_PROPERTY_SUPPORTED_MAJOR,
|
||||||
|
NEXTCLOUD_SERVER_VERSION_MOUNT_ROOT_PROPERTY_SUPPORTED_MINOR,
|
||||||
|
NEXTCLOUD_SERVER_VERSION_MOUNT_ROOT_PROPERTY_SUPPORTED_PATCH);
|
||||||
|
}
|
||||||
|
|
||||||
bool Account::serverVersionUnsupported() const
|
bool Account::serverVersionUnsupported() const
|
||||||
{
|
{
|
||||||
if (serverVersionInt() == 0) {
|
if (serverVersionInt() == 0) {
|
||||||
|
|
|
@ -247,6 +247,8 @@ public:
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] int serverVersionInt() const;
|
[[nodiscard]] int serverVersionInt() const;
|
||||||
|
|
||||||
|
[[nodiscard]] bool serverHasMountRootProperty() const;
|
||||||
|
|
||||||
static constexpr int makeServerVersion(const int majorVersion, const int minorVersion, const int patchVersion) {
|
static constexpr int makeServerVersion(const int majorVersion, const int minorVersion, const int patchVersion) {
|
||||||
return (majorVersion << 16) + (minorVersion << 8) + patchVersion;
|
return (majorVersion << 16) + (minorVersion << 8) + patchVersion;
|
||||||
};
|
};
|
||||||
|
|
|
@ -220,7 +220,7 @@ void CaseClashConflictSolver::processLeadingOrTrailingSpacesError(const QString
|
||||||
void CaseClashConflictSolver::checkIfAllowedToRename()
|
void CaseClashConflictSolver::checkIfAllowedToRename()
|
||||||
{
|
{
|
||||||
const auto propfindJob = new PropfindJob(_account, QDir::cleanPath(remoteTargetFilePath()));
|
const auto propfindJob = new PropfindJob(_account, QDir::cleanPath(remoteTargetFilePath()));
|
||||||
propfindJob->setProperties({ "http://owncloud.org/ns:permissions" });
|
propfindJob->setProperties({"http://owncloud.org/ns:permissions", "http://nextcloud.org/ns:is-mount-root"});
|
||||||
connect(propfindJob, &PropfindJob::result, this, &CaseClashConflictSolver::onPropfindPermissionSuccess);
|
connect(propfindJob, &PropfindJob::result, this, &CaseClashConflictSolver::onPropfindPermissionSuccess);
|
||||||
connect(propfindJob, &PropfindJob::finishedWithError, this, &CaseClashConflictSolver::onPropfindPermissionError);
|
connect(propfindJob, &PropfindJob::finishedWithError, this, &CaseClashConflictSolver::onPropfindPermissionError);
|
||||||
propfindJob->start();
|
propfindJob->start();
|
||||||
|
|
|
@ -1438,14 +1438,18 @@ void ProcessDirectoryJob::processFileAnalyzeLocalInfo(
|
||||||
|
|
||||||
// Check local permission if we are allowed to put move the file here
|
// Check local permission if we are allowed to put move the file here
|
||||||
// Technically we should use the permissions from the server, but we'll assume it is the same
|
// Technically we should use the permissions from the server, but we'll assume it is the same
|
||||||
|
const auto serverHasMountRootProperty = _discoveryData->_account->serverHasMountRootProperty();
|
||||||
const auto isExternalStorage = base._remotePerm.hasPermission(RemotePermissions::IsMounted);
|
const auto isExternalStorage = base._remotePerm.hasPermission(RemotePermissions::IsMounted);
|
||||||
const auto movePerms = checkMovePermissions(base._remotePerm, originalPath, item->isDirectory());
|
const auto movePerms = checkMovePermissions(base._remotePerm, originalPath, item->isDirectory());
|
||||||
if (!movePerms.sourceOk || !movePerms.destinationOk || isExternalStorage || isE2eeMoveOnlineOnlyItemWithCfApi) {
|
if (!movePerms.sourceOk || !movePerms.destinationOk || (serverHasMountRootProperty && isExternalStorage) || isE2eeMoveOnlineOnlyItemWithCfApi) {
|
||||||
qCInfo(lcDisco) << "Move without permission to rename base file, "
|
qCInfo(lcDisco) << "Move without permission to rename base file, "
|
||||||
<< "source:" << movePerms.sourceOk
|
<< "source:" << movePerms.sourceOk
|
||||||
<< ", target:" << movePerms.destinationOk
|
<< ", target:" << movePerms.destinationOk
|
||||||
<< ", targetNew:" << movePerms.destinationNewOk
|
<< ", targetNew:" << movePerms.destinationNewOk
|
||||||
<< ", isExternalStorage:" << isExternalStorage;
|
<< ", isExternalStorage:" << isExternalStorage
|
||||||
|
<< ", serverHasMountRootProperty:" << serverHasMountRootProperty
|
||||||
|
<< ", base._remotePerm:" << base._remotePerm.toString()
|
||||||
|
<< ", base.path():" << base.path();
|
||||||
|
|
||||||
// If we can create the destination, do that.
|
// If we can create the destination, do that.
|
||||||
// Permission errors on the destination will be handled by checkPermissions later.
|
// Permission errors on the destination will be handled by checkPermissions later.
|
||||||
|
|
|
@ -419,6 +419,7 @@ void DiscoverySingleDirectoryJob::start()
|
||||||
<< "http://nextcloud.org/ns:lock-time"
|
<< "http://nextcloud.org/ns:lock-time"
|
||||||
<< "http://nextcloud.org/ns:lock-timeout";
|
<< "http://nextcloud.org/ns:lock-timeout";
|
||||||
}
|
}
|
||||||
|
props << "http://nextcloud.org/ns:is-mount-root";
|
||||||
|
|
||||||
lsColJob->setProperties(props);
|
lsColJob->setProperties(props);
|
||||||
|
|
||||||
|
@ -458,7 +459,7 @@ SyncFileItem::EncryptionStatus DiscoverySingleDirectoryJob::requiredEncryptionSt
|
||||||
return _encryptionStatusRequired;
|
return _encryptionStatusRequired;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void propertyMapToRemoteInfo(const QMap<QString, QString> &map, RemoteInfo &result)
|
static void propertyMapToRemoteInfo(const QMap<QString, QString> &map, RemotePermissions::MountedPermissionAlgorithm algorithm, RemoteInfo &result)
|
||||||
{
|
{
|
||||||
for (auto it = map.constBegin(); it != map.constEnd(); ++it) {
|
for (auto it = map.constBegin(); it != map.constEnd(); ++it) {
|
||||||
QString property = it.key();
|
QString property = it.key();
|
||||||
|
@ -490,7 +491,7 @@ static void propertyMapToRemoteInfo(const QMap<QString, QString> &map, RemoteInf
|
||||||
} else if (property == "dDC") {
|
} else if (property == "dDC") {
|
||||||
result.directDownloadCookies = value;
|
result.directDownloadCookies = value;
|
||||||
} else if (property == "permissions") {
|
} else if (property == "permissions") {
|
||||||
result.remotePerm = RemotePermissions::fromServerString(value);
|
result.remotePerm = RemotePermissions::fromServerString(value, algorithm, map);
|
||||||
} else if (property == "checksums") {
|
} else if (property == "checksums") {
|
||||||
result.checksumHeader = findBestChecksum(value.toUtf8());
|
result.checksumHeader = findBestChecksum(value.toUtf8());
|
||||||
} else if (property == "share-types" && !value.isEmpty()) {
|
} else if (property == "share-types" && !value.isEmpty()) {
|
||||||
|
@ -560,7 +561,10 @@ void DiscoverySingleDirectoryJob::directoryListingIteratedSlot(const QString &fi
|
||||||
// The first entry is for the folder itself, we should process it differently.
|
// The first entry is for the folder itself, we should process it differently.
|
||||||
_ignoredFirst = true;
|
_ignoredFirst = true;
|
||||||
if (map.contains("permissions")) {
|
if (map.contains("permissions")) {
|
||||||
auto perm = RemotePermissions::fromServerString(map.value("permissions"));
|
auto perm = RemotePermissions::fromServerString(map.value("permissions"),
|
||||||
|
_account->serverHasMountRootProperty() ? RemotePermissions::MountedPermissionAlgorithm::UseMountRootProperty : RemotePermissions::MountedPermissionAlgorithm::WildGuessMountedSubProperty,
|
||||||
|
map);
|
||||||
|
qCInfo(lcDiscovery()) << file << map.value("permissions") << map;
|
||||||
emit firstDirectoryPermissions(perm);
|
emit firstDirectoryPermissions(perm);
|
||||||
_isExternalStorage = perm.hasPermission(RemotePermissions::IsMounted);
|
_isExternalStorage = perm.hasPermission(RemotePermissions::IsMounted);
|
||||||
}
|
}
|
||||||
|
@ -585,22 +589,17 @@ void DiscoverySingleDirectoryJob::directoryListingIteratedSlot(const QString &fi
|
||||||
_size = map.value("size").toInt();
|
_size = map.value("size").toInt();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
RemoteInfo result;
|
RemoteInfo result;
|
||||||
int slash = file.lastIndexOf('/');
|
int slash = file.lastIndexOf('/');
|
||||||
result.name = file.mid(slash + 1);
|
result.name = file.mid(slash + 1);
|
||||||
result.size = -1;
|
result.size = -1;
|
||||||
propertyMapToRemoteInfo(map, result);
|
propertyMapToRemoteInfo(map,
|
||||||
|
_account->serverHasMountRootProperty() ? RemotePermissions::MountedPermissionAlgorithm::UseMountRootProperty : RemotePermissions::MountedPermissionAlgorithm::WildGuessMountedSubProperty,
|
||||||
|
result);
|
||||||
if (result.isDirectory)
|
if (result.isDirectory)
|
||||||
result.size = 0;
|
result.size = 0;
|
||||||
|
|
||||||
if (_isExternalStorage && result.remotePerm.hasPermission(RemotePermissions::IsMounted)) {
|
qCInfo(lcDiscovery()) << file << map.value("permissions") << result.remotePerm.toString() << map;
|
||||||
/* All the entries in a external storage have 'M' in their permission. However, for all
|
|
||||||
purposes in the desktop client, we only need to know about the mount points.
|
|
||||||
So replace the 'M' by a 'm' for every sub entries in an external storage */
|
|
||||||
result.remotePerm.unsetPermission(RemotePermissions::IsMounted);
|
|
||||||
result.remotePerm.setPermission(RemotePermissions::IsMountedSub);
|
|
||||||
}
|
|
||||||
_results.push_back(std::move(result));
|
_results.push_back(std::move(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -139,10 +139,13 @@ void PropagateRemoteMkdir::finalizeMkColJob(QNetworkReply::NetworkError err, con
|
||||||
|
|
||||||
propagator()->_activeJobList.append(this);
|
propagator()->_activeJobList.append(this);
|
||||||
auto propfindJob = new PropfindJob(propagator()->account(), jobPath, this);
|
auto propfindJob = new PropfindJob(propagator()->account(), jobPath, this);
|
||||||
propfindJob->setProperties({QByteArrayLiteral("http://owncloud.org/ns:share-types"), QByteArrayLiteral("http://owncloud.org/ns:permissions")});
|
propfindJob->setProperties({QByteArrayLiteral("http://owncloud.org/ns:share-types"), QByteArrayLiteral("http://owncloud.org/ns:permissions"), QByteArrayLiteral("http://nextcloud.org/ns:is-mount-root")});
|
||||||
connect(propfindJob, &PropfindJob::result, this, [this, jobPath](const QVariantMap &result){
|
connect(propfindJob, &PropfindJob::result, this, [this, jobPath](const QVariantMap &result){
|
||||||
propagator()->_activeJobList.removeOne(this);
|
propagator()->_activeJobList.removeOne(this);
|
||||||
_item->_remotePerm = RemotePermissions::fromServerString(result.value(QStringLiteral("permissions")).toString());
|
_item->_remotePerm = RemotePermissions::fromServerString(result.value(QStringLiteral("permissions")).toString(),
|
||||||
|
propagator()->account()->serverHasMountRootProperty() ? RemotePermissions::MountedPermissionAlgorithm::UseMountRootProperty : RemotePermissions::MountedPermissionAlgorithm::WildGuessMountedSubProperty,
|
||||||
|
result);
|
||||||
|
|
||||||
_item->_sharedByMe = !result.value(QStringLiteral("share-types")).toString().isEmpty();
|
_item->_sharedByMe = !result.value(QStringLiteral("share-types")).toString().isEmpty();
|
||||||
_item->_isShared = _item->_remotePerm.hasPermission(RemotePermissions::IsShared) || _item->_sharedByMe;
|
_item->_isShared = _item->_remotePerm.hasPermission(RemotePermissions::IsShared) || _item->_sharedByMe;
|
||||||
_item->_lastShareStateFetchedTimestamp = QDateTime::currentMSecsSinceEpoch();
|
_item->_lastShareStateFetchedTimestamp = QDateTime::currentMSecsSinceEpoch();
|
||||||
|
@ -231,6 +234,7 @@ void PropagateRemoteMkdir::slotMkcolJobFinished()
|
||||||
|
|
||||||
_item->_fileId = _job->reply()->rawHeader("OC-FileId");
|
_item->_fileId = _job->reply()->rawHeader("OC-FileId");
|
||||||
|
|
||||||
|
qCInfo(lcPropagateRemoteMkdir()) << "mkcol job error string:" << _item->_errorString << _job->errorString();
|
||||||
_item->_errorString = _job->errorString();
|
_item->_errorString = _job->errorString();
|
||||||
|
|
||||||
const auto jobHttpReasonPhraseString = _job->reply()->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
|
const auto jobHttpReasonPhraseString = _job->reply()->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
|
||||||
|
|
|
@ -169,7 +169,7 @@ SyncFileItemPtr SyncFileItem::fromSyncJournalFileRecord(const SyncJournalFileRec
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
SyncFileItemPtr SyncFileItem::fromProperties(const QString &filePath, const QMap<QString, QString> &properties)
|
SyncFileItemPtr SyncFileItem::fromProperties(const QString &filePath, const QMap<QString, QString> &properties, RemotePermissions::MountedPermissionAlgorithm algorithm)
|
||||||
{
|
{
|
||||||
SyncFileItemPtr item(new SyncFileItem);
|
SyncFileItemPtr item(new SyncFileItem);
|
||||||
item->_file = filePath;
|
item->_file = filePath;
|
||||||
|
@ -182,7 +182,7 @@ SyncFileItemPtr SyncFileItem::fromProperties(const QString &filePath, const QMap
|
||||||
item->_fileId = properties.value(QStringLiteral("id")).toUtf8();
|
item->_fileId = properties.value(QStringLiteral("id")).toUtf8();
|
||||||
|
|
||||||
if (properties.contains(QStringLiteral("permissions"))) {
|
if (properties.contains(QStringLiteral("permissions"))) {
|
||||||
item->_remotePerm = RemotePermissions::fromServerString(properties.value("permissions"));
|
item->_remotePerm = RemotePermissions::fromServerString(properties.value("permissions"), algorithm, properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!properties.value(QStringLiteral("share-types")).isEmpty()) {
|
if (!properties.value(QStringLiteral("share-types")).isEmpty()) {
|
||||||
|
|
|
@ -133,7 +133,7 @@ public:
|
||||||
|
|
||||||
/** Creates a basic SyncFileItem from remote properties
|
/** Creates a basic SyncFileItem from remote properties
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] static SyncFileItemPtr fromProperties(const QString &filePath, const QMap<QString, QString> &properties);
|
[[nodiscard]] static SyncFileItemPtr fromProperties(const QString &filePath, const QMap<QString, QString> &properties, RemotePermissions::MountedPermissionAlgorithm algorithm);
|
||||||
|
|
||||||
|
|
||||||
SyncFileItem()
|
SyncFileItem()
|
||||||
|
|
|
@ -45,4 +45,8 @@ constexpr int NEXTCLOUD_SERVER_VERSION_SECURE_FILEDROP_MIN_SUPPORTED_MAJOR = @NE
|
||||||
constexpr int NEXTCLOUD_SERVER_VERSION_SECURE_FILEDROP_MIN_SUPPORTED_MINOR = @NEXTCLOUD_SERVER_VERSION_SECURE_FILEDROP_MIN_SUPPORTED_MINOR@;
|
constexpr int NEXTCLOUD_SERVER_VERSION_SECURE_FILEDROP_MIN_SUPPORTED_MINOR = @NEXTCLOUD_SERVER_VERSION_SECURE_FILEDROP_MIN_SUPPORTED_MINOR@;
|
||||||
constexpr int NEXTCLOUD_SERVER_VERSION_SECURE_FILEDROP_MIN_SUPPORTED_PATCH = @NEXTCLOUD_SERVER_VERSION_SECURE_FILEDROP_MIN_SUPPORTED_PATCH@;
|
constexpr int NEXTCLOUD_SERVER_VERSION_SECURE_FILEDROP_MIN_SUPPORTED_PATCH = @NEXTCLOUD_SERVER_VERSION_SECURE_FILEDROP_MIN_SUPPORTED_PATCH@;
|
||||||
|
|
||||||
|
constexpr int NEXTCLOUD_SERVER_VERSION_MOUNT_ROOT_PROPERTY_SUPPORTED_MAJOR = @NEXTCLOUD_SERVER_VERSION_MOUNT_ROOT_PROPERTY_SUPPORTED_MAJOR@;
|
||||||
|
constexpr int NEXTCLOUD_SERVER_VERSION_MOUNT_ROOT_PROPERTY_SUPPORTED_MINOR = @NEXTCLOUD_SERVER_VERSION_MOUNT_ROOT_PROPERTY_SUPPORTED_MINOR@;
|
||||||
|
constexpr int NEXTCLOUD_SERVER_VERSION_MOUNT_ROOT_PROPERTY_SUPPORTED_PATCH = @NEXTCLOUD_SERVER_VERSION_MOUNT_ROOT_PROPERTY_SUPPORTED_PATCH@;
|
||||||
|
|
||||||
#endif // VERSION_H
|
#endif // VERSION_H
|
||||||
|
|
Loading…
Reference in a new issue