Permalink
Browse files

the CGI plugin now:

 * properly parses the CGI response
 * passes HTTP_COOKIES, SCRIPT_FILENAME, SCRIPT_NAME to the CGI script
 * allows for an "index" file that gets invoked automatically when no other file
 * is specified
 * properly serves static files via internal redirects

TODO:
 * code is messy
 * in complex setups the scrips may be invoked with wrong parameters
 * the "index" file functionality is based on the assumption that urlParts[1]
 * always contains the directory where the app is located
  • Loading branch information...
1 parent 1ec70a2 commit bff0efcad5a16e242a7f96ca6c06cb698a9d9839 @paulbarbu committed May 10, 2014
@@ -1,6 +1,7 @@
#include <QDebug>
#include <QProcess>
#include <QFileInfo>
+#include <QDir>
#include "cgihttprequesthandler.h"
#include "cgiresponseparser.h"
@@ -20,7 +21,6 @@ CgiHTTPRequestHandler::CgiHTTPRequestHandler(const QHash<QString, QVariant> &s)
void CgiHTTPRequestHandler::createResponse(const HTTPRequest &requestData)
{
//TODO: on some setups the plugins blocks on process.waitForFinished
- //TODO: correctly parse CGI output
// http://127.0.0.1:8282/cgi/info.php/asd
// => SCRIPT_FILENAME cgi-bin-dir + /info.php/
@@ -57,7 +57,7 @@ void CgiHTTPRequestHandler::createResponse(const HTTPRequest &requestData)
qDebug() << settings;
- QFileInfo info(settings.value("cgi-dir", "").toString());
+ QFileInfo info(settings["docroot"].toString() + settings["cgi-dir"].toString());
if(!info.isReadable() || !info.isDir()){
response.setStatusCode(500);
@@ -71,27 +71,64 @@ void CgiHTTPRequestHandler::createResponse(const HTTPRequest &requestData)
}
int extPos = urlParts[1].indexOf(".");
+ slashPos = urlParts[1].indexOf('/', extPos);
+
+ QString extension;
if(-1 == extPos){
- response.setStatusCode(404);
- response.setReasonPhrase("Not Found");
+ qDebug() << "urlpatrs" <<urlParts[1];
+ bool found = false;
+ //TODO: this should be modified to check more directory levels, not just two
+ QDir cgiDir(info.filePath() + urlParts[1]);
+ QStringList files = cgiDir.entryList(QDir::Files); //TODO: cgi/wp
+
+ //TODO: this is ugly, but (for now) I have no way of knowing which one is an extension
+ foreach(QString key, settings.keys()){
+ if(files.contains(settings["index-filename"].toString() + "." + key)){
+ found = true;
+ extension = key;
+ urlParts[1] += "/" + settings["index-filename"].toString() + "." + key;
+ break;
+ }
+ }
- emit responseWritten(response);
- emit endOfWriting();
- return;
+ if(!found){
+ response.setStatusCode(404);
+ response.setReasonPhrase("Not Found");
+
+ emit responseWritten(response);
+ emit endOfWriting();
+ return;
+ }
+ }
+ else{
+ extension = urlParts[1].mid(extPos+1, slashPos-extPos-1);
+ qDebug() << "Extension:" << extension;
+ if(!settings.contains(extension)){
+ response.setStatusCode(404);
+ response.setReasonPhrase("Not Found");
+
+ emit responseWritten(response);
+ emit endOfWriting();
+ return;
+ }
}
- slashPos = urlParts[1].indexOf('/', extPos);
+ QString path = settings[extension].toString();
- QString extension(urlParts[1].mid(extPos+1, slashPos-extPos-1));
+ if("*" == path){
+ //TODO: this is ruined now
+ path = settings["docroot"].toString() + settings["cgi-dir"].toString() + urlParts[1];
+ }
+ else if("static_file" == path){
+ qDebug() << "STATIC_FILE IN CGI:" << extension;
- qDebug() << "Extension:" << extension;
- if(!settings.contains(extension)){
- response.setStatusCode(404);
- response.setReasonPhrase("Not Found");
+ HTTPRequest r = requestData;
+ QString newPath = r.url.path();
+ newPath.replace(settings.value("virtual-cgi-dir", "").toString(), "/" + settings.value("cgi-dir", "").toString());
- emit responseWritten(response);
- emit endOfWriting();
+ r.url.setPath(newPath);
+ emit redirect(r);
return;
}
@@ -102,13 +139,7 @@ void CgiHTTPRequestHandler::createResponse(const HTTPRequest &requestData)
QProcess process;
process.setProcessEnvironment(env);
- process.setWorkingDirectory(settings["cgi-dir"].toString());
-
- QString path = settings[extension].toString();
-
- if("*" == path){
- path = settings["cgi-dir"].toString() + urlParts[1];
- }
+ process.setWorkingDirectory(settings["docroot"].toString() + settings["cgi-dir"].toString());
qDebug() << "Starting process:" << path;
process.start(path);
@@ -197,14 +228,14 @@ void CgiHTTPRequestHandler::setEnvironment(const HTTPRequest &requestData)
env.insert("REDIRECT_STATUS", "200");
//absolute path to the script
- env.insert("SCRIPT_FILENAME", settings["cgi-dir"].toString() + urlParts[1]);
- qDebug() << "SCRIPT_FILENAME" << settings["cgi-dir"].toString() + urlParts[1];
+ env.insert("SCRIPT_FILENAME", settings["docroot"].toString() + settings["cgi-dir"].toString() + urlParts[1]);
+ qDebug() << "SCRIPT_FILENAME" << settings["docroot"].toString() + settings["cgi-dir"].toString() + urlParts[1];
env.insert("SCRIPT_NAME", requestData.url.path());
qDebug() << "SCRIPT_NAME" << requestData.url.path();
- env.insert("PATH_INFO", pathInfo);
- qDebug() << "PATH_INFO" << pathInfo;
+ env.insert("PATH_INFO", "");//pathInfo);
+ qDebug() << "PATH_INFO" << "";//pathInfo;
env.insert("REQUEST_METHOD", requestData.method);
qDebug() << "REQUEST_METHOD" << requestData.method;
@@ -218,6 +249,9 @@ void CgiHTTPRequestHandler::setEnvironment(const HTTPRequest &requestData)
env.insert("SERVER_NAME", requestData.host.toString());
qDebug() << "SERVER_NAME" << requestData.host.toString();
+ env.insert("HTTP_HOST", requestData.host.toString() + ":" + QString::number(requestData.port));
+ qDebug() << "HTTP_HOST" << requestData.host.toString() + ":" + QString::number(requestData.port);
+
env.insert("SERVER_PROTOCOL", requestData.protocol + "/" + QString::number(requestData.protocolVersion));
qDebug() << "SERVER_PROTOCOL:" << QString(requestData.protocol + "/" + QString::number(requestData.protocolVersion));
@@ -247,4 +281,12 @@ void CgiHTTPRequestHandler::setEnvironment(const HTTPRequest &requestData)
env.insert("CONTENT_TYPE", requestData.contentType);
qDebug() << "CONTENT_TYPE" << requestData.contentType;
}
+
+ QString cookies;
+ foreach(QNetworkCookie c, requestData.cookieJar){
+ cookies += c.toRawForm(QNetworkCookie::NameAndValueOnly) + ";";
+ }
+
+ env.insert("HTTP_COOKIE", cookies);
+ qDebug() << "HTTP_COOKIE" << cookies;
}
@@ -4,7 +4,6 @@
#include <QProcessEnvironment>
#include "httprequesthandler.h"
-#include "cgiresponse.h"
class CgiHTTPRequestHandler : public HTTPRequestHandler
{
@@ -17,7 +16,7 @@ class CgiHTTPRequestHandler : public HTTPRequestHandler
QString pathInfo;
QStringList urlParts;
- CgiResponse response;
+ HTTPResponse response;
int timeout;
QProcessEnvironment env;
};
View
@@ -15,13 +15,11 @@ DEFINES += CGIPLUGIN_LIBRARY
SOURCES += cgiplugin.cpp \
cgiresponseparser.cpp \
- cgiresponse.cpp \
cgihttprequesthandler.cpp
HEADERS += cgiplugin.h\
cgiplugin_global.h \
cgiresponseparser.h \
- cgiresponse.h \
cgihttprequesthandler.h
QMAKE_CXXFLAGS += -std=c++11
View
@@ -1,47 +0,0 @@
-#include <QMultiHash>
-
-#include "cgiresponse.h"
-
-void CgiResponse::setCgiField(const QString &key, const QString &value)
-{
- cgiFields.insert(key, value);
-}
-
-QByteArray CgiResponse::get() const
-{
- QByteArray statusCode = getStatusCode();
- QByteArray reasonPhrase = getReasonPhrase();
- QMultiHash<QByteArray, QByteArray> fields = getFields();
- QByteArray body = getBody();
-
- if("" == statusCode || "" == reasonPhrase){
- return "";
- }
-
- QByteArray r = "HTTP/1.0 " + statusCode + " " + reasonPhrase + "\r\n";
-
- QMultiHash<QByteArray, QByteArray>::const_iterator i;
- for(i = fields.constBegin(); i != fields.constEnd(); ++i){
- r += i.key() + ": " + i.value() + "\r\n";
- }
-
- QHash<QString, QString>::const_iterator j;
- for(j = cgiFields.constBegin(); j != cgiFields.constEnd(); ++j){
- r += i.key() + ": " + i.value() + "\r\n";
- }
-
- r += "\r\n" + body;
-
- return r;
-}
-
-QByteArray CgiResponse::getPartial()
-{
- return get();
-}
-
-void CgiResponse::clear()
-{
- HTTPResponse::clear();
- cgiFields.clear();
-}
View
@@ -1,22 +0,0 @@
-#ifndef CGIRESPONSE_H
-#define CGIRESPONSE_H
-
-#include <QHash>
-
-#include "httpresponse.h"
-
-class CgiResponse : public HTTPResponse
-{
-public:
- explicit CgiResponse() : HTTPResponse() {}
- void setCgiField(const QString &key, const QString &value);
-
- QByteArray get() const;
- QByteArray getPartial();
-
- void clear();
-private:
- QHash<QString, QString> cgiFields;
-};
-
-#endif // CGIRESPONSE_H
@@ -22,21 +22,43 @@ bool CgiResponseParser::parse()
}
}
+
response.setStatusCode(200);
response.setReasonPhrase("OK");
QByteArray headers = rawResponse.left(pos);
if(!parseHeaders(headers)){
- qDebug() << "Cannot parse the header";
- return false;
+ if("\n\n" == headBodySep){
+ headBodySep = "\r\n\r\n";
+ }
+ else{
+ headBodySep = "\n\n";
+ }
+
+ pos = rawResponse.indexOf(headBodySep);
+
+ if(-1 == pos){
+ qDebug() << "No separator between header and body";
+ return false;
+ }
+
+ response.clear();
+
+ response.setStatusCode(200);
+ response.setReasonPhrase("OK");
+ headers = rawResponse.left(pos);
+ if(!parseHeaders(headers)){
+ qDebug() << "Cannot parse the header";
+ return false;
+ }
}
response.setBody(rawResponse.right(rawResponse.size() - pos - headBodySep.size()));
return true;
}
-CgiResponse CgiResponseParser::getResponse() const
+HTTPResponse CgiResponseParser::getResponse() const
{
return response;
}
@@ -73,10 +95,6 @@ bool CgiResponseParser::parseHeaders(const QByteArray &headers)
return false;
}
}
- else if("Location" == key){
- //TODO: implement redirects
- response.setCgiField(key, value);
- }
else{
response.setHeaderField(key, value);
}
@@ -2,21 +2,20 @@
#define CGIRESPONSEPARSER_H
#include <QByteArray>
-
-#include "cgiresponse.h"
+#include "httpresponse.h"
class CgiResponseParser
{
public:
- CgiResponseParser(const QByteArray &r) : rawResponse(r) {};
+ CgiResponseParser(const QByteArray &r) : rawResponse(r) {}
bool parse();
- CgiResponse getResponse() const;
+ HTTPResponse getResponse() const;
private:
bool parseHeaders(const QByteArray &headers);
bool parseStatus(const QString &statusLine);
QByteArray rawResponse;
- CgiResponse response;
+ HTTPResponse response;
};
#endif // CGIRESPONSEPARSER_H

0 comments on commit bff0efc

Please sign in to comment.