summaryrefslogtreecommitdiffstats
path: root/src/requestinterceptor.h
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-02 17:37:48 +0200
committerDanilo M. <danix@danix.xyz>2026-08-04 12:52:24 +0200
commitab4498ba12107529b8545f7d03dfe27433a3ffe2 (patch)
treea6de6af4523c6c36136f5b57a69a2fd0e87e3230 /src/requestinterceptor.h
parent18dffc348f722fc79ed336523982541283bc84e1 (diff)
downloadqtmaildir-ab4498ba12107529b8545f7d03dfe27433a3ffe2.tar.gz
qtmaildir-ab4498ba12107529b8545f7d03dfe27433a3ffe2.zip
feat: add deny-by-default web request interceptor
Diffstat (limited to 'src/requestinterceptor.h')
-rw-r--r--src/requestinterceptor.h42
1 files changed, 42 insertions, 0 deletions
diff --git a/src/requestinterceptor.h b/src/requestinterceptor.h
new file mode 100644
index 0000000..817a4d1
--- /dev/null
+++ b/src/requestinterceptor.h
@@ -0,0 +1,42 @@
+#pragma once
+
+#include <QSet>
+#include <QUrl>
+#include <QWebEngineUrlRequestInterceptor>
+
+/// Deny-by-default request policy for the message view.
+///
+/// A message body is untrusted input from a stranger. Everything is blocked
+/// unless explicitly permitted: remote loads leak the fact that a message was
+/// read (tracking pixels) and file: loads would expose the local filesystem.
+class RequestInterceptor : public QWebEngineUrlRequestInterceptor
+{
+ Q_OBJECT
+public:
+ explicit RequestInterceptor(QObject *parent = nullptr);
+
+ /// The whole policy, as a pure function so it can be tested directly.
+ bool shouldAllow(const QUrl &url);
+
+ void interceptRequest(QWebEngineUrlRequestInfo &info) override;
+
+ /// Content-IDs belonging to the currently displayed message.
+ void setAllowedCids(const QSet<QString> &cids) { m_allowedCids = cids; }
+
+ /// Per-message opt-in, triggered by the user clicking "Load remote content".
+ /// Never persisted, never carried to the next message.
+ void setAllowRemote(bool allow) { m_allowRemote = allow; }
+ bool allowRemote() const { return m_allowRemote; }
+
+ /// True once any request has been denied, so the UI can offer the button.
+ bool blockedAnything() const { return m_blockedAnything; }
+
+ /// Called before rendering a new message: clears both the remote grant and
+ /// the blocked flag.
+ void resetForNewMessage();
+
+private:
+ QSet<QString> m_allowedCids;
+ bool m_allowRemote = false;
+ bool m_blockedAnything = false;
+};