1 /****************************************************************************
3 ** Copyright (C) Qxt Foundation. Some rights reserved.
5 ** This file is part of the QxtWeb module of the Qt eXTension library
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
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.
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.
21 ** <http://libqxt.org> <foundation@libqxt.org>
23 ****************************************************************************/
24 #include "qxtfcgiconnector.h"
25 #include "qxtfcgiconnector_p.h"
28 #include <QTextStream>
29 #include "qxtstdstreambufdevice.h"
30 #include "qxtsignalwaiter.h"
33 QxtFcgiConnector::QxtFcgiConnector():QxtAbstractWebConnector()
35 qRegisterMetaType<server_t>("server_t");
36 qRegisterMetaTypeStreamOperators<server_t>("server_t");
37 QXT_INIT_PRIVATE(QxtFcgiConnector);
40 int QxtFcgiConnector::start (quint16 ,const QHostAddress & )
43 return QxtSignalWaiter::wait(&qxt_d(),SIGNAL(started()),20000);
47 QIODevice * QxtFcgiConnector::socket()
53 QByteArray QxtFcgiConnector::content(quint64 maxsize)
55 char * clenstr = FCGX_GetParam("CONTENT_LENGTH", qxt_d().request.envp);
56 quint64 clen = maxsize;
60 clen = strtol(clenstr, &clenstr, 10);
63 qDebug()<< "can't parse \"CONTENT_LENGTH="
64 << FCGX_GetParam("CONTENT_LENGTH", qxt_d().request.envp)
69 // *always* put a cap on the amount of data that will be read
70 if (clen > maxsize) clen = maxsize;
74 content.resize(clen+200);
75 std::cin.read(content.data(), clen+200);
77 clen = std::cin.gcount();
81 // *never* read stdin when CONTENT_LENGTH is missing or unparsable
85 // Chew up any remaining stdin - this shouldn't be necessary
86 // but is because mod_fastcgi doesn't handle it correctly.
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);
97 void QxtFcgiConnector::sendHeader(server_t & answer)
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";
104 server_t::const_iterator i = answer.constBegin();
105 while (i != answer.constEnd())
107 qxt_d().io->write(i.key()+": "+i.value()+"\r\n");
110 qxt_d().io->write("\r\n");
113 void QxtFcgiConnector::close()
115 emit(aboutToClose());
117 emit(qxt_d().close_ss());
121 /* ********** IMPL ***********/
124 QxtFcgiConnectorPrivate::QxtFcgiConnectorPrivate()
128 qRegisterMetaType<server_t>("server_t");
129 qRegisterMetaTypeStreamOperators<server_t>("server_t");
132 void QxtFcgiConnectorPrivate::run()
134 qRegisterMetaType<server_t>("server_t");
135 qRegisterMetaTypeStreamOperators<server_t>("server_t");
139 FCGX_InitRequest(&request, 0, 0);
141 ///FIXME: i just need a damn fd to use select() on. arrg
142 while (FCGX_Accept_r(&request) == 0)
145 fcgi_streambuf fio_in(request.in);
146 fcgi_streambuf fio_out(request.out);
147 fcgi_streambuf fio_err(request.err);
150 #if HAVE_IOSTREAM_WITHASSIGN_STREAMBUF
152 std::cout = &fio_out;
153 std::cerr = &fio_err;
155 std::cin.rdbuf(&fio_in);
156 std::cout.rdbuf(&fio_out);
157 std::cerr.rdbuf(&fio_err);
160 io= new QxtStdStreambufDevice (&fio_in,&fio_out);
163 const char * const * envp=request.envp;
164 for ( ; *envp; ++envp)
166 QByteArray ee(*envp);
167 SERVER[ee.left(ee.indexOf('='))]=ee.mid(ee.indexOf('=')+1);
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.
173 QxtSignalWaiter::wait(this,SIGNAL(close_ss()));