Skip to content

Commit f9949ee

Browse files
committed
edit locally requires a valid token
check on server that the token received during a request to open a local file is indeed a valid one Signed-off-by: Matthieu Gallien <matthieu.gallien@nextcloud.com>
1 parent 615c02e commit f9949ee

3 files changed

Lines changed: 49 additions & 19 deletions

File tree

src/gui/application.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
#include <QMessageBox>
6262
#include <QDesktopServices>
6363
#include <QGuiApplication>
64+
#include <QUrlQuery>
6465

6566
class QSocket;
6667

@@ -764,8 +765,16 @@ void Application::handleEditLocally(const QUrl &url) const
764765
// for a sample URL "nc://open/admin@nextcloud.lan:8080/Photos/lovely.jpg", QUrl::path would return "admin@nextcloud.lan:8080/Photos/lovely.jpg"
765766
const auto accountDisplayName = pathSplit.takeFirst();
766767
const auto fileRemotePath = pathSplit.join('/');
768+
const auto urlQuery = QUrlQuery{url};
767769

768-
FolderMan::instance()->editFileLocally(accountDisplayName, fileRemotePath);
770+
auto token = QString{};
771+
if (urlQuery.hasQueryItem(QStringLiteral("token"))) {
772+
token = urlQuery.queryItemValue(QStringLiteral("token"));
773+
} else {
774+
qCWarning(lcApplication) << "Invalid URL for file local editing: missing token";
775+
}
776+
777+
FolderMan::instance()->editFileLocally(accountDisplayName, fileRemotePath, token);
769778
}
770779

771780
QString substLang(const QString &lang)

src/gui/folderman.cpp

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,7 +1422,7 @@ void FolderMan::setDirtyNetworkLimits()
14221422
}
14231423
}
14241424

1425-
void FolderMan::editFileLocally(const QString &accountDisplayName, const QString &relPath)
1425+
void FolderMan::editFileLocally(const QString &accountDisplayName, const QString &relPath, const QString &token)
14261426
{
14271427
const auto showError = [this](const OCC::AccountStatePtr accountState, const QString &errorMessage, const QString &subject) {
14281428
if (accountState && accountState->account()) {
@@ -1447,6 +1447,12 @@ void FolderMan::editFileLocally(const QString &accountDisplayName, const QString
14471447
messageBox->raise();
14481448
};
14491449

1450+
if (token.isEmpty()) {
1451+
qCWarning(lcFolderMan) << "Edit locally request is missing a valid token. Impossible to open the file.";
1452+
showError({}, tr("Edit locally request is not valid. Opening the file is forbidden."), accountDisplayName);
1453+
return;
1454+
}
1455+
14501456
const auto accountFound = AccountManager::instance()->account(accountDisplayName);
14511457

14521458
if (!accountFound) {
@@ -1488,23 +1494,38 @@ void FolderMan::editFileLocally(const QString &accountDisplayName, const QString
14881494
showError(accountFound, tr("Could not find a file for local editing. Make sure its path is valid and it is synced locally."), relPath);
14891495
return;
14901496
}
1491-
folderForFile->startSync();
1492-
_localFileEditingSyncFinishedConnections.insert(localFilePath, QObject::connect(folderForFile, &Folder::syncFinished, this,
1493-
[this, localFilePath](const OCC::SyncResult &result) {
1494-
Q_UNUSED(result);
1495-
const auto foundConnectionIt = _localFileEditingSyncFinishedConnections.find(localFilePath);
1496-
if (foundConnectionIt != std::end(_localFileEditingSyncFinishedConnections) && foundConnectionIt.value()) {
1497-
QObject::disconnect(foundConnectionIt.value());
1498-
_localFileEditingSyncFinishedConnections.erase(foundConnectionIt);
1499-
}
1500-
// In case the VFS mode is enabled and a file is not yet hydrated, we must call QDesktopServices::openUrl
1501-
// from a separate thread, or, there will be a freeze. To avoid searching for a specific folder and checking
1502-
// if the VFS is enabled - we just always call it from a separate thread.
1503-
QtConcurrent::run([localFilePath]() {
1504-
QDesktopServices::openUrl(QUrl::fromLocalFile(localFilePath));
1497+
1498+
const auto checkTokenForEditLocally = new SimpleApiJob(accountFound->account(), QStringLiteral("/ocs/v2.php/apps/files/api/v1/openlocaleditor/%1").arg(token));
1499+
checkTokenForEditLocally->setVerb(SimpleApiJob::Verb::Post);
1500+
checkTokenForEditLocally->setBody(QByteArray{"path=/"}.append(relPath.toUtf8()));
1501+
connect(checkTokenForEditLocally, &SimpleApiJob::resultReceived, checkTokenForEditLocally, [this, folderForFile, localFilePath, showError, accountFound, relPath] (int statusCode) {
1502+
constexpr auto HTTP_OK_CODE = 200;
1503+
if (statusCode != HTTP_OK_CODE) {
15051504
Systray::instance()->destroyEditFileLocallyLoadingDialog();
1506-
});
1507-
}));
1505+
showError(accountFound, tr("Could not validate the request to open a file from server."), relPath);
1506+
qCInfo(lcFolderMan()) << "token check result" << statusCode;
1507+
return;
1508+
}
1509+
1510+
folderForFile->startSync();
1511+
_localFileEditingSyncFinishedConnections.insert(localFilePath, QObject::connect(folderForFile, &Folder::syncFinished, this,
1512+
[this, localFilePath](const OCC::SyncResult &result) {
1513+
Q_UNUSED(result);
1514+
const auto foundConnectionIt = _localFileEditingSyncFinishedConnections.find(localFilePath);
1515+
if (foundConnectionIt != std::end(_localFileEditingSyncFinishedConnections) && foundConnectionIt.value()) {
1516+
QObject::disconnect(foundConnectionIt.value());
1517+
_localFileEditingSyncFinishedConnections.erase(foundConnectionIt);
1518+
}
1519+
// In case the VFS mode is enabled and a file is not yet hydrated, we must call QDesktopServices::openUrl
1520+
// from a separate thread, or, there will be a freeze. To avoid searching for a specific folder and checking
1521+
// if the VFS is enabled - we just always call it from a separate thread.
1522+
QtConcurrent::run([localFilePath]() {
1523+
QDesktopServices::openUrl(QUrl::fromLocalFile(localFilePath));
1524+
Systray::instance()->destroyEditFileLocallyLoadingDialog();
1525+
});
1526+
}));
1527+
});
1528+
checkTokenForEditLocally->start();
15081529
}
15091530

15101531
void FolderMan::trayOverallStatus(const QList<Folder *> &folders,

src/gui/folderman.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ class FolderMan : public QObject
214214
void setDirtyNetworkLimits();
215215

216216
/** opens a file with default app, if the file is present **/
217-
void editFileLocally(const QString &accountDisplayName, const QString &relPath);
217+
void editFileLocally(const QString &accountDisplayName, const QString &relPath, const QString &token);
218218

219219
signals:
220220
/**

0 commit comments

Comments
 (0)