Improve tracker entries handling
[qBittorrent.git] / src / webui / webapplication.h
blob4d3cf28e4194211bd7d54bd10d4bc2bf9c7b3eaa
1 /*
2 * Bittorrent Client using Qt and libtorrent.
3 * Copyright (C) 2014, 2017, 2022 Vladimir Golovnev <glassez@yandex.ru>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 * In addition, as a special exception, the copyright holders give permission to
20 * link this program with the OpenSSL project's "OpenSSL" library (or with
21 * modified versions of it that use the same license as the "OpenSSL" library),
22 * and distribute the linked executables. You must obey the GNU General Public
23 * License in all respects for all of the code used other than "OpenSSL". If you
24 * modify file(s), you may extend this exception to your version of the file(s),
25 * but you are not obligated to do so. If you do not wish to do so, delete this
26 * exception statement from your version.
29 #pragma once
31 #include <type_traits>
32 #include <utility>
34 #include <QDateTime>
35 #include <QElapsedTimer>
36 #include <QHash>
37 #include <QHostAddress>
38 #include <QMap>
39 #include <QObject>
40 #include <QRegularExpression>
41 #include <QSet>
42 #include <QTranslator>
43 #include <QVector>
45 #include "base/applicationcomponent.h"
46 #include "base/global.h"
47 #include "base/http/irequesthandler.h"
48 #include "base/http/responsebuilder.h"
49 #include "base/http/types.h"
50 #include "base/path.h"
51 #include "base/utils/net.h"
52 #include "base/utils/version.h"
53 #include "api/isessionmanager.h"
55 inline const Utils::Version<3, 2> API_VERSION {2, 9, 2};
57 class APIController;
58 class AuthController;
59 class WebApplication;
61 class WebSession final : public ApplicationComponent<QObject>, public ISession
63 public:
64 explicit WebSession(const QString &sid, IApplication *app);
66 QString id() const override;
68 bool hasExpired(qint64 seconds) const;
69 void updateTimestamp();
71 template <typename T>
72 void registerAPIController(const QString &scope)
74 static_assert(std::is_base_of_v<APIController, T>, "Class should be derived from APIController.");
75 m_apiControllers[scope] = new T(app(), this);
78 APIController *getAPIController(const QString &scope) const;
80 private:
81 const QString m_sid;
82 QElapsedTimer m_timer; // timestamp
83 QMap<QString, APIController *> m_apiControllers;
86 class WebApplication final : public ApplicationComponent<QObject>
87 , public Http::IRequestHandler, public ISessionManager
88 , private Http::ResponseBuilder
90 Q_OBJECT
91 Q_DISABLE_COPY_MOVE(WebApplication)
93 public:
94 explicit WebApplication(IApplication *app, QObject *parent = nullptr);
95 ~WebApplication() override;
97 Http::Response processRequest(const Http::Request &request, const Http::Environment &env) override;
99 QString clientId() const override;
100 WebSession *session() override;
101 void sessionStart() override;
102 void sessionEnd() override;
104 const Http::Request &request() const;
105 const Http::Environment &env() const;
107 private:
108 void doProcessRequest();
109 void configure();
111 void declarePublicAPI(const QString &apiPath);
113 void sendFile(const Path &path);
114 void sendWebUIFile();
116 void translateDocument(QString &data) const;
118 // Session management
119 QString generateSid() const;
120 void sessionInitialize();
121 bool isAuthNeeded();
122 bool isPublicAPI(const QString &scope, const QString &action) const;
124 bool isCrossSiteRequest(const Http::Request &request) const;
125 bool validateHostHeader(const QStringList &domains) const;
127 QHostAddress resolveClientAddress() const;
129 // Persistent data
130 QHash<QString, WebSession *> m_sessions;
132 // Current data
133 WebSession *m_currentSession = nullptr;
134 Http::Request m_request;
135 Http::Environment m_env;
136 QHash<QString, QString> m_params;
137 const QString m_cacheID;
139 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};
141 QSet<QString> m_publicAPIs;
142 const QHash<std::pair<QString, QString>, QString> m_allowedMethod =
144 // <<controller name, action name>, HTTP method>
145 {{u"app"_s, u"setPreferences"_s}, Http::METHOD_POST},
146 {{u"app"_s, u"shutdown"_s}, Http::METHOD_POST},
147 {{u"auth"_s, u"login"_s}, Http::METHOD_POST},
148 {{u"auth"_s, u"logout"_s}, Http::METHOD_POST},
149 {{u"rss"_s, u"addFeed"_s}, Http::METHOD_POST},
150 {{u"rss"_s, u"setFeedURL"_s}, Http::METHOD_POST},
151 {{u"rss"_s, u"addFolder"_s}, Http::METHOD_POST},
152 {{u"rss"_s, u"markAsRead"_s}, Http::METHOD_POST},
153 {{u"rss"_s, u"moveItem"_s}, Http::METHOD_POST},
154 {{u"rss"_s, u"refreshItem"_s}, Http::METHOD_POST},
155 {{u"rss"_s, u"removeItem"_s}, Http::METHOD_POST},
156 {{u"rss"_s, u"removeRule"_s}, Http::METHOD_POST},
157 {{u"rss"_s, u"renameRule"_s}, Http::METHOD_POST},
158 {{u"rss"_s, u"setRule"_s}, Http::METHOD_POST},
159 {{u"search"_s, u"delete"_s}, Http::METHOD_POST},
160 {{u"search"_s, u"enablePlugin"_s}, Http::METHOD_POST},
161 {{u"search"_s, u"installPlugin"_s}, Http::METHOD_POST},
162 {{u"search"_s, u"start"_s}, Http::METHOD_POST},
163 {{u"search"_s, u"stop"_s}, Http::METHOD_POST},
164 {{u"search"_s, u"uninstallPlugin"_s}, Http::METHOD_POST},
165 {{u"search"_s, u"updatePlugins"_s}, Http::METHOD_POST},
166 {{u"torrents"_s, u"add"_s}, Http::METHOD_POST},
167 {{u"torrents"_s, u"addPeers"_s}, Http::METHOD_POST},
168 {{u"torrents"_s, u"addTags"_s}, Http::METHOD_POST},
169 {{u"torrents"_s, u"addTrackers"_s}, Http::METHOD_POST},
170 {{u"torrents"_s, u"bottomPrio"_s}, Http::METHOD_POST},
171 {{u"torrents"_s, u"createCategory"_s}, Http::METHOD_POST},
172 {{u"torrents"_s, u"createTags"_s}, Http::METHOD_POST},
173 {{u"torrents"_s, u"decreasePrio"_s}, Http::METHOD_POST},
174 {{u"torrents"_s, u"delete"_s}, Http::METHOD_POST},
175 {{u"torrents"_s, u"deleteTags"_s}, Http::METHOD_POST},
176 {{u"torrents"_s, u"editCategory"_s}, Http::METHOD_POST},
177 {{u"torrents"_s, u"editTracker"_s}, Http::METHOD_POST},
178 {{u"torrents"_s, u"filePrio"_s}, Http::METHOD_POST},
179 {{u"torrents"_s, u"increasePrio"_s}, Http::METHOD_POST},
180 {{u"torrents"_s, u"pause"_s}, Http::METHOD_POST},
181 {{u"torrents"_s, u"reannounce"_s}, Http::METHOD_POST},
182 {{u"torrents"_s, u"recheck"_s}, Http::METHOD_POST},
183 {{u"torrents"_s, u"removeCategories"_s}, Http::METHOD_POST},
184 {{u"torrents"_s, u"removeTags"_s}, Http::METHOD_POST},
185 {{u"torrents"_s, u"removeTrackers"_s}, Http::METHOD_POST},
186 {{u"torrents"_s, u"rename"_s}, Http::METHOD_POST},
187 {{u"torrents"_s, u"renameFile"_s}, Http::METHOD_POST},
188 {{u"torrents"_s, u"renameFolder"_s}, Http::METHOD_POST},
189 {{u"torrents"_s, u"resume"_s}, Http::METHOD_POST},
190 {{u"torrents"_s, u"setAutoManagement"_s}, Http::METHOD_POST},
191 {{u"torrents"_s, u"setCategory"_s}, Http::METHOD_POST},
192 {{u"torrents"_s, u"setDownloadLimit"_s}, Http::METHOD_POST},
193 {{u"torrents"_s, u"setDownloadPath"_s}, Http::METHOD_POST},
194 {{u"torrents"_s, u"setForceStart"_s}, Http::METHOD_POST},
195 {{u"torrents"_s, u"setLocation"_s}, Http::METHOD_POST},
196 {{u"torrents"_s, u"setSavePath"_s}, Http::METHOD_POST},
197 {{u"torrents"_s, u"setShareLimits"_s}, Http::METHOD_POST},
198 {{u"torrents"_s, u"setSuperSeeding"_s}, Http::METHOD_POST},
199 {{u"torrents"_s, u"setUploadLimit"_s}, Http::METHOD_POST},
200 {{u"torrents"_s, u"toggleFirstLastPiecePrio"_s}, Http::METHOD_POST},
201 {{u"torrents"_s, u"toggleSequentialDownload"_s}, Http::METHOD_POST},
202 {{u"torrents"_s, u"topPrio"_s}, Http::METHOD_POST},
203 {{u"transfer"_s, u"banPeers"_s}, Http::METHOD_POST},
204 {{u"transfer"_s, u"setDownloadLimit"_s}, Http::METHOD_POST},
205 {{u"transfer"_s, u"setSpeedLimitsMode"_s}, Http::METHOD_POST},
206 {{u"transfer"_s, u"setUploadLimit"_s}, Http::METHOD_POST},
207 {{u"transfer"_s, u"toggleSpeedLimitsMode"_s}, Http::METHOD_POST},
209 bool m_isAltUIUsed = false;
210 Path m_rootFolder;
212 struct TranslatedFile
214 QByteArray data;
215 QString mimeType;
216 QDateTime lastModified;
218 QHash<Path, TranslatedFile> m_translatedFiles;
219 QString m_currentLocale;
220 QTranslator m_translator;
221 bool m_translationFileLoaded = false;
223 AuthController *m_authController = nullptr;
224 bool m_isLocalAuthEnabled = false;
225 bool m_isAuthSubnetWhitelistEnabled = false;
226 QVector<Utils::Net::Subnet> m_authSubnetWhitelist;
227 int m_sessionTimeout = 0;
228 QString m_sessionCookieName;
230 // security related
231 QStringList m_domainList;
232 bool m_isCSRFProtectionEnabled = true;
233 bool m_isSecureCookieEnabled = true;
234 bool m_isHostHeaderValidationEnabled = true;
235 bool m_isHttpsEnabled = false;
237 // Reverse proxy
238 bool m_isReverseProxySupportEnabled = false;
239 QVector<Utils::Net::Subnet> m_trustedReverseProxyList;
240 QHostAddress m_clientAddress;
242 QVector<Http::Header> m_prebuiltHeaders;