Enable customizing the save statistics time interval
[qBittorrent.git] / src / webui / webapplication.h
blob80530b15dd3e55a223b27f5712e7ff760a6991ab
1 /*
2 * Bittorrent Client using Qt and libtorrent.
3 * Copyright (C) 2014-2024 Vladimir Golovnev <glassez@yandex.ru>
4 * Copyright (C) 2024 Radu Carpa <radu.carpa@cern.ch>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * In addition, as a special exception, the copyright holders give permission to
21 * link this program with the OpenSSL project's "OpenSSL" library (or with
22 * modified versions of it that use the same license as the "OpenSSL" library),
23 * and distribute the linked executables. You must obey the GNU General Public
24 * License in all respects for all of the code used other than "OpenSSL". If you
25 * modify file(s), you may extend this exception to your version of the file(s),
26 * but you are not obligated to do so. If you do not wish to do so, delete this
27 * exception statement from your version.
30 #pragma once
32 #include <type_traits>
33 #include <utility>
35 #include <QDateTime>
36 #include <QElapsedTimer>
37 #include <QHash>
38 #include <QHostAddress>
39 #include <QList>
40 #include <QMap>
41 #include <QObject>
42 #include <QRegularExpression>
43 #include <QSet>
44 #include <QTranslator>
46 #include "base/applicationcomponent.h"
47 #include "base/global.h"
48 #include "base/http/irequesthandler.h"
49 #include "base/http/responsebuilder.h"
50 #include "base/http/types.h"
51 #include "base/path.h"
52 #include "base/utils/net.h"
53 #include "base/utils/thread.h"
54 #include "base/utils/version.h"
55 #include "api/isessionmanager.h"
57 inline const Utils::Version<3, 2> API_VERSION {2, 11, 3};
59 class QTimer;
61 class APIController;
62 class AuthController;
63 class FreeDiskSpaceChecker;
64 class WebApplication;
66 namespace BitTorrent
68 class TorrentCreationManager;
71 class WebSession final : public ApplicationComponent<QObject>, public ISession
73 public:
74 explicit WebSession(const QString &sid, IApplication *app);
76 QString id() const override;
78 bool hasExpired(qint64 seconds) const;
79 void updateTimestamp();
81 void registerAPIController(const QString &scope, APIController *controller);
82 APIController *getAPIController(const QString &scope) const;
84 private:
85 const QString m_sid;
86 QElapsedTimer m_timer; // timestamp
87 QMap<QString, APIController *> m_apiControllers;
90 class WebApplication final : public ApplicationComponent<QObject>
91 , public Http::IRequestHandler, public ISessionManager
92 , private Http::ResponseBuilder
94 Q_OBJECT
95 Q_DISABLE_COPY_MOVE(WebApplication)
97 public:
98 explicit WebApplication(IApplication *app, QObject *parent = nullptr);
99 ~WebApplication() override;
101 Http::Response processRequest(const Http::Request &request, const Http::Environment &env) override;
103 const Http::Request &request() const;
104 const Http::Environment &env() const;
106 void setUsername(const QString &username);
107 void setPasswordHash(const QByteArray &passwordHash);
109 private:
110 QString clientId() const override;
111 WebSession *session() override;
112 void sessionStart() override;
113 void sessionEnd() override;
115 void doProcessRequest();
116 void configure();
118 void declarePublicAPI(const QString &apiPath);
120 void sendFile(const Path &path);
121 void sendWebUIFile();
123 void translateDocument(QString &data) const;
125 // Session management
126 QString generateSid() const;
127 void sessionInitialize();
128 bool isAuthNeeded();
129 bool isPublicAPI(const QString &scope, const QString &action) const;
131 bool isOriginTrustworthy() const;
132 bool isCrossSiteRequest(const Http::Request &request) const;
133 bool validateHostHeader(const QStringList &domains) const;
135 // reverse proxy
136 QHostAddress resolveClientAddress() const;
138 // Persistent data
139 QHash<QString, WebSession *> m_sessions;
141 // Current data
142 WebSession *m_currentSession = nullptr;
143 Http::Request m_request;
144 Http::Environment m_env;
145 QHash<QString, QString> m_params;
146 const QString m_cacheID;
148 const QRegularExpression m_apiPathPattern {u"^/api/v2/(?<scope>[A-Za-z_][A-Za-z_0-9]*)/(?<action>[A-Za-z_][A-Za-z_0-9]*)$"_s};
150 QSet<QString> m_publicAPIs;
151 const QHash<std::pair<QString, QString>, QString> m_allowedMethod =
153 // <<controller name, action name>, HTTP method>
154 {{u"app"_s, u"sendTestEmail"_s}, Http::METHOD_POST},
155 {{u"app"_s, u"setPreferences"_s}, Http::METHOD_POST},
156 {{u"app"_s, u"shutdown"_s}, Http::METHOD_POST},
157 {{u"auth"_s, u"login"_s}, Http::METHOD_POST},
158 {{u"auth"_s, u"logout"_s}, Http::METHOD_POST},
159 {{u"rss"_s, u"addFeed"_s}, Http::METHOD_POST},
160 {{u"rss"_s, u"addFolder"_s}, Http::METHOD_POST},
161 {{u"rss"_s, u"markAsRead"_s}, Http::METHOD_POST},
162 {{u"rss"_s, u"moveItem"_s}, Http::METHOD_POST},
163 {{u"rss"_s, u"refreshItem"_s}, Http::METHOD_POST},
164 {{u"rss"_s, u"removeItem"_s}, Http::METHOD_POST},
165 {{u"rss"_s, u"removeRule"_s}, Http::METHOD_POST},
166 {{u"rss"_s, u"renameRule"_s}, Http::METHOD_POST},
167 {{u"rss"_s, u"setFeedURL"_s}, Http::METHOD_POST},
168 {{u"rss"_s, u"setRule"_s}, Http::METHOD_POST},
169 {{u"search"_s, u"delete"_s}, Http::METHOD_POST},
170 {{u"search"_s, u"enablePlugin"_s}, Http::METHOD_POST},
171 {{u"search"_s, u"installPlugin"_s}, Http::METHOD_POST},
172 {{u"search"_s, u"start"_s}, Http::METHOD_POST},
173 {{u"search"_s, u"stop"_s}, Http::METHOD_POST},
174 {{u"search"_s, u"uninstallPlugin"_s}, Http::METHOD_POST},
175 {{u"search"_s, u"updatePlugins"_s}, Http::METHOD_POST},
176 {{u"torrentcreator"_s, u"addTask"_s}, Http::METHOD_POST},
177 {{u"torrentcreator"_s, u"deleteTask"_s}, Http::METHOD_POST},
178 {{u"torrents"_s, u"add"_s}, Http::METHOD_POST},
179 {{u"torrents"_s, u"addPeers"_s}, Http::METHOD_POST},
180 {{u"torrents"_s, u"addTags"_s}, Http::METHOD_POST},
181 {{u"torrents"_s, u"addTrackers"_s}, Http::METHOD_POST},
182 {{u"torrents"_s, u"addWebSeeds"_s}, Http::METHOD_POST},
183 {{u"transfer"_s, u"banPeers"_s}, Http::METHOD_POST},
184 {{u"torrents"_s, u"bottomPrio"_s}, Http::METHOD_POST},
185 {{u"torrents"_s, u"createCategory"_s}, Http::METHOD_POST},
186 {{u"torrents"_s, u"createTags"_s}, Http::METHOD_POST},
187 {{u"torrents"_s, u"decreasePrio"_s}, Http::METHOD_POST},
188 {{u"torrents"_s, u"delete"_s}, Http::METHOD_POST},
189 {{u"torrents"_s, u"deleteTags"_s}, Http::METHOD_POST},
190 {{u"torrents"_s, u"editCategory"_s}, Http::METHOD_POST},
191 {{u"torrents"_s, u"editTracker"_s}, Http::METHOD_POST},
192 {{u"torrents"_s, u"editWebSeed"_s}, Http::METHOD_POST},
193 {{u"torrents"_s, u"filePrio"_s}, Http::METHOD_POST},
194 {{u"torrents"_s, u"increasePrio"_s}, Http::METHOD_POST},
195 {{u"torrents"_s, u"reannounce"_s}, Http::METHOD_POST},
196 {{u"torrents"_s, u"recheck"_s}, Http::METHOD_POST},
197 {{u"torrents"_s, u"removeCategories"_s}, Http::METHOD_POST},
198 {{u"torrents"_s, u"removeTags"_s}, Http::METHOD_POST},
199 {{u"torrents"_s, u"removeTrackers"_s}, Http::METHOD_POST},
200 {{u"torrents"_s, u"removeWebSeeds"_s}, Http::METHOD_POST},
201 {{u"torrents"_s, u"rename"_s}, Http::METHOD_POST},
202 {{u"torrents"_s, u"renameFile"_s}, Http::METHOD_POST},
203 {{u"torrents"_s, u"renameFolder"_s}, Http::METHOD_POST},
204 {{u"torrents"_s, u"setAutoManagement"_s}, Http::METHOD_POST},
205 {{u"torrents"_s, u"setCategory"_s}, Http::METHOD_POST},
206 {{u"torrents"_s, u"setDownloadLimit"_s}, Http::METHOD_POST},
207 {{u"torrents"_s, u"setDownloadPath"_s}, Http::METHOD_POST},
208 {{u"torrents"_s, u"setForceStart"_s}, Http::METHOD_POST},
209 {{u"torrents"_s, u"setLocation"_s}, Http::METHOD_POST},
210 {{u"torrents"_s, u"setSavePath"_s}, Http::METHOD_POST},
211 {{u"torrents"_s, u"setShareLimits"_s}, Http::METHOD_POST},
212 {{u"torrents"_s, u"setSSLParameters"_s}, Http::METHOD_POST},
213 {{u"torrents"_s, u"setSuperSeeding"_s}, Http::METHOD_POST},
214 {{u"torrents"_s, u"setUploadLimit"_s}, Http::METHOD_POST},
215 {{u"transfer"_s, u"setDownloadLimit"_s}, Http::METHOD_POST},
216 {{u"transfer"_s, u"setSpeedLimitsMode"_s}, Http::METHOD_POST},
217 {{u"transfer"_s, u"setUploadLimit"_s}, Http::METHOD_POST},
218 {{u"torrents"_s, u"start"_s}, Http::METHOD_POST},
219 {{u"torrents"_s, u"stop"_s}, Http::METHOD_POST},
220 {{u"torrents"_s, u"toggleFirstLastPiecePrio"_s}, Http::METHOD_POST},
221 {{u"torrents"_s, u"toggleSequentialDownload"_s}, Http::METHOD_POST},
222 {{u"transfer"_s, u"toggleSpeedLimitsMode"_s}, Http::METHOD_POST},
223 {{u"torrents"_s, u"topPrio"_s}, Http::METHOD_POST},
225 bool m_isAltUIUsed = false;
226 Path m_rootFolder;
228 struct TranslatedFile
230 QByteArray data;
231 QString mimeType;
232 QDateTime lastModified;
234 QHash<Path, TranslatedFile> m_translatedFiles;
235 QString m_currentLocale;
236 QTranslator m_translator;
237 bool m_translationFileLoaded = false;
239 AuthController *m_authController = nullptr;
240 bool m_isLocalAuthEnabled = false;
241 bool m_isAuthSubnetWhitelistEnabled = false;
242 QList<Utils::Net::Subnet> m_authSubnetWhitelist;
243 int m_sessionTimeout = 0;
244 QString m_sessionCookieName;
246 // security related
247 QStringList m_domainList;
248 bool m_isCSRFProtectionEnabled = true;
249 bool m_isSecureCookieEnabled = true;
250 bool m_isHostHeaderValidationEnabled = true;
251 bool m_isHttpsEnabled = false;
253 // Reverse proxy
254 bool m_isReverseProxySupportEnabled = false;
255 QList<Utils::Net::Subnet> m_trustedReverseProxyList;
256 QHostAddress m_clientAddress;
258 QList<Http::Header> m_prebuiltHeaders;
260 Utils::Thread::UniquePtr m_workerThread;
261 FreeDiskSpaceChecker *m_freeDiskSpaceChecker = nullptr;
262 QTimer *m_freeDiskSpaceCheckingTimer = nullptr;
263 BitTorrent::TorrentCreationManager *m_torrentCreationManager = nullptr;