From 6096506bd654f65c8c3a5d186fdf4a62ca386935 Mon Sep 17 00:00:00 2001 From: sledgehammer999 Date: Thu, 1 May 2014 18:28:38 +0300 Subject: [PATCH] Implement alternatives to QHttpRequestHeader and QHttpResponseHeader. --- src/webui/httpheader.cpp | 161 +++++++++++++++++++++++++++++++ src/webui/httpheader.h | 75 ++++++++++++++ src/webui/httprequestheader.cpp | 112 +++++++++++++++++++++ src/webui/httprequestheader.h | 59 +++++++++++ src/webui/httpresponseheader.cpp | 131 +++++++++++++++++++++++++ src/webui/httpresponseheader.h | 56 +++++++++++ src/webui/webui.pri | 10 +- 7 files changed, 602 insertions(+), 2 deletions(-) create mode 100644 src/webui/httpheader.cpp create mode 100644 src/webui/httpheader.h create mode 100644 src/webui/httprequestheader.cpp create mode 100644 src/webui/httprequestheader.h create mode 100644 src/webui/httpresponseheader.cpp create mode 100644 src/webui/httpresponseheader.h diff --git a/src/webui/httpheader.cpp b/src/webui/httpheader.cpp new file mode 100644 index 000000000..e681c25b1 --- /dev/null +++ b/src/webui/httpheader.cpp @@ -0,0 +1,161 @@ +/* + * 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 > &values) { + for (int i=0; i < values.size(); ++i) { + setValue(values[i].first, values[i].second); + } +} + +QString HttpHeader::toString() const { + QString str; + typedef QMultiHash::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 > HttpHeader::values() const { + QList > list; + typedef QMultiHash::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(); +} diff --git a/src/webui/httpheader.h b/src/webui/httpheader.h new file mode 100644 index 000000000..7a7ac8b2f --- /dev/null +++ b/src/webui/httpheader.h @@ -0,0 +1,75 @@ +/* + * 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 +#include +#include +#include + +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 > &values); + virtual QString toString() const; + QString value(const QString &key) const; + QList > values() const; + +protected: + void parse(const QString &str); + void setValid(bool valid = true); + +private: + QMultiHash m_headers; + bool m_valid; +}; + +#endif // HTTPHEADER_H diff --git a/src/webui/httprequestheader.cpp b/src/webui/httprequestheader.cpp new file mode 100644 index 000000000..f799ac8e3 --- /dev/null +++ b/src/webui/httprequestheader.cpp @@ -0,0 +1,112 @@ +/* + * 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; + +} diff --git a/src/webui/httprequestheader.h b/src/webui/httprequestheader.h new file mode 100644 index 000000000..0723eca60 --- /dev/null +++ b/src/webui/httprequestheader.h @@ -0,0 +1,59 @@ +/* + * 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 diff --git a/src/webui/httpresponseheader.cpp b/src/webui/httpresponseheader.cpp new file mode 100644 index 000000000..f95abc20d --- /dev/null +++ b/src/webui/httpresponseheader.cpp @@ -0,0 +1,131 @@ +/* + * 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; + +} diff --git a/src/webui/httpresponseheader.h b/src/webui/httpresponseheader.h new file mode 100644 index 000000000..4a54ef5a9 --- /dev/null +++ b/src/webui/httpresponseheader.h @@ -0,0 +1,56 @@ +/* + * 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 diff --git a/src/webui/webui.pri b/src/webui/webui.pri index 4cae09b6c..ae4c6cedd 100644 --- a/src/webui/webui.pri +++ b/src/webui/webui.pri @@ -8,7 +8,10 @@ HEADERS += $$PWD/httpserver.h \ $$PWD/jsonlist.h \ $$PWD/jsondict.h \ $$PWD/btjson.h \ - $$PWD/prefjson.h + $$PWD/prefjson.h \ + $$PWD/httpheader.h \ + $$PWD/httprequestheader.h \ + $$PWD/httpresponseheader.h SOURCES += $$PWD/httpserver.cpp \ $$PWD/httpconnection.cpp \ @@ -18,6 +21,9 @@ SOURCES += $$PWD/httpserver.cpp \ $$PWD/jsondict.cpp \ $$PWD/btjson.cpp \ $$PWD/json.cpp \ - $$PWD/prefjson.cpp + $$PWD/prefjson.cpp \ + $$PWD/httpheader.cpp \ + $$PWD/httprequestheader.cpp \ + $$PWD/httpresponseheader.cpp RESOURCES += $$PWD/webui.qrc