sledgehammer999
10 years ago
67 changed files with 2146 additions and 1873 deletions
After Width: | Height: | Size: 1.5 KiB |
@ -0,0 +1,174 @@
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* 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) |
||||
{ |
||||
if (isBanned()) |
||||
{ |
||||
status(403, "Forbidden"); |
||||
print(QObject::tr("Your IP address has been banned after too many failed authentication attempts.")); |
||||
return; |
||||
} |
||||
|
||||
sessionInitialize(); |
||||
|
||||
if (!sessionActive() && !isAuthNeeded()) sessionStart(); |
||||
} |
||||
|
||||
HttpResponse AbstractRequestHandler::run() |
||||
{ |
||||
response_ = HttpResponse(); |
||||
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,89 @@
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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 ABSTRACTREQUESTHANDLER_H |
||||
#define ABSTRACTREQUESTHANDLER_H |
||||
|
||||
#include <QString> |
||||
#include "httptypes.h" |
||||
|
||||
class WebApplication; |
||||
struct WebSession; |
||||
|
||||
class AbstractRequestHandler |
||||
{ |
||||
friend class WebApplication; |
||||
|
||||
public: |
||||
AbstractRequestHandler( |
||||
const HttpRequest& request, const HttpEnvironment& env, |
||||
WebApplication* app); |
||||
|
||||
HttpResponse run(); |
||||
|
||||
protected: |
||||
virtual void processRequest() = 0; |
||||
|
||||
void status(uint code, const QString& text); |
||||
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 printFile(const QString& path); |
||||
|
||||
// Session management
|
||||
bool sessionActive() const { return session_ != 0; } |
||||
void sessionInitialize(); |
||||
void sessionStart(); |
||||
void sessionEnd(); |
||||
|
||||
// Ban management
|
||||
bool isBanned() const; |
||||
int failedAttempts() const; |
||||
void resetFailedAttempts(); |
||||
void increaseFailedAttempts(); |
||||
|
||||
bool isAuthNeeded(); |
||||
|
||||
// save data to temporary file on disk and return its name (or empty string if fails)
|
||||
static QString saveTmpFile(const QByteArray& data); |
||||
|
||||
inline WebSession* session() { return session_; } |
||||
inline HttpRequest request() const { return request_; } |
||||
inline HttpEnvironment env() const { return env_; } |
||||
|
||||
private: |
||||
WebApplication* app_; |
||||
WebSession* session_; |
||||
const HttpRequest request_; |
||||
const HttpEnvironment env_; |
||||
HttpResponse response_; |
||||
|
||||
void print_impl(const QByteArray& data, const QString& type); |
||||
}; |
||||
|
||||
#endif // ABSTRACTREQUESTHANDLER_H
|
@ -0,0 +1,75 @@
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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 EXTRA_TRANSLATIONS_H |
||||
#define EXTRA_TRANSLATIONS_H |
||||
|
||||
#include <QObject> |
||||
|
||||
// Additional translations for Web UI
|
||||
static const char *__TRANSLATIONS__[] = { |
||||
QT_TRANSLATE_NOOP("HttpServer", "File"), |
||||
QT_TRANSLATE_NOOP("HttpServer", "Edit"), |
||||
QT_TRANSLATE_NOOP("HttpServer", "Help"), |
||||
QT_TRANSLATE_NOOP("HttpServer", "Download Torrents from their URL or Magnet link"), |
||||
QT_TRANSLATE_NOOP("HttpServer", "Only one link per line"), |
||||
QT_TRANSLATE_NOOP("HttpServer", "Download local torrent"), |
||||
QT_TRANSLATE_NOOP("HttpServer", "Torrent files were correctly added to download list."), |
||||
QT_TRANSLATE_NOOP("HttpServer", "Point to torrent file"), |
||||
QT_TRANSLATE_NOOP("HttpServer", "Download"), |
||||
QT_TRANSLATE_NOOP("HttpServer", "Are you sure you want to delete the selected torrents from the transfer list and hard disk?"), |
||||
QT_TRANSLATE_NOOP("HttpServer", "Download rate limit must be greater than 0 or disabled."), |
||||
QT_TRANSLATE_NOOP("HttpServer", "Upload rate limit must be greater than 0 or disabled."), |
||||
QT_TRANSLATE_NOOP("HttpServer", "Maximum number of connections limit must be greater than 0 or disabled."), |
||||
QT_TRANSLATE_NOOP("HttpServer", "Maximum number of connections per torrent limit must be greater than 0 or disabled."), |
||||
QT_TRANSLATE_NOOP("HttpServer", "Maximum number of upload slots per torrent limit must be greater than 0 or disabled."), |
||||
QT_TRANSLATE_NOOP("HttpServer", "Unable to save program preferences, qBittorrent is probably unreachable."), |
||||
QT_TRANSLATE_NOOP("HttpServer", "Language"), |
||||
QT_TRANSLATE_NOOP("HttpServer", "The port used for incoming connections must be greater than 1024 and less than 65535."), |
||||
QT_TRANSLATE_NOOP("HttpServer", "The port used for the Web UI must be greater than 1024 and less than 65535."), |
||||
QT_TRANSLATE_NOOP("HttpServer", "The Web UI username must be at least 3 characters long."), |
||||
QT_TRANSLATE_NOOP("HttpServer", "The Web UI password must be at least 3 characters long."), |
||||
QT_TRANSLATE_NOOP("HttpServer", "Save"), |
||||
QT_TRANSLATE_NOOP("HttpServer", "qBittorrent client is not reachable"), |
||||
QT_TRANSLATE_NOOP("HttpServer", "HTTP Server"), |
||||
QT_TRANSLATE_NOOP("HttpServer", "The following parameters are supported:"), |
||||
QT_TRANSLATE_NOOP("HttpServer", "Torrent path"), |
||||
QT_TRANSLATE_NOOP("HttpServer", "Torrent name"), |
||||
QT_TRANSLATE_NOOP("HttpServer", "qBittorrent has been shutdown."), |
||||
QT_TRANSLATE_NOOP("HttpServer", "Unable to log in, qBittorrent is probably unreachable."), |
||||
QT_TRANSLATE_NOOP("HttpServer", "Invalid Username or Password."), |
||||
QT_TRANSLATE_NOOP("HttpServer", "Password"), |
||||
QT_TRANSLATE_NOOP("HttpServer", "Login"), |
||||
QT_TRANSLATE_NOOP("HttpServer", "qBittorrent web User Interface") |
||||
}; |
||||
|
||||
static const struct { const char *source; const char *comment; } __COMMENTED_TRANSLATIONS__[] = { |
||||
QT_TRANSLATE_NOOP3("HttpServer", "Downloaded", "Is the file downloaded or not?") |
||||
}; |
||||
|
||||
#endif // EXTRA_TRANSLATIONS_H
|
@ -1,161 +0,0 @@
@@ -1,161 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent. |
||||
* Copyright (C) 2014 sledgehammer999 |
||||
* |
||||
* 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. |
||||
* |
||||
* Contact : hammered999@gmail.com |
||||
*/ |
||||
|
||||
#include "httpheader.h" |
||||
|
||||
HttpHeader::HttpHeader() : m_valid(true) {} |
||||
|
||||
HttpHeader::HttpHeader(const QString &str) : m_valid(true) { |
||||
parse(str); |
||||
} |
||||
|
||||
HttpHeader::~HttpHeader() {} |
||||
|
||||
void HttpHeader::addValue(const QString &key, const QString &value) { |
||||
m_headers.insert(key.toLower(), value.trimmed()); |
||||
} |
||||
|
||||
QStringList HttpHeader::allValues(const QString &key) const { |
||||
QStringList list = m_headers.values(key); |
||||
return list; |
||||
} |
||||
|
||||
uint HttpHeader::contentLength() const { |
||||
QString lenVal = m_headers.value("content-length"); |
||||
return lenVal.toUInt(); |
||||
} |
||||
|
||||
QString HttpHeader::contentType() const { |
||||
QString str = m_headers.value("content-type"); |
||||
// content-type might have a parameter so we need to strip it.
|
||||
// eg. application/x-www-form-urlencoded; charset=utf-8
|
||||
int index = str.indexOf(';'); |
||||
if (index == -1) |
||||
return str; |
||||
else |
||||
return str.left(index); |
||||
} |
||||
|
||||
bool HttpHeader::hasContentLength() const { |
||||
return m_headers.contains("content-length"); |
||||
} |
||||
|
||||
bool HttpHeader::hasContentType() const { |
||||
return m_headers.contains("content-type"); |
||||
} |
||||
|
||||
bool HttpHeader::hasKey(const QString &key) const { |
||||
return m_headers.contains(key.toLower()); |
||||
} |
||||
|
||||
bool HttpHeader::isValid() const { |
||||
return m_valid; |
||||
} |
||||
|
||||
QStringList HttpHeader::keys() const { |
||||
QStringList list = m_headers.keys(); |
||||
return list; |
||||
} |
||||
|
||||
void HttpHeader::removeAllValues(const QString &key) { |
||||
m_headers.remove(key); |
||||
} |
||||
|
||||
void HttpHeader::removeValue(const QString &key) { |
||||
m_headers.remove(key); |
||||
} |
||||
|
||||
void HttpHeader::setContentLength(int len) { |
||||
m_headers.replace("content-length", QString::number(len)); |
||||
} |
||||
|
||||
void HttpHeader::setContentType(const QString &type) { |
||||
m_headers.replace("content-type", type.trimmed()); |
||||
} |
||||
|
||||
void HttpHeader::setValue(const QString &key, const QString &value) { |
||||
m_headers.replace(key.toLower(), value.trimmed()); |
||||
} |
||||
|
||||
void HttpHeader::setValues(const QList<QPair<QString, QString> > &values) { |
||||
for (int i=0; i < values.size(); ++i) { |
||||
setValue(values[i].first, values[i].second); |
||||
} |
||||
} |
||||
|
||||
QString HttpHeader::toString() const { |
||||
QString str; |
||||
typedef QMultiHash<QString, QString>::const_iterator h_it; |
||||
|
||||
for (h_it it = m_headers.begin(), itend = m_headers.end(); |
||||
it != itend; ++it) { |
||||
str = str + it.key() + ": " + it.value() + "\r\n"; |
||||
} |
||||
|
||||
str += "\r\n"; |
||||
return str; |
||||
} |
||||
|
||||
QString HttpHeader::value(const QString &key) const { |
||||
return m_headers.value(key.toLower()); |
||||
} |
||||
|
||||
QList<QPair<QString, QString> > HttpHeader::values() const { |
||||
QList<QPair<QString, QString> > list; |
||||
typedef QMultiHash<QString, QString>::const_iterator h_it; |
||||
|
||||
for (h_it it = m_headers.begin(), itend = m_headers.end(); |
||||
it != itend; ++it) { |
||||
list.append(qMakePair(it.key(), it.value())); |
||||
} |
||||
|
||||
return list; |
||||
} |
||||
|
||||
void HttpHeader::parse(const QString &str) { |
||||
QStringList headers = str.split("\r\n", QString::SkipEmptyParts, Qt::CaseInsensitive); |
||||
for (int i=0; i < headers.size(); ++i) { |
||||
int index = headers[i].indexOf(':', Qt::CaseInsensitive); |
||||
if (index == -1) { |
||||
setValid(false); |
||||
break; |
||||
} |
||||
|
||||
QString key = headers[i].left(index); |
||||
QString value = headers[i].right(headers[i].size() - index - 1); |
||||
m_headers.insert(key.toLower(), value.trimmed()); |
||||
} |
||||
} |
||||
|
||||
void HttpHeader::setValid(bool valid) { |
||||
m_valid = valid; |
||||
if (!m_valid) |
||||
m_headers.clear(); |
||||
} |
@ -1,75 +0,0 @@
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent. |
||||
* Copyright (C) 2014 sledgehammer999 |
||||
* |
||||
* 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. |
||||
* |
||||
* Contact : hammered999@gmail.com |
||||
*/ |
||||
|
||||
#ifndef HTTPHEADER_H |
||||
#define HTTPHEADER_H |
||||
|
||||
#include <QString> |
||||
#include <QStringList> |
||||
#include <QMultiHash> |
||||
#include <QPair> |
||||
|
||||
class HttpHeader { |
||||
|
||||
public: |
||||
HttpHeader(); |
||||
HttpHeader(const QString &str); |
||||
virtual ~HttpHeader(); |
||||
void addValue(const QString &key, const QString &value); |
||||
QStringList allValues(const QString &key) const; |
||||
uint contentLength() const; |
||||
QString contentType() const; |
||||
bool hasContentLength() const; |
||||
bool hasContentType() const; |
||||
bool hasKey(const QString &key) const; |
||||
bool isValid() const; |
||||
QStringList keys() const; |
||||
virtual int majorVersion() const =0; |
||||
virtual int minorVersion() const =0; |
||||
void removeAllValues(const QString &key); |
||||
void removeValue(const QString &key); |
||||
void setContentLength(int len); |
||||
void setContentType(const QString &type); |
||||
void setValue(const QString &key, const QString &value); |
||||
void setValues(const QList<QPair<QString, QString> > &values); |
||||
virtual QString toString() const; |
||||
QString value(const QString &key) const; |
||||
QList<QPair<QString, QString> > values() const; |
||||
|
||||
protected: |
||||
void parse(const QString &str); |
||||
void setValid(bool valid = true); |
||||
|
||||
private: |
||||
QMultiHash<QString, QString> m_headers; |
||||
bool m_valid; |
||||
}; |
||||
|
||||
#endif // HTTPHEADER_H
|
@ -1,112 +0,0 @@
@@ -1,112 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent. |
||||
* Copyright (C) 2014 sledgehammer999 |
||||
* |
||||
* 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. |
||||
* |
||||
* Contact : hammered999@gmail.com |
||||
*/ |
||||
|
||||
#include "httprequestheader.h" |
||||
|
||||
|
||||
HttpRequestHeader::HttpRequestHeader() : HttpHeader(), m_majorVersion(1), m_minorVersion(1) {} |
||||
|
||||
HttpRequestHeader::HttpRequestHeader(const QString &method, const QString &path, int majorVer, int minorVer) : |
||||
HttpHeader(), m_method(method), m_path(path), m_majorVersion(majorVer), m_minorVersion(minorVer) {} |
||||
|
||||
HttpRequestHeader::HttpRequestHeader(const QString &str): HttpHeader() { |
||||
int line = str.indexOf("\r\n", 0, Qt::CaseInsensitive); |
||||
QString req = str.left(line); |
||||
QString headers = str.right(str.size() - line - 2); //"\r\n" == 2
|
||||
QStringList method = req.split(" ", QString::SkipEmptyParts, Qt::CaseInsensitive); |
||||
if (method.size() != 3) |
||||
setValid(false); |
||||
else { |
||||
m_method = method[0]; |
||||
m_path = method[1]; |
||||
if (parseVersions(method[2])) |
||||
parse(headers); |
||||
else |
||||
setValid(false); |
||||
} |
||||
} |
||||
|
||||
int HttpRequestHeader::majorVersion() const { |
||||
return m_majorVersion; |
||||
} |
||||
|
||||
int HttpRequestHeader::minorVersion() const { |
||||
return m_minorVersion; |
||||
} |
||||
|
||||
QString HttpRequestHeader::method() const { |
||||
return m_method; |
||||
} |
||||
|
||||
QString HttpRequestHeader::path() const { |
||||
return m_path; |
||||
} |
||||
|
||||
void HttpRequestHeader::setRequest(const QString &method, const QString &path, int majorVer, int minorVer) { |
||||
m_method = method; |
||||
m_path = path; |
||||
m_majorVersion = majorVer; |
||||
m_minorVersion = minorVer; |
||||
} |
||||
|
||||
QString HttpRequestHeader::toString() const { |
||||
QString str = m_method + " "; |
||||
str+= m_path + " "; |
||||
str+= "HTTP/" + QString::number(m_majorVersion) + "." + QString::number(m_minorVersion) + "\r\n"; |
||||
str += HttpHeader::toString(); |
||||
return str; |
||||
} |
||||
|
||||
bool HttpRequestHeader::parseVersions(const QString &str) { |
||||
if (str.size() <= 5) // HTTP/ which means version missing
|
||||
return false; |
||||
|
||||
if (str.left(4) != "HTTP") |
||||
return false; |
||||
|
||||
QString versions = str.right(str.size() - 5); // Strip "HTTP/"
|
||||
|
||||
int decPoint = versions.indexOf('.'); |
||||
if (decPoint == -1) |
||||
return false; |
||||
|
||||
bool ok; |
||||
|
||||
m_majorVersion = versions.left(decPoint).toInt(&ok); |
||||
if (!ok) |
||||
return false; |
||||
|
||||
m_minorVersion = versions.right(versions.size() - decPoint - 1).toInt(&ok); |
||||
if (!ok) |
||||
return false; |
||||
|
||||
return true; |
||||
|
||||
} |
@ -1,59 +0,0 @@
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent. |
||||
* Copyright (C) 2014 sledgehammer999 |
||||
* |
||||
* 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. |
||||
* |
||||
* Contact : hammered999@gmail.com |
||||
*/ |
||||
|
||||
#ifndef HTTPREQUESTHEADER_H |
||||
#define HTTPREQUESTHEADER_H |
||||
|
||||
#include "httpheader.h" |
||||
|
||||
class HttpRequestHeader: public HttpHeader { |
||||
public: |
||||
HttpRequestHeader(); |
||||
// The path argument must be properly encoded for an HTTP request.
|
||||
HttpRequestHeader(const QString &method, const QString &path, int majorVer = 1, int minorVer = 1); |
||||
HttpRequestHeader(const QString &str); |
||||
virtual int majorVersion() const; |
||||
virtual int minorVersion() const; |
||||
QString method() const; |
||||
// This is the raw path from the header. No decoding/encoding is performed.
|
||||
QString path() const; |
||||
// The path argument must be properly encoded for an HTTP request.
|
||||
void setRequest(const QString &method, const QString &path, int majorVer = 1, int minorVer = 1); |
||||
virtual QString toString() const; |
||||
|
||||
private: |
||||
bool parseVersions(const QString &str); |
||||
QString m_method; |
||||
QString m_path; |
||||
int m_majorVersion; |
||||
int m_minorVersion; |
||||
}; |
||||
|
||||
#endif // HTTPREQUESTHEADER_H
|
@ -1,131 +0,0 @@
@@ -1,131 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent. |
||||
* Copyright (C) 2014 sledgehammer999 |
||||
* |
||||
* 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. |
||||
* |
||||
* Contact : hammered999@gmail.com |
||||
*/ |
||||
|
||||
#include "httpresponseheader.h" |
||||
|
||||
HttpResponseHeader::HttpResponseHeader(): HttpHeader(), m_code(200), m_majorVersion(1), m_minorVersion(1) {} |
||||
|
||||
HttpResponseHeader::HttpResponseHeader(int code, const QString &text, int majorVer, int minorVer): |
||||
HttpHeader(), m_code(code), m_text(text), m_majorVersion(majorVer), m_minorVersion(minorVer) {} |
||||
|
||||
HttpResponseHeader::HttpResponseHeader(const QString &str): HttpHeader() { |
||||
int line = str.indexOf("\r\n", 0, Qt::CaseInsensitive); |
||||
QString res = str.left(line); |
||||
QString headers = str.right(str.size() - line - 2); //"\r\n" == 2
|
||||
QStringList status = res.split(" ", QString::SkipEmptyParts, Qt::CaseInsensitive); |
||||
if (status.size() != 3 || status.size() != 2) //reason-phrase could be empty
|
||||
setValid(false); |
||||
else { |
||||
if (parseVersions(status[0])) { |
||||
bool ok; |
||||
m_code = status[1].toInt(&ok); |
||||
if (ok) { |
||||
m_text = status[2]; |
||||
parse(headers); |
||||
} |
||||
else |
||||
setValid(false); |
||||
} |
||||
else |
||||
setValid(false); |
||||
} |
||||
} |
||||
|
||||
int HttpResponseHeader::majorVersion() const { |
||||
return m_majorVersion; |
||||
} |
||||
|
||||
int HttpResponseHeader::minorVersion() const { |
||||
return m_minorVersion; |
||||
} |
||||
|
||||
QString HttpResponseHeader::reasonPhrase() const { |
||||
return m_text; |
||||
} |
||||
|
||||
void HttpResponseHeader::setStatusLine(int code, const QString &text, int majorVer, int minorVer) { |
||||
m_code = code; |
||||
m_text = text; |
||||
m_majorVersion = majorVer; |
||||
m_minorVersion = minorVer; |
||||
} |
||||
|
||||
int HttpResponseHeader::statusCode() const { |
||||
return m_code; |
||||
} |
||||
|
||||
QString HttpResponseHeader::toString() const { |
||||
QString str = "HTTP/" + QString::number(m_majorVersion) + "." + QString::number(m_minorVersion) + " "; |
||||
|
||||
QString code = QString::number(m_code); |
||||
if (code.size() > 3) { |
||||
str+= code.left(3) + " "; |
||||
} |
||||
else if (code.size() < 3) { |
||||
int padding = 3 - code.size(); |
||||
for (int i = 0; i < padding; ++i) |
||||
code.push_back("0"); |
||||
str += code + " "; |
||||
} |
||||
else { |
||||
str += code + " "; |
||||
} |
||||
|
||||
str += m_text + "\r\n"; |
||||
str += HttpHeader::toString(); |
||||
return str; |
||||
} |
||||
|
||||
bool HttpResponseHeader::parseVersions(const QString &str) { |
||||
if (str.size() <= 5) // HTTP/ which means version missing
|
||||
return false; |
||||
|
||||
if (str.left(4) != "HTTP") |
||||
return false; |
||||
|
||||
QString versions = str.right(str.size() - 5); // Strip "HTTP/"
|
||||
|
||||
int decPoint = versions.indexOf('.'); |
||||
if (decPoint == -1) |
||||
return false; |
||||
|
||||
bool ok; |
||||
|
||||
m_majorVersion = versions.left(decPoint).toInt(&ok); |
||||
if (!ok) |
||||
return false; |
||||
|
||||
m_minorVersion = versions.right(versions.size() - decPoint - 1).toInt(&ok); |
||||
if (!ok) |
||||
return false; |
||||
|
||||
return true; |
||||
|
||||
} |
@ -1,56 +0,0 @@
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent. |
||||
* Copyright (C) 2014 sledgehammer999 |
||||
* |
||||
* 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. |
||||
* |
||||
* Contact : hammered999@gmail.com |
||||
*/ |
||||
|
||||
#ifndef HTTPRESPONSEHEADER_H |
||||
#define HTTPRESPONSEHEADER_H |
||||
|
||||
#include "httpheader.h" |
||||
|
||||
class HttpResponseHeader: public HttpHeader { |
||||
public: |
||||
HttpResponseHeader(); |
||||
HttpResponseHeader(int code, const QString &text = QString(), int majorVer = 1, int minorVer = 1); |
||||
HttpResponseHeader(const QString &str); |
||||
virtual int majorVersion() const; |
||||
virtual int minorVersion() const; |
||||
QString reasonPhrase() const; |
||||
void setStatusLine(int code, const QString &text = QString(), int majorVer = 1, int minorVer = 1); |
||||
int statusCode() const; |
||||
virtual QString toString() const; |
||||
|
||||
private: |
||||
bool parseVersions(const QString &str); |
||||
int m_code; |
||||
QString m_text; |
||||
int m_majorVersion; |
||||
int m_minorVersion; |
||||
}; |
||||
|
||||
#endif // HTTPRESPONSEHEADER_H
|
@ -0,0 +1,89 @@
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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 HTTPTYPES_H |
||||
#define HTTPTYPES_H |
||||
|
||||
#include <QString> |
||||
#include <QMap> |
||||
#include <QHostAddress> |
||||
|
||||
typedef QMap<QString, QString> QStringMap; |
||||
|
||||
const QString HEADER_SET_COOKIE = "Set-Cookie"; |
||||
const QString HEADER_CONTENT_TYPE = "Content-Type"; |
||||
const QString HEADER_CONTENT_ENCODING = "Content-Encoding"; |
||||
const QString HEADER_CONTENT_LENGTH = "Content-Length"; |
||||
|
||||
const QString CONTENT_TYPE_CSS = "text/css"; |
||||
const QString CONTENT_TYPE_GIF = "image/gif"; |
||||
const QString CONTENT_TYPE_HTML = "text/html"; |
||||
const QString CONTENT_TYPE_JS = "text/javascript"; |
||||
const QString CONTENT_TYPE_PNG = "image/png"; |
||||
const QString CONTENT_TYPE_TXT = "text/plain"; |
||||
|
||||
struct HttpEnvironment |
||||
{ |
||||
QHostAddress clientAddress; |
||||
}; |
||||
|
||||
struct UploadedFile |
||||
{ |
||||
QString filename; // original filename
|
||||
QString type; // MIME type
|
||||
QByteArray data; // File data
|
||||
}; |
||||
|
||||
struct HttpRequest |
||||
{ |
||||
QString method; |
||||
QString path; |
||||
QStringMap headers; |
||||
QStringMap gets; |
||||
QStringMap posts; |
||||
QMap<QString, UploadedFile> files; |
||||
}; |
||||
|
||||
struct HttpResponseStatus |
||||
{ |
||||
uint code; |
||||
QString text; |
||||
|
||||
HttpResponseStatus(uint code = 200, const QString& text = "OK"): code(code), text(text) {} |
||||
}; |
||||
|
||||
struct HttpResponse |
||||
{ |
||||
HttpResponseStatus status; |
||||
QStringMap headers; |
||||
QByteArray content; |
||||
|
||||
HttpResponse(uint code = 200, const QString& text = "OK"): status(code, text) {} |
||||
}; |
||||
|
||||
#endif // HTTPTYPES_H
|
@ -0,0 +1,588 @@
@@ -0,0 +1,588 @@
|
||||
/*
|
||||
* 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" |
||||
|
||||
using namespace libtorrent; |
||||
|
||||
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"; |
||||
|
||||
#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(json, torrents); |
||||
ADD_ACTION(json, preferences); |
||||
ADD_ACTION(json, transferInfo); |
||||
ADD_ACTION(json, propertiesGeneral); |
||||
ADD_ACTION(json, propertiesTrackers); |
||||
ADD_ACTION(json, propertiesFiles); |
||||
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, 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); |
||||
|
||||
return actions; |
||||
} |
||||
|
||||
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(); |
||||
|
||||
if ((request().posts["username"] == pref->getWebUiUsername()) && (pass == pref->getWebUiPassword())) |
||||
{ |
||||
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() |
||||
{ |
||||
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); |
||||
} |
||||
|
||||
void RequestHandler::action_public_images() |
||||
{ |
||||
const QString path = ":/Icons/" + args_.join("/"); |
||||
printFile(path); |
||||
} |
||||
|
||||
void RequestHandler::action_json_torrents() |
||||
{ |
||||
print(btjson::getTorrents(), CONTENT_TYPE_JS); |
||||
} |
||||
|
||||
void RequestHandler::action_json_preferences() |
||||
{ |
||||
print(prefjson::getPreferences(), CONTENT_TYPE_JS); |
||||
} |
||||
|
||||
void RequestHandler::action_json_transferInfo() |
||||
{ |
||||
print(btjson::getTransferInfo(), CONTENT_TYPE_JS); |
||||
} |
||||
|
||||
void RequestHandler::action_json_propertiesGeneral() |
||||
{ |
||||
print(btjson::getPropertiesForTorrent(args_.front()), CONTENT_TYPE_JS); |
||||
} |
||||
|
||||
void RequestHandler::action_json_propertiesTrackers() |
||||
{ |
||||
print(btjson::getTrackersForTorrent(args_.front()), CONTENT_TYPE_JS); |
||||
} |
||||
|
||||
void RequestHandler::action_json_propertiesFiles() |
||||
{ |
||||
print(btjson::getFilesForTorrent(args_.front()), CONTENT_TYPE_JS); |
||||
} |
||||
|
||||
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.
|
||||
|
||||
QTimer::singleShot(0, qApp, SLOT(quit())); |
||||
} |
||||
|
||||
void RequestHandler::action_command_download() |
||||
{ |
||||
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; |
||||
|
||||
foreach(const UploadedFile& torrent, request().files) |
||||
{ |
||||
QString filePath = saveTmpFile(torrent.data); |
||||
|
||||
if (!filePath.isEmpty()) |
||||
{ |
||||
QBtSession::instance()->addTorrent(filePath); |
||||
// Clean up
|
||||
fsutils::forceRemove(filePath); |
||||
print(QLatin1String("<script type=\"text/javascript\">window.parent.hideAll();</script>")); |
||||
} |
||||
else |
||||
{ |
||||
qWarning() << "I/O Error: Could not create temporary file"; |
||||
} |
||||
} |
||||
} |
||||
|
||||
void RequestHandler::action_command_addTrackers() |
||||
{ |
||||
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() |
||||
{ |
||||
QBtSession::instance()->resumeAllTorrents(); |
||||
} |
||||
|
||||
void RequestHandler::action_command_pauseAll() |
||||
{ |
||||
QBtSession::instance()->pauseAllTorrents(); |
||||
} |
||||
|
||||
void RequestHandler::action_command_resume() |
||||
{ |
||||
QBtSession::instance()->resumeTorrent(request().posts["hash"]); |
||||
} |
||||
|
||||
void RequestHandler::action_command_pause() |
||||
{ |
||||
QBtSession::instance()->pauseTorrent(request().posts["hash"]); |
||||
} |
||||
|
||||
void RequestHandler::action_command_setPreferences() |
||||
{ |
||||
prefjson::setPreferences(request().posts["json"]); |
||||
} |
||||
|
||||
void RequestHandler::action_command_setFilePrio() |
||||
{ |
||||
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() |
||||
{ |
||||
print(QByteArray::number(QBtSession::instance()->getSession()->settings().upload_rate_limit)); |
||||
} |
||||
|
||||
void RequestHandler::action_command_getGlobalDlLimit() |
||||
{ |
||||
print(QByteArray::number(QBtSession::instance()->getSession()->settings().download_rate_limit)); |
||||
} |
||||
|
||||
void RequestHandler::action_command_setGlobalUpLimit() |
||||
{ |
||||
qlonglong limit = request().posts["limit"].toLongLong(); |
||||
if (limit == 0) limit = -1; |
||||
|
||||
QBtSession::instance()->setUploadRateLimit(limit); |
||||
Preferences::instance()->setGlobalUploadLimit(limit/1024.); |
||||
} |
||||
|
||||
void RequestHandler::action_command_setGlobalDlLimit() |
||||
{ |
||||
qlonglong limit = request().posts["limit"].toLongLong(); |
||||
if (limit == 0) limit = -1; |
||||
|
||||
QBtSession::instance()->setDownloadRateLimit(limit); |
||||
Preferences::instance()->setGlobalDownloadLimit(limit/1024.); |
||||
} |
||||
|
||||
void RequestHandler::action_command_getTorrentUpLimit() |
||||
{ |
||||
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() |
||||
{ |
||||
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() |
||||
{ |
||||
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() |
||||
{ |
||||
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_delete() |
||||
{ |
||||
QStringList hashes = request().posts["hashes"].split("|"); |
||||
|
||||
foreach (const QString &hash, hashes) |
||||
{ |
||||
QBtSession::instance()->deleteTorrent(hash, false); |
||||
} |
||||
} |
||||
|
||||
void RequestHandler::action_command_deletePerm() |
||||
{ |
||||
QStringList hashes = request().posts["hashes"].split("|"); |
||||
|
||||
foreach (const QString &hash, hashes) |
||||
{ |
||||
QBtSession::instance()->deleteTorrent(hash, true); |
||||
} |
||||
} |
||||
|
||||
void RequestHandler::action_command_increasePrio() |
||||
{ |
||||
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() |
||||
{ |
||||
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() |
||||
{ |
||||
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() |
||||
{ |
||||
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() |
||||
{ |
||||
QBtSession::instance()->recheckTorrent(request().posts["hash"]); |
||||
} |
||||
|
||||
bool RequestHandler::isPublicScope() |
||||
{ |
||||
return (scope_ == DEFAULT_SCOPE); |
||||
} |
||||
|
||||
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(); |
@ -0,0 +1,100 @@
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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_json_torrents(); |
||||
void action_json_preferences(); |
||||
void action_json_transferInfo(); |
||||
void action_json_propertiesGeneral(); |
||||
void action_json_propertiesTrackers(); |
||||
void action_json_propertiesFiles(); |
||||
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_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(); |
||||
|
||||
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,309 @@
@@ -0,0 +1,309 @@
|
||||
/*
|
||||
* 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. |
||||
*/ |
||||
|
||||
#ifdef DISABLE_GUI |
||||
#include <QCoreApplication> |
||||
#else |
||||
#include <QApplication> |
||||
#endif |
||||
#include <QDateTime> |
||||
#include <QTimer> |
||||
#include <QFile> |
||||
#include <QDebug> |
||||
#include "preferences.h" |
||||
#include "requesthandler.h" |
||||
#include "webapplication.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; |
||||
}; |
||||
|
||||
// WebApplication
|
||||
|
||||
WebApplication::WebApplication(QObject *parent) |
||||
: QObject(parent) |
||||
{ |
||||
} |
||||
|
||||
WebApplication::~WebApplication() |
||||
{ |
||||
// cleanup sessions data
|
||||
foreach (WebSession* session, sessions_.values()) |
||||
delete session; |
||||
} |
||||
|
||||
WebApplication *WebApplication::instance() |
||||
{ |
||||
static WebApplication inst; |
||||
return &inst; |
||||
} |
||||
|
||||
void WebApplication::UnbanTimerEvent() |
||||
{ |
||||
UnbanTimer* ubantimer = static_cast<UnbanTimer*>(sender()); |
||||
qDebug("Ban period has expired for %s", qPrintable(ubantimer->peerIp().toString())); |
||||
clientFailedAttempts_.remove(ubantimer->peerIp()); |
||||
ubantimer->deleteLater(); |
||||
} |
||||
|
||||
bool WebApplication::sessionInitialize(AbstractRequestHandler* _this) |
||||
{ |
||||
if (_this->session_ == 0) |
||||
{ |
||||
QString cookie = _this->request_.headers.value("cookie"); |
||||
//qDebug() << Q_FUNC_INFO << "cookie: " << cookie;
|
||||
|
||||
QString sessionId; |
||||
const QString SID_START = C_SID + "="; |
||||
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)) |
||||
{ |
||||
_this->session_ = sessions_[sessionId]; |
||||
return true; |
||||
} |
||||
else |
||||
{ |
||||
qDebug() << Q_FUNC_INFO << "session does not exist!"; |
||||
} |
||||
} |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
bool WebApplication::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; |
||||
} |
||||
|
||||
QString WebApplication::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 WebApplication::translateDocument(QString& data) |
||||
{ |
||||
const QRegExp regex(QString::fromUtf8("_\\(([\\w\\s?!:\\/\\(\\),%µ&\\-\\.]+)\\)")); |
||||
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" |
||||
}; |
||||
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 WebApplication::isBanned(const AbstractRequestHandler *_this) const |
||||
{ |
||||
return clientFailedAttempts_.value(_this->env_.clientAddress, 0) >= MAX_AUTH_FAILED_ATTEMPTS; |
||||
} |
||||
|
||||
int WebApplication::failedAttempts(const AbstractRequestHandler* _this) const |
||||
{ |
||||
return clientFailedAttempts_.value(_this->env_.clientAddress, 0); |
||||
} |
||||
|
||||
void WebApplication::resetFailedAttempts(AbstractRequestHandler* _this) |
||||
{ |
||||
clientFailedAttempts_.remove(_this->env_.clientAddress); |
||||
} |
||||
|
||||
void WebApplication::increaseFailedAttempts(AbstractRequestHandler* _this) |
||||
{ |
||||
const int nb_fail = clientFailedAttempts_.value(_this->env_.clientAddress, 0) + 1; |
||||
|
||||
clientFailedAttempts_[_this->env_.clientAddress] = nb_fail; |
||||
if (nb_fail == MAX_AUTH_FAILED_ATTEMPTS) |
||||
{ |
||||
// Max number of failed attempts reached
|
||||
// Start ban period
|
||||
UnbanTimer* ubantimer = new UnbanTimer(_this->env_.clientAddress, this); |
||||
connect(ubantimer, SIGNAL(timeout()), SLOT(UnbanTimerEvent())); |
||||
ubantimer->start(); |
||||
} |
||||
} |
||||
|
||||
bool WebApplication::sessionStart(AbstractRequestHandler *_this) |
||||
{ |
||||
if (_this->session_ == 0) |
||||
{ |
||||
_this->session_ = new WebSession(generateSid()); |
||||
sessions_[_this->session_->id] = _this->session_; |
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
bool WebApplication::sessionEnd(AbstractRequestHandler *_this) |
||||
{ |
||||
if ((_this->session_ != 0) && (sessions_.contains(_this->session_->id))) |
||||
{ |
||||
sessions_.remove(_this->session_->id); |
||||
delete _this->session_; |
||||
_this->session_ = 0; |
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
QStringMap WebApplication::initializeContentTypeByExtMap() |
||||
{ |
||||
QStringMap map; |
||||
|
||||
map["htm"] = CONTENT_TYPE_HTML; |
||||
map["html"] = CONTENT_TYPE_HTML; |
||||
map["css"] = CONTENT_TYPE_CSS; |
||||
map["gif"] = CONTENT_TYPE_GIF; |
||||
map["png"] = CONTENT_TYPE_PNG; |
||||
map["js"] = CONTENT_TYPE_JS; |
||||
|
||||
return map; |
||||
} |
||||
|
||||
const QStringMap WebApplication::CONTENT_TYPE_BY_EXT = WebApplication::initializeContentTypeByExtMap(); |
@ -0,0 +1,87 @@
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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 WEBAPPLICATION_H |
||||
#define WEBAPPLICATION_H |
||||
|
||||
#include <QObject> |
||||
#include <QMap> |
||||
#include <QHash> |
||||
#include "httptypes.h" |
||||
|
||||
struct WebSession |
||||
{ |
||||
const QString id; |
||||
|
||||
WebSession(const QString& id): id(id) {} |
||||
}; |
||||
|
||||
const QString C_SID = "SID"; // name of session id cookie
|
||||
const int BAN_TIME = 3600000; // 1 hour
|
||||
const int MAX_AUTH_FAILED_ATTEMPTS = 5; |
||||
|
||||
class AbstractRequestHandler; |
||||
|
||||
class WebApplication: public QObject |
||||
{ |
||||
Q_OBJECT |
||||
Q_DISABLE_COPY(WebApplication) |
||||
|
||||
public: |
||||
WebApplication(QObject* parent = 0); |
||||
virtual ~WebApplication(); |
||||
|
||||
static WebApplication* instance(); |
||||
|
||||
bool isBanned(const AbstractRequestHandler* _this) const; |
||||
int failedAttempts(const AbstractRequestHandler *_this) const; |
||||
void resetFailedAttempts(AbstractRequestHandler* _this); |
||||
void increaseFailedAttempts(AbstractRequestHandler* _this); |
||||
|
||||
bool sessionStart(AbstractRequestHandler* _this); |
||||
bool sessionEnd(AbstractRequestHandler* _this); |
||||
bool sessionInitialize(AbstractRequestHandler* _this); |
||||
|
||||
bool readFile(const QString &path, QByteArray& data, QString& type); |
||||
|
||||
private slots: |
||||
void UnbanTimerEvent(); |
||||
|
||||
private: |
||||
QMap<QString, WebSession*> sessions_; |
||||
QHash<QHostAddress, int> clientFailedAttempts_; |
||||
QMap<QString, QByteArray> translatedFiles_; |
||||
|
||||
QString generateSid(); |
||||
static void translateDocument(QString& data); |
||||
|
||||
static const QStringMap CONTENT_TYPE_BY_EXT; |
||||
static QStringMap initializeContentTypeByExtMap(); |
||||
}; |
||||
|
||||
#endif // WEBAPPLICATION_H
|
@ -1,37 +1,39 @@
@@ -1,37 +1,39 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0"> |
||||
<qresource prefix="webui/"> |
||||
<file>html/index.html</file> |
||||
<file>html/download.html</file> |
||||
<file>html/addtrackers.html</file> |
||||
<file>html/upload.html</file> |
||||
<file>html/about.html</file> |
||||
<file>html/filters.html</file> |
||||
<file>html/transferlist.html</file> |
||||
<file>html/prop-general.html</file> |
||||
<file>html/prop-trackers.html</file> |
||||
<file>html/prop-files.html</file> |
||||
<file>html/properties.html</file> |
||||
<file>html/uploadlimit.html</file> |
||||
<file>html/downloadlimit.html</file> |
||||
<file>html/preferences.html</file> |
||||
<file>html/preferences_content.html</file> |
||||
<file>html/confirmdeletion.html</file> |
||||
<file>css/Core.css</file> |
||||
<file>css/Layout.css</file> |
||||
<file>css/Window.css</file> |
||||
<file>css/Tabs.css</file> |
||||
<file>css/dynamicTable.css</file> |
||||
<file>css/style.css</file> |
||||
<file>scripts/excanvas-compressed.js</file> |
||||
<file>scripts/mocha-yc.js</file> |
||||
<file>scripts/mocha-init.js</file> |
||||
<file>scripts/mootools-1.2-core-yc.js</file> |
||||
<file>scripts/mootools-1.2-more.js</file> |
||||
<file>scripts/dynamicTable.js</file> |
||||
<file>scripts/client.js</file> |
||||
<file>scripts/download.js</file> |
||||
<file>scripts/progressbar.js</file> |
||||
<file>scripts/contextmenu.js</file> |
||||
<file>scripts/parametrics.js</file> |
||||
<RCC> |
||||
<qresource prefix="/"> |
||||
<file>www/private/index.html</file> |
||||
<file>www/private/login.html</file> |
||||
<file>www/public/css/Core.css</file> |
||||
<file>www/public/css/dynamicTable.css</file> |
||||
<file>www/public/css/Layout.css</file> |
||||
<file>www/public/css/style.css</file> |
||||
<file>www/public/css/Tabs.css</file> |
||||
<file>www/public/css/Window.css</file> |
||||
<file>www/public/scripts/client.js</file> |
||||
<file>www/public/scripts/contextmenu.js</file> |
||||
<file>www/public/scripts/download.js</file> |
||||
<file>www/public/scripts/dynamicTable.js</file> |
||||
<file>www/public/scripts/excanvas-compressed.js</file> |
||||
<file>www/public/scripts/mocha.js</file> |
||||
<file>www/public/scripts/mocha-init.js</file> |
||||
<file>www/public/scripts/mocha-yc.js</file> |
||||
<file>www/public/scripts/mootools-1.2-core-yc.js</file> |
||||
<file>www/public/scripts/mootools-1.2-more.js</file> |
||||
<file>www/public/scripts/parametrics.js</file> |
||||
<file>www/public/scripts/progressbar.js</file> |
||||
<file>www/public/about.html</file> |
||||
<file>www/public/addtrackers.html</file> |
||||
<file>www/public/confirmdeletion.html</file> |
||||
<file>www/public/download.html</file> |
||||
<file>www/public/downloadlimit.html</file> |
||||
<file>www/public/filters.html</file> |
||||
<file>www/public/preferences.html</file> |
||||
<file>www/public/preferences_content.html</file> |
||||
<file>www/public/properties.html</file> |
||||
<file>www/public/prop-files.html</file> |
||||
<file>www/public/prop-general.html</file> |
||||
<file>www/public/prop-trackers.html</file> |
||||
<file>www/public/transferlist.html</file> |
||||
<file>www/public/upload.html</file> |
||||
<file>www/public/uploadlimit.html</file> |
||||
</qresource> |
||||
</RCC> |
||||
|
@ -0,0 +1,76 @@
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" dir="ltr"> |
||||
<head> |
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> |
||||
<meta http-equiv="X-UA-Compatible" content="IE=8" /> |
||||
<title>qBittorrent web User Interface</title> |
||||
<link rel="stylesheet" type="text/css" href="/css/style.css" /> |
||||
<script type="text/javascript" src="scripts/mootools-1.2-core-yc.js" charset="utf-8"></script> |
||||
<script type="text/javascript"> |
||||
window.addEvent('domready', function() { |
||||
$('loginform').addEvent('submit', function(e) { |
||||
new Event(e).stop(); |
||||
submitLoginForm(); |
||||
}); |
||||
}); |
||||
|
||||
function submitLoginForm() { |
||||
new Request({ |
||||
url: '/login', |
||||
method: 'post', |
||||
data: $('loginform').toQueryString(), |
||||
onFailure: function() { |
||||
alert("_(Unable to log in, qBittorrent is probably unreachable.)"); |
||||
}, |
||||
onSuccess: function(text) { |
||||
if (text == "Ok.") { |
||||
// Session started. Simply reload page. |
||||
window.location.reload(); |
||||
} else { |
||||
$('error_msg').set('html', '_(Invalid Username or Password.)'); |
||||
} |
||||
} |
||||
}).send(); |
||||
} |
||||
</script> |
||||
<style> |
||||
.col { |
||||
display: inline-block; |
||||
vertical-align: middle; |
||||
} |
||||
.row { |
||||
margin-bottom: 5px; |
||||
} |
||||
#main { |
||||
margin-left: auto; |
||||
margin-right: auto; |
||||
text-align: center; |
||||
padding-top: 5em; |
||||
} |
||||
#formplace { |
||||
text-align: left; |
||||
padding: 10px; |
||||
} |
||||
#error_msg { |
||||
color: #f00; |
||||
} |
||||
</style> |
||||
</head> |
||||
<body> |
||||
<div id="main"> |
||||
<h1>_(qBittorrent web User Interface)</h1> |
||||
<div id="logo" class="col"> |
||||
<img src="images/skin/mascot.png" /> |
||||
</div> |
||||
<div id="formplace" class="col"> |
||||
<form id="loginform" action=""> |
||||
<div class="row"><label for="username">_(Name)</label><br /><input type="text" id="username" name="username" /></div> |
||||
<div class="row"><label for="password">_(Password)</label><br /><input type="password" id="password" name="password" /></div> |
||||
<div class="row"><input type="submit" id="login" value="_(Login)" /></div> |
||||
</form> |
||||
</div> |
||||
<div id="error_msg"></div> |
||||
</div> |
||||
</body> |
||||
</html> |
Loading…
Reference in new issue