Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ build*
cscope.*
tags
t1.cfg
.idea

## Ignore Visual Studio Code config & environment files

Expand Down
4 changes: 4 additions & 0 deletions src/gui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ set(client_SRCS
proxyauthdialog.cpp
tooltipupdater.h
tooltipupdater.cpp
urischemehandler.h
urischemehandler.cpp
notificationconfirmjob.h
notificationconfirmjob.cpp
guiutility.h
Expand Down Expand Up @@ -237,6 +239,8 @@ set(client_SRCS
wizard/flow2authcredspage.cpp
wizard/flow2authwidget.h
wizard/flow2authwidget.cpp
wizard/providersignuppage.h
wizard/providersignuppage.cpp
wizard/owncloudsetuppage.h
wizard/owncloudsetuppage.cpp
wizard/termsofservicecheckwidget.h
Expand Down
46 changes: 28 additions & 18 deletions src/gui/application.cpp
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 @@ -15,13 +15,13 @@
#include "configfile.h"
#include "connectionvalidator.h"
#include "creds/abstractcredentials.h"
#include "editlocallymanager.h"
#include "folder.h"
#include "folderman.h"
#include "logger.h"
#include "pushnotifications.h"
#include "socketapi/socketapi.h"
#include "theme.h"
#include "urischemehandler.h"

#if defined(BUILD_UPDATER)
#include "updater/ocupdater.h"
Expand Down Expand Up @@ -49,7 +49,6 @@
#include <QMessageBox>
#include <QDesktopServices>
#include <QGuiApplication>
#include <QUrlQuery>
#include <QVersionNumber>
#include <QRandomGenerator>
#include <QHttp2Configuration>
Expand Down Expand Up @@ -124,7 +123,7 @@
{
ConfigFile configFile;
const auto shouldTryToMigrate = configFile.shouldTryToMigrate();
if (!shouldTryToMigrate) {

Check warning on line 126 in src/gui/application.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

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

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ33sz53n1POGIojLbDn&open=AZ33sz53n1POGIojLbDn&pullRequest=9969
qCInfo(lcApplication) << "This is not an upgrade/downgrade/migration. Proceed to read current application config file.";
configFile.setMigrationPhase(ConfigFile::MigrationPhase::Done);
return false;
Expand Down Expand Up @@ -300,7 +299,7 @@
qCDebug(lcApplication) << "Failed to move the old config directory to its new location (" << legacyDir << "to" << confDir << ")";

// Try to move the files one by one
if (QFileInfo(confDir).isDir() || QDir().mkdir(confDir)) {

Check failure on line 302 in src/gui/application.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this TOCTOU race condition window when accessing files

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ33sz53n1POGIojLbDp&open=AZ33sz53n1POGIojLbDp&pullRequest=9969
const QStringList filesList = QDir(legacyDir).entryList(QDir::Files);
qCDebug(lcApplication) << "Will move the individual files" << filesList;
for (const auto &name : filesList) {
Expand All @@ -312,7 +311,7 @@
} else {
#ifndef Q_OS_WIN
// Create a symbolic link so a downgrade of the client would still find the config.
QFile::link(confDir, legacyDir);

Check failure on line 314 in src/gui/application.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this TOCTOU race condition window when accessing files

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ33sz53n1POGIojLbDo&open=AZ33sz53n1POGIojLbDo&pullRequest=9969
#endif
}
}
Expand Down Expand Up @@ -418,7 +417,7 @@
_gui->setupCloudProviders();
#endif

if (_theme->doNotUseProxy()) {

Check warning on line 420 in src/gui/application.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace "->" with "::" for access to "Theme::doNotUseProxy".

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ33sz53n1POGIojLbDr&open=AZ33sz53n1POGIojLbDr&pullRequest=9969
ConfigFile().setProxyType(QNetworkProxy::NoProxy);
const auto &allAccounts = AccountManager::instance()->accounts();
for (const auto &accountState : allAccounts) {
Expand Down Expand Up @@ -476,7 +475,7 @@

_gui->createTray();

handleEditLocallyFromOptions();
handleUriFromOptions();

#ifdef Q_OS_MACOS
// If any sync folder needs sandbox reapproval after upgrading to v33+,
Expand Down Expand Up @@ -600,7 +599,7 @@
const auto foldersRestoreMessage = foldersListSize > 1
? tr("%1 folders", "number of folders imported").arg(QString::number(foldersListSize))
: tr("1 folder");
const auto messageBox = new QMessageBox(QMessageBox::Information,

Check failure on line 602 in src/gui/application.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=AZ33sz53n1POGIojLbDs&open=AZ33sz53n1POGIojLbDs&pullRequest=9969
tr("Legacy import"),
tr("Imported %1 and %2 from a legacy desktop client.\n%3",
"number of accounts and folders imported. list of users.")
Expand All @@ -617,7 +616,7 @@
qCWarning(lcApplication) << accountsListSize << "account(s) migrated:" << prettyNamesList(accounts);
}

void Application::setupConfigFile()

Check warning on line 619 in src/gui/application.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=AZ33sz53n1POGIojLbDt&open=AZ33sz53n1POGIojLbDt&pullRequest=9969
{
// Migrate from version <= 2.4
setApplicationName(_theme->appNameGUI());
Expand Down Expand Up @@ -656,7 +655,7 @@
const QStringList filesList = QDir(oldDir).entryList(QDir::Files);
qCDebug(lcApplication) << "Will move the individual files" << filesList;
for (const auto &name : filesList) {
if (!QFile::rename(oldDir + "/" + name, confDir + "/" + name)) {

Check failure on line 658 in src/gui/application.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=AZ33sz53n1POGIojLbDu&open=AZ33sz53n1POGIojLbDu&pullRequest=9969
qCDebug(lcApplication) << "Fallback move of " << name << "also failed";
}
}
Expand All @@ -669,9 +668,9 @@
}
}

AccountManager::AccountsRestoreResult Application::restoreLegacyAccount()

Check warning on line 671 in src/gui/application.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=AZ33sz53n1POGIojLbDw&open=AZ33sz53n1POGIojLbDw&pullRequest=9969
{
ConfigFile cfg;

Check warning on line 673 in src/gui/application.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "cfg" of type "class OCC::ConfigFile" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ33sz53n1POGIojLbDx&open=AZ33sz53n1POGIojLbDx&pullRequest=9969
const auto tryMigrate = cfg.overrideServerUrl().isEmpty();
auto accountsRestoreResult = AccountManager::AccountsRestoreFailure;
if (accountsRestoreResult = AccountManager::instance()->restore(tryMigrate);
Expand Down Expand Up @@ -748,7 +747,7 @@
// FIXME: This is not ideal yet since a ConnectionValidator might already be running and is in
// progress of timing out in some seconds.
// Maybe we need 2 validators, one triggered by timer, one by network configuration changes?
void Application::slotSystemOnlineConfigurationChanged()

Check warning on line 750 in src/gui/application.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=AZ33sz53n1POGIojLbDy&open=AZ33sz53n1POGIojLbDy&pullRequest=9969

Check warning on line 750 in src/gui/application.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=AZ33sz53n1POGIojLbDz&open=AZ33sz53n1POGIojLbDz&pullRequest=9969
{
if (QNetworkInformation::instance()->reachability() == QNetworkInformation::Reachability::Site ||
QNetworkInformation::instance()->reachability() == QNetworkInformation::Reachability::Online) {
Expand Down Expand Up @@ -844,7 +843,7 @@
qApp->quit();
}

handleEditLocallyFromOptions();
handleUriFromOptions();

if (AccountSetupCommandLineManager::instance()->isCommandLineParsed()) {
AccountSetupCommandLineManager::instance()->setupAccountFromCommandLine();
Expand Down Expand Up @@ -931,18 +930,21 @@
} else if (option.endsWith(QStringLiteral(APPLICATION_DOTVIRTUALFILE_SUFFIX))) {
// virtual file, open it after the Folder were created (if the app is not terminated)
QTimer::singleShot(0, this, [this, option] { openVirtualFile(option); });
} else if (option.startsWith(QStringLiteral(APPLICATION_URI_HANDLER_SCHEME "://open"))) {
// see the section Local file editing of the Architecture page of the user documentation
_editFileLocallyUrl = QUrl::fromUserInput(option);
if (!_editFileLocallyUrl.isValid()) {
_editFileLocallyUrl.clear();
const auto errorParsingLocalFileEditingUrl = QStringLiteral("The supplied url for local file editing '%1' is invalid!").arg(option);
qCInfo(lcApplication) << errorParsingLocalFileEditingUrl;
showHint(errorParsingLocalFileEditingUrl.toStdString());
} else if (option.startsWith(QStringLiteral(APPLICATION_URI_HANDLER_SCHEME "://"))) {
_uriSchemeUrl = QUrl{option};
qCInfo(lcApplication) << "Command line contains custom URI scheme request:"
<< "scheme=" << _uriSchemeUrl.scheme()
<< "host=" << _uriSchemeUrl.host()
<< "path=" << _uriSchemeUrl.path();
if (!_uriSchemeUrl.isValid()) {
_uriSchemeUrl.clear();
const auto errorParsingUri = QStringLiteral("The supplied url '%1' is invalid!").arg(option);
qCInfo(lcApplication) << errorParsingUri;
showHint(errorParsingUri.toStdString());
}
} else if (option == QStringLiteral("--overrideserverurl")) {
if (it.hasNext() && !it.peekNext().startsWith(QLatin1String("--"))) {
const auto overrideUrl = it.next();

Check warning on line 947 in src/gui/application.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Avoid this unnecessary copy by using a "const" reference.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ33sz53n1POGIojLbD0&open=AZ33sz53n1POGIojLbD0&pullRequest=9969
const auto isUrlValid = (overrideUrl.startsWith(QStringLiteral("http://")) || overrideUrl.startsWith(QStringLiteral("https://")))
&& QUrl::fromUserInput(overrideUrl).isValid();
if (!isUrlValid) {
Expand Down Expand Up @@ -1071,14 +1073,19 @@
_helpOnly = true;
}

void Application::handleEditLocallyFromOptions()
void Application::handleUriFromOptions()
{
if (!_editFileLocallyUrl.isValid()) {
if (!_uriSchemeUrl.isValid()) {
qCDebug(lcApplication) << "No pending custom URI scheme request from command line options.";
return;
}

EditLocallyManager::instance()->handleRequest(_editFileLocallyUrl);
_editFileLocallyUrl.clear();
qCInfo(lcApplication) << "Dispatching pending custom URI scheme request from command line options:"
<< "scheme=" << _uriSchemeUrl.scheme()
<< "host=" << _uriSchemeUrl.host()
<< "path=" << _uriSchemeUrl.path();
UriSchemeHandler::handleUri(_uriSchemeUrl);
_uriSchemeUrl.clear();
}

QString enforcedLanguage()
Expand Down Expand Up @@ -1138,7 +1145,7 @@
if (!qtTranslator->load(qtTrFile, qtTrPath)) {
if (!qtTranslator->load(qtTrFile, trPath)) {
if (!qtTranslator->load(qtBaseTrFile, qtTrPath)) {
if (!qtTranslator->load(qtBaseTrFile, trPath)) {

Check warning on line 1148 in src/gui/application.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Merge this "if" statement with the enclosing one.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ33sz53n1POGIojLbD4&open=AZ33sz53n1POGIojLbD4&pullRequest=9969
qCDebug(lcApplication()) << "impossible to load Qt translation catalog" << qtBaseTrFile;
}
}
Expand Down Expand Up @@ -1239,8 +1246,11 @@
} else if (!openEvent->url().isEmpty() && openEvent->url().isValid()) {
// On macOS, Qt does not handle receiving a custom URI as it does on other systems (as an application argument).
// Instead, it sends out a QFileOpenEvent. We therefore need custom handling for our URI handling on macOS.
qCInfo(lcApplication) << "macOS: Opening local file for editing: " << openEvent->url();
EditLocallyManager::instance()->handleRequest(openEvent->url());
qCInfo(lcApplication) << "macOS QFileOpenEvent contains custom URI scheme request:"
<< "scheme=" << openEvent->url().scheme()
<< "host=" << openEvent->url().host()
<< "path=" << openEvent->url().path();
UriSchemeHandler::handleUri(openEvent->url());
} else {
const auto errorParsingLocalFileEditingUrl = QStringLiteral("The supplied url for local file editing '%1' is invalid!").arg(openEvent->url().toString());
qCInfo(lcApplication) << errorParsingLocalFileEditingUrl;
Expand Down
4 changes: 2 additions & 2 deletions src/gui/application.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
* @brief The Application class
* @ingroup gui
*/
class Application : public QApplication

Check warning on line 53 in src/gui/application.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 23 it currently has.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ33sz6pn1POGIojLbEA&open=AZ33sz6pn1POGIojLbEA&pullRequest=9969

Check warning on line 53 in src/gui/application.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Class has 44 methods, which is greater than the 35 authorized. Split it into smaller classes.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ33sz6pn1POGIojLbEB&open=AZ33sz6pn1POGIojLbEB&pullRequest=9969

Check failure on line 53 in src/gui/application.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this class' destructor so that the class follows the rule of Zero.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ33sz6pn1POGIojLbD_&open=AZ33sz6pn1POGIojLbD_&pullRequest=9969
{
Q_OBJECT
public:
Expand Down Expand Up @@ -109,13 +109,13 @@
void slotCleanup();
void slotAccountStateAdded(OCC::AccountState *accountState);
void slotAccountStateRemoved(OCC::AccountState *accountState);
void slotSystemOnlineConfigurationChanged();

Check warning on line 112 in src/gui/application.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=AZ33sz6pn1POGIojLbEC&open=AZ33sz6pn1POGIojLbEC&pullRequest=9969
void slotGuiIsShowingSettings();

private:
void setHelp();

void handleEditLocallyFromOptions();
void handleUriFromOptions();

AccountManager::AccountsRestoreResult restoreLegacyAccount();
void setupConfigFile();
Expand Down Expand Up @@ -153,7 +153,7 @@
bool _userTriggeredConnect = false;
bool _debugMode = false;
bool _backgroundMode = false;
QUrl _editFileLocallyUrl;
QUrl _uriSchemeUrl;

ClientProxy _proxy;

Expand Down
20 changes: 18 additions & 2 deletions src/gui/cocoainitializer_mac.mm
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
#import <AppKit/NSApplication.h>

#include "application.h"
#include "editlocallymanager.h"
#include "urischemehandler.h"

#include <QTimer>

/* In theory, we should be able to just capture QFileOpenEvents
* when we open our custom URLs in our Application class and be
Expand Down Expand Up @@ -51,7 +53,21 @@ - (void)handleURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEv
{
NSURL* url = [NSURL URLWithString:[[event paramDescriptorForKeyword:keyDirectObject] stringValue]];
const auto qtUrl = QUrl::fromNSURL(url);
OCC::EditLocallyManager::instance()->handleRequest(qtUrl);
qCInfo(OCC::lcApplication) << "macOS AppleEvent contains custom URI scheme request:"
<< "scheme=" << qtUrl.scheme()
<< "host=" << qtUrl.host()
<< "path=" << qtUrl.path();
if (qApp) {
QTimer::singleShot(0, qApp, [qtUrl] {
qCInfo(OCC::lcApplication) << "Dispatching macOS AppleEvent custom URI scheme request:"
<< "scheme=" << qtUrl.scheme()
<< "host=" << qtUrl.host()
<< "path=" << qtUrl.path();
OCC::UriSchemeHandler::handleUri(qtUrl);
});
} else {
qCWarning(OCC::lcApplication) << "Could not dispatch macOS AppleEvent custom URI scheme request because qApp is not available yet.";
}
Comment on lines +68 to +70
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve AppleEvent URLs when qApp is not ready

In URLEventHandler::handleURLEvent, the new if (qApp) ... else branch drops the URL entirely when qApp is null, which can happen during cold-start handling because this handler is explicitly registered before launch is complete (src/gui/cocoainitializer_mac.mm comment at lines 23-26, and CocoaInitializer is created before Application in src/gui/main.cpp). In that startup window, login/signup deep links are lost and never retried, so the URI flow can fail intermittently on macOS.

Useful? React with 👍 / 👎.

}

@end
Expand Down
20 changes: 14 additions & 6 deletions src/gui/creds/flow2auth.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
/*
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: GPL-2.0-or-later
Expand All @@ -8,7 +8,6 @@
#include "abstractnetworkjob.h"
#include "account.h"
#include "config.h"
#include "configfile.h"
#include "guiutility.h"
#include "networkjobs.h"
#include "theme.h"
Expand All @@ -21,16 +20,23 @@
#include <QJsonObject>
#include <QJsonDocument>

#include <chrono>

namespace OCC {

Q_LOGGING_CATEGORY(lcFlow2auth, "nextcloud.sync.credentials.flow2auth", QtInfoMsg)

namespace {
constexpr auto loginFlowV2PollInterval = std::chrono::seconds(1);
}

Flow2Auth::Flow2Auth(Account *account, QObject *parent)
: QObject(parent)
, _account(account)
{
_pollTimer.setInterval(1000);
_pollTimer.setInterval(static_cast<int>(
std::chrono::duration_cast<std::chrono::milliseconds>(loginFlowV2PollInterval).count()));
_pollTimer.setTimerType(Qt::PreciseTimer);
QObject::connect(&_pollTimer, &QTimer::timeout, this, &Flow2Auth::slotPollTimerTimeout);
}

Expand Down Expand Up @@ -79,7 +85,7 @@
request.setHeader(QNetworkRequest::ContentLengthHeader, "0");
request.setHeader(QNetworkRequest::UserAgentHeader, Utility::userAgentString());

auto job = _account->sendRequest("POST", loginV2url, request);

Check warning on line 88 in src/gui/creds/flow2auth.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "job" of type "class OCC::SimpleNetworkJob *" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ4CvkVfL-vDBhHF32Y_&open=AZ4CvkVfL-vDBhHF32Y_&pullRequest=9969
job->setTimeout(qMin(30 * 1000ll, job->timeoutMsec()));

QObject::connect(job, &SimpleNetworkJob::finishedSignal, this, [this, action](QNetworkReply *reply) {
Expand All @@ -101,7 +107,7 @@
_loginUrl = loginUrl;

if (_account->isUsernamePrefillSupported()) {
constexpr auto setUserNameForLogin = [] (const auto &userName, auto &loginUrl) -> void {

Check warning on line 110 in src/gui/creds/flow2auth.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the redundant return type of this lambda.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ4CvkVfL-vDBhHF32ZB&open=AZ4CvkVfL-vDBhHF32ZB&pullRequest=9969
auto query = QUrlQuery(loginUrl);
query.addQueryItem(QStringLiteral("user"), userName);
loginUrl.setQuery(query);
Expand All @@ -117,10 +123,12 @@
_pollToken = pollToken;
_pollEndpoint = pollEndpoint;

// Start polling
std::chrono::milliseconds polltime = ConfigFile().remotePollInterval();
qCInfo(lcFlow2auth) << "setting remote poll timer interval to" << polltime.count() << "msec";
_secondsInterval = (polltime.count() / 1000);
// Start polling. Login Flow v2 is an interactive handshake, so use a
// short interval instead of the global remote sync poll interval.
qCInfo(lcFlow2auth) << "setting login flow v2 poll timer interval to"
<< std::chrono::duration_cast<std::chrono::milliseconds>(loginFlowV2PollInterval).count()
<< "msec";
_secondsInterval = loginFlowV2PollInterval.count();
_secondsLeft = _secondsInterval;
emit statusChanged(PollStatus::statusPollCountdown, _secondsLeft);

Expand All @@ -128,7 +136,7 @@
_pollTimer.start();
}

switch (action) {

Check failure on line 139 in src/gui/creds/flow2auth.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add a "default" case to this switch statement.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ4CvkVfL-vDBhHF32ZA&open=AZ4CvkVfL-vDBhHF32ZA&pullRequest=9969
case actionOpenBrowser:
// Try to open Browser
if (!Utility::openBrowser(authorisationLink())) {
Expand Down Expand Up @@ -169,10 +177,10 @@
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");

auto requestBody = new QBuffer;
QUrlQuery arguments(QStringLiteral("token=%1").arg(_pollToken));

Check warning on line 180 in src/gui/creds/flow2auth.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "arguments" of type "class QUrlQuery" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ4CvkVfL-vDBhHF32ZC&open=AZ4CvkVfL-vDBhHF32ZC&pullRequest=9969
requestBody->setData(arguments.query(QUrl::FullyEncoded).toLatin1());

auto job = _account->sendRequest("POST", _pollEndpoint, request, requestBody);

Check warning on line 183 in src/gui/creds/flow2auth.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "job" of type "class OCC::SimpleNetworkJob *" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ4CvkVfL-vDBhHF32ZD&open=AZ4CvkVfL-vDBhHF32ZD&pullRequest=9969
job->setTimeout(qMin(30 * 1000ll, job->timeoutMsec()));

QObject::connect(job, &SimpleNetworkJob::finishedSignal, this, [this](QNetworkReply *reply) {
Expand Down Expand Up @@ -219,7 +227,7 @@
});
}

QJsonObject Flow2Auth::handleResponse(QNetworkReply *reply)

Check warning on line 230 in src/gui/creds/flow2auth.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "reply" of type "class QNetworkReply *" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ4CvkVfL-vDBhHF32ZF&open=AZ4CvkVfL-vDBhHF32ZF&pullRequest=9969
{
const auto jsonData = reply->readAll();
QJsonParseError jsonParseError{};
Expand Down
65 changes: 53 additions & 12 deletions src/gui/owncloudsetupwizard.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: 2012 ownCloud GmbH
* SPDX-License-Identifier: GPL-2.0-or-later
*/

#include "accessmanager.h"

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

View workflow job for this annotation

GitHub Actions / build

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

'accessmanager.h' file not found
#include "account.h"
#include "accountmanager.h"
#include "clientproxy.h"
Expand All @@ -17,6 +17,7 @@
#include "owncloudsetupwizard.h"
#include "owncloudpropagator_p.h"
#include "sslerrordialog.h"
#include "wizard/flow2authcredspage.h"
#include "wizard/owncloudwizard.h"
#include "wizard/owncloudwizardcommon.h"
#include "account.h"
Expand Down Expand Up @@ -91,6 +92,30 @@
owncloudSetupWizard->startWizard();
}

void OwncloudSetupWizard::runWizardForLoginFlow(QObject *obj, const char *amember, const QUrl &serverUrl, QWidget *parent)

Check warning on line 95 in src/gui/owncloudsetupwizard.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/owncloudsetupwizard.cpp:95:27 [readability-convert-member-functions-to-static]

method 'runWizardForLoginFlow' can be made static

Check warning on line 95 in src/gui/owncloudsetupwizard.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Make the type of this parameter a pointer-to-const. The current type of "obj" is "class QObject *".

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ33sz41n1POGIojLbDb&open=AZ33sz41n1POGIojLbDb&pullRequest=9969

Check warning on line 95 in src/gui/owncloudsetupwizard.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "amember" of type "const char *" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ33sz41n1POGIojLbDd&open=AZ33sz41n1POGIojLbDd&pullRequest=9969

Check warning on line 95 in src/gui/owncloudsetupwizard.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "obj" of type "class QObject *" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ33sz41n1POGIojLbDc&open=AZ33sz41n1POGIojLbDc&pullRequest=9969

Check warning on line 95 in src/gui/owncloudsetupwizard.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "parent" of type "class QWidget *" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ33sz41n1POGIojLbDe&open=AZ33sz41n1POGIojLbDe&pullRequest=9969
{
#if defined ENFORCE_SINGLE_ACCOUNT
if (!AccountManager::instance()->accounts().isEmpty()) {
return;
}
#endif

if (!owncloudSetupWizard.isNull()) {
qCInfo(lcWizard) << "Restarting existing setup wizard for URI login flow.";
FolderMan::instance()->setSyncEnabled(false);
owncloudSetupWizard->startWizardForLoginFlow(serverUrl);
bringWizardToFrontIfVisible();
return;
}

owncloudSetupWizard = new OwncloudSetupWizard(parent);
connect(owncloudSetupWizard, SIGNAL(ownCloudWizardDone(int)), obj, amember);
connect(owncloudSetupWizard->_ocWizard, &OwncloudWizard::wizardClosed, obj, [] { owncloudSetupWizard.clear(); });

FolderMan::instance()->setSyncEnabled(false);
owncloudSetupWizard->startWizardForLoginFlow(serverUrl);
}

bool OwncloudSetupWizard::bringWizardToFrontIfVisible()
{
if (owncloudSetupWizard.isNull()) {
Expand All @@ -103,14 +128,35 @@

void OwncloudSetupWizard::startWizard()
{
AccountPtr account = AccountManager::createAccount();
account->setCredentials(CredentialsFactory::create("dummy"));
const auto defaultUrl =
Theme::instance()->multipleOverrideServers() ? QString{} : Theme::instance()->overrideServerUrl();
account->setUrl(defaultUrl);
initializeWizardAccount(QUrl{defaultUrl});

const auto isEnforcedServerSetup =
Theme::instance()->startLoginFlowAutomatically() && Theme::instance()->forceOverrideServerUrl() && !_ocWizard->account()->url().isEmpty();

#ifdef WITH_PROVIDERS
const auto startPage = isEnforcedServerSetup ? WizardCommon::Page_ServerSetup : WizardCommon::Page_Welcome;
#else // WITH_PROVIDERS
const auto startPage = WizardCommon::Page_ServerSetup;
#endif // WITH_PROVIDERS
openWizardAtPage(startPage);
}

void OwncloudSetupWizard::startWizardForLoginFlow(const QUrl &serverUrl)
{
initializeWizardAccount(serverUrl);
_ocWizard->_credentialsPage = _ocWizard->_flow2CredsPage;
openWizardAtPage(WizardCommon::Page_Flow2AuthCreds);
}

void OwncloudSetupWizard::initializeWizardAccount(const QUrl &serverUrl)

Check warning on line 153 in src/gui/owncloudsetupwizard.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/owncloudsetupwizard.cpp:153:27 [readability-convert-member-functions-to-static]

method 'initializeWizardAccount' can be made static
{
AccountPtr account = AccountManager::createAccount();

Check warning on line 155 in src/gui/owncloudsetupwizard.cpp

View workflow job for this annotation

GitHub Actions / build

src/gui/owncloudsetupwizard.cpp:155:16 [cppcoreguidelines-init-variables]

variable 'account' is not initialized
account->setCredentials(CredentialsFactory::create("dummy"));
account->setUrl(serverUrl);
_ocWizard->setAccount(account);
_ocWizard->setOCUrl(account->url().toString());

_remoteFolder = Theme::instance()->defaultServerFolder();
// remoteFolder may be empty, which means /
QString localFolder = Theme::instance()->defaultClientFolder();
Expand All @@ -132,15 +178,10 @@
// remember the local folder to compare later if it changed, but clean first
_initLocalFolder = Utility::trailingSlashPath(QDir::fromNativeSeparators(localFolder));
_ocWizard->setRemoteFolder(_remoteFolder);
}

const auto isEnforcedServerSetup =
Theme::instance()->startLoginFlowAutomatically() && Theme::instance()->forceOverrideServerUrl() && !account->url().isEmpty();

#ifdef WITH_PROVIDERS
const auto startPage = isEnforcedServerSetup ? WizardCommon::Page_ServerSetup : WizardCommon::Page_Welcome;
#else // WITH_PROVIDERS
const auto startPage = WizardCommon::Page_ServerSetup;
#endif // WITH_PROVIDERS
void OwncloudSetupWizard::openWizardAtPage(WizardCommon::Pages startPage)

Check warning on line 183 in src/gui/owncloudsetupwizard.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "startPage" of type "enum OCC::WizardCommon::Pages" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ33sz41n1POGIojLbDf&open=AZ33sz41n1POGIojLbDf&pullRequest=9969
{
_ocWizard->setStartId(startPage);
_ocWizard->restart();
_ocWizard->adjustWizardSize();
Expand All @@ -155,7 +196,7 @@
account->setUrl(serverURL);

account->setProxyType(proxySettings._proxyType);
switch (proxySettings._proxyType)

Check failure on line 199 in src/gui/owncloudsetupwizard.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add a "default" case to this switch statement.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ33sz41n1POGIojLbDh&open=AZ33sz41n1POGIojLbDh&pullRequest=9969
{
case QNetworkProxy::HttpCachingProxy:
case QNetworkProxy::FtpCachingProxy:
Expand All @@ -166,7 +207,7 @@
account->networkAccessManager()->setProxy({QNetworkProxy::NoProxy});
break;
case QNetworkProxy::Socks5Proxy:
case QNetworkProxy::HttpProxy:

Check warning on line 210 in src/gui/owncloudsetupwizard.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

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

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ33sz41n1POGIojLbDg&open=AZ33sz41n1POGIojLbDg&pullRequest=9969
account->setProxyHostName(proxySettings._host);
account->setProxyPort(proxySettings._port);
account->setProxyNeedsAuth(proxySettings._needsAuth == WizardProxySettingsDialog::ProxyAuthentication::AuthenticationRequired);
Expand Down Expand Up @@ -406,11 +447,11 @@
job->setFollowRedirects(false);
job->setProperties(QList<QByteArray>() << "getlastmodified");
connect(job, &PropfindJob::result, _ocWizard, &OwncloudWizard::successfulStep);
connect(job, &PropfindJob::finishedWithError, this, [this] (QNetworkReply *reply) -> void {

Check warning on line 450 in src/gui/owncloudsetupwizard.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the redundant return type of this lambda.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ33sz41n1POGIojLbDi&open=AZ33sz41n1POGIojLbDi&pullRequest=9969

Check warning on line 450 in src/gui/owncloudsetupwizard.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "reply" of type "class QNetworkReply *" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ33sz41n1POGIojLbDj&open=AZ33sz41n1POGIojLbDj&pullRequest=9969
if (reply && reply->error() == QNetworkReply::ContentAccessDenied) {
// A 403 might indicate that the terms of service need to be signed.
// catch this special case here, fall back to the standard error handler if it's not TOS-related
auto davException = OCC::getExceptionFromReply(reply);

Check warning on line 454 in src/gui/owncloudsetupwizard.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "davException" of type "struct std::pair<class QByteArray, class QByteArray>" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ33sz41n1POGIojLbDl&open=AZ33sz41n1POGIojLbDl&pullRequest=9969

Check warning on line 454 in src/gui/owncloudsetupwizard.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this declaration by a structured binding declaration.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ33sz41n1POGIojLbDk&open=AZ33sz41n1POGIojLbDk&pullRequest=9969
if (!davException.first.isEmpty() && davException.first == QStringLiteral(R"(OCA\TermsOfService\TermsNotSignedException)")) {
// authentication was successful, but the user hasn't signed the terms of service yet. Prompt for that in the next step
qCInfo(lcWizard) << "Terms of service not accepted yet! Will prompt the user in the next step";
Expand Down Expand Up @@ -444,7 +485,7 @@

// strip the expected path
QString path = redirectUrl.path();
static QString expectedPath = u'/' + _ocWizard->account()->davPath();

Check warning on line 488 in src/gui/owncloudsetupwizard.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unmodified variable "expectedPath" of type "class QString" should be const-qualified.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ33sz41n1POGIojLbDm&open=AZ33sz41n1POGIojLbDm&pullRequest=9969
if (path.endsWith(expectedPath)) {
path.chop(expectedPath.size());
redirectUrl.setPath(path);
Expand Down
6 changes: 6 additions & 0 deletions src/gui/owncloudsetupwizard.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,18 @@
#ifndef OWNCLOUDSETUPWIZARD_H
#define OWNCLOUDSETUPWIZARD_H

#include <QObject>

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

View workflow job for this annotation

GitHub Actions / build

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

'QObject' file not found
#include <QWidget>
#include <QProcess>
#include <QNetworkReply>
#include <QPointer>
#include <QUrl>

#include "accountfwd.h"
#include "theme.h"
#include "networkjobs.h"

#include "wizard/owncloudwizardcommon.h"
#include "wizard/wizardproxysettingsdialog.h"

namespace OCC {
Expand All @@ -30,12 +32,13 @@
* @brief The OwncloudSetupWizard class
* @ingroup gui
*/
class OwncloudSetupWizard : public QObject

Check warning on line 35 in src/gui/owncloudsetupwizard.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Class has 37 methods, which is greater than the 35 authorized. Split it into smaller classes.

See more on https://sonarcloud.io/project/issues?id=nextcloud_desktop&issues=AZ33sz3Nn1POGIojLbDZ&open=AZ33sz3Nn1POGIojLbDZ&pullRequest=9969
{
Q_OBJECT
public:
/** Run the wizard */
static void runWizard(QObject *obj, const char *amember, QWidget *parent = nullptr);
static void runWizardForLoginFlow(QObject *obj, const char *amember, const QUrl &serverUrl, QWidget *parent = nullptr);
static bool bringWizardToFrontIfVisible();

signals:
Expand Down Expand Up @@ -67,6 +70,9 @@
explicit OwncloudSetupWizard(QObject *parent = nullptr);
~OwncloudSetupWizard() override;
void startWizard();
void startWizardForLoginFlow(const QUrl &serverUrl);
void initializeWizardAccount(const QUrl &serverUrl);
void openWizardAtPage(WizardCommon::Pages startPage);
void testOwnCloudConnect();
void createRemoteFolder();
void finalizeSetup(bool);
Expand Down
Loading
Loading