Skip to content
1 change: 1 addition & 0 deletions src/common/preparedsqlquerymanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

#pragma once

#include "ocsynclib.h"

Check failure on line 9 in src/common/preparedsqlquerymanager.h

View workflow job for this annotation

GitHub Actions / build

src/common/preparedsqlquerymanager.h:9:10 [clang-diagnostic-error]

'ocsynclib.h' file not found
#include "ownsql.h"
#include "common/asserts.h"

Expand Down Expand Up @@ -95,9 +95,10 @@
GetE2EeLockedFolderQuery,
GetE2EeLockedFoldersQuery,
DeleteE2EeLockedFolderQuery,
ListAllTopLevelE2eeFoldersStatusLessThanQuery,

Check warning on line 98 in src/common/preparedsqlquerymanager.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename this identifier to be shorter or equal to 31 characters.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrqWNNkyc6hI4c6uhNz&open=AZrqWNNkyc6hI4c6uhNz&pullRequest=8502
FolderUpdateInvalidEncryptionStatus,
FileUpdateInvalidEncryptionStatus,
HasFileIdQuery,

PreparedQueryCount
};
Expand Down
56 changes: 56 additions & 0 deletions src/common/syncjournaldb.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
/*
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2014 ownCloud GmbH
* SPDX-License-Identifier: LGPL-2.1-or-later
*/

#include <QCryptographicHash>

Check failure on line 7 in src/common/syncjournaldb.cpp

View workflow job for this annotation

GitHub Actions / build

src/common/syncjournaldb.cpp:7:10 [clang-diagnostic-error]

'QCryptographicHash' file not found
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QLoggingCategory>
#include <QStringList>
#include <QElapsedTimer>
Expand Down Expand Up @@ -33,6 +35,8 @@
static constexpr auto MAJOR_VERSION_3 = 3;
static constexpr auto MINOR_VERSION_16 = 16;

using namespace Qt::StringLiterals;

namespace OCC {

Q_LOGGING_CATEGORY(lcDb, "nextcloud.sync.database", QtInfoMsg)
Expand Down Expand Up @@ -115,7 +119,7 @@
const QString &remotePath,
const QString &user)
{
QString journalPath = QStringLiteral(".sync_");

Check warning on line 122 in src/common/syncjournaldb.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace the redundant type with "auto".

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNv2-AmAAmoZrwMS&open=AZrpGNv2-AmAAmoZrwMS&pullRequest=8502

QString key = QStringLiteral("%1@%2:%3").arg(user, remoteUrl.toString(), remotePath);

Expand Down Expand Up @@ -1004,7 +1008,7 @@
#endif

qint64 h = 0;
int len = bytes.length();

Check warning on line 1011 in src/common/syncjournaldb.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

implicit conversion loses integer precision: 'qsizetype' (aka 'long long') to 'int'

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNv2-AmAAmoZrwMQ&open=AZrpGNv2-AmAAmoZrwMQ&pullRequest=8502

h = c_jhash64((uint8_t *)bytes.data(), len, 0);
return h;
Expand Down Expand Up @@ -1057,7 +1061,7 @@
return tr("Failed to connect database."); // checkConnect failed.
}

int plen = record._path.length();

Check warning on line 1064 in src/common/syncjournaldb.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

implicit conversion loses integer precision: 'qsizetype' (aka 'long long') to 'int'

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNv2-AmAAmoZrwMR&open=AZrpGNv2-AmAAmoZrwMR&pullRequest=8502

QByteArray etag(record._etag);
if (etag.isEmpty()) {
Expand Down Expand Up @@ -1129,7 +1133,7 @@
return {};
}

bool SyncJournalDb::getRootE2eFolderRecord(const QString &remoteFolderPath, SyncJournalFileRecord *rec)

Check warning on line 1136 in src/common/syncjournaldb.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "rec" of type "class OCC::SyncJournalFileRecord *" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNv2-AmAAmoZrwMZ&open=AZrpGNv2-AmAAmoZrwMZ&pullRequest=8502
{
Q_ASSERT(rec);
rec->_path.clear();
Expand Down Expand Up @@ -1769,6 +1773,58 @@
return true;
}

bool SyncJournalDb::hasFileIds(const QList<qint64> &fileIds)
{
if (fileIds.isEmpty()) {
// no need to check the db if no file id matches
return false;
}

QMutexLocker locker(&_mutex);

if (!checkConnect()) {
return false;
}

// quick workaround for looking up pure numeric file IDs: cast it to integer
//
// using `IN` with a list of IDs does not allow for a prepared query: the execution plan
// would be different depending on the amount of elements as each element is added to a
// temporary table one-by-one. with `json_each()`, all that changes is one string
// parameter which is perfect for creating a prepared query :)
const auto query = _queryManager.get(
PreparedSqlQueryManager::HasFileIdQuery,
"SELECT 1 FROM metadata, json_each(?1) file_ids WHERE CAST(metadata.fileid AS INTEGER) = CAST(file_ids.value AS INTEGER) LIMIT 1;"_ba,
_db
);
if (!query) {
qCWarning(lcDb) << "database error:" << query->error();
return false;
}

// we have a prepared query, so let's build up a JSON array of file IDs to check for.
// Strings are used here to avoid any surprises during serialisation: JSON only really
// has a double type, and who knows when the representation changes to the +e* variant.
QJsonArray fileIdStrings = {};
for (const auto &fileId : fileIds) {
fileIdStrings.append(QString::number(fileId));
}
const auto fileIdsParameter = QJsonDocument(fileIdStrings).toJson(QJsonDocument::Compact);
query->bindValue(1, fileIdsParameter);

if (!query->exec()) {
qCWarning(lcDb) << "file id query failed:" << query->error();
return false;
}

if (query->next().hasData && query->intValue(0) == 1) {
// at least one file ID from the passed list is present
return true;
}

return false;
}

