diff options
Diffstat (limited to 'plugins/webinterface/httpclienthandler.cpp')
-rw-r--r-- | plugins/webinterface/httpclienthandler.cpp | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/plugins/webinterface/httpclienthandler.cpp b/plugins/webinterface/httpclienthandler.cpp new file mode 100644 index 0000000..d925466 --- /dev/null +++ b/plugins/webinterface/httpclienthandler.cpp @@ -0,0 +1,237 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@gmail.com * + * * + * 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. * + ***************************************************************************/ +#include <qsocket.h> +#include <qhttp.h> +#include <util/log.h> +#include <util/mmapfile.h> +#include "httpserver.h" +#include "httpclienthandler.h" +#include "httpresponseheader.h" +#include "php_handler.h" + +using namespace bt; + +namespace kt +{ + + HttpClientHandler::HttpClientHandler(HttpServer* srv,QSocket* sock) : srv(srv),client(sock),php_response_hdr(200) + { + state = WAITING_FOR_REQUEST; + bytes_read = 0; + php = 0; + } + + + HttpClientHandler::~HttpClientHandler() + { + delete client; + delete php; + } + + void HttpClientHandler::readyToRead() + { + if (state == WAITING_FOR_REQUEST) + { + while (client->canReadLine()) + { + QString line = client->readLine(); + header_data += line; + if (header_data.endsWith("\r\n\r\n")) + { + // We have got the header, so lets parse it + handleRequest(); + break; + } + } + } + else if (state == WAITING_FOR_CONTENT) + { + Uint32 ba = client->bytesAvailable(); + if (ba + bytes_read < header.contentLength()) + { + client->readBlock((char*)request_data.data() + bytes_read,ba); + bytes_read += ba; + } + else + { + Uint32 left = header.contentLength() - bytes_read; + client->readBlock((char*)request_data.data() + bytes_read,left); + bytes_read += left; + srv->handlePost(this,header,request_data); + + header_data = ""; + request_data.resize(0); + state = WAITING_FOR_REQUEST; + if (client->bytesAvailable() > 0) + readyToRead(); + } + } + } + + void HttpClientHandler::handleRequest() + { + header = QHttpRequestHeader(header_data); + // Out(SYS_WEB|LOG_DEBUG) << "Parsing request : " << header.toString() << endl; + if (header.method() == "POST") + { + if (header.hasContentLength()) + { + request_data.resize(header.contentLength()); + state = WAITING_FOR_CONTENT; + bytes_read = 0; + if (client->bytesAvailable() > 0) + readyToRead(); + } + } + else if (header.method() == "GET") + { + srv->handleGet(this,header); + header_data = ""; + request_data.resize(0); + } + else + { + srv->handleUnsupportedMethod(this); + } + } + + bool HttpClientHandler::sendFile(HttpResponseHeader & hdr,const QString & full_path) + { + // Out(SYS_WEB|LOG_DEBUG) << "Sending file " << full_path << endl; + // first look in cache + MMapFile* c = srv->cacheLookup(full_path); + + if (!c) + { + // not in cache so load it + c = new MMapFile(); + if (!c->open(full_path,MMapFile::READ)) + { + delete c; + Out(SYS_WEB|LOG_DEBUG) << "Failed to open file " << full_path << endl; + return false; + } + srv->insertIntoCache(full_path,c); + } + + hdr.setValue("Content-Length",QString::number(c->getSize())); + + // Out(SYS_WEB|LOG_DEBUG) << "HTTP header : " << endl; + // Out(SYS_WEB|LOG_DEBUG) << hdr.toString() << endl; + + QCString d = hdr.toString().utf8(); + client->writeBlock(d.data(),d.length()); + + Uint32 written = 0; + Uint32 total = c->getSize(); + const char* data = (const char*)c->getDataPointer(); + while (written < total) + { + Uint32 w = client->writeBlock(data + written,total - written); + written += w; + } + client->flush(); + // Out(SYS_WEB|LOG_DEBUG) << "Finished sending " << full_path << " (" << written << " bytes)" << endl; + return true; + } + +#define HTTP_404_ERROR "<html><head><title>404 Not Found</title></head><body>The requested file was not found !</body></html>" +#define HTTP_500_ERROR "<html><head><title>HTTP/1.1 500 Internal Server Error</title></head><body>HTTP/1.1 Internal Server Error<br>%1</body></html>" + + + void HttpClientHandler::send404(HttpResponseHeader & hdr,const QString & path) + { + // Out(SYS_WEB|LOG_DEBUG) << "Sending 404 " << path << endl; + QString data = HTTP_404_ERROR; + hdr.setValue("Content-Length",QString::number(data.length())); + + QTextStream os(client); + os.setEncoding( QTextStream::UnicodeUTF8 ); + os << hdr.toString(); + os << data; + } + + void HttpClientHandler::send500(HttpResponseHeader & hdr) + { + // Out(SYS_WEB|LOG_DEBUG) << "Sending 500 " << endl; + QString data = QString(HTTP_500_ERROR).arg("An internal server error occured !"); + hdr.setValue("Content-Length",QString::number(data.length())); + + QTextStream os(client); + os.setEncoding( QTextStream::UnicodeUTF8 ); + os << hdr.toString(); + os << data; + } + + void HttpClientHandler::sendResponse(const HttpResponseHeader & hdr) + { + // Out(SYS_WEB|LOG_DEBUG) << "Sending response " << hdr.toString() << endl; + QTextStream os(client); + os.setEncoding( QTextStream::UnicodeUTF8 ); + os << hdr.toString(); + } + + void HttpClientHandler::executePHPScript( + PhpInterface* php_iface, + HttpResponseHeader & hdr, + const QString & php_exe, + const QString & php_file, + const QMap<QString,QString> & args) + { + // Out(SYS_WEB|LOG_DEBUG) << "Launching PHP script " << php_file << endl; + php = new PhpHandler(php_exe,php_iface); + if (!php->executeScript(php_file,args)) + { + QString data = QString(HTTP_500_ERROR).arg("Failed to launch PHP executable !"); + hdr.setResponseCode(500); + hdr.setValue("Content-Length",QString::number(data.utf8().length())); + + QTextStream os(client); + os.setEncoding( QTextStream::UnicodeUTF8 ); + os << hdr.toString(); + os << data; + state = WAITING_FOR_REQUEST; + } + else + { + php_response_hdr = hdr; + connect(php,SIGNAL(finished()),this,SLOT(onPHPFinished())); + state = PROCESSING_PHP; + } + } + + void HttpClientHandler::onPHPFinished() + { + const QByteArray & output = php->getOutput(); + php_response_hdr.setValue("Content-Length",QString::number(output.size())); + + QTextStream os(client); + os.setEncoding( QTextStream::UnicodeUTF8 ); + os << php_response_hdr.toString(); + os.writeRawBytes(output.data(),output.size()); + + php->deleteLater(); + php = 0; + state = WAITING_FOR_REQUEST; + } +} + +#include "httpclienthandler.moc" + |