mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-08-14 02:27:09 -07:00
Fix prefjson::setPreferences() doesn't actually save.
This commit is contained in:
parent
8e1698d563
commit
2707f5205f
37 changed files with 1972 additions and 1763 deletions
111
src/core/http/connection.cpp
Normal file
111
src/core/http/connection.cpp
Normal file
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2006 Ishan Arora and Christophe Dumez
|
||||
*
|
||||
* 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 : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include <QTcpSocket>
|
||||
#include <QDebug>
|
||||
#include "types.h"
|
||||
#include "requestparser.h"
|
||||
#include "responsegenerator.h"
|
||||
#include "irequesthandler.h"
|
||||
#include "connection.h"
|
||||
|
||||
using namespace Http;
|
||||
|
||||
Connection::Connection(QTcpSocket *socket, IRequestHandler *requestHandler, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_socket(socket)
|
||||
, m_requestHandler(requestHandler)
|
||||
{
|
||||
m_socket->setParent(this);
|
||||
connect(m_socket, SIGNAL(readyRead()), SLOT(read()));
|
||||
connect(m_socket, SIGNAL(disconnected()), SLOT(deleteLater()));
|
||||
}
|
||||
|
||||
Connection::~Connection()
|
||||
{
|
||||
}
|
||||
|
||||
void Connection::read()
|
||||
{
|
||||
m_receivedData.append(m_socket->readAll());
|
||||
|
||||
Request request;
|
||||
RequestParser::ErrorCode err = RequestParser::parse(m_receivedData, request);
|
||||
switch (err)
|
||||
{
|
||||
case RequestParser::IncompleteRequest:
|
||||
// Partial request waiting for the rest
|
||||
break;
|
||||
case RequestParser::BadRequest:
|
||||
sendResponse(Response(400, "Bad Request"));
|
||||
break;
|
||||
case RequestParser::NoError:
|
||||
Environment env;
|
||||
env.clientAddress = m_socket->peerAddress();
|
||||
Response response = m_requestHandler->processRequest(request, env);
|
||||
if (acceptsGzipEncoding(request.headers["accept-encoding"]))
|
||||
response.headers[HEADER_CONTENT_ENCODING] = "gzip";
|
||||
sendResponse(response);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Connection::sendResponse(const Response &response)
|
||||
{
|
||||
m_socket->write(ResponseGenerator::generate(response));
|
||||
m_socket->disconnectFromHost();
|
||||
}
|
||||
|
||||
bool Connection::acceptsGzipEncoding(const QString &encoding)
|
||||
{
|
||||
int pos = encoding.indexOf("gzip", 0, Qt::CaseInsensitive);
|
||||
if (pos == -1)
|
||||
return false;
|
||||
|
||||
// Let's see if there's a qvalue of 0.0 following
|
||||
if (encoding[pos + 4] != ';') //there isn't, so it accepts gzip anyway
|
||||
return true;
|
||||
|
||||
//So let's find = and the next comma
|
||||
pos = encoding.indexOf("=", pos + 4, Qt::CaseInsensitive);
|
||||
int comma_pos = encoding.indexOf(",", pos, Qt::CaseInsensitive);
|
||||
|
||||
QString value;
|
||||
if (comma_pos == -1)
|
||||
value = encoding.mid(pos + 1, comma_pos);
|
||||
else
|
||||
value = encoding.mid(pos + 1, comma_pos - (pos + 1));
|
||||
|
||||
if (value.toDouble() == 0.0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
71
src/core/http/connection.h
Normal file
71
src/core/http/connection.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2006 Ishan Arora and Christophe Dumez
|
||||
*
|
||||
* 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 : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HTTP_CONNECTION_H
|
||||
#define HTTP_CONNECTION_H
|
||||
|
||||
#include <QObject>
|
||||
#include "types.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QTcpSocket;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Http
|
||||
{
|
||||
|
||||
class IRequestHandler;
|
||||
|
||||
class Connection : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(Connection)
|
||||
|
||||
public:
|
||||
Connection(QTcpSocket *socket, IRequestHandler *requestHandler, QObject *parent = 0);
|
||||
~Connection();
|
||||
|
||||
private slots:
|
||||
void read();
|
||||
|
||||
private:
|
||||
static bool acceptsGzipEncoding(const QString &encoding);
|
||||
void sendResponse(const Response &response);
|
||||
|
||||
QTcpSocket *m_socket;
|
||||
IRequestHandler *m_requestHandler;
|
||||
QByteArray m_receivedData;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // HTTP_CONNECTION_H
|
47
src/core/http/irequesthandler.h
Normal file
47
src/core/http/irequesthandler.h
Normal file
|
@ -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
|
||||
|
377
src/core/http/requestparser.cpp
Normal file
377
src/core/http/requestparser.cpp
Normal file
|
@ -0,0 +1,377 @@
|
|||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2006 Ishan Arora and Christophe Dumez
|
||||
*
|
||||
* 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 : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include <QStringList>
|
||||
#include <QUrl>
|
||||
//#include <QVariant>
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
|
||||
#include <QUrlQuery>
|
||||
#endif
|
||||
#include <QDir>
|
||||
#include <QTemporaryFile>
|
||||
#include <QDebug>
|
||||
#include "requestparser.h"
|
||||
|
||||
const QByteArray EOL("\r\n");
|
||||
const QByteArray EOH("\r\n\r\n");
|
||||
|
||||
inline QString unquoted(const QString& str)
|
||||
{
|
||||
if ((str[0] == '\"') && (str[str.length() - 1] == '\"'))
|
||||
return str.mid(1, str.length() - 2);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
using namespace Http;
|
||||
|
||||
RequestParser::ErrorCode RequestParser::parse(const QByteArray& data, Request& request, uint maxContentLength)
|
||||
{
|
||||
return RequestParser(maxContentLength).parseHttpRequest(data, request);
|
||||
}
|
||||
|
||||
RequestParser::RequestParser(uint maxContentLength)
|
||||
: m_maxContentLength(maxContentLength)
|
||||
{
|
||||
}
|
||||
|
||||
RequestParser::ErrorCode RequestParser::parseHttpRequest(const QByteArray& data, Request& request)
|
||||
{
|
||||
m_request = Request();
|
||||
|
||||
// Parse HTTP request header
|
||||
const int header_end = data.indexOf(EOH);
|
||||
if (header_end < 0)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << "incomplete request";
|
||||
return IncompleteRequest;
|
||||
}
|
||||
|
||||
if (!parseHttpHeader(data.left(header_end)))
|
||||
{
|
||||
qWarning() << Q_FUNC_INFO << "header parsing error";
|
||||
return BadRequest;
|
||||
}
|
||||
|
||||
// Parse HTTP request message
|
||||
int content_length = 0;
|
||||
if (m_request.headers.contains("content-length"))
|
||||
{
|
||||
content_length = m_request.headers["content-length"].toInt();
|
||||
if (content_length > static_cast<int>(m_maxContentLength))
|
||||
{
|
||||
qWarning() << Q_FUNC_INFO << "bad request: message too long";
|
||||
return BadRequest;
|
||||
}
|
||||
|
||||
QByteArray content = data.mid(header_end + EOH.length(), content_length);
|
||||
if (content.length() < content_length)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << "incomplete request";
|
||||
return IncompleteRequest;
|
||||
}
|
||||
|
||||
if (!parseContent(content))
|
||||
{
|
||||
qWarning() << Q_FUNC_INFO << "message parsing error";
|
||||
return BadRequest;
|
||||
}
|
||||
}
|
||||
|
||||
// qDebug() << Q_FUNC_INFO;
|
||||
// qDebug() << "HTTP Request header:";
|
||||
// qDebug() << data.left(header_end) << "\n";
|
||||
|
||||
request = m_request;
|
||||
return NoError;
|
||||
}
|
||||
|
||||
bool RequestParser::parseStartingLine(const QString &line)
|
||||
{
|
||||
const QRegExp rx("^([A-Z]+)\\s+(\\S+)\\s+HTTP/\\d\\.\\d$");
|
||||
|
||||
if (rx.indexIn(line.trimmed()) >= 0)
|
||||
{
|
||||
m_request.method = rx.cap(1);
|
||||
|
||||
QUrl url = QUrl::fromEncoded(rx.cap(2).toLatin1());
|
||||
m_request.path = url.path(); // Path
|
||||
|
||||
// Parse GET parameters
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
|
||||
QListIterator<QPair<QString, QString> > i(url.queryItems());
|
||||
#else
|
||||
QListIterator<QPair<QString, QString> > i(QUrlQuery(url).queryItems());
|
||||
#endif
|
||||
while (i.hasNext())
|
||||
{
|
||||
QPair<QString, QString> pair = i.next();
|
||||
m_request.gets[pair.first] = pair.second;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
qWarning() << Q_FUNC_INFO << "invalid http header:" << line;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RequestParser::parseHeaderLine(const QString &line, QPair<QString, QString>& out)
|
||||
{
|
||||
int i = line.indexOf(QLatin1Char(':'));
|
||||
if (i == -1)
|
||||
{
|
||||
qWarning() << Q_FUNC_INFO << "invalid http header:" << line;
|
||||
return false;
|
||||
}
|
||||
|
||||
out = qMakePair(line.left(i).trimmed().toLower(), line.mid(i + 1).trimmed());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RequestParser::parseHttpHeader(const QByteArray &data)
|
||||
{
|
||||
QString str = QString::fromUtf8(data);
|
||||
QStringList lines = str.trimmed().split(EOL);
|
||||
|
||||
QStringList headerLines;
|
||||
foreach (const QString& line, lines)
|
||||
{
|
||||
if (line[0].isSpace()) // header line continuation
|
||||
{
|
||||
if (!headerLines.isEmpty()) // really continuation
|
||||
{
|
||||
headerLines.last() += QLatin1Char(' ');
|
||||
headerLines.last() += line.trimmed();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
headerLines.append(line);
|
||||
}
|
||||
}
|
||||
|
||||
if (headerLines.isEmpty())
|
||||
return false; // Empty header
|
||||
|
||||
QStringList::Iterator it = headerLines.begin();
|
||||
if (!parseStartingLine(*it))
|
||||
return false;
|
||||
|
||||
++it;
|
||||
for (; it != headerLines.end(); ++it)
|
||||
{
|
||||
QPair<QString, QString> header;
|
||||
if (!parseHeaderLine(*it, header))
|
||||
return false;
|
||||
|
||||
m_request.headers[header.first] = header.second;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QList<QByteArray> RequestParser::splitMultipartData(const QByteArray& data, const QByteArray& boundary)
|
||||
{
|
||||
QList<QByteArray> ret;
|
||||
QByteArray sep = boundary + EOL;
|
||||
const int sepLength = sep.size();
|
||||
|
||||
int start = 0, end = 0;
|
||||
if ((end = data.indexOf(sep, start)) >= 0)
|
||||
{
|
||||
start = end + sepLength; // skip first boundary
|
||||
|
||||
while ((end = data.indexOf(sep, start)) >= 0)
|
||||
{
|
||||
ret << data.mid(start, end - start);
|
||||
start = end + sepLength;
|
||||
}
|
||||
|
||||
// last or single part
|
||||
sep = boundary + "--" + EOL;
|
||||
if ((end = data.indexOf(sep, start)) >= 0)
|
||||
ret << data.mid(start, end - start);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool RequestParser::parseContent(const QByteArray& data)
|
||||
{
|
||||
// Parse message content
|
||||
qDebug() << Q_FUNC_INFO << "Content-Length: " << m_request.headers["content-length"];
|
||||
qDebug() << Q_FUNC_INFO << "data.size(): " << data.size();
|
||||
|
||||
// Parse url-encoded POST data
|
||||
if (m_request.headers["content-type"].startsWith("application/x-www-form-urlencoded"))
|
||||
{
|
||||
QUrl url;
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
|
||||
url.setEncodedQuery(data);
|
||||
QListIterator<QPair<QString, QString> > i(url.queryItems());
|
||||
#else
|
||||
url.setQuery(data);
|
||||
QListIterator<QPair<QString, QString> > i(QUrlQuery(url).queryItems(QUrl::FullyDecoded));
|
||||
#endif
|
||||
while (i.hasNext())
|
||||
{
|
||||
QPair<QString, QString> pair = i.next();
|
||||
m_request.posts[pair.first.toLower()] = pair.second;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Parse multipart/form data (torrent file)
|
||||
/**
|
||||
data has the following format (if boundary is "cH2ae0GI3KM7GI3Ij5ae0ei4Ij5Ij5")
|
||||
|
||||
--cH2ae0GI3KM7GI3Ij5ae0ei4Ij5Ij5
|
||||
Content-Disposition: form-data; name=\"Filename\"
|
||||
|
||||
PB020344.torrent
|
||||
--cH2ae0GI3KM7GI3Ij5ae0ei4Ij5Ij5
|
||||
Content-Disposition: form-data; name=\"torrentfile"; filename=\"PB020344.torrent\"
|
||||
Content-Type: application/x-bittorrent
|
||||
|
||||
BINARY DATA IS HERE
|
||||
--cH2ae0GI3KM7GI3Ij5ae0ei4Ij5Ij5
|
||||
Content-Disposition: form-data; name=\"Upload\"
|
||||
|
||||
Submit Query
|
||||
--cH2ae0GI3KM7GI3Ij5ae0ei4Ij5Ij5--
|
||||
**/
|
||||
QString content_type = m_request.headers["content-type"];
|
||||
if (content_type.startsWith("multipart/form-data"))
|
||||
{
|
||||
const QRegExp boundaryRegexQuoted("boundary=\"([ \\w'()+,-\\./:=\\?]+)\"");
|
||||
const QRegExp boundaryRegexNotQuoted("boundary=([\\w'()+,-\\./:=\\?]+)");
|
||||
|
||||
QByteArray boundary;
|
||||
if (boundaryRegexQuoted.indexIn(content_type) < 0)
|
||||
{
|
||||
if (boundaryRegexNotQuoted.indexIn(content_type) < 0)
|
||||
{
|
||||
qWarning() << "Could not find boundary in multipart/form-data header!";
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
boundary = "--" + boundaryRegexNotQuoted.cap(1).toLatin1();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
boundary = "--" + boundaryRegexQuoted.cap(1).toLatin1();
|
||||
}
|
||||
|
||||
qDebug() << "Boundary is " << boundary;
|
||||
QList<QByteArray> parts = splitMultipartData(data, boundary);
|
||||
qDebug() << parts.size() << "parts in data";
|
||||
|
||||
foreach (const QByteArray& part, parts)
|
||||
{
|
||||
if (!parseFormData(part))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
qWarning() << Q_FUNC_INFO << "unknown content type:" << qPrintable(content_type);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RequestParser::parseFormData(const QByteArray& data)
|
||||
{
|
||||
// Parse form data header
|
||||
const int header_end = data.indexOf(EOH);
|
||||
if (header_end < 0)
|
||||
{
|
||||
qDebug() << "Invalid form data: \n" << data;
|
||||
return false;
|
||||
}
|
||||
|
||||
QString header_str = QString::fromUtf8(data.left(header_end));
|
||||
QStringList lines = header_str.trimmed().split(EOL);
|
||||
QStringMap headers;
|
||||
foreach (const QString& line, lines)
|
||||
{
|
||||
QPair<QString, QString> header;
|
||||
if (!parseHeaderLine(line, header))
|
||||
return false;
|
||||
|
||||
headers[header.first] = header.second;
|
||||
}
|
||||
|
||||
QStringMap disposition;
|
||||
if (!headers.contains("content-disposition") ||
|
||||
!parseHeaderValue(headers["content-disposition"], disposition) ||
|
||||
!disposition.contains("name"))
|
||||
{
|
||||
qDebug() << "Invalid form data header: \n" << header_str;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (disposition.contains("filename"))
|
||||
{
|
||||
UploadedFile ufile;
|
||||
ufile.filename = disposition["filename"];
|
||||
ufile.type = disposition["content-type"];
|
||||
ufile.data = data.mid(header_end + EOH.length());
|
||||
|
||||
m_request.files[disposition["name"]] = ufile;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_request.posts[disposition["name"]] = QString::fromUtf8(data.mid(header_end + EOH.length()));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RequestParser::parseHeaderValue(const QString& value, QStringMap& out)
|
||||
{
|
||||
QStringList items = value.split(QLatin1Char(';'));
|
||||
out[""] = items[0];
|
||||
|
||||
for (QStringList::size_type i = 1; i < items.size(); ++i)
|
||||
{
|
||||
int pos = items[i].indexOf("=");
|
||||
if (pos < 0)
|
||||
return false;
|
||||
|
||||
out[items[i].left(pos).trimmed()] = unquoted(items[i].mid(pos + 1).trimmed());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
69
src/core/http/requestparser.h
Normal file
69
src/core/http/requestparser.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2006 Ishan Arora and Christophe Dumez
|
||||
*
|
||||
* 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 : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#ifndef HTTP_REQUESTPARSER_H
|
||||
#define HTTP_REQUESTPARSER_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
namespace Http
|
||||
{
|
||||
|
||||
class RequestParser
|
||||
{
|
||||
public:
|
||||
enum ErrorCode { NoError = 0, IncompleteRequest, BadRequest };
|
||||
|
||||
// when result != NoError parsed request is undefined
|
||||
// Warning! Header names are converted to lower-case.
|
||||
static ErrorCode parse(const QByteArray& data, Request& request, uint maxContentLength = 10000000 /* ~10MB */);
|
||||
|
||||
private:
|
||||
RequestParser(uint maxContentLength);
|
||||
|
||||
ErrorCode parseHttpRequest(const QByteArray& data, Request& request);
|
||||
|
||||
bool parseHttpHeader(const QByteArray& data);
|
||||
bool parseStartingLine(const QString &line);
|
||||
bool parseContent(const QByteArray& data);
|
||||
bool parseFormData(const QByteArray& data);
|
||||
QList<QByteArray> splitMultipartData(const QByteArray& data, const QByteArray& boundary);
|
||||
|
||||
static bool parseHeaderLine(const QString& line, QPair<QString, QString>& out);
|
||||
static bool parseHeaderValue(const QString& value, QStringMap& out);
|
||||
|
||||
const uint m_maxContentLength;
|
||||
Request m_request;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // HTTP_REQUESTPARSER_H
|
74
src/core/http/responsebuilder.cpp
Normal file
74
src/core/http/responsebuilder.cpp
Normal file
|
@ -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;
|
||||
}
|
60
src/core/http/responsebuilder.h
Normal file
60
src/core/http/responsebuilder.h
Normal file
|
@ -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
|
133
src/core/http/responsegenerator.cpp
Normal file
133
src/core/http/responsegenerator.cpp
Normal file
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2006 Ishan Arora and Christophe Dumez
|
||||
*
|
||||
* 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 : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
#include <zlib.h>
|
||||
#include "responsegenerator.h"
|
||||
|
||||
bool gCompress(QByteArray data, QByteArray& dest_buffer);
|
||||
|
||||
using namespace Http;
|
||||
|
||||
QByteArray ResponseGenerator::generate(Response response)
|
||||
{
|
||||
if (response.headers[HEADER_CONTENT_ENCODING] == "gzip")
|
||||
{
|
||||
// A gzip seems to have 23 bytes overhead.
|
||||
// Also "Content-Encoding: gzip\r\n" is 26 bytes long
|
||||
// So we only benefit from gzip if the message is bigger than 23+26 = 49
|
||||
// If the message is smaller than 49 bytes we actually send MORE data if we gzip
|
||||
QByteArray dest_buf;
|
||||
if ((response.content.size() > 49) && (gCompress(response.content, dest_buf)))
|
||||
{
|
||||
response.content = dest_buf;
|
||||
}
|
||||
else
|
||||
{
|
||||
response.headers.remove(HEADER_CONTENT_ENCODING);
|
||||
}
|
||||
}
|
||||
|
||||
if (response.content.length() > 0)
|
||||
response.headers[HEADER_CONTENT_LENGTH] = QString::number(response.content.length());
|
||||
|
||||
QString ret(QLatin1String("HTTP/1.1 %1 %2\r\n%3\r\n"));
|
||||
|
||||
QString header;
|
||||
foreach (const QString& key, response.headers.keys())
|
||||
header += QString("%1: %2\r\n").arg(key).arg(response.headers[key]);
|
||||
|
||||
ret = ret.arg(response.status.code).arg(response.status.text).arg(header);
|
||||
|
||||
// qDebug() << Q_FUNC_INFO;
|
||||
// qDebug() << "HTTP Response header:";
|
||||
// qDebug() << ret;
|
||||
|
||||
return ret.toUtf8() + response.content;
|
||||
}
|
||||
|
||||
bool gCompress(QByteArray data, QByteArray& dest_buffer)
|
||||
{
|
||||
static const int BUFSIZE = 128 * 1024;
|
||||
char tmp_buf[BUFSIZE];
|
||||
int ret;
|
||||
|
||||
z_stream strm;
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
strm.next_in = reinterpret_cast<unsigned char*>(data.data());
|
||||
strm.avail_in = data.length();
|
||||
strm.next_out = reinterpret_cast<unsigned char*>(tmp_buf);
|
||||
strm.avail_out = BUFSIZE;
|
||||
|
||||
//windowBits = 15+16 to enable gzip
|
||||
//From the zlib manual: windowBits can also be greater than 15 for optional gzip encoding. Add 16 to windowBits
|
||||
//to write a simple gzip header and trailer around the compressed data instead of a zlib wrapper.
|
||||
ret = deflateInit2(&strm, Z_BEST_COMPRESSION, Z_DEFLATED, 15+16, 8, Z_DEFAULT_STRATEGY);
|
||||
|
||||
if (ret != Z_OK)
|
||||
return false;
|
||||
|
||||
while (strm.avail_in != 0)
|
||||
{
|
||||
ret = deflate(&strm, Z_NO_FLUSH);
|
||||
if (ret != Z_OK)
|
||||
return false;
|
||||
|
||||
if (strm.avail_out == 0)
|
||||
{
|
||||
dest_buffer.append(tmp_buf, BUFSIZE);
|
||||
strm.next_out = reinterpret_cast<unsigned char*>(tmp_buf);
|
||||
strm.avail_out = BUFSIZE;
|
||||
}
|
||||
}
|
||||
|
||||
int deflate_res = Z_OK;
|
||||
while (deflate_res == Z_OK)
|
||||
{
|
||||
if (strm.avail_out == 0)
|
||||
{
|
||||
dest_buffer.append(tmp_buf, BUFSIZE);
|
||||
strm.next_out = reinterpret_cast<unsigned char*>(tmp_buf);
|
||||
strm.avail_out = BUFSIZE;
|
||||
}
|
||||
|
||||
deflate_res = deflate(&strm, Z_FINISH);
|
||||
}
|
||||
|
||||
if (deflate_res != Z_STREAM_END)
|
||||
return false;
|
||||
|
||||
dest_buffer.append(tmp_buf, BUFSIZE - strm.avail_out);
|
||||
deflateEnd(&strm);
|
||||
|
||||
return true;
|
||||
}
|
49
src/core/http/responsegenerator.h
Normal file
49
src/core/http/responsegenerator.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2006 Ishan Arora and Christophe Dumez
|
||||
*
|
||||
* 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 : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HTTP_RESPONSEGENERATOR_H
|
||||
#define HTTP_RESPONSEGENERATOR_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
namespace Http
|
||||
{
|
||||
|
||||
class ResponseGenerator
|
||||
{
|
||||
public:
|
||||
static QByteArray generate(Response response);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // HTTP_RESPONSEGENERATOR_H
|
100
src/core/http/server.cpp
Normal file
100
src/core/http/server.cpp
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||
* Copyright (C) 2006 Ishan Arora <ishan@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.
|
||||
*/
|
||||
|
||||
#ifndef QT_NO_OPENSSL
|
||||
#include <QSslSocket>
|
||||
#else
|
||||
#include <QTcpSocket>
|
||||
#endif
|
||||
#include "connection.h"
|
||||
#include "server.h"
|
||||
|
||||
using namespace Http;
|
||||
|
||||
Server::Server(IRequestHandler *requestHandler, QObject* parent)
|
||||
: QTcpServer(parent)
|
||||
, m_requestHandler(requestHandler)
|
||||
#ifndef QT_NO_OPENSSL
|
||||
, m_https(false)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
Server::~Server()
|
||||
{
|
||||
}
|
||||
|
||||
#ifndef QT_NO_OPENSSL
|
||||
void Server::enableHttps(const QSslCertificate &certificate, const QSslKey &key)
|
||||
{
|
||||
m_certificate = certificate;
|
||||
m_key = key;
|
||||
m_https = true;
|
||||
}
|
||||
|
||||
void Server::disableHttps()
|
||||
{
|
||||
m_https = false;
|
||||
m_certificate.clear();
|
||||
m_key.clear();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
|
||||
void Server::incomingConnection(qintptr socketDescriptor)
|
||||
#else
|
||||
void Server::incomingConnection(int socketDescriptor)
|
||||
#endif
|
||||
{
|
||||
QTcpSocket *serverSocket;
|
||||
#ifndef QT_NO_OPENSSL
|
||||
if (m_https)
|
||||
serverSocket = new QSslSocket(this);
|
||||
else
|
||||
#endif
|
||||
serverSocket = new QTcpSocket(this);
|
||||
if (serverSocket->setSocketDescriptor(socketDescriptor))
|
||||
{
|
||||
#ifndef QT_NO_OPENSSL
|
||||
if (m_https)
|
||||
{
|
||||
static_cast<QSslSocket*>(serverSocket)->setProtocol(QSsl::AnyProtocol);
|
||||
static_cast<QSslSocket*>(serverSocket)->setPrivateKey(m_key);
|
||||
static_cast<QSslSocket*>(serverSocket)->setLocalCertificate(m_certificate);
|
||||
static_cast<QSslSocket*>(serverSocket)->startServerEncryption();
|
||||
}
|
||||
#endif
|
||||
new Connection(serverSocket, m_requestHandler, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
serverSocket->deleteLater();
|
||||
}
|
||||
}
|
80
src/core/http/server.h
Normal file
80
src/core/http/server.h
Normal file
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2006 Ishan Arora and 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.
|
||||
*
|
||||
* Contact : chris@qbittorrent.org
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HTTP_SERVER_H
|
||||
#define HTTP_SERVER_H
|
||||
|
||||
#include <QTcpServer>
|
||||
#ifndef QT_NO_OPENSSL
|
||||
#include <QSslCertificate>
|
||||
#include <QSslKey>
|
||||
#endif
|
||||
|
||||
namespace Http
|
||||
{
|
||||
|
||||
class IRequestHandler;
|
||||
class Connection;
|
||||
|
||||
class Server : public QTcpServer
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(Server)
|
||||
|
||||
public:
|
||||
Server(IRequestHandler *requestHandler, QObject *parent = 0);
|
||||
~Server();
|
||||
|
||||
#ifndef QT_NO_OPENSSL
|
||||
void enableHttps(const QSslCertificate &certificate, const QSslKey &key);
|
||||
void disableHttps();
|
||||
#endif
|
||||
|
||||
private:
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
|
||||
void incomingConnection(qintptr socketDescriptor);
|
||||
#else
|
||||
void incomingConnection(int socketDescriptor);
|
||||
#endif
|
||||
|
||||
private:
|
||||
IRequestHandler *m_requestHandler;
|
||||
#ifndef QT_NO_OPENSSL
|
||||
bool m_https;
|
||||
QSslCertificate m_certificate;
|
||||
QSslKey m_key;
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // HTTP_SERVER_H
|
95
src/core/http/types.h
Normal file
95
src/core/http/types.h
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* 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 HTTP_TYPES_H
|
||||
#define HTTP_TYPES_H
|
||||
|
||||
#include <QString>
|
||||
#include <QMap>
|
||||
#include <QHostAddress>
|
||||
|
||||
typedef QMap<QString, QString> QStringMap;
|
||||
|
||||
namespace Http
|
||||
{
|
||||
|
||||
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 HEADER_CACHE_CONTROL = "Cache-Control";
|
||||
|
||||
const QString CONTENT_TYPE_CSS = "text/css; charset=UTF-8";
|
||||
const QString CONTENT_TYPE_GIF = "image/gif";
|
||||
const QString CONTENT_TYPE_HTML = "text/html; charset=UTF-8";
|
||||
const QString CONTENT_TYPE_JS = "text/javascript; charset=UTF-8";
|
||||
const QString CONTENT_TYPE_PNG = "image/png";
|
||||
const QString CONTENT_TYPE_TXT = "text/plain; charset=UTF-8";
|
||||
|
||||
struct Environment
|
||||
{
|
||||
QHostAddress clientAddress;
|
||||
};
|
||||
|
||||
struct UploadedFile
|
||||
{
|
||||
QString filename; // original filename
|
||||
QString type; // MIME type
|
||||
QByteArray data; // File data
|
||||
};
|
||||
|
||||
struct Request
|
||||
{
|
||||
QString method;
|
||||
QString path;
|
||||
QStringMap headers;
|
||||
QStringMap gets;
|
||||
QStringMap posts;
|
||||
QMap<QString, UploadedFile> files;
|
||||
};
|
||||
|
||||
struct ResponseStatus
|
||||
{
|
||||
uint code;
|
||||
QString text;
|
||||
|
||||
ResponseStatus(uint code = 200, const QString& text = "OK"): code(code), text(text) {}
|
||||
};
|
||||
|
||||
struct Response
|
||||
{
|
||||
ResponseStatus status;
|
||||
QStringMap headers;
|
||||
QByteArray content;
|
||||
|
||||
Response(uint code = 200, const QString& text = "OK"): status(code, text) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // HTTP_TYPES_H
|
Loading…
Add table
Add a link
Reference in a new issue