Optional<SyncJournalDb::HasHydratedDehydrated> SyncJournalDb::hasHydratedOrDehydratedFiles(const QByteArray &filename)
{
QMutexLocker locker(&_mutex);
Expand Down Expand Up @@ -2708,7 +2764,7 @@
{
ConflictRecord entry;

QMutexLocker locker(&_mutex);

Check warning on line 2767 in src/common/syncjournaldb.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "locker" of type "class QMutexLocker<class QRecursiveMutex>" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNv2-AmAAmoZrwMc&open=AZrpGNv2-AmAAmoZrwMc&pullRequest=8502
if (!checkConnect()) {
return entry;
}
Expand Down
2 changes: 2 additions & 0 deletions src/common/syncjournaldb.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#ifndef SYNCJOURNALDB_H
#define SYNCJOURNALDB_H

#include <QObject>

Check failure on line 10 in src/common/syncjournaldb.h

View workflow job for this annotation

GitHub Actions / build

src/common/syncjournaldb.h:10:10 [clang-diagnostic-error]

'QObject' file not found
#include <QDateTime>
#include <QHash>
#include <QMutex>
Expand Down Expand Up @@ -76,6 +76,8 @@
[[nodiscard]] bool updateLocalMetadata(const QString &filename,
qint64 modtime, qint64 size, quint64 inode, const SyncJournalFileLockInfo &lockInfo);

[[nodiscard]] bool hasFileIds(const QList<qint64> &fileIds);

/// Return value for hasHydratedOrDehydratedFiles()
struct HasHydratedDehydrated
{
Expand Down
12 changes: 12 additions & 0 deletions src/gui/folder.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/*
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2014 ownCloud GmbH
* SPDX-License-Identifier: GPL-2.0-or-later
*/

#include "common/syncjournaldb.h"

Check failure on line 7 in src/gui/folder.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/folder.cpp:7:10 [clang-diagnostic-error]

'common/syncjournaldb.h' file not found
#include "config.h"

#include "account.h"
Expand Down Expand Up @@ -92,6 +92,7 @@

connect(_accountState.data(), &AccountState::isConnectedChanged, this, &Folder::canSyncChanged);
connect(_engine.data(), &SyncEngine::rootEtag, this, &Folder::etagRetrievedFromSyncEngine);
connect(_engine.data(), &SyncEngine::rootFileIdReceived, this, &Folder::rootFileIdReceivedFromSyncEngine);

connect(_engine.data(), &SyncEngine::started, this, &Folder::slotSyncStarted, Qt::QueuedConnection);
connect(_engine.data(), &SyncEngine::finished, this, &Folder::slotSyncFinished, Qt::QueuedConnection);
Expand Down Expand Up @@ -203,7 +204,7 @@

QString Folder::shortGuiRemotePathOrAppName() const
{
if (remotePath().length() > 0 && remotePath() != QLatin1String("/")) {

Check warning on line 207 in src/gui/folder.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use "isEmpty()" to check whether the container is empty or not.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNij-AmAAmoZrwJx&open=AZrpGNij-AmAAmoZrwJx&pullRequest=8502
QString a = QFile(remotePath()).fileName();
if (a.startsWith('/')) {
a = a.remove(0, 1);
Expand Down Expand Up @@ -396,7 +397,13 @@
_lastEtag = etag;
}

void Folder::rootFileIdReceivedFromSyncEngine(const qint64 fileId)

Check warning on line 400 in src/gui/folder.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename this identifier to be shorter or equal to 31 characters.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNij-AmAAmoZrwJz&open=AZrpGNij-AmAAmoZrwJz&pullRequest=8502
{
qCDebug(lcFolder).nospace() << "retrieved root fileId=" << fileId;
_rootFileId = fileId;
}

void Folder::showSyncResultPopup()

Check warning on line 406 in src/gui/folder.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/folder.cpp:406:14 [readability-convert-member-functions-to-static]

method 'showSyncResultPopup' can be made static
{
if (_syncResult.firstItemNew()) {
createGuiLog(_syncResult.firstItemNew()->destination(), LogStatusNew, _syncResult.numNewItems());
Expand Down Expand Up @@ -612,7 +619,7 @@
} else {
const auto pinState = _vfs->pinState(relativePath.toString());
if (pinState && *pinState == PinState::Excluded) {
if (!_vfs->setPinState(relativePath.toString(), PinState::Inherited)) {

Check failure on line 622 in src/gui/folder.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this code to not nest more than 3 if|for|do|while|switch statements.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNij-AmAAmoZrwJ3&open=AZrpGNij-AmAAmoZrwJ3&pullRequest=8502
qCWarning(lcFolder) << "Could not switch pin state of" << relativePath << "from" << *pinState << "to inherited";
}
}
Expand Down Expand Up @@ -657,10 +664,10 @@
if (*pinState == PinState::Unspecified) {
spurious = false;
}
if (*pinState == PinState::AlwaysLocal && record.isVirtualFile()) {

Check failure on line 667 in src/gui/folder.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this code to not nest more than 3 if|for|do|while|switch statements.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNij-AmAAmoZrwJ5&open=AZrpGNij-AmAAmoZrwJ5&pullRequest=8502
spurious = false;
}
if (*pinState == PinState::OnlineOnly && record.isFile()) {

Check failure on line 670 in src/gui/folder.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this code to not nest more than 3 if|for|do|while|switch statements.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNij-AmAAmoZrwJ6&open=AZrpGNij-AmAAmoZrwJ6&pullRequest=8502
spurious = false;
}
} else {
Expand Down Expand Up @@ -892,7 +899,7 @@
removeFromSettings();

auto settings = _accountState->settings();
QString settingsGroup = QStringLiteral("Multifolders");

Check warning on line 902 in src/gui/folder.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace the redundant type with "auto".

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNij-AmAAmoZrwJ8&open=AZrpGNij-AmAAmoZrwJ8&pullRequest=8502

// True if the folder path appears in only one account
const auto folderMap = FolderMan::instance()->map();
Expand Down Expand Up @@ -1002,7 +1009,12 @@
}
}

bool Folder::hasFileIds(const QList<qint64>& fileIds) const

Check warning on line 1012 in src/gui/folder.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/folder.cpp:1012:14 [modernize-use-trailing-return-type]

use a trailing return type for this function
{
return fileIds.contains(_rootFileId) || journalDb()->hasFileIds(fileIds);
}

QString Folder::filePath(const QString& fileName)

Check warning on line 1017 in src/gui/folder.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/folder.cpp:1017:17 [modernize-use-trailing-return-type]

use a trailing return type for this function
{
const auto folderDir = QDir(_canonicalLocalPath);

Expand Down Expand Up @@ -1597,7 +1609,7 @@
Logger::instance()->postGuiLog(Theme::instance()->appNameGUI(), fullMessage);
}

void Folder::slotHydrationStarts()

Check warning on line 1612 in src/gui/folder.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

This function should be declared "const".

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNij-AmAAmoZrwKE&open=AZrpGNij-AmAAmoZrwKE&pullRequest=8502
{
// // Abort any running full sync run and reschedule
// if (_engine->isSyncRunning()) {
Expand Down Expand Up @@ -1722,7 +1734,7 @@
const auto isDownDirection = (dir == SyncFileItem::Down);
const QString msg = isDownDirection ? tr("A large number of files in the server have been deleted.\nPlease confirm if you'd like to proceed with these deletions.\nAlternatively, you can restore all deleted files by uploading from '%1' folder to the server.")
: tr("A large number of files in your local '%1' folder have been deleted.\nPlease confirm if you'd like to proceed with these deletions.\nAlternatively, you can restore all deleted files by downloading them from the server.");
auto msgBox = new QMessageBox(QMessageBox::Warning, tr("Remove all files?"),

Check failure on line 1737 in src/gui/folder.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace the use of "new" with an operation that automatically manages the memory.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNij-AmAAmoZrwKK&open=AZrpGNij-AmAAmoZrwKK&pullRequest=8502
msg.arg(shortGuiLocalPath()), QMessageBox::NoButton);
msgBox->setAttribute(Qt::WA_DeleteOnClose);
msgBox->setWindowFlags(msgBox->windowFlags() | Qt::WindowStaysOnTopHint);
Expand Down
8 changes: 8 additions & 0 deletions src/gui/folder.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
/*
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2014 ownCloud GmbH
Expand All @@ -7,7 +7,7 @@
#ifndef MIRALL_FOLDER_H
#define MIRALL_FOLDER_H

#include "syncresult.h"

Check failure on line 10 in src/gui/folder.h

View workflow job for this annotation

GitHub Actions / build

src/gui/folder.h:10:10 [clang-diagnostic-error]

'syncresult.h' file not found
#include "progressdispatcher.h"
#include "common/syncjournaldb.h"
#include "networkjobs.h"
Expand Down Expand Up @@ -316,6 +316,9 @@
void blacklistPath(const QString &path);
void migrateBlackListPath(const QString &legacyPath);

/// whether the current folder contains any of the passed fileIds
[[nodiscard]] bool hasFileIds(const QList<qint64>& fileIds) const;

signals:
void syncStateChange();
void syncStarted();
Expand Down Expand Up @@ -429,6 +432,8 @@
void etagRetrieved(const QByteArray &, const QDateTime &tp);
void etagRetrievedFromSyncEngine(const QByteArray &, const QDateTime &time);

void rootFileIdReceivedFromSyncEngine(qint64 fileId);

Check warning on line 435 in src/gui/folder.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename this identifier to be shorter or equal to 31 characters.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNjg-AmAAmoZrwKT&open=AZrpGNjg-AmAAmoZrwKT&pullRequest=8502

void slotEmitFinishedDelayed();

void slotNewBigFolderDiscovered(const QString &, bool isExternal);
Expand Down Expand Up @@ -585,6 +590,9 @@
QMetaObject::Connection _officeFileLockReleaseUnlockFailure;
QMetaObject::Connection _fileLockSuccess;
QMetaObject::Connection _fileLockFailure;

/// The remote file ID of the current folder.
qint64 _rootFileId = 0;
};
}

Expand Down
25 changes: 23 additions & 2 deletions src/gui/folderman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
namespace {
constexpr auto settingsAccountsC = "Accounts";
constexpr auto settingsFoldersC = "Folders";
constexpr auto settingsFoldersWithPlaceholdersC = "FoldersWithPlaceholders";

Check warning on line 37 in src/gui/folderman.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename this identifier to be shorter or equal to 31 characters.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNSl-AmAAmoZrwJE&open=AZrpGNSl-AmAAmoZrwJE&pullRequest=8502
constexpr auto settingsVersionC = "version";
constexpr auto maxFoldersVersion = 1;

Expand Down Expand Up @@ -225,7 +225,7 @@
folder->processSwitchedToVirtualFiles();
}

return _folderMap.size();

Check warning on line 228 in src/gui/folderman.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

implicit conversion loses integer precision: 'size_type' (aka 'long long') to 'int'

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNSl-AmAAmoZrwJC&open=AZrpGNSl-AmAAmoZrwJC&pullRequest=8502
}

void FolderMan::setupFoldersHelper(QSettings &settings, AccountStatePtr account, const QStringList &ignoreKeys, bool backwardsCompatible, bool foldersWithPlaceholders)
Expand Down Expand Up @@ -491,7 +491,7 @@
return a;
}

void FolderMan::setupLegacyFolder(const QString &fileNamePath, AccountState *accountState)

Check warning on line 494 in src/gui/folderman.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "accountState" of type "class OCC::AccountState *" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNSl-AmAAmoZrwJJ&open=AZrpGNSl-AmAAmoZrwJJ&pullRequest=8502
{
qCInfo(lcFolderMan) << " ` -> setting up:" << fileNamePath;
QString escapedFileNamePath(fileNamePath);
Expand Down Expand Up @@ -960,7 +960,7 @@
void FolderMan::slotStartScheduledFolderSync()
{
if (isAnySyncRunning()) {
for (auto f : std::as_const(_folderMap)) {

Check warning on line 963 in src/gui/folderman.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "f" of type "class OCC::Folder *" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNSl-AmAAmoZrwJL&open=AZrpGNSl-AmAAmoZrwJL&pullRequest=8502
if (f->isSyncRunning())
qCInfo(lcFolderMan) << "Currently folder " << f->remoteUrl().toString() << " is running, wait for finish!";
}
Expand Down Expand Up @@ -1553,7 +1553,7 @@
f->wipeForRemoval();

// wipe data
QDir userFolder(f->path());

Check warning on line 1556 in src/gui/folderman.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "userFolder" of type "class QDir" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNSl-AmAAmoZrwJS&open=AZrpGNSl-AmAAmoZrwJS&pullRequest=8502
if (userFolder.exists()) {
success = FileSystem::removeRecursively(f->path());
if (!success) {
Expand Down Expand Up @@ -1675,7 +1675,7 @@
leaveShareJob->addRawHeader("e2e-token", folderToken);
connect(leaveShareJob, &SimpleApiJob::resultReceived, this, [this, folder, localFile](int statusCode) {
qCDebug(lcFolderMan) << "slotLeaveShare callback statusCode" << statusCode;
Q_UNUSED(statusCode);

Check warning on line 1678 in src/gui/folderman.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Modify the macro definition so that it needs to be followed by a semicolon, or remove this empty statement.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNSl-AmAAmoZrwJX&open=AZrpGNSl-AmAAmoZrwJX&pullRequest=8502
if (_removeE2eeShareJob) {
_removeE2eeShareJob->unlockFolder(EncryptedFolderMetadataHandler::UnlockFolderWithResult::Success);
connect(_removeE2eeShareJob.data(), &UpdateE2eeFolderUsersMetadataJob::folderUnlocked, this, [this, folder] {
Expand Down Expand Up @@ -1793,7 +1793,7 @@
}
}

QString FolderMan::trayTooltipStatusString(SyncResult::Status syncStatus, bool hasUnresolvedConflicts, bool paused, ProgressInfo *const progress)

Check warning on line 1796 in src/gui/folderman.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "hasUnresolvedConflicts" of type "_Bool" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNSl-AmAAmoZrwJf&open=AZrpGNSl-AmAAmoZrwJf&pullRequest=8502
{
QString folderMessage;
switch (syncStatus) {
Expand All @@ -1806,7 +1806,7 @@
case SyncResult::SyncPrepare:
folderMessage = tr("Preparing for sync.");
break;
case SyncResult::SyncRunning:

Check warning on line 1809 in src/gui/folderman.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Reduce this switch case number of lines from 31 to at most 5, for example by extracting code into methods.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNSl-AmAAmoZrwJh&open=AZrpGNSl-AmAAmoZrwJh&pullRequest=8502
if (progress && progress->status() == ProgressInfo::Propagation) {
const auto estimatedEta = progress->totalProgress().estimatedEta;
if (progress->totalSize() == 0) {
Expand All @@ -1824,7 +1824,7 @@
}
} else {
QString totalSizeStr = Utility::octetsToString(progress->totalSize());
if (progress->trustEta()) {

Check failure on line 1827 in src/gui/folderman.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this code to not nest more than 3 if|for|do|while|switch statements.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNSl-AmAAmoZrwJc&open=AZrpGNSl-AmAAmoZrwJc&pullRequest=8502
if (estimatedEta == 0) {
folderMessage = tr("Syncing %1 (A few seconds left)").arg(totalSizeStr);
} else {
Expand Down Expand Up @@ -1882,7 +1882,7 @@

if (!FileSystem::fileExists(path)) {
QString parentPath = selFile.dir().path();
if (parentPath != path) {

Check warning on line 1885 in src/gui/folderman.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use the init-statement to declare "parentPath" inside the if statement.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNSm-AmAAmoZrwJk&open=AZrpGNSm-AmAAmoZrwJk&pullRequest=8502
return checkPathValidityRecursive(parentPath);
}

Expand Down Expand Up @@ -2084,15 +2084,35 @@

void FolderMan::slotProcessFilesPushNotification(Account *account)
{
qCInfo(lcFolderMan) << "Got files push notification for account" << account;
qCDebug(lcFolderMan) << "received notify_file push notification account=" << account->displayName();

for (auto folder : std::as_const(_folderMap)) {

Check warning on line 2089 in src/gui/folderman.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "folder" of type "class OCC::Folder *" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNSm-AmAAmoZrwJl&open=AZrpGNSm-AmAAmoZrwJl&pullRequest=8502
// Just run on the folders that belong to this account
if (folder->accountState()->account() != account) {
continue;
}

qCInfo(lcFolderMan) << "Schedule folder" << folder << "for sync";
qCInfo(lcFolderMan).nospace() << "scheduling sync folder=" << folder->alias() << " account=" << account->displayName() << " reason=notify_file";
scheduleFolder(folder);
}
}

void FolderMan::slotProcessFileIdsPushNotification(Account *account, const QList<qint64> &fileIds)
{
qCDebug(lcFolderMan).nospace() << "received notify_file_id push notification account=" << account->displayName() << " fileIds=" << fileIds;

for (auto folder : std::as_const(_folderMap)) {
// Just run on the folders that belong to this account
if (folder->accountState()->account() != account) {
continue;
}

if (!folder->hasFileIds(fileIds)) {
qCDebug(lcFolderMan).nospace() << "no matching file ids, ignoring folder=" << folder->alias() << " account=" << account->displayName();
continue;
}

qCInfo(lcFolderMan).nospace() << "scheduling sync folder=" << folder->alias() << " account=" << account->displayName() << " reason=notify_file_id";
scheduleFolder(folder);
}
}
Expand All @@ -2104,6 +2124,7 @@
if (pushNotificationsFilesReady(account)) {
qCInfo(lcFolderMan) << "Push notifications ready";
connect(pushNotifications, &PushNotifications::filesChanged, this, &FolderMan::slotProcessFilesPushNotification, Qt::UniqueConnection);
connect(pushNotifications, &PushNotifications::fileIdsChanged, this, &FolderMan::slotProcessFileIdsPushNotification, Qt::UniqueConnection);
}
}

Expand Down
1 change: 1 addition & 0 deletions src/gui/folderman.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#ifndef FOLDERMAN_H
#define FOLDERMAN_H

#include <QByteArray>

Check failure on line 10 in src/gui/folderman.h

View workflow job for this annotation

GitHub Actions / build

src/gui/folderman.h:10:10 [clang-diagnostic-error]

'QByteArray' file not found
#include <QObject>
#include <QQueue>
#include <QList>
Expand Down Expand Up @@ -330,6 +330,7 @@

void slotSetupPushNotifications(const OCC::Folder::Map &);
void slotProcessFilesPushNotification(OCC::Account *account);
void slotProcessFileIdsPushNotification(OCC::Account *account, const QList<qint64> &fileIds);

Check warning on line 333 in src/gui/folderman.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename this identifier to be shorter or equal to 31 characters.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNhB-AmAAmoZrwJt&open=AZrpGNhB-AmAAmoZrwJt&pullRequest=8502
void slotConnectToPushNotifications(const OCC::AccountPtr &account);

void slotLeaveShare(const QString &localFile, const QByteArray &folderToken = {});
Expand Down
1 change: 1 addition & 0 deletions src/libsync/discovery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -415,14 +415,14 @@
}
item->_status = SyncFileItem::FileNameInvalid;
break;
case CSYNC_FILE_EXCLUDE_TRAILING_SPACE:

Check warning on line 418 in src/libsync/discovery.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Reduce this switch case number of lines from 6 to at most 5, for example by extracting code into methods.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNq8-AmAAmoZrwLl&open=AZrpGNq8-AmAAmoZrwLl&pullRequest=8502
item->_errorString = tr("Filename contains trailing spaces.");
item->_status = SyncFileItem::FileNameInvalid;
if (isLocal && !maybeRenameForWindowsCompatibility(_discoveryData->_localDir + item->_file, excluded)) {
item->_errorString += QStringLiteral(" %1").arg(tr("Cannot be renamed or uploaded."));
}
break;
case CSYNC_FILE_EXCLUDE_LEADING_SPACE:

Check warning on line 425 in src/libsync/discovery.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Reduce this switch case number of lines from 6 to at most 5, for example by extracting code into methods.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNq8-AmAAmoZrwLk&open=AZrpGNq8-AmAAmoZrwLk&pullRequest=8502
item->_errorString = tr("Filename contains leading spaces.");
item->_status = SyncFileItem::FileNameInvalid;
if (isLocal && !maybeRenameForWindowsCompatibility(_discoveryData->_localDir + item->_file, excluded)) {
Expand Down Expand Up @@ -682,7 +682,7 @@
_pendingAsyncJobs++;
_discoveryData->checkSelectiveSyncNewFolder(path._server,
serverEntry.remotePerm,
[=, this](bool result) {

Check failure on line 685 in src/libsync/discovery.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Explicitly capture all local variables required in this lambda.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNq8-AmAAmoZrwLo&open=AZrpGNq8-AmAAmoZrwLo&pullRequest=8502
--_pendingAsyncJobs;
if (!result) {
processFileAnalyzeLocalInfo(item, path, localEntry, serverEntry, dbEntry, _queryServer);
Expand Down Expand Up @@ -1463,7 +1463,7 @@
item->_checksumHeader.clear();
item->_size = localEntry.size;
item->_modtime = localEntry.modtime;
item->_type = localEntry.isDirectory && !localEntry.isVirtualFile ? ItemTypeDirectory : localEntry.isDirectory ? ItemTypeVirtualDirectory : localEntry.isVirtualFile ? ItemTypeVirtualFile : ItemTypeFile;

Check warning on line 1466 in src/libsync/discovery.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Extract this nested conditional operator into an independent statement.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNq8-AmAAmoZrwLx&open=AZrpGNq8-AmAAmoZrwLx&pullRequest=8502
_childModified = true;

if (!localEntry.caseClashConflictingName.isEmpty()) {
Expand Down Expand Up @@ -1579,7 +1579,7 @@
item->_e2eEncryptionServerCapability = EncryptionStatusEnums::fromEndToEndEncryptionApiVersion(_discoveryData->_account->capabilities().clientSideEncryptionVersion());
if (item->_e2eEncryptionStatus != item->_e2eEncryptionServerCapability) {
item->_e2eEncryptionStatus = item->_e2eEncryptionServerCapability;
if (base._e2eEncryptionStatus != SyncJournalFileRecord::EncryptionStatus::NotEncrypted) {

Check failure on line 1582 in src/libsync/discovery.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this code to not nest more than 3 if|for|do|while|switch statements.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNq8-AmAAmoZrwLv&open=AZrpGNq8-AmAAmoZrwLv&pullRequest=8502
Q_ASSERT(item->_e2eEncryptionStatus != SyncFileItem::EncryptionStatus::NotEncrypted);
}
}
Expand Down Expand Up @@ -1849,7 +1849,7 @@
if (_discoveryData->_syncOptions._vfs && _discoveryData->_syncOptions._vfs->mode() != OCC::Vfs::Off &&
(item->_type == CSyncEnums::ItemTypeFile || item->_type == CSyncEnums::ItemTypeDirectory) &&
item->_instruction == CSyncEnums::CSYNC_INSTRUCTION_NONE &&
FileSystem::isLnkFile((_discoveryData->_localDir + path._local)) &&

Check warning on line 1852 in src/libsync/discovery.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove these redundant parentheses.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNq8-AmAAmoZrwL6&open=AZrpGNq8-AmAAmoZrwL6&pullRequest=8502
!_discoveryData->_syncOptions._vfs->isPlaceHolderInSync(_discoveryData->_localDir + path._local)) {
item->_instruction = CSyncEnums::CSYNC_INSTRUCTION_SYNC;
item->_direction = SyncFileItem::Down;
Expand Down Expand Up @@ -2102,10 +2102,10 @@
return matchingEditorsKeepingFileBusy;
}

const auto isMatchingFileExtension = std::find_if(std::cbegin(fileExtensionsToCheckIfOpenForSigning), std::cend(fileExtensionsToCheckIfOpenForSigning),
[path](const auto &matchingExtension) {
return path._local.endsWith(matchingExtension, Qt::CaseInsensitive);
}) != std::cend(fileExtensionsToCheckIfOpenForSigning);

Check warning on line 2108 in src/libsync/discovery.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace with the version of "std::ranges::find_if" that takes a range.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNq8-AmAAmoZrwL8&open=AZrpGNq8-AmAAmoZrwL8&pullRequest=8502

if (!isMatchingFileExtension) {
return matchingEditorsKeepingFileBusy;
Expand Down Expand Up @@ -2271,6 +2271,7 @@
}

connect(serverJob, &DiscoverySingleDirectoryJob::etag, this, &ProcessDirectoryJob::etag);
connect(serverJob, &DiscoverySingleDirectoryJob::firstDirectoryFileId, this, &ProcessDirectoryJob::rootFileIdReceived);
connect(serverJob, &DiscoverySingleDirectoryJob::setfolderQuota, this, &ProcessDirectoryJob::setFolderQuota);
_discoveryData->_currentlyActiveJobs++;
_pendingAsyncJobs++;
Expand Down Expand Up @@ -2349,7 +2350,7 @@
void ProcessDirectoryJob::startAsyncLocalQuery()
{
QString localPath = _discoveryData->_localDir + _currentFolder._local;
auto localJob = new DiscoverySingleLocalDirectoryJob(_discoveryData->_account, localPath, _discoveryData->_syncOptions._vfs.data(), _discoveryData->_fileSystemReliablePermissions);

Check failure on line 2353 in src/libsync/discovery.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace the use of "new" with an operation that automatically manages the memory.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNq8-AmAAmoZrwMC&open=AZrpGNq8-AmAAmoZrwMC&pullRequest=8502

_discoveryData->_currentlyActiveJobs++;
_pendingAsyncJobs++;
Expand Down Expand Up @@ -2437,12 +2438,12 @@
}
}

bool ProcessDirectoryJob::maybeRenameForWindowsCompatibility(const QString &absoluteFileName,

Check warning on line 2441 in src/libsync/discovery.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

This function should be declared "const".

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNq8-AmAAmoZrwMF&open=AZrpGNq8-AmAAmoZrwMF&pullRequest=8502

Check warning on line 2441 in src/libsync/discovery.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename this identifier to be shorter or equal to 31 characters.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNq8-AmAAmoZrwME&open=AZrpGNq8-AmAAmoZrwME&pullRequest=8502
CSYNC_EXCLUDE_TYPE excludeReason)
{
auto result = true;

const auto leadingAndTrailingSpacesFilesAllowed = !_discoveryData->_shouldEnforceWindowsFileNameCompatibility || _discoveryData->_leadingAndTrailingSpacesFilesAllowed.contains(absoluteFileName);

Check warning on line 2446 in src/libsync/discovery.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rename this identifier to be shorter or equal to 31 characters.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNq8-AmAAmoZrwMJ&open=AZrpGNq8-AmAAmoZrwMJ&pullRequest=8502
if (leadingAndTrailingSpacesFilesAllowed) {
return result;
}
Expand Down
1 change: 1 addition & 0 deletions src/libsync/discovery.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

#pragma once

#include <QObject>

Check failure on line 9 in src/libsync/discovery.h

View workflow job for this annotation

GitHub Actions / build

src/libsync/discovery.h:9:10 [clang-diagnostic-error]

'QObject' file not found
#include <cstdint>
#include "csync_exclude.h"
#include "discoveryphase.h"
Expand Down Expand Up @@ -39,7 +39,7 @@
*
* Results are fed outwards via the DiscoveryPhase::itemDiscovered() signal.
*/
class ProcessDirectoryJob : public QObject

Check warning on line 42 in src/libsync/discovery.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this structure so it has no more than 20 fields, rather than the 21 it currently has.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNr8-AmAAmoZrwML&open=AZrpGNr8-AmAAmoZrwML&pullRequest=8502
{
Q_OBJECT

Expand Down Expand Up @@ -308,6 +308,7 @@
// The root etag of this directory was fetched
void etag(const QByteArray &, const QDateTime &time);
void updatedRootFolderQuota(const int64_t &bytesUsed, const int64_t &bytesAvailable);
void rootFileIdReceived(qint64 fileId);

private slots:
void setFolderQuota(const OCC::FolderQuota &folderQuota);
Expand Down
10 changes: 10 additions & 0 deletions src/libsync/discoveryphase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@

QString adjustRenamedPath(const QMap<QString, QString> &renamedItems, const QString &original)
{
int slashPos = original.size();

Check warning on line 152 in src/libsync/discoveryphase.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

implicit conversion loses integer precision: 'qsizetype' (aka 'long long') to 'int'

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNlF-AmAAmoZrwKU&open=AZrpGNlF-AmAAmoZrwKU&pullRequest=8502
while ((slashPos = original.lastIndexOf('/', slashPos - 1)) > 0) {
auto it = renamedItems.constFind(original.left(slashPos));
if (it != renamedItems.constEnd()) {
Expand Down Expand Up @@ -256,7 +256,7 @@
continue;
}

auto item = *it;

Check warning on line 259 in src/libsync/discoveryphase.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "item" of type "class QSharedPointer<class OCC::SyncFileItem>" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNlF-AmAAmoZrwKb&open=AZrpGNlF-AmAAmoZrwKb&pullRequest=8502
if (!(item->_instruction == CSYNC_INSTRUCTION_REMOVE || item->_direction == SyncFileItem::Up)) {
qCInfo(lcDiscovery) << "will not request permanent deletion for" << originalPath << "as the instruction is not CSYNC_INSTRUCTION_REMOVE, or the direction is not Up";
continue;
Expand Down Expand Up @@ -330,7 +330,7 @@
DiscoverySingleLocalDirectoryJob::DiscoverySingleLocalDirectoryJob(const AccountPtr &account,
const QString &localPath,
OCC::Vfs *vfs,
bool fileSystemReliablePermissions,

Check warning on line 333 in src/libsync/discoveryphase.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "fileSystemReliablePermissions" of type "_Bool" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNlF-AmAAmoZrwKd&open=AZrpGNlF-AmAAmoZrwKd&pullRequest=8502
QObject *parent)
: QObject{parent}
, QRunnable{}
Expand Down Expand Up @@ -426,7 +426,7 @@
const QString &path,
const QString &remoteRootFolderPath,
const QSet<QString> &topLevelE2eeFolderPaths,
SyncFileItem::EncryptionStatus parentEncryptionStatus,

Check warning on line 429 in src/libsync/discoveryphase.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "parentEncryptionStatus" of type "enum OCC::EncryptionStatusEnums::ItemEncryptionStatus" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNlF-AmAAmoZrwKg&open=AZrpGNlF-AmAAmoZrwKg&pullRequest=8502
QObject *parent)
: QObject(parent)
, _subPath(remoteRootFolderPath + path)
Expand Down Expand Up @@ -483,7 +483,7 @@
return _encryptionStatusRequired;
}

void DiscoverySingleDirectoryJob::directoryListingIteratedSlot(const QString &file, const QMap<QString, QString> &map)

Check warning on line 486 in src/libsync/discoveryphase.cpp

View workflow job for this annotation

GitHub Actions / build

src/libsync/discoveryphase.cpp:486:35 [readability-function-cognitive-complexity]

function 'directoryListingIteratedSlot' has cognitive complexity of 26 (threshold 25)
{
if (!_ignoredFirst) {
// The first entry is for the folder itself, we should process it differently.
Expand All @@ -503,9 +503,19 @@
}
}
if (map.contains("fileid"_L1)) {
// this is from the "oc:fileid" property, this is the plain ID without any special format (e.g. "2")
_localFileId = map.value("fileid"_L1).toUtf8();

bool ok = false;

Check warning on line 509 in src/libsync/discoveryphase.cpp

View workflow job for this annotation

GitHub Actions / build

src/libsync/discoveryphase.cpp:509:18 [readability-identifier-length]

variable name 'ok' is too short, expected at least 3 characters
if (qint64 numericFileId = _localFileId.toLongLong(&ok, 10); ok) {

Check warning on line 510 in src/libsync/discoveryphase.cpp

View workflow job for this annotation

GitHub Actions / build

src/libsync/discoveryphase.cpp:510:24 [cppcoreguidelines-init-variables]

variable 'numericFileId' is not initialized
qCDebug(lcDiscovery).nospace() << "received numericFileId=" << numericFileId;
emit firstDirectoryFileId(numericFileId);

Check warning on line 512 in src/libsync/discoveryphase.cpp

View workflow job for this annotation

GitHub Actions / build

src/libsync/discoveryphase.cpp:512:22 [cppcoreguidelines-init-variables]

variable 'firstDirectoryFileId' is not initialized
} else {
qCWarning(lcDiscovery).nospace() << "conversion to qint64 failed _localFileId=" << _localFileId;
}
}
if (map.contains("id"_L1)) {
// this is from the "oc:id" property, the format is e.g. "00000002oc123xyz987e"
_fileId = map.value("id"_L1).toUtf8();
}
if (map.contains("is-encrypted"_L1) && map.value("is-encrypted"_L1) == "1"_L1) {
Expand Down Expand Up @@ -534,7 +544,7 @@
}
} else {
RemoteInfo result;
int slash = file.lastIndexOf(u'/');

Check warning on line 547 in src/libsync/discoveryphase.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

implicit conversion loses integer precision: 'qsizetype' (aka 'long long') to 'int'

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNlF-AmAAmoZrwKX&open=AZrpGNlF-AmAAmoZrwKX&pullRequest=8502
result.name = file.mid(slash + 1);
result.size = -1;
LsColJob::propertyMapToRemoteInfo(map,
Expand Down Expand Up @@ -654,7 +664,7 @@
statusCode == 404 ? QByteArray{} : json.toJson(QJsonDocument::Compact),
RootEncryptedFolderInfo(Utility::fullRemotePathToRemoteSyncRootRelative(topLevelFolderPath, _remoteRootFolderPath)),
job->signature());
connect(e2EeFolderMetadata, &FolderMetadata::setupComplete, this, [this, e2EeFolderMetadata] {

Check warning on line 667 in src/libsync/discoveryphase.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

This lambda has 37 lines, which is greater than the 20 lines authorized. Split it into several lambdas or functions, or make it a named function.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNlF-AmAAmoZrwKq&open=AZrpGNlF-AmAAmoZrwKq&pullRequest=8502
e2EeFolderMetadata->deleteLater();
if (!e2EeFolderMetadata->isValid()) {
emit finished(HttpError{0, tr("Encrypted metadata setup error!")});
Expand Down
1 change: 1 addition & 0 deletions src/libsync/discoveryphase.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ class DiscoverySingleDirectoryJob : public QObject
void etag(const QByteArray &, const QDateTime &time);
void finished(const OCC::HttpResult<QVector<OCC::RemoteInfo>> &result);
void setfolderQuota(const OCC::FolderQuota &folderQuota);
void firstDirectoryFileId(qint64 fileId);

private slots:
void directoryListingIteratedSlot(const QString &, const QMap<QString, QString> &);
Expand Down
45 changes: 41 additions & 4 deletions src/libsync/pushnotifications.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
/*
* SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: GPL-2.0-or-later
Expand All @@ -7,9 +7,13 @@
#include "creds/abstractcredentials.h"
#include "account.h"

#include <QJsonArray>

namespace {
static constexpr int MAX_ALLOWED_FAILED_AUTHENTICATION_ATTEMPTS = 3;
static constexpr int PING_INTERVAL = 30 * 1000;

static constexpr QLatin1String NOTIFY_FILE_ID_PREFIX = QLatin1String{"notify_file_id "};
}

namespace OCC {
Expand Down Expand Up @@ -102,7 +106,9 @@
{
qCInfo(lcPushNotifications) << "Received push notification:" << message;

if (message == "notify_file") {
if (message.startsWith(NOTIFY_FILE_ID_PREFIX)) {
handleNotifyFileId(message);
} else if (message == "notify_file") {
handleNotifyFile();
} else if (message == "notify_activity") {
handleNotifyActivity();
Expand All @@ -124,7 +130,7 @@
return;
}

qCWarning(lcPushNotifications) << "Websocket error on with account" << _account->url() << error;
qCWarning(lcPushNotifications) << "Websocket error on with account" << _account->displayName() << _account->url() << error;
closeWebSocket();
emit connectionLost();
}
Expand Down Expand Up @@ -153,7 +159,7 @@

void PushNotifications::onWebSocketSslErrors(const QList<QSslError> &errors)
{
qCWarning(lcPushNotifications) << "Websocket ssl errors on with account" << _account->url() << errors;
qCWarning(lcPushNotifications) << "Websocket ssl errors on with account" << _account->displayName() << _account->url() << errors;
closeWebSocket();
emit authenticationFailed();
}
Expand All @@ -164,7 +170,7 @@
const auto capabilities = _account->capabilities();
const auto webSocketUrl = capabilities.pushNotificationsWebSocketUrl();

qCInfo(lcPushNotifications) << "Open connection to websocket on" << webSocketUrl << "for account" << _account->url();
qCInfo(lcPushNotifications) << "Open connection to websocket on" << webSocketUrl << "for account" << _account->displayName() << _account->url();
connect(_webSocket, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::errorOccurred), this, &PushNotifications::onWebSocketError);
connect(_webSocket, &QWebSocket::sslErrors, this, &PushNotifications::onWebSocketSslErrors);
_webSocket->open(webSocketUrl);
Expand All @@ -184,6 +190,8 @@
{
qCInfo(lcPushNotifications) << "Authenticated successful on websocket";
_failedAuthenticationAttemptsCount = 0;
qCDebug(lcPushNotifications) << "Requesting opt-in to 'notify_file_id' notifications";
_webSocket->sendTextMessage("listen notify_file_id");
_isReady = true;
startPingTimer();
emit ready();
Expand All @@ -202,6 +210,35 @@
emitFilesChanged();
}

void PushNotifications::handleNotifyFileId(const QString &message)
{
qCDebug(lcPushNotifications) << "File-ID push notification arrived";

QList<qint64> fileIds{};
QJsonParseError parseError;
const auto fileIdsJson = message.mid(NOTIFY_FILE_ID_PREFIX.length());
const auto jsonDoc = QJsonDocument::fromJson(fileIdsJson.toUtf8(), &parseError);

if (parseError.error != QJsonParseError::NoError) {
qCWarning(lcPushNotifications).nospace() << "could not parse received list of file IDs error=" << parseError.error << " errorString=" << parseError.errorString() << " fileIdsJson=" << fileIdsJson;
return;
}

if (const auto jsonArray = jsonDoc.array(); jsonDoc.isArray()) {
for (const auto& jsonFileid : jsonArray) {
if (const auto fileid = jsonFileid.toInteger(); jsonFileid.isDouble()) {
fileIds.push_back(fileid);
}
}
}

if (fileIds.empty()) {
return;
}

emit fileIdsChanged(_account, fileIds);
}

void PushNotifications::handleInvalidCredentials()
{
qCInfo(lcPushNotifications) << "Invalid credentials submitted to websocket";
Expand Down
6 changes: 6 additions & 0 deletions src/libsync/pushnotifications.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

#pragma once

#include <QWebSocket>

Check failure on line 8 in src/libsync/pushnotifications.h

View workflow job for this annotation

GitHub Actions / build

src/libsync/pushnotifications.h:8:10 [clang-diagnostic-error]

'QWebSocket' file not found
#include <QTimer>

#include "capabilities.h"
Expand Down Expand Up @@ -65,6 +65,11 @@
*/
void filesChanged(OCC::Account *account);

/**
* Will be emitted if specific files on the server changed
*/
void fileIdsChanged(OCC::Account *account, const QList<qint64> &fileIds);

/**
* Will be emitted if activities have been changed on the server
*/
Expand Down Expand Up @@ -111,6 +116,7 @@

void handleAuthenticated();
void handleNotifyFile();
void handleNotifyFileId(const QString &message);
void handleInvalidCredentials();
void handleNotifyNotification();
void handleNotifyActivity();
Expand Down
11 changes: 11 additions & 0 deletions src/libsync/syncengine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@
const auto lockOwnerTypeToSkipReadonly = _account->capabilities().filesLockTypeAvailable()
? SyncFileItem::LockOwnerType::TokenLock
: SyncFileItem::LockOwnerType::UserLock;
if (item->_locked == SyncFileItem::LockStatus::LockedItem

Check failure on line 386 in src/libsync/syncengine.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this code to not nest more than 3 if|for|do|while|switch statements.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNnH-AmAAmoZrwKy&open=AZrpGNnH-AmAAmoZrwKy&pullRequest=8502
&& (item->_lockOwnerType != lockOwnerTypeToSkipReadonly || item->_lockOwnerId != account()->davUser())) {
qCDebug(lcEngine()) << filePath << "file is locked: making it read only";
FileSystem::setFileReadOnly(filePath, true);
Expand All @@ -397,7 +397,7 @@

// Update on-disk virtual file metadata
if (modificationHappened && item->_type == ItemTypeVirtualFile) {
auto r = _syncOptions._vfs->updateMetadata(*item, filePath, {});

Check warning on line 400 in src/libsync/syncengine.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "r" of type "class OCC::Result<enum OCC::Vfs::ConvertToPlaceholderResult, class QString>" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNnH-AmAAmoZrwKz&open=AZrpGNnH-AmAAmoZrwKz&pullRequest=8502
if (!r) {
item->_status = SyncFileItem::Status::NormalError;
item->_instruction = CSYNC_INSTRUCTION_ERROR;
Expand Down Expand Up @@ -763,6 +763,7 @@
_discoveryPhase->startJob(discoveryJob);
connect(discoveryJob, &ProcessDirectoryJob::etag, this, &SyncEngine::slotRootEtagReceived);
connect(discoveryJob, &ProcessDirectoryJob::updatedRootFolderQuota, account().data(), &Account::rootFolderQuotaChanged);
connect(discoveryJob, &ProcessDirectoryJob::rootFileIdReceived, this, &SyncEngine::slotRootFileIdReceived);
connect(_discoveryPhase.get(), &DiscoveryPhase::addErrorToGui, this, &SyncEngine::addErrorToGui);
}

Expand Down Expand Up @@ -794,6 +795,16 @@
}
}

void SyncEngine::slotRootFileIdReceived(const qint64 fileId)
{
if (_rootFileIdReceived) {
return;
}
_rootFileId = fileId;
_rootFileIdReceived = true;
emit rootFileIdReceived(fileId);
}

void SyncEngine::slotNewItem(const SyncFileItemPtr &item)
{
_progressInfo->adjustTotalsForFile(*item);
Expand Down Expand Up @@ -1115,7 +1126,7 @@
qCInfo(lcEngine) << "#### Post-Reconcile end #################################################### " << _stopWatch.addLapTime(QStringLiteral("Post-Reconcile Finished")) << "ms";
}

bool SyncEngine::handleMassDeletion()

Check failure on line 1129 in src/libsync/syncengine.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this function to reduce its Cognitive Complexity from 33 to the 25 allowed.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNnH-AmAAmoZrwK_&open=AZrpGNnH-AmAAmoZrwK_&pullRequest=8502
{
const auto displayDialog = ConfigFile().promptDeleteFiles() && !_syncOptions.isCmd();
const auto allFilesDeleted = !_hasNoneFiles && _hasRemoveFile;
Expand Down Expand Up @@ -1200,7 +1211,7 @@
};

lambda(callback);
}

Check failure on line 1214 in src/libsync/syncengine.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Potential leak of memory pointed to by field 'value'

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNnH-AmAAmoZrwLM&open=AZrpGNnH-AmAAmoZrwLM&pullRequest=8502

void SyncEngine::slotAddTouchedFile(const QString &fn)
{
Expand Down Expand Up @@ -1238,7 +1249,7 @@
_leadingAndTrailingSpacesFilesAllowed.append(filePath);
}

void SyncEngine::setLocalDiscoveryEnforceWindowsFileNameCompatibility(bool value)

Check warning on line 1252 in src/libsync/syncengine.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "value" of type "_Bool" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZrpGNnH-AmAAmoZrwLH&open=AZrpGNnH-AmAAmoZrwLH&pullRequest=8502
{
_shouldEnforceWindowsFileNameCompatibility = value;
}
Expand Down
Loading
Loading