Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
10 changes: 6 additions & 4 deletions src/libsync/accessmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* SPDX-License-Identifier: GPL-2.0-or-later
*/

#include <QLoggingCategory>

Check failure on line 7 in src/libsync/accessmanager.cpp

View workflow job for this annotation

GitHub Actions / build

src/libsync/accessmanager.cpp:7:10 [clang-diagnostic-error]

'QLoggingCategory' file not found
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QNetworkProxy>
Expand Down Expand Up @@ -82,10 +82,12 @@
}
#endif

// We handle redirects ourselves in AbstractNetworkJob::slotFinished
// Qt's automatic handling of redirects will transmit all set headers from the original
// request again, including e.g. `Authorization`.
newRequest.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::ManualRedirectPolicy);
if (!newRequest.attribute(QNetworkRequest::RedirectPolicyAttribute).isValid()) {
// We handle redirects ourselves in AbstractNetworkJob::slotFinished
// Qt's automatic handling of redirects will transmit all set headers from the original
// request again, including e.g. `Authorization`.
newRequest.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::ManualRedirectPolicy);
}

const auto reply = QNetworkAccessManager::createRequest(op, newRequest, outgoingData);
HttpLogger::logRequest(reply, op, outgoingData);
Expand Down
7 changes: 6 additions & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,16 @@ set_target_properties(testutils PROPERTIES FOLDER Tests)
nextcloud_add_test(NextcloudPropagator)
if(Qt${QT_VERSION_MAJOR}HttpServer_FOUND)
target_compile_definitions(NextcloudPropagatorTest PRIVATE HAVE_QHTTPSERVER=1)
target_link_libraries(NextcloudPropagatorTest PRIVATE Qt6::HttpServer)
target_link_libraries(NextcloudPropagatorTest PRIVATE Qt::HttpServer)
endif()

IF(BUILD_UPDATER)
nextcloud_add_test(Updater)

if(Qt${QT_VERSION_MAJOR}HttpServer_FOUND)
target_compile_definitions(UpdaterTest PRIVATE HAVE_QHTTPSERVER=1)
target_link_libraries(UpdaterTest PRIVATE Qt::HttpServer)
endif()
endif()

nextcloud_add_test(NetrcParser)
Expand Down
76 changes: 75 additions & 1 deletion test/testupdater.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
/*
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2014 ownCloud, Inc.
Expand All @@ -8,11 +8,21 @@
* any purpose.
*/

#include <QtTest>

Check failure on line 11 in test/testupdater.cpp

View workflow job for this annotation

GitHub Actions / build

test/testupdater.cpp:11:10 [clang-diagnostic-error]

'QtTest' file not found

#include "common/filesystembase.h"
#include "updater/updater.h"
#include "updater/ocupdater.h"
#include "configfile.h"
#include "logger.h"
#include "filesystem.h"

using namespace Qt::StringLiterals;

#ifdef HAVE_QHTTPSERVER
#include <QHttpServer>
#include <QTcpServer>
#endif

using namespace OCC;

Expand Down Expand Up @@ -41,7 +51,71 @@
QVERIFY(currVersion < highVersion);
}

#ifdef HAVE_QHTTPSERVER
void testUpdaterDownloadRedirect()
{
QTemporaryDir tempDir;
ConfigFile::setConfDir(tempDir.path()); // we don't want to pollute the user's config file
QVERIFY(tempDir.isValid());
QDir dir(tempDir.path());

// set up a download server that provides the version info and redirects the download request to e.g. some object storage
QHttpServer httpServer;
httpServer.route("/updateinfo.xml", [](const QHttpServerRequest &request, QHttpServerResponder &responder) -> void {
auto downloadTarget = request.url();
downloadTarget.setPath("/Nextcloud.msi");
qInfo() << "redirecting to" << downloadTarget;

QHttpHeaders headers;
headers.append(QHttpHeaders::WellKnownHeader::ContentType, "application/xml"_ba);

auto xmlResponse = "<?xml version=\"1.0\"?>\n<owncloudclient><version>600.0.0</version><versionstring>Nextcloud Client 600.0.0</versionstring><downloadurl>"_ba;
xmlResponse.append(downloadTarget.toEncoded());
xmlResponse.append("</downloadurl><web>https://nextcloud.com/install</web></owncloudclient>"_ba);

responder.write(xmlResponse, headers);
});
httpServer.route("/Nextcloud.msi", [](QHttpServerResponder &responder) -> void {
QHttpHeaders headers;
headers.append(QHttpHeaders::WellKnownHeader::Location, "/storage/blob/42?signature=1234abcd&signatureVersion=2026-01-21"_ba);
responder.write(""_ba, headers, QHttpServerResponder::StatusCode::Found);
});

bool redirectHit = false;
httpServer.route("/storage/blob/42", [&redirectHit](QHttpServerResponder &responder) -> void {
QHttpHeaders headers;
headers.append(QHttpHeaders::WellKnownHeader::ContentType, "application/octet-stream"_ba);
redirectHit = true;

responder.write("This would be the installer"_ba, headers);
});

QTcpServer tcpServer;
QVERIFY(tcpServer.listen(QHostAddress::LocalHost));
QVERIFY(httpServer.bind(&tcpServer));
const QString baseUrl = "http://%1:%2"_L1.arg(tcpServer.serverAddress().toString(), QString::number(tcpServer.serverPort()));
qInfo() << "Listening on" << baseUrl;

NSISUpdater updater(QUrl("%1/updateinfo.xml"_L1.arg(baseUrl)));
QSignalSpy downloadAvailableSpy(&updater, &OCUpdater::newUpdateAvailable);
updater.checkForUpdate();
downloadAvailableSpy.wait();
QCOMPARE(downloadAvailableSpy.size(), 1);
QVERIFY(redirectHit);

ConfigFile cfg;
QSettings settings(cfg.configFile(), QSettings::IniFormat);
const auto downloadedUpdateFilePath = settings.value("Updater/updateAvailable"_L1).toString(); // anonymous const in ocupdater.cpp
const auto expectedUpdateFilePath = FileSystem::joinPath(cfg.configPath(), "Nextcloud.msi");
QCOMPARE(downloadedUpdateFilePath, expectedUpdateFilePath);
QFile updateFile(expectedUpdateFilePath);
QVERIFY(updateFile.open(QIODevice::ReadOnly));
const auto updateContents = updateFile.readAll();
updateFile.close();
QCOMPARE(updateContents, "This would be the installer"_ba);
}
#endif
};

QTEST_APPLESS_MAIN(TestUpdater)
QTEST_GUILESS_MAIN(TestUpdater)

Check warning on line 120 in test/testupdater.cpp

View workflow job for this annotation

GitHub Actions / build

test/testupdater.cpp:120:20 [cppcoreguidelines-avoid-non-const-global-variables]

variable 'TestUpdater' is non-const and globally accessible, consider making it const
#include "testupdater.moc"
Loading