00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00028 #include <stdlib.h>
00029 #include <qhttp.h>
00030 #include <qstringlist.h>
00031 #include <qfileinfo.h>
00032 #include <qstring.h>
00033 #include <qhostaddress.h>
00034 #include <klocale.h>
00035
00036 #include "wshttpserver.h"
00037
00038 WSHttpServer::WSHttpServer( QObject* parent)
00039 : QServerSocket(Config().WWW.Port, 1, parent)
00040 {
00041 if(ok())
00042 {
00043 emit message(i18n("Web server started on port: %1").arg(Config().WWW.Port));
00044 }
00045 else
00046 {
00047 QString error = i18n("Could not initialize webserver. Construction failed on port ");
00048 error += QString::number(Config().WWW.Port);
00049 error += ".";
00050
00051 emit message(error);
00052 emit message(error, Configuration::Debug);
00053 }
00054 }
00055
00056 WSHttpServer::~WSHttpServer()
00057 {
00058 }
00059
00060 void WSHttpServer::newConnection( int socket )
00061 {
00062 QSocket* s = new QSocket( this );
00063 connect( s, SIGNAL(readyRead()), this, SLOT(readClient()) );
00064 connect( s, SIGNAL(delayedCloseFinished()), this, SLOT(discardClient()) );
00065 connect( s, SIGNAL(connectionClosed()), this, SLOT(closeClient()) );
00066 connect( s, SIGNAL(error(int)), this, SLOT(onError(int)) );
00067 s->setSocket( socket );
00068
00069 emit message((s->peerAddress()).toString() + i18n(" connected."));
00070
00071 emit newConnect();
00072 }
00073
00074 void WSHttpServer::readClient()
00075 {
00076 QSocket* socket = (QSocket*)sender();
00077 QString header_line = "";
00078 while( socket->canReadLine() )
00079 {
00080 header_line.append(socket->readLine());
00081 }
00082
00083 QHttpRequestHeader this_header( header_line );
00084 if (this_header.method() == "GET" )
00085 {
00086 QString fn = this_header.path();
00087
00088 emit message((socket->peerAddress()).toString() + i18n(" requested: ") + fn + ".");
00089
00090 fn = fn.right(fn.length() - 1);
00091 QString path = getFilePath(fn);
00092 if(!path.isEmpty())
00093 {
00094 QFile f(path);
00095 if(f.open(IO_ReadOnly))
00096 {
00097 QByteArray data = f.readAll();
00098
00099 QHttpResponseHeader head;
00100 sendHttpResponse(socket, 200, "Ok", head, data);
00101 f.close();
00102 }
00103 else
00104 {
00105 sendHttpError(socket, 400, "Bad Request", "<h1>The server could not handle your request.</h1>");
00106 }
00107 }
00108 else
00109 {
00110 sendHttpError(socket, 404, "File Not Found", "<h1>The file does not exist.</h1>");
00111 }
00112 }
00113 else
00114 {
00115
00116 sendHttpError(socket, 405, "Method Not Allowed", "This is a minimal server. I only accept GET");
00117 }
00118
00119 socket->close();
00120 if(socket->state() == QSocket::Idle)
00121 {
00122 emit message((socket->peerAddress()).toString() + i18n(" disconnected."));
00123 socket->deleteLater();
00124 emit endConnect();
00125 }
00126 }
00127
00128 QString WSHttpServer::getFilePath(const QString& filename)
00129 {
00130 QStringList files = Config().WWW.Files;
00131
00132 QString ret = "";
00133
00134 for ( QStringList::Iterator it = files.begin(); it != files.end(); ++it )
00135 {
00136 QFileInfo fi(*it);
00137 if(filename == fi.fileName())
00138 {
00139 ret = *it;
00140 break;
00141 }
00142 }
00143
00144 return ret;
00145 }
00146
00147 void WSHttpServer::discardClient()
00148 {
00149 QSocket* socket = (QSocket*)sender();
00150
00151 emit message((socket->peerAddress()).toString() + i18n(" disconnected."));
00152
00153 delete socket;
00154 emit endConnect();
00155 }
00156
00157 void WSHttpServer::closeClient()
00158 {
00159 QSocket* socket = (QSocket*)sender();
00160 socket->flush();
00161 socket->close();
00162 if(socket->state() == QSocket::Idle)
00163 {
00164 emit message((socket->peerAddress()).toString() + i18n(" disconnected."));
00165 delete socket;
00166 emit endConnect();
00167 }
00168 }
00169
00170 void WSHttpServer::onError(int errno)
00171 {
00172 QSocket* socket = (QSocket*)sender();
00173 if(errno == QSocket::ErrConnectionRefused)
00174 {
00175 emit message((socket->peerAddress()).toString() + i18n(": connection refused."));
00176 }
00177 else if(QSocket::ErrHostNotFound)
00178 {
00179 emit message((socket->peerAddress()).toString() + i18n(": host not found."));
00180 }
00181 else
00182 {
00183 emit message((socket->peerAddress()).toString() + i18n(": read failed."));
00184 }
00185
00186 socket->flush();
00187 socket->close();
00188 if(socket->state() == QSocket::Idle)
00189 {
00190 emit message((socket->peerAddress()).toString() + i18n(" disconnected."));
00191 delete socket;
00192 emit endConnect();
00193 }
00194 }
00195
00196 void WSHttpServer::sendHttpError(QSocket* s, int error_code, const QString& reason, const QString data)
00197 {
00198 QHttpResponseHeader head;
00199 sendHttpResponse(s, error_code, reason, head, data);
00200 }
00201
00202 void WSHttpServer::sendHttpResponse(QSocket* s, int status_code, const QString& reason, QHttpHeader& headers, QString resp)
00203 {
00204
00205 QByteArray output;
00206 QTextStream ts_resp( output, IO_WriteOnly );
00207 ts_resp.setEncoding( QTextStream::UnicodeUTF8 );
00208 ts_resp << resp;
00209 headers.setValue("Content-Type", "text/html; charset=\"utf-8\"");
00210 headers.setValue("Connection","close");
00211 sendHttpResponse(s, status_code, reason, headers, output);
00212 }
00213
00214 void WSHttpServer::sendHttpResponse(QSocket* s, int status_code, const QString& reason, QHttpHeader& headers, QByteArray output)
00215 {
00216 int output_length = output.size();
00217 if((output_length > 256) && (headers.value("Accept-Encoding") == "deflate"))
00218 {
00219 headers.setValue("Content-Encoding","deflate");
00220 QByteArray compressed_output = qCompress(output);
00221 output_length = compressed_output.size();
00222 output = compressed_output;
00223 }
00224
00225 headers.setContentLength(output_length);
00226
00227
00228 QByteArray head_out;
00229 QTextStream header_resp(head_out, IO_WriteOnly);
00230 header_resp << "HTTP/1.1 " << status_code << " " << reason << "\r\n";
00231 QStringList::const_iterator sit;
00232 QStringList keys = headers.keys();
00233 for( sit = keys.begin(); sit != keys.end(); sit++)
00234 {
00235 header_resp << (*sit) << ": " << headers.value( *sit ) << "\r\n";
00236 }
00237 header_resp << "\r\n";
00238
00239
00240 int header_length = head_out.size();
00241 int tmp = 0;
00242 tmp += s->writeBlock(head_out.data(), header_length);
00243
00244
00245 tmp = 0;
00246 tmp += s->writeBlock(output.data(), output_length);
00247
00248 QString msg = (s->peerAddress()).toString();
00249 msg += ": " + QString::number(status_code) + " - " + reason + ".";
00250
00251 emit message( msg );
00252 emit wroteToClient();
00253 }