| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 |
- /*
- Copyright 2017 Herik Lima de Castro and Marcelo Medeiros Eler
- Distributed under MIT license, or public domain if desired and
- recognized in your jurisdiction.
- See file LICENSE for detail.
- */
- #include "httpparser.h"
- #include <QDebug>
- #include <QMultiMap>
- #include <QNetworkRequest>
- #include "constants.h"
- #include "qglobal.h"
- CWF_BEGIN_NAMESPACE
- bool HttpParser::extractHeaderAndBody(QByteArray &httpMessage)
- {
- int index = httpMessage.indexOf(HTTP::END_OF_MESSAGE);
- if (index != -1) {
- index += 4;
- int size = httpMessage.size();
- for (int it = index; it < size; ++it) {
- body.push_back(httpMessage[it]);
- }
- httpMessage.remove(index, httpMessage.size());
- valid = true;
- } else {
- valid = false;
- }
- return valid;
- }
- void HttpParser::doParseHttpHeader(QByteArray &httpMessage)
- {
- httpMessage.replace("\r", "");
- QByteArrayList lines(httpMessage.split('\n'));
- QByteArrayList firstHeaderLine;
- if (!lines.empty())
- firstHeaderLine = lines[0].split(' ');
- if (firstHeaderLine.size() < 3) {
- valid = false;
- return;
- }
- method = firstHeaderLine[0].toUpper();
- url = std::move(firstHeaderLine[1]);
- httpVersion = std::move(firstHeaderLine[2]);
- doParseUrl();
- int size = lines.size();
- for (int i = 1, column = 0; i < size; ++i) {
- QByteArray &line = lines[i];
- if (line.isEmpty())
- continue;
- column = line.indexOf(':');
- headerField.insert(line.left(column).trimmed(), line.mid(column + 1).trimmed());
- }
- contentLenght = headerField.value(HTTP::CONTENT_LENGTH).toLongLong();
- contentType = headerField.value(HTTP::CONTENT_TYPE);
- multiPart = contentType.contains(HTTP::MULTIPART);
- if (contentType.contains(HTTP::URLENCODED))
- doParseBody();
- extractCookies();
- if (multiPart) {
- qint64 bodySize = body.size();
- readFile = bodySize == contentLenght;
- if (readFile)
- doParseFiles();
- }
- valid = true;
- }
- void HttpParser::doParseUrl()
- {
- if (url.contains("?") && url.contains("=")) {
- QByteArrayList realUrl(url.split('?'));
- url = std::move(realUrl[0]);
- QByteArrayList tempParam;
- if (realUrl.size() > 1)
- tempParam = realUrl[1].split('&');
- int size = tempParam.size();
- for (int i = 0; i < size; ++i) {
- QByteArrayList p(tempParam[i].split('='));
- if (p.size() == 2)
- parameters.insert(p[0], p[1]);
- else if (p.size() == 1)
- parameters.insert(p[0], "");
- }
- }
- }
- void HttpParser::doParseBody()
- {
- if (body.contains("&")) {
- QByteArrayList tempBody(body.split('&'));
- int size = tempBody.size();
- for (int i = 0; i < size; ++i) {
- QByteArrayList p(tempBody[i].split('='));
- if (p.size() == 2)
- parameters.insert(p[0], p[1]);
- else if (p.size() == 1)
- parameters.insert(p[0], "");
- }
- } else {
- QByteArrayList p(body.split('='));
- if (p.size() == 2)
- parameters.insert(p[0], p[1]);
- else if (p.size() == 1)
- parameters.insert(p[0], "");
- }
- }
- void HttpParser::extractCookies()
- {
- QByteArrayList temp(headerField.values(HTTP::COOKIE));
- int size = temp.size();
- for (int i = 0; i < size; ++i) {
- const QByteArray &txt = temp[i].replace(";", ";\n");
- ;
- QList<QNetworkCookie> cookiesList = QNetworkCookie::parseCookies(txt);
- for (QNetworkCookie &cookie : cookiesList) {
- if (cookie.name() == HTTP::SESSION_ID)
- sessionId = cookie.value();
- cookies.push_back(std::move(cookie));
- }
- }
- }
- void HttpParser::doParseFiles()
- {
- // --------------------------493060581858925222102364
- /*
- ----------------------------493060581858925222102364\r\n
- Content-Disposition: form-data; name=\"file\"; filename=\"a\"\r\n
- Content-Type: application/octet-stream\r\n
- \r\n
- n
- \r\n
- ----------------------------493060581858925222102364\r\n
- Content-Disposition: form-data; name=\"file\"; filename=\"aa\"\r\n
- Content-Type: application/octet-stream\r\n
- \r\n
- 1\r\n2\r\n
- \r\n
- ----------------------------493060581858925222102364--\r\n
- */
- // 提取 boundary
- const QString ContentType = headerField.value("Content-Type");
- QByteArray boundary = "--------";
- const QStringList ContentTypeList = ContentType.split(";");
- for (const QString &type : ContentTypeList) {
- if (type.indexOf("boundary") != -1) {
- boundary = type.trimmed().toUtf8();
- boundary = boundary.replace("\"", "");
- boundary = boundary.replace("boundary=", "");
- }
- }
- const QByteArray endBoundary = "--" + boundary + "--";
- QByteArray body = this->body;
- QByteArrayList cont(body.split('\n'));
- body.clear();
- int total = cont.size();
- QByteArray fileName;
- bool isContent = false;
- for (int i = 0; i < total; ++i) {
- QByteArray &temp = cont[i];
- if (temp.contains(endBoundary)) {
- break;
- }
- // 文件开始
- if (temp.contains(boundary)) {
- isContent = false;
- if (!fileName.isEmpty()) {
- body.chop(2);
- files.insert(fileName, body);
- }
- fileName.clear();
- body.clear();
- continue;
- }
- if (temp.contains(HTTP::CONTENT_DISPOSITION_COLON_SPACE)) {
- temp.replace(HTTP::CONTENT_DISPOSITION_COLON, "")
- .replace(HTTP::FORM_DATA_COLON_SPACE, "")
- .replace("\r", "")
- .replace("\"", "");
- if (temp.contains(HTTP::FILENAME)) {
- const QByteArrayList tmp(temp.split(';'));
- for (int j = 0; j < tmp.size(); ++j) {
- QByteArrayList keyValue(tmp[j].split('='));
- if (keyValue.size() >= 2) {
- const QByteArray &key = keyValue[0];
- const QByteArray &value = keyValue[1];
- if (key.contains(HTTP::FILENAME)) {
- fileName = std::move(value);
- break;
- }
- }
- }
- }
- isContent = true;
- } else if (temp.contains(HTTP::CONTENT_TYPE)) {
- isContent = true;
- } else {
- if (temp.size() > 0) {
- char ch = temp.back();
- if (ch == '\r') {
- if (isContent) {
- isContent = false;
- // 开始 ?
- continue;
- }
- }
- }
- body += temp + "\n";
- }
- }
- if (!fileName.isEmpty()) {
- body.chop(2);
- files.insert(fileName, body);
- }
- }
- void HttpParser::doParse(QByteArray &httpMessage)
- {
- //qDebug() << httpMessage;
- if (extractHeaderAndBody(httpMessage)) {
- doParseHttpHeader(httpMessage);
- }
- }
- CWF_END_NAMESPACE
|