/thirdparty/qxt/qxtweb-standalone/qxtweb/qxtscgiserverconnector.cpp

http://github.com/tomahawk-player/tomahawk · C++ · 191 lines · 106 code · 27 blank · 58 comment · 12 complexity · 0eff8a466b12d20b66de86bc98eba680 MD5 · raw file

  1. /****************************************************************************
  2. **
  3. ** Copyright (C) Qxt Foundation. Some rights reserved.
  4. **
  5. ** This file is part of the QxtWeb module of the Qxt library.
  6. **
  7. ** This library is free software; you can redistribute it and/or modify it
  8. ** under the terms of the Common Public License, version 1.0, as published
  9. ** by IBM, and/or under the terms of the GNU Lesser General Public License,
  10. ** version 2.1, as published by the Free Software Foundation.
  11. **
  12. ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
  13. ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
  14. ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
  15. ** FITNESS FOR A PARTICULAR PURPOSE.
  16. **
  17. ** You should have received a copy of the CPL and the LGPL along with this
  18. ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files
  19. ** included with the source distribution for more information.
  20. ** If you did not receive a copy of the licenses, contact the Qxt Foundation.
  21. **
  22. ** <http://libqxt.org> <foundation@libqxt.org>
  23. **
  24. ****************************************************************************/
  25. /*!
  26. \class QxtScgiServerConnector
  27. \inmodule QxtWeb
  28. \brief The QxtScgiServerConnector class provides an SCGI connector for QxtHttpSessionManager
  29. QxtScgiServerConnector implements the SCGI protocoll supported by almost all modern web servers.
  30. \sa QxtHttpSessionManager
  31. */
  32. #include "qxthttpsessionmanager.h"
  33. #include "qxtwebevent.h"
  34. #include <QTcpServer>
  35. #include <QHash>
  36. #include <QTcpSocket>
  37. #include <QString>
  38. #ifndef QXT_DOXYGEN_RUN
  39. class QxtScgiServerConnectorPrivate : public QxtPrivate<QxtScgiServerConnector>
  40. {
  41. public:
  42. QTcpServer* server;
  43. };
  44. #endif
  45. /*!
  46. * Creates a QxtHttpServerConnector with the given \a parent.
  47. */
  48. QxtScgiServerConnector::QxtScgiServerConnector(QObject* parent) : QxtAbstractHttpConnector(parent)
  49. {
  50. QXT_INIT_PRIVATE(QxtScgiServerConnector);
  51. qxt_d().server = new QTcpServer(this);
  52. QObject::connect(qxt_d().server, SIGNAL(newConnection()), this, SLOT(acceptConnection()));
  53. }
  54. /*!
  55. * \reimp
  56. */
  57. bool QxtScgiServerConnector::listen(const QHostAddress& iface, quint16 port)
  58. {
  59. return qxt_d().server->listen(iface, port);
  60. }
  61. /*!
  62. * \internal
  63. */
  64. void QxtScgiServerConnector::acceptConnection()
  65. {
  66. QTcpSocket* socket = qxt_d().server->nextPendingConnection();
  67. addConnection(socket);
  68. }
  69. /*!
  70. * \reimp
  71. */
  72. bool QxtScgiServerConnector::canParseRequest(const QByteArray& buffer)
  73. {
  74. if (buffer.size() < 10)
  75. return false;
  76. QString expectedsize;
  77. for (int i = 0;i < 10;i++)
  78. {
  79. if (buffer.at(i) == ':')
  80. {
  81. break;
  82. }
  83. else
  84. {
  85. expectedsize += buffer.at(i);
  86. }
  87. }
  88. if (expectedsize.isEmpty())
  89. {
  90. //protocoll error
  91. return false;
  92. }
  93. return (buffer.size() > expectedsize.toInt());
  94. }
  95. /*!
  96. * \reimp
  97. */
  98. QHttpRequestHeader QxtScgiServerConnector::parseRequest(QByteArray& buffer)
  99. {
  100. QString expectedsize_s;
  101. for (int i = 0;i < 20;i++)
  102. {
  103. if (buffer.at(i) == ':')
  104. {
  105. break;
  106. }
  107. else
  108. {
  109. expectedsize_s += buffer.at(i);
  110. }
  111. }
  112. if (expectedsize_s.isEmpty())
  113. {
  114. //protocoll error
  115. return QHttpRequestHeader();
  116. }
  117. buffer = buffer.right(buffer.size() - (expectedsize_s.count() + 1));
  118. QHttpRequestHeader request_m;
  119. QByteArray name;
  120. int i = 0;
  121. while ((i = buffer.indexOf('\0')) > -1)
  122. {
  123. if (name.isEmpty())
  124. {
  125. name = buffer.left(i);
  126. }
  127. else
  128. {
  129. request_m.setValue(QString::fromAscii(name).toLower(), QString::fromAscii(buffer.left(i)));
  130. name = "";
  131. }
  132. buffer = buffer.mid(i + 1);
  133. }
  134. request_m.setRequest(request_m.value("request_method"), request_m.value("request_uri"), 1, 0);
  135. foreach(const QString& key, request_m.keys())
  136. {
  137. if (key.startsWith(QString("http_")))
  138. {
  139. request_m.setValue(key.right(key.size() - 5), request_m.value(key));
  140. }
  141. }
  142. request_m.setValue("Connection", "close");
  143. buffer.chop(1);
  144. return request_m;
  145. }
  146. /*!
  147. * \reimp
  148. */
  149. void QxtScgiServerConnector::writeHeaders(QIODevice* device, const QHttpResponseHeader& response_m)
  150. {
  151. device->write(("Status:" + QString::number(response_m.statusCode()) + ' ' + response_m.reasonPhrase() + "\r\n").toAscii());
  152. foreach(const QString& key, response_m.keys())
  153. {
  154. device->write((key + ':' + response_m.value(key) + "\r\n").toAscii());
  155. }
  156. device->write("\r\n");
  157. }