Ok, the long awaited config wizard is here (at least in a very basic state). There...
[quassel.git] / src / contrib / libqxt-2007-10-24 / src / web / qxtfcgiconnector.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) Qxt Foundation. Some rights reserved.
4 **
5 ** This file is part of the QxtWeb  module of the Qt eXTension library
6 **
7 ** This library is free software; you can redistribute it and/or modify it
8 ** under the terms of th Common Public License, version 1.0, as published by
9 ** IBM.
10 **
11 ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
12 ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
13 ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
14 ** FITNESS FOR A PARTICULAR PURPOSE.
15 **
16 ** You should have received a copy of the CPL along with this file.
17 ** See the LICENSE file and the cpl1.0.txt file included with the source
18 ** distribution for more information. If you did not receive a copy of the
19 ** license, contact the Qxt Foundation.
20 **
21 ** <http://libqxt.org>  <foundation@libqxt.org>
22 **
23 ****************************************************************************/
24 #include "qxtfcgiconnector.h"
25 #include "qxtfcgiconnector_p.h"
26 #include <QTcpSocket>
27 #include <QTcpServer>
28 #include <QTextStream>
29 #include "qxtstdstreambufdevice.h"
30 #include "qxtsignalwaiter.h"
31
32
33 QxtFcgiConnector::QxtFcgiConnector():QxtAbstractWebConnector()
34 {
35     qRegisterMetaType<server_t>("server_t");
36     qRegisterMetaTypeStreamOperators<server_t>("server_t");
37     QXT_INIT_PRIVATE(QxtFcgiConnector);
38 }
39
40 int QxtFcgiConnector::start (quint16 ,const QHostAddress & )
41 {
42     qxt_d().start();
43     return QxtSignalWaiter::wait(&qxt_d(),SIGNAL(started()),20000);
44
45 }
46
47 QIODevice * QxtFcgiConnector::socket()
48 {
49     return qxt_d().io;
50 }
51
52
53 QByteArray QxtFcgiConnector::content(quint64 maxsize)
54 {
55     char * clenstr = FCGX_GetParam("CONTENT_LENGTH", qxt_d().request.envp);
56     quint64 clen = maxsize;
57     QByteArray content;
58     if (clenstr)
59     {
60         clen = strtol(clenstr, &clenstr, 10);
61         if (*clenstr)
62         {
63             qDebug()<< "can't parse \"CONTENT_LENGTH="
64                  << FCGX_GetParam("CONTENT_LENGTH", qxt_d().request.envp)
65                  << "\"\n";
66             clen = maxsize;
67         }
68
69         // *always* put a cap on the amount of data that will be read
70         if (clen > maxsize) clen = maxsize;
71
72
73
74         content.resize(clen+200);
75         std::cin.read(content.data(), clen+200);
76
77         clen = std::cin.gcount();
78     }
79     else
80     {
81         // *never* read stdin when CONTENT_LENGTH is missing or unparsable
82         clen = 0;
83     }
84
85     // Chew up any remaining stdin - this shouldn't be necessary
86     // but is because mod_fastcgi doesn't handle it correctly.
87
88     // ignore() doesn't set the eof bit in some versions of glibc++
89     // so use gcount() instead of eof()...
90     do std::cin.ignore(1024); while (std::cin.gcount() == 1024);
91
92     return content;
93
94 }
95
96
97 void QxtFcgiConnector::sendHeader(server_t & answer)
98 {
99     if (!answer.contains("Status"))
100         answer["Status"]="200 OK";
101     if (!answer.contains("Content-Type"))
102         answer["Content-Type"]="text/html; charset=utf-8";
103
104     server_t::const_iterator i = answer.constBegin();
105     while (i != answer.constEnd())
106     {
107         qxt_d().io->write(i.key()+": "+i.value()+"\r\n");
108         ++i;
109     }
110     qxt_d().io->write("\r\n");
111 }
112
113 void  QxtFcgiConnector::close()
114 {
115     emit(aboutToClose());
116     qxt_d().open=false;
117     emit(qxt_d().close_ss());
118 }
119
120
121 /* ********** IMPL ***********/
122
123
124 QxtFcgiConnectorPrivate::QxtFcgiConnectorPrivate()
125 {
126     open=false;
127     io=0;
128     qRegisterMetaType<server_t>("server_t");
129     qRegisterMetaTypeStreamOperators<server_t>("server_t");
130 }
131
132 void QxtFcgiConnectorPrivate::run()
133 {
134     qRegisterMetaType<server_t>("server_t");
135     qRegisterMetaTypeStreamOperators<server_t>("server_t");
136
137     
138     FCGX_Init();
139     FCGX_InitRequest(&request, 0, 0);
140
141     ///FIXME: i just need a damn fd to use select() on. arrg
142     while (FCGX_Accept_r(&request) == 0)
143     {
144         open=true;
145         fcgi_streambuf   fio_in(request.in);
146         fcgi_streambuf   fio_out(request.out);
147         fcgi_streambuf   fio_err(request.err);
148
149
150 #if HAVE_IOSTREAM_WITHASSIGN_STREAMBUF
151         std::cin  = &fio_in;
152         std::cout = &fio_out;
153         std::cerr = &fio_err;
154 #else
155         std::cin.rdbuf(&fio_in);
156         std::cout.rdbuf(&fio_out);
157         std::cerr.rdbuf(&fio_err);
158 #endif
159
160         io= new QxtStdStreambufDevice (&fio_in,&fio_out);
161
162         server_t SERVER;
163         const char * const * envp=request.envp;
164         for ( ; *envp; ++envp)
165         {
166             QByteArray ee(*envp);
167             SERVER[ee.left(ee.indexOf('='))]=ee.mid(ee.indexOf('=')+1);
168         }
169         emit(qxt_p().incomming(SERVER));
170         /// heck this is a frikin waste of RAM, cpu and my nerves.
171         /// I hope those arrogants retards burn in hell for it.
172         if (open)
173             QxtSignalWaiter::wait(this,SIGNAL(close_ss()));
174         open=false;
175         delete(io);
176         io=0;
177
178     }
179 }
180
181
182
183
184
185
186
187
188
189