From 3cd56fce103ab62887c5592827d78a1197cd926a Mon Sep 17 00:00:00 2001
From: Carl Schwan <carl@carlschwan.eu>
Date: Fri, 24 Apr 2026 14:41:45 +0200
Subject: [PATCH] bookserver: Add authentication token

---
 src/bookserver.cpp         | 7 +++++--
 src/bookserver.h           | 3 ++-
 src/main.cpp               | 4 ++--
 src/navigation.cpp         | 8 ++++++++
 src/navigation.h           | 8 ++++++++
 src/qml/EpubViewerPage.qml | 2 +-
 6 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/src/bookserver.cpp b/src/bookserver.cpp
index 2bc74cb..014b4ed 100644
--- a/src/bookserver.cpp
+++ b/src/bookserver.cpp
@@ -8,9 +8,12 @@ using namespace Qt::StringLiterals;
 #include <QFileInfo>
 #include <QTcpServer>
 
-BookServer::BookServer()
+BookServer::BookServer(const QString &token)
 {
-    server.route(u"/book"_s, [](const QHttpServerRequest &request) {
+    server.route(u"/book"_s, [token](const QHttpServerRequest &request) {
+        if (request.query().queryItemValue(u"token"_s) != token) {
+            return QHttpServerResponse{QHttpServerResponder::StatusCode::Unauthorized};
+        }
         // + is an standing for %20
         // fromPercentEncoded doesn't handle it but it needs to come first
         // otherwise we end up with %2B -> + -> ' ' which won't be the correct path
diff --git a/src/bookserver.h b/src/bookserver.h
index 0eb4e9d..9c97e70 100644
--- a/src/bookserver.h
+++ b/src/bookserver.h
@@ -5,11 +5,12 @@
 
 #include <QHttpServer>
 #include <QHttpServerResponse>
+#include <QString>
 
 class BookServer
 {
 public:
-    BookServer();
+    explicit BookServer(const QString &token);
 
 private:
     QHttpServer server;
diff --git a/src/main.cpp b/src/main.cpp
index 3500fcb..2ca1b8a 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -83,8 +83,6 @@ int main(int argc, char *argv[])
     parser.process(app);
     about.processCommandLine(&parser);
 
-    BookServer bookServer;
-
     engine.loadFromModule("org.kde.arianna", "Main");
     if (engine.rootObjects().isEmpty()) {
         return -1;
@@ -92,6 +90,8 @@ int main(int argc, char *argv[])
 
     auto navigation = engine.singletonInstance<Navigation *>("org.kde.arianna", "Navigation");
 
+    BookServer bookServer(navigation->bookServerToken());
+
     QObject::connect(&service,
                      &KDBusService::activateRequested,
                      &engine,
diff --git a/src/navigation.cpp b/src/navigation.cpp
index e6acdd3..166ecbb 100644
--- a/src/navigation.cpp
+++ b/src/navigation.cpp
@@ -3,9 +3,17 @@
 
 #include "navigation.h"
 
+#include <QUuid>
+
 Navigation::Navigation(QObject *parent)
     : QObject(parent)
+    , m_bookServerToken(QUuid::createUuid().toString(QUuid::WithoutBraces))
+{
+}
+
+QString Navigation::bookServerToken() const
 {
+    return m_bookServerToken;
 }
 
 #include "moc_navigation.cpp"
diff --git a/src/navigation.h b/src/navigation.h
index f18d4f5..0a5dcfe 100644
--- a/src/navigation.h
+++ b/src/navigation.h
@@ -4,6 +4,7 @@
 #pragma once
 
 #include <QObject>
+#include <QString>
 #include <qqmlintegration.h>
 
 #include "categoryentriesmodel.h"
@@ -14,13 +15,20 @@ class Navigation : public QObject
     QML_SINGLETON
     QML_ELEMENT
 
+    Q_PROPERTY(QString bookServerToken READ bookServerToken CONSTANT)
+
 public:
     explicit Navigation(QObject *parent = nullptr);
 
+    QString bookServerToken() const;
+
 Q_SIGNALS:
     void openBook(const QString &fileName, const QString &locations, const QString &currentLocation, const BookEntry &entry);
 
     void openLibrary(const QString &title, CategoryEntriesModel *model, bool replace);
 
     void openSettings();
+
+private:
+    QString m_bookServerToken;
 };
diff --git a/src/qml/EpubViewerPage.qml b/src/qml/EpubViewerPage.qml
index 343ff64..eb2d89b 100644
--- a/src/qml/EpubViewerPage.qml
+++ b/src/qml/EpubViewerPage.qml
@@ -53,7 +53,7 @@ Kirigami.Page {
         // HACK: renderTo and options are the value of layouts.auto, but referencing layouts.auto here crashes
         const renderTo = "'viewer'";
         const options = JSON.stringify({ width: '100%', flow: 'paginated', maxSpreadColumns: 2 });
-        const urlNormalized = JSON.stringify('http://127.0.0.1:45961/book?url=' + encodeURIComponent(root.url));
+        const urlNormalized = JSON.stringify('http://127.0.0.1:45961/book?token=' + Navigation.bookServerToken + '&url=' + encodeURIComponent(root.url));
         const initCfi = currentLocation ? JSON.stringify(currentLocation) : "null";
         console.info("opening book", root.url, " to ", initCfi);
         view.runJavaScript(`openSync(${urlNormalized}, ${initCfi})`);
-- 
GitLab

