httpparser.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*
  2. Copyright 2017 Herik Lima de Castro and Marcelo Medeiros Eler
  3. Distributed under MIT license, or public domain if desired and
  4. recognized in your jurisdiction.
  5. See file LICENSE for detail.
  6. */
  7. #include "httpparser.h"
  8. #include <QDebug>
  9. #include <QMultiMap>
  10. #include <QNetworkRequest>
  11. #include "constants.h"
  12. #include "qglobal.h"
  13. CWF_BEGIN_NAMESPACE
  14. bool HttpParser::extractHeaderAndBody(QByteArray &httpMessage)
  15. {
  16. int index = httpMessage.indexOf(HTTP::END_OF_MESSAGE);
  17. if (index != -1) {
  18. index += 4;
  19. int size = httpMessage.size();
  20. for (int it = index; it < size; ++it) {
  21. body.push_back(httpMessage[it]);
  22. }
  23. httpMessage.remove(index, httpMessage.size());
  24. valid = true;
  25. } else {
  26. valid = false;
  27. }
  28. return valid;
  29. }
  30. void HttpParser::doParseHttpHeader(QByteArray &httpMessage)
  31. {
  32. httpMessage.replace("\r", "");
  33. QByteArrayList lines(httpMessage.split('\n'));
  34. QByteArrayList firstHeaderLine;
  35. if (!lines.empty())
  36. firstHeaderLine = lines[0].split(' ');
  37. if (firstHeaderLine.size() < 3) {
  38. valid = false;
  39. return;
  40. }
  41. method = firstHeaderLine[0].toUpper();
  42. url = std::move(firstHeaderLine[1]);
  43. httpVersion = std::move(firstHeaderLine[2]);
  44. doParseUrl();
  45. int size = lines.size();
  46. for (int i = 1, column = 0; i < size; ++i) {
  47. QByteArray &line = lines[i];
  48. if (line.isEmpty())
  49. continue;
  50. column = line.indexOf(':');
  51. headerField.insert(line.left(column).trimmed(), line.mid(column + 1).trimmed());
  52. }
  53. contentLenght = headerField.value(HTTP::CONTENT_LENGTH).toLongLong();
  54. contentType = headerField.value(HTTP::CONTENT_TYPE);
  55. multiPart = contentType.contains(HTTP::MULTIPART);
  56. if (contentType.contains(HTTP::URLENCODED))
  57. doParseBody();
  58. extractCookies();
  59. if (multiPart) {
  60. qint64 bodySize = body.size();
  61. readFile = bodySize == contentLenght;
  62. if (readFile)
  63. doParseFiles();
  64. }
  65. valid = true;
  66. }
  67. void HttpParser::doParseUrl()
  68. {
  69. if (url.contains("?") && url.contains("=")) {
  70. QByteArrayList realUrl(url.split('?'));
  71. url = std::move(realUrl[0]);
  72. QByteArrayList tempParam;
  73. if (realUrl.size() > 1)
  74. tempParam = realUrl[1].split('&');
  75. int size = tempParam.size();
  76. for (int i = 0; i < size; ++i) {
  77. QByteArrayList p(tempParam[i].split('='));
  78. if (p.size() == 2)
  79. parameters.insert(p[0], p[1]);
  80. else if (p.size() == 1)
  81. parameters.insert(p[0], "");
  82. }
  83. }
  84. }
  85. void HttpParser::doParseBody()
  86. {
  87. if (body.contains("&")) {
  88. QByteArrayList tempBody(body.split('&'));
  89. int size = tempBody.size();
  90. for (int i = 0; i < size; ++i) {
  91. QByteArrayList p(tempBody[i].split('='));
  92. if (p.size() == 2)
  93. parameters.insert(p[0], p[1]);
  94. else if (p.size() == 1)
  95. parameters.insert(p[0], "");
  96. }
  97. } else {
  98. QByteArrayList p(body.split('='));
  99. if (p.size() == 2)
  100. parameters.insert(p[0], p[1]);
  101. else if (p.size() == 1)
  102. parameters.insert(p[0], "");
  103. }
  104. }
  105. void HttpParser::extractCookies()
  106. {
  107. QByteArrayList temp(headerField.values(HTTP::COOKIE));
  108. int size = temp.size();
  109. for (int i = 0; i < size; ++i) {
  110. const QByteArray &txt = temp[i].replace(";", ";\n");
  111. ;
  112. QList<QNetworkCookie> cookiesList = QNetworkCookie::parseCookies(txt);
  113. for (QNetworkCookie &cookie : cookiesList) {
  114. if (cookie.name() == HTTP::SESSION_ID)
  115. sessionId = cookie.value();
  116. cookies.push_back(std::move(cookie));
  117. }
  118. }
  119. }
  120. void HttpParser::doParseFiles()
  121. {
  122. // --------------------------493060581858925222102364
  123. /*
  124. ----------------------------493060581858925222102364\r\n
  125. Content-Disposition: form-data; name=\"file\"; filename=\"a\"\r\n
  126. Content-Type: application/octet-stream\r\n
  127. \r\n
  128. n
  129. \r\n
  130. ----------------------------493060581858925222102364\r\n
  131. Content-Disposition: form-data; name=\"file\"; filename=\"aa\"\r\n
  132. Content-Type: application/octet-stream\r\n
  133. \r\n
  134. 1\r\n2\r\n
  135. \r\n
  136. ----------------------------493060581858925222102364--\r\n
  137. */
  138. // 提取 boundary
  139. const QString ContentType = headerField.value("Content-Type");
  140. QByteArray boundary = "--------";
  141. const QStringList ContentTypeList = ContentType.split(";");
  142. for (const QString &type : ContentTypeList) {
  143. if (type.indexOf("boundary") != -1) {
  144. boundary = type.trimmed().toUtf8();
  145. boundary = boundary.replace("\"", "");
  146. boundary = boundary.replace("boundary=", "");
  147. }
  148. }
  149. const QByteArray endBoundary = "--" + boundary + "--";
  150. QByteArray body = this->body;
  151. QByteArrayList cont(body.split('\n'));
  152. body.clear();
  153. int total = cont.size();
  154. QByteArray fileName;
  155. bool isContent = false;
  156. for (int i = 0; i < total; ++i) {
  157. QByteArray &temp = cont[i];
  158. if (temp.contains(endBoundary)) {
  159. break;
  160. }
  161. // 文件开始
  162. if (temp.contains(boundary)) {
  163. isContent = false;
  164. if (!fileName.isEmpty()) {
  165. body.chop(2);
  166. files.insert(fileName, body);
  167. }
  168. fileName.clear();
  169. body.clear();
  170. continue;
  171. }
  172. if (temp.contains(HTTP::CONTENT_DISPOSITION_COLON_SPACE)) {
  173. temp.replace(HTTP::CONTENT_DISPOSITION_COLON, "")
  174. .replace(HTTP::FORM_DATA_COLON_SPACE, "")
  175. .replace("\r", "")
  176. .replace("\"", "");
  177. if (temp.contains(HTTP::FILENAME)) {
  178. const QByteArrayList tmp(temp.split(';'));
  179. for (int j = 0; j < tmp.size(); ++j) {
  180. QByteArrayList keyValue(tmp[j].split('='));
  181. if (keyValue.size() >= 2) {
  182. const QByteArray &key = keyValue[0];
  183. const QByteArray &value = keyValue[1];
  184. if (key.contains(HTTP::FILENAME)) {
  185. fileName = std::move(value);
  186. break;
  187. }
  188. }
  189. }
  190. }
  191. isContent = true;
  192. } else if (temp.contains(HTTP::CONTENT_TYPE)) {
  193. isContent = true;
  194. } else {
  195. if (temp.size() > 0) {
  196. char ch = temp.back();
  197. if (ch == '\r') {
  198. if (isContent) {
  199. isContent = false;
  200. // 开始 ?
  201. continue;
  202. }
  203. }
  204. }
  205. body += temp + "\n";
  206. }
  207. }
  208. if (!fileName.isEmpty()) {
  209. body.chop(2);
  210. files.insert(fileName, body);
  211. }
  212. }
  213. void HttpParser::doParse(QByteArray &httpMessage)
  214. {
  215. //qDebug() << httpMessage;
  216. if (extractHeaderAndBody(httpMessage)) {
  217. doParseHttpHeader(httpMessage);
  218. }
  219. }
  220. CWF_END_NAMESPACE