Main Page | Class List | File List | Class Members | File Members | Related Pages

wshttpserver.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005 by Bojan D.                                        *
00003  *   bojan_d@users.sourceforge.net                                         *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
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                 //MUST be GET:
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         // the output
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         //This is the headers:
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         //Write the headers out:
00240         int header_length = head_out.size();
00241         int tmp = 0;
00242         tmp += s->writeBlock(head_out.data(), header_length);
00243                                 
00244         //Write the body out:
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 }

Generated on Mon Sep 5 12:52:34 2005 for kwebsnap.kdevelop by  doxygen 1.3.9.1