Vladimir Golovnev (Glassez)
10 years ago
37 changed files with 1918 additions and 1709 deletions
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent. |
||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru> |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License |
||||
* as published by the Free Software Foundation; either version 2 |
||||
* of the License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
* |
||||
* In addition, as a special exception, the copyright holders give permission to |
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with |
||||
* modified versions of it that use the same license as the "OpenSSL" library), |
||||
* and distribute the linked executables. You must obey the GNU General Public |
||||
* License in all respects for all of the code used other than "OpenSSL". If you |
||||
* modify file(s), you may extend this exception to your version of the file(s), |
||||
* but you are not obligated to do so. If you do not wish to do so, delete this |
||||
* exception statement from your version. |
||||
*/ |
||||
|
||||
#ifndef HTTP_IREQUESTHANDLER_H |
||||
#define HTTP_IREQUESTHANDLER_H |
||||
|
||||
#include "types.h" |
||||
|
||||
namespace Http |
||||
{ |
||||
|
||||
class IRequestHandler |
||||
{ |
||||
public: |
||||
virtual ~IRequestHandler() {} |
||||
virtual Response processRequest(const Request &request, const Environment &env) = 0; |
||||
}; |
||||
|
||||
} |
||||
|
||||
#endif // HTTP_IREQUESTHANDLER_H
|
||||
|
@ -0,0 +1,74 @@
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent. |
||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru> |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License |
||||
* as published by the Free Software Foundation; either version 2 |
||||
* of the License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
* |
||||
* In addition, as a special exception, the copyright holders give permission to |
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with |
||||
* modified versions of it that use the same license as the "OpenSSL" library), |
||||
* and distribute the linked executables. You must obey the GNU General Public |
||||
* License in all respects for all of the code used other than "OpenSSL". If you |
||||
* modify file(s), you may extend this exception to your version of the file(s), |
||||
* but you are not obligated to do so. If you do not wish to do so, delete this |
||||
* exception statement from your version. |
||||
*/ |
||||
|
||||
#include "responsebuilder.h" |
||||
|
||||
using namespace Http; |
||||
|
||||
ResponseBuilder::ResponseBuilder(QObject *parent) |
||||
: QObject(parent) |
||||
{ |
||||
} |
||||
|
||||
void ResponseBuilder::status(uint code, const QString &text) |
||||
{ |
||||
m_response.status = ResponseStatus(code, text); |
||||
} |
||||
|
||||
void ResponseBuilder::header(const QString &name, const QString &value) |
||||
{ |
||||
m_response.headers[name] = value; |
||||
} |
||||
|
||||
void ResponseBuilder::print(const QString &text, const QString &type) |
||||
{ |
||||
print_impl(text.toUtf8(), type); |
||||
} |
||||
|
||||
void ResponseBuilder::print(const QByteArray &data, const QString &type) |
||||
{ |
||||
print_impl(data, type); |
||||
} |
||||
|
||||
void ResponseBuilder::clear() |
||||
{ |
||||
m_response = Response(); |
||||
} |
||||
|
||||
Response ResponseBuilder::response() const |
||||
{ |
||||
return m_response; |
||||
} |
||||
|
||||
void ResponseBuilder::print_impl(const QByteArray &data, const QString &type) |
||||
{ |
||||
if (!m_response.headers.contains(HEADER_CONTENT_TYPE)) |
||||
m_response.headers[HEADER_CONTENT_TYPE] = type; |
||||
|
||||
m_response.content += data; |
||||
} |
@ -0,0 +1,60 @@
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent. |
||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru> |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License |
||||
* as published by the Free Software Foundation; either version 2 |
||||
* of the License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
* |
||||
* In addition, as a special exception, the copyright holders give permission to |
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with |
||||
* modified versions of it that use the same license as the "OpenSSL" library), |
||||
* and distribute the linked executables. You must obey the GNU General Public |
||||
* License in all respects for all of the code used other than "OpenSSL". If you |
||||
* modify file(s), you may extend this exception to your version of the file(s), |
||||
* but you are not obligated to do so. If you do not wish to do so, delete this |
||||
* exception statement from your version. |
||||
*/ |
||||
|
||||
#ifndef HTTP_RESPONSEBUILDER_H |
||||
#define HTTP_RESPONSEBUILDER_H |
||||
|
||||
#include <QObject> |
||||
#include "types.h" |
||||
|
||||
namespace Http |
||||
{ |
||||
|
||||
class ResponseBuilder : public QObject |
||||
{ |
||||
public: |
||||
explicit ResponseBuilder(QObject *parent = 0); |
||||
|
||||
protected: |
||||
void status(uint code = 200, const QString &text = QLatin1String("OK")); |
||||
void header(const QString &name, const QString &value); |
||||
void print(const QString &text, const QString &type = CONTENT_TYPE_HTML); |
||||
void print(const QByteArray &data, const QString &type = CONTENT_TYPE_HTML); |
||||
void clear(); |
||||
|
||||
Response response() const; |
||||
|
||||
private: |
||||
void print_impl(const QByteArray &data, const QString &type); |
||||
|
||||
Response m_response; |
||||
}; |
||||
|
||||
} |
||||
|
||||
#endif // HTTP_RESPONSEBUILDER_H
|
@ -1,35 +0,0 @@
@@ -1,35 +0,0 @@
|
||||
#ifndef QPEER_H |
||||
#define QPEER_H |
||||
|
||||
#include <libtorrent/entry.hpp> |
||||
#include <QString> |
||||
|
||||
struct QPeer { |
||||
|
||||
bool operator!=(const QPeer &other) const { |
||||
return qhash() != other.qhash(); |
||||
} |
||||
|
||||
bool operator==(const QPeer &other) const { |
||||
return qhash() == other.qhash(); |
||||
} |
||||
|
||||
QString qhash() const { |
||||
return ip+":"+QString::number(port); |
||||
} |
||||
|
||||
libtorrent::entry toEntry(bool no_peer_id) const { |
||||
libtorrent::entry::dictionary_type peer_map; |
||||
if (!no_peer_id) |
||||
peer_map["id"] = libtorrent::entry(peer_id.toStdString()); |
||||
peer_map["ip"] = libtorrent::entry(ip.toStdString()); |
||||
peer_map["port"] = libtorrent::entry(port); |
||||
return libtorrent::entry(peer_map); |
||||
} |
||||
|
||||
QString ip; |
||||
QString peer_id; |
||||
int port; |
||||
}; |
||||
|
||||
#endif // QPEER_H
|
@ -1,9 +0,0 @@
@@ -1,9 +0,0 @@
|
||||
INCLUDEPATH += $$PWD |
||||
|
||||
HEADERS += \ |
||||
$$PWD/qtracker.h \ |
||||
$$PWD/trackerannouncerequest.h \ |
||||
$$PWD/qpeer.h |
||||
|
||||
SOURCES += \ |
||||
$$PWD/qtracker.cpp |
@ -1,15 +0,0 @@
@@ -1,15 +0,0 @@
|
||||
#ifndef TRACKERANNOUNCEREQUEST_H |
||||
#define TRACKERANNOUNCEREQUEST_H |
||||
|
||||
#include <qpeer.h> |
||||
|
||||
struct TrackerAnnounceRequest { |
||||
QString info_hash; |
||||
QString event; |
||||
int numwant; |
||||
QPeer peer; |
||||
// Extensions
|
||||
bool no_peer_id; |
||||
}; |
||||
|
||||
#endif // TRACKERANNOUNCEREQUEST_H
|
@ -1,167 +0,0 @@
@@ -1,167 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent. |
||||
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru> |
||||
* Copyright (C) 2012, Christophe Dumez <chris@qbittorrent.org> |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License |
||||
* as published by the Free Software Foundation; either version 2 |
||||
* of the License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
* |
||||
* In addition, as a special exception, the copyright holders give permission to |
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with |
||||
* modified versions of it that use the same license as the "OpenSSL" library), |
||||
* and distribute the linked executables. You must obey the GNU General Public |
||||
* License in all respects for all of the code used other than "OpenSSL". If you |
||||
* modify file(s), you may extend this exception to your version of the file(s), |
||||
* but you are not obligated to do so. If you do not wish to do so, delete this |
||||
* exception statement from your version. |
||||
*/ |
||||
|
||||
#include <QDebug> |
||||
#include <QDir> |
||||
#include <QTemporaryFile> |
||||
#include <QNetworkCookie> |
||||
#include "preferences.h" |
||||
#include "webapplication.h" |
||||
#include "abstractrequesthandler.h" |
||||
|
||||
AbstractRequestHandler::AbstractRequestHandler(const HttpRequest &request, const HttpEnvironment &env, WebApplication *app) |
||||
: app_(app), session_(0), request_(request), env_(env) |
||||
{ |
||||
sessionInitialize(); |
||||
if (!sessionActive() && !isAuthNeeded()) |
||||
sessionStart(); |
||||
} |
||||
|
||||
HttpResponse AbstractRequestHandler::run() |
||||
{ |
||||
if (isBanned()) { |
||||
status(403, "Forbidden"); |
||||
print(QObject::tr("Your IP address has been banned after too many failed authentication attempts."), CONTENT_TYPE_TXT); |
||||
} |
||||
else { |
||||
processRequest(); |
||||
} |
||||
|
||||
return response_; |
||||
} |
||||
|
||||
bool AbstractRequestHandler::isAuthNeeded() |
||||
{ |
||||
return |
||||
( |
||||
env_.clientAddress != QHostAddress::LocalHost && |
||||
env_.clientAddress != QHostAddress::LocalHostIPv6 |
||||
) || Preferences::instance()->isWebUiLocalAuthEnabled(); |
||||
} |
||||
|
||||
void AbstractRequestHandler::status(uint code, const QString& text) |
||||
{ |
||||
response_.status = HttpResponseStatus(code, text); |
||||
} |
||||
|
||||
void AbstractRequestHandler::header(const QString& name, const QString& value) |
||||
{ |
||||
response_.headers[name] = value; |
||||
} |
||||
|
||||
void AbstractRequestHandler::print(const QString& text, const QString& type) |
||||
{ |
||||
print_impl(text.toUtf8(), type); |
||||
} |
||||
|
||||
void AbstractRequestHandler::print(const QByteArray& data, const QString& type) |
||||
{ |
||||
print_impl(data, type); |
||||
} |
||||
|
||||
void AbstractRequestHandler::print_impl(const QByteArray& data, const QString& type) |
||||
{ |
||||
if (!response_.headers.contains(HEADER_CONTENT_TYPE)) |
||||
response_.headers[HEADER_CONTENT_TYPE] = type; |
||||
|
||||
response_.content += data; |
||||
} |
||||
|
||||
void AbstractRequestHandler::printFile(const QString& path) |
||||
{ |
||||
QByteArray data; |
||||
QString type; |
||||
|
||||
if (!app_->readFile(path, data, type)) { |
||||
status(404, "Not Found"); |
||||
return; |
||||
} |
||||
|
||||
print(data, type); |
||||
} |
||||
|
||||
void AbstractRequestHandler::sessionInitialize() |
||||
{ |
||||
app_->sessionInitialize(this); |
||||
} |
||||
|
||||
void AbstractRequestHandler::sessionStart() |
||||
{ |
||||
if (app_->sessionStart(this)) { |
||||
QNetworkCookie cookie(C_SID.toUtf8(), session_->id.toUtf8()); |
||||
cookie.setPath("/"); |
||||
header(HEADER_SET_COOKIE, cookie.toRawForm()); |
||||
} |
||||
} |
||||
|
||||
void AbstractRequestHandler::sessionEnd() |
||||
{ |
||||
if (sessionActive()) { |
||||
QNetworkCookie cookie(C_SID.toUtf8(), session_->id.toUtf8()); |
||||
cookie.setPath("/"); |
||||
cookie.setExpirationDate(QDateTime::currentDateTime()); |
||||
|
||||
if (app_->sessionEnd(this)) |
||||
header(HEADER_SET_COOKIE, cookie.toRawForm()); |
||||
} |
||||
} |
||||
|
||||
bool AbstractRequestHandler::isBanned() const |
||||
{ |
||||
return app_->isBanned(this); |
||||
} |
||||
|
||||
int AbstractRequestHandler::failedAttempts() const |
||||
{ |
||||
return app_->failedAttempts(this); |
||||
} |
||||
|
||||
void AbstractRequestHandler::resetFailedAttempts() |
||||
{ |
||||
app_->resetFailedAttempts(this); |
||||
} |
||||
|
||||
void AbstractRequestHandler::increaseFailedAttempts() |
||||
{ |
||||
app_->increaseFailedAttempts(this); |
||||
} |
||||
|
||||
QString AbstractRequestHandler::saveTmpFile(const QByteArray &data) |
||||
{ |
||||
QTemporaryFile tmpfile(QDir::temp().absoluteFilePath("qBT-XXXXXX.torrent")); |
||||
tmpfile.setAutoRemove(false); |
||||
if (tmpfile.open()) { |
||||
tmpfile.write(data); |
||||
tmpfile.close(); |
||||
return tmpfile.fileName(); |
||||
} |
||||
|
||||
qWarning() << "I/O Error: Could not create temporary file"; |
||||
return QString(); |
||||
} |
@ -0,0 +1,413 @@
@@ -0,0 +1,413 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent. |
||||
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru> |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License |
||||
* as published by the Free Software Foundation; either version 2 |
||||
* of the License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
* |
||||
* In addition, as a special exception, the copyright holders give permission to |
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with |
||||
* modified versions of it that use the same license as the "OpenSSL" library), |
||||
* and distribute the linked executables. You must obey the GNU General Public |
||||
* License in all respects for all of the code used other than "OpenSSL". If you |
||||
* modify file(s), you may extend this exception to your version of the file(s), |
||||
* but you are not obligated to do so. If you do not wish to do so, delete this |
||||
* exception statement from your version. |
||||
*/ |
||||
|
||||
#include <QCoreApplication> |
||||
#include <QDateTime> |
||||
#include <QDebug> |
||||
#include <QDir> |
||||
#include <QFile> |
||||
#include <QNetworkCookie> |
||||
#include <QTemporaryFile> |
||||
#include <QTimer> |
||||
|
||||
#include "preferences.h" |
||||
#include "websessiondata.h" |
||||
#include "abstractwebapplication.h" |
||||
|
||||
// UnbanTimer
|
||||
|
||||
class UnbanTimer: public QTimer |
||||
{ |
||||
public: |
||||
UnbanTimer(const QHostAddress& peer_ip, QObject *parent) |
||||
: QTimer(parent), m_peerIp(peer_ip) |
||||
{ |
||||
setSingleShot(true); |
||||
setInterval(BAN_TIME); |
||||
} |
||||
|
||||
inline const QHostAddress& peerIp() const { return m_peerIp; } |
||||
|
||||
private: |
||||
QHostAddress m_peerIp; |
||||
}; |
||||
|
||||
// WebSession
|
||||
|
||||
struct WebSession |
||||
{ |
||||
const QString id; |
||||
uint timestamp; |
||||
WebSessionData data; |
||||
|
||||
WebSession(const QString& id) |
||||
: id(id) |
||||
{ |
||||
} |
||||
|
||||
void updateTimestamp() |
||||
{ |
||||
timestamp = QDateTime::currentDateTime().toTime_t(); |
||||
} |
||||
}; |
||||
|
||||
// AbstractWebApplication
|
||||
|
||||
AbstractWebApplication::AbstractWebApplication(QObject *parent) |
||||
: Http::ResponseBuilder(parent) |
||||
, session_(0) |
||||
{ |
||||
QTimer *timer = new QTimer(this); |
||||
timer->setInterval(60000); // 1 min.
|
||||
connect(timer, SIGNAL(timeout()), SLOT(removeInactiveSessions())); |
||||
} |
||||
|
||||
AbstractWebApplication::~AbstractWebApplication() |
||||
{ |
||||
// cleanup sessions data
|
||||
qDeleteAll(sessions_); |
||||
} |
||||
|
||||
Http::Response AbstractWebApplication::processRequest(const Http::Request &request, const Http::Environment &env) |
||||
{ |
||||
request_ = request; |
||||
env_ = env; |
||||
|
||||
clear(); // clear response
|
||||
|
||||
sessionInitialize(); |
||||
if (!sessionActive() && !isAuthNeeded()) |
||||
sessionStart(); |
||||
|
||||
if (isBanned()) { |
||||
status(403, "Forbidden"); |
||||
print(QObject::tr("Your IP address has been banned after too many failed authentication attempts."), Http::CONTENT_TYPE_TXT); |
||||
} |
||||
else { |
||||
processRequest(); |
||||
} |
||||
|
||||
return response(); |
||||
} |
||||
|
||||
void AbstractWebApplication::UnbanTimerEvent() |
||||
{ |
||||
UnbanTimer* ubantimer = static_cast<UnbanTimer*>(sender()); |
||||
qDebug("Ban period has expired for %s", qPrintable(ubantimer->peerIp().toString())); |
||||
clientFailedAttempts_.remove(ubantimer->peerIp()); |
||||
ubantimer->deleteLater(); |
||||
} |
||||
|
||||
void AbstractWebApplication::removeInactiveSessions() |
||||
{ |
||||
const uint now = QDateTime::currentDateTime().toTime_t(); |
||||
|
||||
foreach (const QString &id, sessions_.keys()) { |
||||
if ((now - sessions_[id]->timestamp) > INACTIVE_TIME) |
||||
delete sessions_.take(id); |
||||
} |
||||
} |
||||
|
||||
bool AbstractWebApplication::sessionInitialize() |
||||
{ |
||||
static const QString SID_START = QLatin1String(C_SID) + QLatin1String("="); |
||||
|
||||
if (session_ == 0) |
||||
{ |
||||
QString cookie = request_.headers.value("cookie"); |
||||
//qDebug() << Q_FUNC_INFO << "cookie: " << cookie;
|
||||
|
||||
QString sessionId; |
||||
int pos = cookie.indexOf(SID_START); |
||||
if (pos >= 0) |
||||
{ |
||||
pos += SID_START.length(); |
||||
int end = cookie.indexOf(QRegExp("[,;]"), pos); |
||||
sessionId = cookie.mid(pos, end >= 0 ? end - pos : end); |
||||
} |
||||
|
||||
// TODO: Additional session check
|
||||
|
||||
if (!sessionId.isNull()) |
||||
{ |
||||
if (sessions_.contains(sessionId)) |
||||
{ |
||||
session_ = sessions_[sessionId]; |
||||
session_->updateTimestamp(); |
||||
return true; |
||||
} |
||||
else |
||||
{ |
||||
qDebug() << Q_FUNC_INFO << "session does not exist!"; |
||||
} |
||||
} |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
bool AbstractWebApplication::readFile(const QString& path, QByteArray &data, QString &type) |
||||
{ |
||||
QString ext = ""; |
||||
int index = path.lastIndexOf('.') + 1; |
||||
if (index > 0) |
||||
ext = path.mid(index); |
||||
|
||||
// find translated file in cache
|
||||
if (translatedFiles_.contains(path)) |
||||
{ |
||||
data = translatedFiles_[path]; |
||||
} |
||||
else |
||||
{ |
||||
QFile file(path); |
||||
if (!file.open(QIODevice::ReadOnly)) |
||||
{ |
||||
qDebug("File %s was not found!", qPrintable(path)); |
||||
return false; |
||||
} |
||||
|
||||
data = file.readAll(); |
||||
file.close(); |
||||
|
||||
// Translate the file
|
||||
if ((ext == "html") || ((ext == "js") && !path.endsWith("excanvas-compressed.js"))) |
||||
{ |
||||
QString dataStr = QString::fromUtf8(data.constData()); |
||||
translateDocument(dataStr); |
||||
|
||||
if (path.endsWith("about.html")) |
||||
{ |
||||
dataStr.replace("${VERSION}", VERSION); |
||||
} |
||||
|
||||
data = dataStr.toUtf8(); |
||||
translatedFiles_[path] = data; // cashing translated file
|
||||
} |
||||
} |
||||
|
||||
type = CONTENT_TYPE_BY_EXT[ext]; |
||||
return true; |
||||
} |
||||
|
||||
WebSessionData *AbstractWebApplication::session() |
||||
{ |
||||
Q_ASSERT(session_ != 0); |
||||
return &session_->data; |
||||
} |
||||
|
||||
|
||||
QString AbstractWebApplication::generateSid() |
||||
{ |
||||
QString sid; |
||||
|
||||
qsrand(QDateTime::currentDateTime().toTime_t()); |
||||
do |
||||
{ |
||||
const size_t size = 6; |
||||
quint32 tmp[size]; |
||||
|
||||
for (size_t i = 0; i < size; ++i) |
||||
tmp[i] = qrand(); |
||||
|
||||
sid = QByteArray::fromRawData(reinterpret_cast<const char *>(tmp), sizeof(quint32) * size).toBase64(); |
||||
} |
||||
while (sessions_.contains(sid)); |
||||
|
||||
return sid; |
||||
} |
||||
|
||||
void AbstractWebApplication::translateDocument(QString& data) |
||||
{ |
||||
const QRegExp regex("QBT_TR\\((([^\\)]|\\)(?!QBT_TR))+)\\)QBT_TR"); |
||||
const QRegExp mnemonic("\\(?&([a-zA-Z]?\\))?"); |
||||
const std::string contexts[] = { |
||||
"TransferListFiltersWidget", "TransferListWidget", "PropertiesWidget", |
||||
"HttpServer", "confirmDeletionDlg", "TrackerList", "TorrentFilesModel", |
||||
"options_imp", "Preferences", "TrackersAdditionDlg", "ScanFoldersModel", |
||||
"PropTabBar", "TorrentModel", "downloadFromURL", "MainWindow", "misc", |
||||
"StatusBar" |
||||
}; |
||||
const size_t context_count = sizeof(contexts) / sizeof(contexts[0]); |
||||
int i = 0; |
||||
bool found = true; |
||||
|
||||
const QString locale = Preferences::instance()->getLocale(); |
||||
bool isTranslationNeeded = !locale.startsWith("en") || locale.startsWith("en_AU") || locale.startsWith("en_GB"); |
||||
|
||||
while(i < data.size() && found) |
||||
{ |
||||
i = regex.indexIn(data, i); |
||||
if (i >= 0) |
||||
{ |
||||
//qDebug("Found translatable string: %s", regex.cap(1).toUtf8().data());
|
||||
QByteArray word = regex.cap(1).toUtf8(); |
||||
|
||||
QString translation = word; |
||||
if (isTranslationNeeded) |
||||
{ |
||||
size_t context_index = 0; |
||||
while ((context_index < context_count) && (translation == word)) |
||||
{ |
||||
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0)) |
||||
translation = qApp->translate(contexts[context_index].c_str(), word.constData(), 0, QCoreApplication::UnicodeUTF8, 1); |
||||
#else |
||||
translation = qApp->translate(contexts[context_index].c_str(), word.constData(), 0, 1); |
||||
#endif |
||||
++context_index; |
||||
} |
||||
} |
||||
// Remove keyboard shortcuts
|
||||
translation.replace(mnemonic, ""); |
||||
|
||||
data.replace(i, regex.matchedLength(), translation); |
||||
i += translation.length(); |
||||
} |
||||
else |
||||
{ |
||||
found = false; // no more translatable strings
|
||||
} |
||||
} |
||||
} |
||||
|
||||
bool AbstractWebApplication::isBanned() const |
||||
{ |
||||
return clientFailedAttempts_.value(env_.clientAddress, 0) >= MAX_AUTH_FAILED_ATTEMPTS; |
||||
} |
||||
|
||||
int AbstractWebApplication::failedAttempts() const |
||||
{ |
||||
return clientFailedAttempts_.value(env_.clientAddress, 0); |
||||
} |
||||
|
||||
void AbstractWebApplication::resetFailedAttempts() |
||||
{ |
||||
clientFailedAttempts_.remove(env_.clientAddress); |
||||
} |
||||
|
||||
void AbstractWebApplication::increaseFailedAttempts() |
||||
{ |
||||
const int nb_fail = clientFailedAttempts_.value(env_.clientAddress, 0) + 1; |
||||
|
||||
clientFailedAttempts_[env_.clientAddress] = nb_fail; |
||||
if (nb_fail == MAX_AUTH_FAILED_ATTEMPTS) |
||||
{ |
||||
// Max number of failed attempts reached
|
||||
// Start ban period
|
||||
UnbanTimer* ubantimer = new UnbanTimer(env_.clientAddress, this); |
||||
connect(ubantimer, SIGNAL(timeout()), SLOT(UnbanTimerEvent())); |
||||
ubantimer->start(); |
||||
} |
||||
} |
||||
|
||||
bool AbstractWebApplication::isAuthNeeded() |
||||
{ |
||||
return (env_.clientAddress != QHostAddress::LocalHost |
||||
&& env_.clientAddress != QHostAddress::LocalHostIPv6) |
||||
|| Preferences::instance()->isWebUiLocalAuthEnabled(); |
||||
} |
||||
|
||||
void AbstractWebApplication::printFile(const QString& path) |
||||
{ |
||||
QByteArray data; |
||||
QString type; |
||||
|
||||
if (!readFile(path, data, type)) { |
||||
status(404, "Not Found"); |
||||
return; |
||||
} |
||||
|
||||
print(data, type); |
||||
} |
||||
|
||||
bool AbstractWebApplication::sessionStart() |
||||
{ |
||||
if (session_ == 0) |
||||
{ |
||||
session_ = new WebSession(generateSid()); |
||||
session_->updateTimestamp(); |
||||
sessions_[session_->id] = session_; |
||||
|
||||
QNetworkCookie cookie(C_SID, session_->id.toUtf8()); |
||||
cookie.setPath(QLatin1String("/")); |
||||
header(Http::HEADER_SET_COOKIE, cookie.toRawForm()); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
bool AbstractWebApplication::sessionEnd() |
||||
{ |
||||
if ((session_ != 0) && (sessions_.contains(session_->id))) |
||||
{ |
||||
QNetworkCookie cookie(C_SID, session_->id.toUtf8()); |
||||
cookie.setPath(QLatin1String("/")); |
||||
cookie.setExpirationDate(QDateTime::currentDateTime()); |
||||
|
||||
sessions_.remove(session_->id); |
||||
delete session_; |
||||
session_ = 0; |
||||
|
||||
header(Http::HEADER_SET_COOKIE, cookie.toRawForm()); |
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
QString AbstractWebApplication::saveTmpFile(const QByteArray &data) |
||||
{ |
||||
QTemporaryFile tmpfile(QDir::temp().absoluteFilePath("qBT-XXXXXX.torrent")); |
||||
tmpfile.setAutoRemove(false); |
||||
if (tmpfile.open()) { |
||||
tmpfile.write(data); |
||||
tmpfile.close(); |
||||
return tmpfile.fileName(); |
||||
} |
||||
|
||||
qWarning() << "I/O Error: Could not create temporary file"; |
||||
return QString(); |
||||
} |
||||
|
||||
QStringMap AbstractWebApplication::initializeContentTypeByExtMap() |
||||
{ |
||||
QStringMap map; |
||||
|
||||
map["htm"] = Http::CONTENT_TYPE_HTML; |
||||
map["html"] = Http::CONTENT_TYPE_HTML; |
||||
map["css"] = Http::CONTENT_TYPE_CSS; |
||||
map["gif"] = Http::CONTENT_TYPE_GIF; |
||||
map["png"] = Http::CONTENT_TYPE_PNG; |
||||
map["js"] = Http::CONTENT_TYPE_JS; |
||||
|
||||
return map; |
||||
} |
||||
|
||||
const QStringMap AbstractWebApplication::CONTENT_TYPE_BY_EXT = AbstractWebApplication::initializeContentTypeByExtMap(); |
@ -1,716 +0,0 @@
@@ -1,716 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent. |
||||
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru> |
||||
* Copyright (C) 2012, Christophe Dumez <chris@qbittorrent.org> |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License |
||||
* as published by the Free Software Foundation; either version 2 |
||||
* of the License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
* |
||||
* In addition, as a special exception, the copyright holders give permission to |
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with |
||||
* modified versions of it that use the same license as the "OpenSSL" library), |
||||
* and distribute the linked executables. You must obey the GNU General Public |
||||
* License in all respects for all of the code used other than "OpenSSL". If you |
||||
* modify file(s), you may extend this exception to your version of the file(s), |
||||
* but you are not obligated to do so. If you do not wish to do so, delete this |
||||
* exception statement from your version. |
||||
*/ |
||||
|
||||
#include <QDebug> |
||||
#ifdef DISABLE_GUI |
||||
#include <QCoreApplication> |
||||
#else |
||||
#include <QApplication> |
||||
#endif |
||||
#include <QTimer> |
||||
#include <QCryptographicHash> |
||||
#include <queue> |
||||
#include <vector> |
||||
#include <libtorrent/session.hpp> |
||||
#ifndef DISABLE_GUI |
||||
#include "iconprovider.h" |
||||
#endif |
||||
#include "misc.h" |
||||
#include "fs_utils.h" |
||||
#include "preferences.h" |
||||
#include "btjson.h" |
||||
#include "prefjson.h" |
||||
#include "qbtsession.h" |
||||
#include "requesthandler.h" |
||||
#include "webapplication.h" |
||||
|
||||
using namespace libtorrent; |
||||
|
||||
static const int API_VERSION = 2; |
||||
static const int API_VERSION_MIN = 2; |
||||
|
||||
const QString WWW_FOLDER = ":/www/public/"; |
||||
const QString PRIVATE_FOLDER = ":/www/private/"; |
||||
const QString DEFAULT_SCOPE = "public"; |
||||
const QString SCOPE_IMAGES = "images"; |
||||
const QString SCOPE_THEME = "theme"; |
||||
const QString DEFAULT_ACTION = "index"; |
||||
const QString WEBUI_ACTION = "webui"; |
||||
const QString VERSION_INFO = "version"; |
||||
const QString MAX_AGE_MONTH = "public, max-age=2592000"; |
||||
|
||||
#define ADD_ACTION(scope, action) actions[#scope][#action] = &RequestHandler::action_##scope##_##action |
||||
|
||||
QMap<QString, QMap<QString, RequestHandler::Action> > RequestHandler::initializeActions() |
||||
{ |
||||
QMap<QString,QMap<QString, RequestHandler::Action> > actions; |
||||
|
||||
ADD_ACTION(public, webui); |
||||
ADD_ACTION(public, index); |
||||
ADD_ACTION(public, login); |
||||
ADD_ACTION(public, logout); |
||||
ADD_ACTION(public, theme); |
||||
ADD_ACTION(public, images); |
||||
ADD_ACTION(query, torrents); |
||||
ADD_ACTION(query, preferences); |
||||
ADD_ACTION(query, transferInfo); |
||||
ADD_ACTION(query, propertiesGeneral); |
||||
ADD_ACTION(query, propertiesTrackers); |
||||
ADD_ACTION(query, propertiesFiles); |
||||
ADD_ACTION(sync, maindata); |
||||
ADD_ACTION(command, shutdown); |
||||
ADD_ACTION(command, download); |
||||
ADD_ACTION(command, upload); |
||||
ADD_ACTION(command, addTrackers); |
||||
ADD_ACTION(command, resumeAll); |
||||
ADD_ACTION(command, pauseAll); |
||||
ADD_ACTION(command, resume); |
||||
ADD_ACTION(command, pause); |
||||
ADD_ACTION(command, setPreferences); |
||||
ADD_ACTION(command, setFilePrio); |
||||
ADD_ACTION(command, getGlobalUpLimit); |
||||
ADD_ACTION(command, getGlobalDlLimit); |
||||
ADD_ACTION(command, setGlobalUpLimit); |
||||
ADD_ACTION(command, setGlobalDlLimit); |
||||
ADD_ACTION(command, getTorrentUpLimit); |
||||
ADD_ACTION(command, getTorrentDlLimit); |
||||
ADD_ACTION(command, setTorrentUpLimit); |
||||
ADD_ACTION(command, setTorrentDlLimit); |
||||
ADD_ACTION(command, alternativeSpeedLimitsEnabled); |
||||
ADD_ACTION(command, toggleAlternativeSpeedLimits); |
||||
ADD_ACTION(command, toggleSequentialDownload); |
||||
ADD_ACTION(command, toggleFirstLastPiecePrio); |
||||
ADD_ACTION(command, delete); |
||||
ADD_ACTION(command, deletePerm); |
||||
ADD_ACTION(command, increasePrio); |
||||
ADD_ACTION(command, decreasePrio); |
||||
ADD_ACTION(command, topPrio); |
||||
ADD_ACTION(command, bottomPrio); |
||||
ADD_ACTION(command, recheck); |
||||
ADD_ACTION(version, api); |
||||
ADD_ACTION(version, api_min); |
||||
ADD_ACTION(version, qbittorrent); |
||||
|
||||
return actions; |
||||
} |
||||
|
||||
#define CHECK_URI(ARGS_NUM) \ |
||||
if (args_.size() != ARGS_NUM) { \ |
||||
status(404, "Not Found"); \ |
||||
return; \ |
||||
} |
||||
#define CHECK_PARAMETERS(PARAMETERS) \ |
||||
QStringList parameters; \ |
||||
parameters << PARAMETERS; \ |
||||
if (parameters.size() != request().posts.size()) { \ |
||||
status(400, "Bad Request"); \ |
||||
return; \ |
||||
} \ |
||||
foreach (QString key, request().posts.keys()) { \ |
||||
if (!parameters.contains(key, Qt::CaseInsensitive)) { \ |
||||
status(400, "Bad Request"); \ |
||||
return; \ |
||||
} \ |
||||
} |
||||
|
||||
void RequestHandler::action_public_index() |
||||
{ |
||||
QString path; |
||||
|
||||
if (!args_.isEmpty()) { |
||||
if (args_.back() == "favicon.ico") |
||||
path = ":/icons/skin/qbittorrent16.png"; |
||||
else |
||||
path = WWW_FOLDER + args_.join("/"); |
||||
} |
||||
|
||||
printFile(path); |
||||
} |
||||
|
||||
void RequestHandler::action_public_webui() |
||||
{ |
||||
if (!sessionActive()) |
||||
printFile(PRIVATE_FOLDER + "login.html"); |
||||
else |
||||
printFile(PRIVATE_FOLDER + "index.html"); |
||||
} |
||||
|
||||
void RequestHandler::action_public_login() |
||||
{ |
||||
const Preferences* const pref = Preferences::instance(); |
||||
QCryptographicHash md5(QCryptographicHash::Md5); |
||||
|
||||
md5.addData(request().posts["password"].toLocal8Bit()); |
||||
QString pass = md5.result().toHex(); |
||||
|
||||
bool equalUser = misc::slowEquals(request().posts["username"].toUtf8(), pref->getWebUiUsername().toUtf8()); |
||||
bool equalPass = misc::slowEquals(pass.toUtf8(), pref->getWebUiPassword().toUtf8()); |
||||
|
||||
if (equalUser && equalPass) { |
||||
sessionStart(); |
||||
print(QByteArray("Ok."), CONTENT_TYPE_TXT); |
||||
} |
||||
else { |
||||
QString addr = env().clientAddress.toString(); |
||||
increaseFailedAttempts(); |
||||
qDebug("client IP: %s (%d failed attempts)", qPrintable(addr), failedAttempts()); |
||||
print(QByteArray("Fails."), CONTENT_TYPE_TXT); |
||||
} |
||||
} |
||||
|
||||
void RequestHandler::action_public_logout() |
||||
{ |
||||
CHECK_URI(0); |
||||
sessionEnd(); |
||||
} |
||||
|
||||
void RequestHandler::action_public_theme() |
||||
{ |
||||
if (args_.size() != 1) { |
||||
status(404, "Not Found"); |
||||
return; |
||||
} |
||||
|
||||
#ifdef DISABLE_GUI |
||||
QString url = ":/icons/oxygen/" + args_.front() + ".png"; |
||||
#else |
||||
QString url = IconProvider::instance()->getIconPath(args_.front()); |
||||
#endif |
||||
qDebug() << Q_FUNC_INFO << "There icon:" << url; |
||||
|
||||
printFile(url); |
||||
header(HEADER_CACHE_CONTROL, MAX_AGE_MONTH); |
||||
} |
||||
|
||||
void RequestHandler::action_public_images() |
||||
{ |
||||
const QString path = ":/icons/" + args_.join("/"); |
||||
printFile(path); |
||||
header(HEADER_CACHE_CONTROL, MAX_AGE_MONTH); |
||||
} |
||||
|
||||
// GET params:
|
||||
// - filter (string): all, downloading, completed, paused, active, inactive
|
||||
// - label (string): torrent label for filtering by it (empty string means "unlabeled"; no "label" param presented means "any label")
|
||||
// - sort (string): name of column for sorting by its value
|
||||
// - reverse (bool): enable reverse sorting
|
||||
// - limit (int): set limit number of torrents returned (if greater than 0, otherwise - unlimited)
|
||||
// - offset (int): set offset (if less than 0 - offset from end)
|
||||
void RequestHandler::action_query_torrents() |
||||
{ |
||||
CHECK_URI(0); |
||||
const QStringMap& gets = request().gets; |
||||
|
||||
print(btjson::getTorrents( |
||||
gets["filter"], gets["label"], gets["sort"], gets["reverse"] == "true", |
||||
gets["limit"].toInt(), gets["offset"].toInt() |
||||
), CONTENT_TYPE_JS); |
||||
} |
||||
|
||||
void RequestHandler::action_query_preferences() |
||||
{ |
||||
CHECK_URI(0); |
||||
print(prefjson::getPreferences(), CONTENT_TYPE_JS); |
||||
} |
||||
|
||||
void RequestHandler::action_query_transferInfo() |
||||
{ |
||||
CHECK_URI(0); |
||||
print(btjson::getTransferInfo(), CONTENT_TYPE_JS); |
||||
} |
||||
|
||||
void RequestHandler::action_query_propertiesGeneral() |
||||
{ |
||||
CHECK_URI(1); |
||||
print(btjson::getPropertiesForTorrent(args_.front()), CONTENT_TYPE_JS); |
||||
} |
||||
|
||||
void RequestHandler::action_query_propertiesTrackers() |
||||
{ |
||||
CHECK_URI(1); |
||||
print(btjson::getTrackersForTorrent(args_.front()), CONTENT_TYPE_JS); |
||||
} |
||||
|
||||
void RequestHandler::action_query_propertiesFiles() |
||||
{ |
||||
CHECK_URI(1); |
||||
print(btjson::getFilesForTorrent(args_.front()), CONTENT_TYPE_JS); |
||||
} |
||||
|
||||
// GET param:
|
||||
// - rid (int): last response id
|
||||
void RequestHandler::action_sync_maindata() |
||||
{ |
||||
CHECK_URI(0); |
||||
print(btjson::getSyncMainData(request().gets["rid"].toInt(), session()->syncMainDataLastResponse, session()->syncMainDataLastAcceptedResponse)); |
||||
} |
||||
|
||||
void RequestHandler::action_version_api() |
||||
{ |
||||
CHECK_URI(0); |
||||
print(QString::number(API_VERSION), CONTENT_TYPE_TXT); |
||||
} |
||||
|
||||
void RequestHandler::action_version_api_min() |
||||
{ |
||||
CHECK_URI(0); |
||||
print(QString::number(API_VERSION_MIN), CONTENT_TYPE_TXT); |
||||
} |
||||
|
||||
void RequestHandler::action_version_qbittorrent() |
||||
{ |
||||
CHECK_URI(0); |
||||
print(QString(VERSION), CONTENT_TYPE_TXT); |
||||
} |
||||
|
||||
void RequestHandler::action_command_shutdown() |
||||
{ |
||||
qDebug() << "Shutdown request from Web UI"; |
||||
// Special case handling for shutdown, we
|
||||
// need to reply to the Web UI before
|
||||
// actually shutting down.
|
||||
|
||||
CHECK_URI(0); |
||||
QTimer::singleShot(0, qApp, SLOT(quit())); |
||||
} |
||||
|
||||
void RequestHandler::action_command_download() |
||||
{ |
||||
CHECK_URI(0); |
||||
CHECK_PARAMETERS("urls"); |
||||
QString urls = request().posts["urls"]; |
||||
QStringList list = urls.split('\n'); |
||||
|
||||
foreach (QString url, list) { |
||||
url = url.trimmed(); |
||||
if (!url.isEmpty()) { |
||||
if (url.startsWith("bc://bt/", Qt::CaseInsensitive)) { |
||||
qDebug("Converting bc link to magnet link"); |
||||
url = misc::bcLinkToMagnet(url); |
||||
} |
||||
else if (url.startsWith("magnet:", Qt::CaseInsensitive)) { |
||||
QBtSession::instance()->addMagnetSkipAddDlg(url); |
||||
} |
||||
else { |
||||
qDebug("Downloading url: %s", qPrintable(url)); |
||||
QBtSession::instance()->downloadUrlAndSkipDialog(url); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
void RequestHandler::action_command_upload() |
||||
{ |
||||
qDebug() << Q_FUNC_INFO; |
||||
CHECK_URI(0); |
||||
|
||||
foreach(const UploadedFile& torrent, request().files) { |
||||
QString filePath = saveTmpFile(torrent.data); |
||||
|
||||
if (!filePath.isEmpty()) { |
||||
QTorrentHandle h = QBtSession::instance()->addTorrent(filePath); |
||||
if (!h.is_valid()) { |
||||
status(415, "Internal Server Error"); |
||||
print(QObject::tr("Error: '%1' is not a valid torrent file.\n").arg(torrent.filename), CONTENT_TYPE_TXT); |
||||
} |
||||
// Clean up
|
||||
fsutils::forceRemove(filePath); |
||||
} |
||||
else { |
||||
qWarning() << "I/O Error: Could not create temporary file"; |
||||
status(500, "Internal Server Error"); |
||||
print(QObject::tr("I/O Error: Could not create temporary file."), CONTENT_TYPE_TXT); |
||||
} |
||||
} |
||||
} |
||||
|
||||
void RequestHandler::action_command_addTrackers() |
||||
{ |
||||
CHECK_URI(0); |
||||
CHECK_PARAMETERS("hash" << "urls"); |
||||
QString hash = request().posts["hash"]; |
||||
|
||||
if (!hash.isEmpty()) { |
||||
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); |
||||
|
||||
if (h.is_valid() && h.has_metadata()) { |
||||
QString urls = request().posts["urls"]; |
||||
QStringList list = urls.split('\n'); |
||||
|
||||
foreach (const QString& url, list) { |
||||
announce_entry e(url.toStdString()); |
||||
h.add_tracker(e); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
void RequestHandler::action_command_resumeAll() |
||||
{ |
||||
CHECK_URI(0); |
||||
QBtSession::instance()->resumeAllTorrents(); |
||||
} |
||||
|
||||
void RequestHandler::action_command_pauseAll() |
||||
{ |
||||
CHECK_URI(0); |
||||
QBtSession::instance()->pauseAllTorrents(); |
||||
} |
||||
|
||||
void RequestHandler::action_command_resume() |
||||
{ |
||||
CHECK_URI(0); |
||||
CHECK_PARAMETERS("hash"); |
||||
QBtSession::instance()->resumeTorrent(request().posts["hash"]); |
||||
} |
||||
|
||||
void RequestHandler::action_command_pause() |
||||
{ |
||||
CHECK_URI(0); |
||||
CHECK_PARAMETERS("hash"); |
||||
QBtSession::instance()->pauseTorrent(request().posts["hash"]); |
||||
} |
||||
|
||||
void RequestHandler::action_command_setPreferences() |
||||
{ |
||||
CHECK_URI(0); |
||||
CHECK_PARAMETERS("json"); |
||||
prefjson::setPreferences(request().posts["json"]); |
||||
} |
||||
|
||||
void RequestHandler::action_command_setFilePrio() |
||||
{ |
||||
CHECK_URI(0); |
||||
CHECK_PARAMETERS("hash" << "id" << "priority"); |
||||
QString hash = request().posts["hash"]; |
||||
int file_id = request().posts["id"].toInt(); |
||||
int priority = request().posts["priority"].toInt(); |
||||
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); |
||||
|
||||
if (h.is_valid() && h.has_metadata()) |
||||
h.file_priority(file_id, priority); |
||||
} |
||||
|
||||
void RequestHandler::action_command_getGlobalUpLimit() |
||||
{ |
||||
CHECK_URI(0); |
||||
print(QByteArray::number(QBtSession::instance()->getSession()->settings().upload_rate_limit)); |
||||
} |
||||
|
||||
void RequestHandler::action_command_getGlobalDlLimit() |
||||
{ |
||||
CHECK_URI(0); |
||||
print(QByteArray::number(QBtSession::instance()->getSession()->settings().download_rate_limit)); |
||||
} |
||||
|
||||
void RequestHandler::action_command_setGlobalUpLimit() |
||||
{ |
||||
CHECK_URI(0); |
||||
CHECK_PARAMETERS("limit"); |
||||
qlonglong limit = request().posts["limit"].toLongLong(); |
||||
if (limit == 0) limit = -1; |
||||
|
||||
QBtSession::instance()->setUploadRateLimit(limit); |
||||
if (Preferences::instance()->isAltBandwidthEnabled()) |
||||
Preferences::instance()->setAltGlobalUploadLimit(limit / 1024.); |
||||
else |
||||
Preferences::instance()->setGlobalUploadLimit(limit / 1024.); |
||||
} |
||||
|
||||
void RequestHandler::action_command_setGlobalDlLimit() |
||||
{ |
||||
CHECK_URI(0); |
||||
CHECK_PARAMETERS("limit"); |
||||
qlonglong limit = request().posts["limit"].toLongLong(); |
||||
if (limit == 0) limit = -1; |
||||
|
||||
QBtSession::instance()->setDownloadRateLimit(limit); |
||||
if (Preferences::instance()->isAltBandwidthEnabled()) |
||||
Preferences::instance()->setAltGlobalDownloadLimit(limit / 1024.); |
||||
else |
||||
Preferences::instance()->setGlobalDownloadLimit(limit / 1024.); |
||||
} |
||||
|
||||
void RequestHandler::action_command_getTorrentUpLimit() |
||||
{ |
||||
CHECK_URI(0); |
||||
CHECK_PARAMETERS("hash"); |
||||
QString hash = request().posts["hash"]; |
||||
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); |
||||
|
||||
if (h.is_valid()) |
||||
print(QByteArray::number(h.upload_limit())); |
||||
} |
||||
|
||||
void RequestHandler::action_command_getTorrentDlLimit() |
||||
{ |
||||
CHECK_URI(0); |
||||
CHECK_PARAMETERS("hash"); |
||||
QString hash = request().posts["hash"]; |
||||
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); |
||||
|
||||
if (h.is_valid()) |
||||
print(QByteArray::number(h.download_limit())); |
||||
} |
||||
|
||||
void RequestHandler::action_command_setTorrentUpLimit() |
||||
{ |
||||
CHECK_URI(0); |
||||
CHECK_PARAMETERS("hash" << "limit"); |
||||
QString hash = request().posts["hash"]; |
||||
qlonglong limit = request().posts["limit"].toLongLong(); |
||||
if (limit == 0) limit = -1; |
||||
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); |
||||
|
||||
if (h.is_valid()) |
||||
h.set_upload_limit(limit); |
||||
} |
||||
|
||||
void RequestHandler::action_command_setTorrentDlLimit() |
||||
{ |
||||
CHECK_URI(0); |
||||
CHECK_PARAMETERS("hash" << "limit"); |
||||
QString hash = request().posts["hash"]; |
||||
qlonglong limit = request().posts["limit"].toLongLong(); |
||||
if (limit == 0) limit = -1; |
||||
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); |
||||
|
||||
if (h.is_valid()) |
||||
h.set_download_limit(limit); |
||||
} |
||||
|
||||
void RequestHandler::action_command_toggleAlternativeSpeedLimits() |
||||
{ |
||||
CHECK_URI(0); |
||||
QBtSession::instance()->useAlternativeSpeedsLimit(!Preferences::instance()->isAltBandwidthEnabled()); |
||||
} |
||||
|
||||
void RequestHandler::action_command_alternativeSpeedLimitsEnabled() |
||||
{ |
||||
CHECK_URI(0); |
||||
print(QByteArray::number(Preferences::instance()->isAltBandwidthEnabled())); |
||||
} |
||||
|
||||
void RequestHandler::action_command_toggleSequentialDownload() |
||||
{ |
||||
CHECK_URI(0); |
||||
CHECK_PARAMETERS("hashes"); |
||||
QStringList hashes = request().posts["hashes"].split("|"); |
||||
foreach (const QString &hash, hashes) { |
||||
try { |
||||
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); |
||||
h.toggleSequentialDownload(); |
||||
} |
||||
catch(invalid_handle&) {} |
||||
} |
||||
} |
||||
|
||||
void RequestHandler::action_command_toggleFirstLastPiecePrio() |
||||
{ |
||||
CHECK_URI(0); |
||||
CHECK_PARAMETERS("hashes"); |
||||
QStringList hashes = request().posts["hashes"].split("|"); |
||||
foreach (const QString &hash, hashes) { |
||||
try { |
||||
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); |
||||
h.toggleFirstLastPiecePrio(); |
||||
} |
||||
catch(invalid_handle&) {} |
||||
} |
||||
} |
||||
|
||||
void RequestHandler::action_command_delete() |
||||
{ |
||||
CHECK_URI(0); |
||||
CHECK_PARAMETERS("hashes"); |
||||
QStringList hashes = request().posts["hashes"].split("|"); |
||||
foreach (const QString &hash, hashes) |
||||
QBtSession::instance()->deleteTorrent(hash, false); |
||||
} |
||||
|
||||
void RequestHandler::action_command_deletePerm() |
||||
{ |
||||
CHECK_URI(0); |
||||
CHECK_PARAMETERS("hashes"); |
||||
QStringList hashes = request().posts["hashes"].split("|"); |
||||
foreach (const QString &hash, hashes) |
||||
QBtSession::instance()->deleteTorrent(hash, true); |
||||
} |
||||
|
||||
void RequestHandler::action_command_increasePrio() |
||||
{ |
||||
CHECK_URI(0); |
||||
CHECK_PARAMETERS("hashes"); |
||||
QStringList hashes = request().posts["hashes"].split("|"); |
||||
|
||||
std::priority_queue<QPair<int, QTorrentHandle>, |
||||
std::vector<QPair<int, QTorrentHandle> >, |
||||
std::greater<QPair<int, QTorrentHandle> > > torrent_queue; |
||||
|
||||
// Sort torrents by priority
|
||||
foreach (const QString &hash, hashes) { |
||||
try { |
||||
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); |
||||
if (!h.is_seed()) |
||||
torrent_queue.push(qMakePair(h.queue_position(), h)); |
||||
} |
||||
catch(invalid_handle&) {} |
||||
} |
||||
|
||||
// Increase torrents priority (starting with the ones with highest priority)
|
||||
while(!torrent_queue.empty()) { |
||||
QTorrentHandle h = torrent_queue.top().second; |
||||
|
||||
try { |
||||
h.queue_position_up(); |
||||
} |
||||
catch(invalid_handle&) {} |
||||
|
||||
torrent_queue.pop(); |
||||
} |
||||
} |
||||
|
||||
void RequestHandler::action_command_decreasePrio() |
||||
{ |
||||
CHECK_URI(0); |
||||
CHECK_PARAMETERS("hashes"); |
||||
QStringList hashes = request().posts["hashes"].split("|"); |
||||
|
||||
std::priority_queue<QPair<int, QTorrentHandle>, |
||||
std::vector<QPair<int, QTorrentHandle> >, |
||||
std::less<QPair<int, QTorrentHandle> > > torrent_queue; |
||||
|
||||
// Sort torrents by priority
|
||||
foreach (const QString &hash, hashes) { |
||||
try { |
||||
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); |
||||
|
||||
if (!h.is_seed()) |
||||
torrent_queue.push(qMakePair(h.queue_position(), h)); |
||||
} |
||||
catch(invalid_handle&) {} |
||||
} |
||||
|
||||
// Decrease torrents priority (starting with the ones with lowest priority)
|
||||
while(!torrent_queue.empty()) { |
||||
QTorrentHandle h = torrent_queue.top().second; |
||||
|
||||
try { |
||||
h.queue_position_down(); |
||||
} |
||||
catch(invalid_handle&) {} |
||||
|
||||
torrent_queue.pop(); |
||||
} |
||||
} |
||||
|
||||
void RequestHandler::action_command_topPrio() |
||||
{ |
||||
CHECK_URI(0); |
||||
CHECK_PARAMETERS("hashes"); |
||||
foreach (const QString &hash, request().posts["hashes"].split("|")) { |
||||
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); |
||||
if (h.is_valid()) h.queue_position_top(); |
||||
} |
||||
} |
||||
|
||||
void RequestHandler::action_command_bottomPrio() |
||||
{ |
||||
CHECK_URI(0); |
||||
CHECK_PARAMETERS("hashes"); |
||||
foreach (const QString &hash, request().posts["hashes"].split("|")) { |
||||
QTorrentHandle h = QBtSession::instance()->getTorrentHandle(hash); |
||||
if (h.is_valid()) h.queue_position_bottom(); |
||||
} |
||||
} |
||||
|
||||
void RequestHandler::action_command_recheck() |
||||
{ |
||||
CHECK_URI(0); |
||||
CHECK_PARAMETERS("hash"); |
||||
QBtSession::instance()->recheckTorrent(request().posts["hash"]); |
||||
} |
||||
|
||||
bool RequestHandler::isPublicScope() |
||||
{ |
||||
return (scope_ == DEFAULT_SCOPE || scope_ == VERSION_INFO); |
||||
} |
||||
|
||||
void RequestHandler::processRequest() |
||||
{ |
||||
if (args_.contains(".") || args_.contains("..")) { |
||||
qDebug() << Q_FUNC_INFO << "Invalid path:" << request().path; |
||||
status(404, "Not Found"); |
||||
return; |
||||
} |
||||
|
||||
if (!isPublicScope() && !sessionActive()) { |
||||
status(403, "Forbidden"); |
||||
return; |
||||
} |
||||
|
||||
if (actions_.value(scope_).value(action_) != 0) { |
||||
(this->*(actions_[scope_][action_]))(); |
||||
} |
||||
else { |
||||
status(404, "Not Found"); |
||||
qDebug() << Q_FUNC_INFO << "Resource not found:" << request().path; |
||||
} |
||||
} |
||||
|
||||
void RequestHandler::parsePath() |
||||
{ |
||||
if(request().path == "/") action_ = WEBUI_ACTION; |
||||
|
||||
// check action for requested path
|
||||
QStringList pathItems = request().path.split('/', QString::SkipEmptyParts); |
||||
if (!pathItems.empty()) { |
||||
if (actions_.contains(pathItems.front())) { |
||||
scope_ = pathItems.front(); |
||||
pathItems.pop_front(); |
||||
} |
||||
} |
||||
|
||||
if (!pathItems.empty()) { |
||||
if (actions_[scope_].contains(pathItems.front())) { |
||||
action_ = pathItems.front(); |
||||
pathItems.pop_front(); |
||||
} |
||||
} |
||||
|
||||
args_ = pathItems; |
||||
} |
||||
|
||||
RequestHandler::RequestHandler(const HttpRequest &request, const HttpEnvironment &env, WebApplication *app) |
||||
: AbstractRequestHandler(request, env, app), scope_(DEFAULT_SCOPE), action_(DEFAULT_ACTION) |
||||
{ |
||||
parsePath(); |
||||
} |
||||
|
||||
QMap<QString, QMap<QString, RequestHandler::Action> > RequestHandler::actions_ = RequestHandler::initializeActions(); |
@ -1,108 +0,0 @@
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent. |
||||
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru> |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License |
||||
* as published by the Free Software Foundation; either version 2 |
||||
* of the License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
* |
||||
* In addition, as a special exception, the copyright holders give permission to |
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with |
||||
* modified versions of it that use the same license as the "OpenSSL" library), |
||||
* and distribute the linked executables. You must obey the GNU General Public |
||||
* License in all respects for all of the code used other than "OpenSSL". If you |
||||
* modify file(s), you may extend this exception to your version of the file(s), |
||||
* but you are not obligated to do so. If you do not wish to do so, delete this |
||||
* exception statement from your version. |
||||
*/ |
||||
|
||||
#ifndef REQUESTHANDLER_H |
||||
#define REQUESTHANDLER_H |
||||
|
||||
#include <QStringList> |
||||
#include "httptypes.h" |
||||
#include "abstractrequesthandler.h" |
||||
|
||||
class WebApplication; |
||||
|
||||
class RequestHandler: public AbstractRequestHandler |
||||
{ |
||||
public: |
||||
RequestHandler( |
||||
const HttpRequest& request, const HttpEnvironment& env, |
||||
WebApplication* app); |
||||
|
||||
private: |
||||
// Actions
|
||||
void action_public_webui(); |
||||
void action_public_index(); |
||||
void action_public_login(); |
||||
void action_public_logout(); |
||||
void action_public_theme(); |
||||
void action_public_images(); |
||||
void action_query_torrents(); |
||||
void action_query_preferences(); |
||||
void action_query_transferInfo(); |
||||
void action_query_propertiesGeneral(); |
||||
void action_query_propertiesTrackers(); |
||||
void action_query_propertiesFiles(); |
||||
void action_sync_maindata(); |
||||
void action_command_shutdown(); |
||||
void action_command_download(); |
||||
void action_command_upload(); |
||||
void action_command_addTrackers(); |
||||
void action_command_resumeAll(); |
||||
void action_command_pauseAll(); |
||||
void action_command_resume(); |
||||
void action_command_pause(); |
||||
void action_command_setPreferences(); |
||||
void action_command_setFilePrio(); |
||||
void action_command_getGlobalUpLimit(); |
||||
void action_command_getGlobalDlLimit(); |
||||
void action_command_setGlobalUpLimit(); |
||||
void action_command_setGlobalDlLimit(); |
||||
void action_command_getTorrentUpLimit(); |
||||
void action_command_getTorrentDlLimit(); |
||||
void action_command_setTorrentUpLimit(); |
||||
void action_command_setTorrentDlLimit(); |
||||
void action_command_alternativeSpeedLimitsEnabled(); |
||||
void action_command_toggleAlternativeSpeedLimits(); |
||||
void action_command_toggleSequentialDownload(); |
||||
void action_command_toggleFirstLastPiecePrio(); |
||||
void action_command_delete(); |
||||
void action_command_deletePerm(); |
||||
void action_command_increasePrio(); |
||||
void action_command_decreasePrio(); |
||||
void action_command_topPrio(); |
||||
void action_command_bottomPrio(); |
||||
void action_command_recheck(); |
||||
void action_version_api(); |
||||
void action_version_api_min(); |
||||
void action_version_qbittorrent(); |
||||
|
||||
typedef void (RequestHandler::*Action)(); |
||||
|
||||
QString scope_; |
||||
QString action_; |
||||
QStringList args_; |
||||
|
||||
void processRequest(); |
||||
|
||||
bool isPublicScope(); |
||||
void parsePath(); |
||||
|
||||
static QMap<QString, QMap<QString, Action> > initializeActions(); |
||||
static QMap<QString, QMap<QString, Action> > actions_; |
||||
}; |
||||
|
||||
#endif // REQUESTHANDLER_H
|
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent. |
||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru> |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License |
||||
* as published by the Free Software Foundation; either version 2 |
||||
* of the License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
* |
||||
* In addition, as a special exception, the copyright holders give permission to |
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with |
||||
* modified versions of it that use the same license as the "OpenSSL" library), |
||||
* and distribute the linked executables. You must obey the GNU General Public |
||||
* License in all respects for all of the code used other than "OpenSSL". If you |
||||
* modify file(s), you may extend this exception to your version of the file(s), |
||||
* but you are not obligated to do so. If you do not wish to do so, delete this |
||||
* exception statement from your version. |
||||
*/ |
||||
|
||||
#ifndef WEBSESSIONDATA |
||||
#define WEBSESSIONDATA |
||||
|
||||
#include <QVariant> |
||||
|
||||
struct WebSessionData |
||||
{ |
||||
QVariantMap syncMainDataLastResponse; |
||||
QVariantMap syncMainDataLastAcceptedResponse; |
||||
}; |
||||
|
||||
#endif // WEBSESSIONDATA
|
||||
|
@ -0,0 +1,102 @@
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent. |
||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru> |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License |
||||
* as published by the Free Software Foundation; either version 2 |
||||
* of the License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
* |
||||
* In addition, as a special exception, the copyright holders give permission to |
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with |
||||
* modified versions of it that use the same license as the "OpenSSL" library), |
||||
* and distribute the linked executables. You must obey the GNU General Public |
||||
* License in all respects for all of the code used other than "OpenSSL". If you |
||||
* modify file(s), you may extend this exception to your version of the file(s), |
||||
* but you are not obligated to do so. If you do not wish to do so, delete this |
||||
* exception statement from your version. |
||||
*/ |
||||
|
||||
#include "webui.h" |
||||
#include "http/server.h" |
||||
#include "webapplication.h" |
||||
#include "dnsupdater.h" |
||||
#include "preferences.h" |
||||
#include "logger.h" |
||||
|
||||
WebUI::WebUI(QObject *parent) : QObject(parent) |
||||
{ |
||||
init(); |
||||
connect(Preferences::instance(), SIGNAL(changed()), SLOT(init())); |
||||
} |
||||
|
||||
void WebUI::init() |
||||
{ |
||||
Preferences* const pref = Preferences::instance(); |
||||
Logger* const logger = Logger::instance(); |
||||
|
||||
if (pref->isWebUiEnabled()) { |
||||
const quint16 port = pref->getWebUiPort(); |
||||
|
||||
if (httpServer_) { |
||||
if (httpServer_->serverPort() != port) |
||||
httpServer_->close(); |
||||
} |
||||
else { |
||||
webapp_ = new WebApplication(this); |
||||
httpServer_ = new Http::Server(webapp_, this); |
||||
} |
||||
|
||||
#ifndef QT_NO_OPENSSL |
||||
if (pref->isWebUiHttpsEnabled()) { |
||||
QSslCertificate cert(pref->getWebUiHttpsCertificate()); |
||||
QSslKey key; |
||||
key = QSslKey(pref->getWebUiHttpsKey(), QSsl::Rsa); |
||||
if (!cert.isNull() && !key.isNull()) |
||||
httpServer_->enableHttps(cert, key); |
||||
else |
||||
httpServer_->disableHttps(); |
||||
} |
||||
else { |
||||
httpServer_->disableHttps(); |
||||
} |
||||
#endif |
||||
|
||||
if (!httpServer_->isListening()) { |
||||
bool success = httpServer_->listen(QHostAddress::Any, port); |
||||
if (success) |
||||
logger->addMessage(tr("The Web UI is listening on port %1").arg(port)); |
||||
else |
||||
logger->addMessage(tr("Web User Interface Error - Unable to bind Web UI to port %1").arg(port), Log::CRITICAL); |
||||
} |
||||
|
||||
// DynDNS
|
||||
if (pref->isDynDNSEnabled()) { |
||||
if (!dynDNSUpdater_) |
||||
dynDNSUpdater_ = new DNSUpdater(this); |
||||
else |
||||
dynDNSUpdater_->updateCredentials(); |
||||
} |
||||
else { |
||||
if (dynDNSUpdater_) |
||||
delete dynDNSUpdater_; |
||||
} |
||||
} |
||||
else { |
||||
if (httpServer_) |
||||
delete httpServer_; |
||||
if (webapp_) |
||||
delete webapp_; |
||||
if (dynDNSUpdater_) |
||||
delete dynDNSUpdater_; |
||||
} |
||||
} |
@ -0,0 +1,55 @@
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent. |
||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru> |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License |
||||
* as published by the Free Software Foundation; either version 2 |
||||
* of the License, or (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; if not, write to the Free Software |
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
* |
||||
* In addition, as a special exception, the copyright holders give permission to |
||||
* link this program with the OpenSSL project's "OpenSSL" library (or with |
||||
* modified versions of it that use the same license as the "OpenSSL" library), |
||||
* and distribute the linked executables. You must obey the GNU General Public |
||||
* License in all respects for all of the code used other than "OpenSSL". If you |
||||
* modify file(s), you may extend this exception to your version of the file(s), |
||||
* but you are not obligated to do so. If you do not wish to do so, delete this |
||||
* exception statement from your version. |
||||
*/ |
||||
|
||||
#ifndef WEBUI_H |
||||
#define WEBUI_H |
||||
|
||||
#include <QObject> |
||||
#include <QPointer> |
||||
|
||||
namespace Http { class Server; } |
||||
class DNSUpdater; |
||||
class AbstractWebApplication; |
||||
|
||||
class WebUI : public QObject |
||||
{ |
||||
Q_OBJECT |
||||
|
||||
public: |
||||
explicit WebUI(QObject *parent = 0); |
||||
|
||||
private slots: |
||||
void init(); |
||||
|
||||
private: |
||||
QPointer<Http::Server> httpServer_; |
||||
QPointer<DNSUpdater> dynDNSUpdater_; |
||||
QPointer<AbstractWebApplication> webapp_; |
||||
}; |
||||
|
||||
#endif // WEBUI_H
|
@ -1,30 +1,25 @@
@@ -1,30 +1,25 @@
|
||||
INCLUDEPATH += $$PWD |
||||
|
||||
HEADERS += $$PWD/httpserver.h \ |
||||
$$PWD/httpconnection.h \ |
||||
HEADERS += \ |
||||
$$PWD/webui.h \ |
||||
$$PWD/btjson.h \ |
||||
$$PWD/prefjson.h \ |
||||
$$PWD/jsonutils.h \ |
||||
$$PWD/extra_translations.h \ |
||||
$$PWD/webapplication.h \ |
||||
$$PWD/abstractrequesthandler.h \ |
||||
$$PWD/requesthandler.h \ |
||||
$$PWD/qtorrentfilter.h |
||||
$$PWD/qtorrentfilter.h \ |
||||
$$PWD/websessiondata.h \ |
||||
$$PWD/abstractwebapplication.h |
||||
|
||||
SOURCES += $$PWD/httpserver.cpp \ |
||||
$$PWD/httpconnection.cpp \ |
||||
$$PWD/httprequestparser.cpp \ |
||||
$$PWD/httpresponsegenerator.cpp \ |
||||
SOURCES += \ |
||||
$$PWD/webui.cpp \ |
||||
$$PWD/btjson.cpp \ |
||||
$$PWD/prefjson.cpp \ |
||||
$$PWD/webapplication.cpp \ |
||||
$$PWD/abstractrequesthandler.cpp \ |
||||
$$PWD/requesthandler.cpp \ |
||||
$$PWD/qtorrentfilter.cpp |
||||
$$PWD/qtorrentfilter.cpp \ |
||||
$$PWD/abstractwebapplication.cpp |
||||
|
||||
# QJson JSON parser/serializer for using with Qt4 |
||||
lessThan(QT_MAJOR_VERSION, 5) { |
||||
include(qjson/qjson.pri) |
||||
} |
||||
lessThan(QT_MAJOR_VERSION, 5): include(qjson/qjson.pri) |
||||
|
||||
RESOURCES += $$PWD/webui.qrc |
||||
|
Loading…
Reference in new issue