POST:20
Content-Type::49
Content-Length::20
Blank
16 bytes
Headers done
input1=&input2=x
input1 =>
input2 => x
POST:20
Content-Type::49
Content-Length::20
Blank
16 bytes
Headers done
input1=&input2=x
input1 =>
input2 => x
To copy to clipboard, switch view to plain text mode
POST:20
Pragma::18
Cache-control::25
Content-Type::49
Headers done
=>
POST:20
Pragma::18
Cache-control::25
Content-Type::49
Headers done
=>
To copy to clipboard, switch view to plain text mode
Note that there is a Content-Type header but not a Content-length. What's going on here? Notice that no blank header-ending line is present either.
HTTPInterface
:: HTTPInterface (QString pass,
unsigned int port,
QObject * p
) password = pass;
if (!pass.size()) {_ok=false;return;}
connect(this,SIGNAL(newConnection()),
this,SLOT(incoming()) );
}
bool HTTPInterface :: ok () const {return _ok;}
void HTTPInterface :: incoming () {
while (QTcpSocket * connection
= nextPendingConnection
()) { new HTTPRequest (connection);
}
}
connect(s,SIGNAL(readyRead()),
this,SLOT(respond()) );
}
HTTPRequest :: ~HTTPRequest () {
qWarning ("~HTTPRequest");
}
namespace {
QString title
= "Remote Administration";
"<h1>"+title+"</h1>\n"
"<h2><a href=\"" + page + "\">" + page + "</a></h2>\n";
"\n<style type=\"text/css\">\n"
"h1 {\n"
"\tcolor: red;\n"
"}\n"
"</style>\n\n";
QRegExp header_space
("[\\s\\n\\r]+");
QRegExp post_var
("([^=]+)=([^&]*)");
};
void HTTPRequest :: respond () {
while (socket->canReadLine()) {
// Headers end with a blank line.
if (anything.indexIn(l) < 0) {
qWarning("Blank");
// If there's non-header content, read it.
if (headers.contains("Content-Length:")) {
l = headers["Content-Length:"][1];
content = socket -> read(l.toLong());
qWarning
(QString("%1 bytes").
arg(l.
toLong()) .toAscii());
}
continue;
}
// Save each header, indexed by the "FOO:" prefix.
headers[tokens[0]] = tokens;
}
.arg(tokens[0]).arg(l.size()).toAscii() );
}
qWarning("Headers done\n");
out << "HTTP/1.0 200 Ok\r\n"
"Content-Type: text/html; charset=\"utf-8\"\r\n"
"\r\n"
"<html><head><title>" << title << "</title></head>\n"
"<body>" << stylesheet << heading;
// Interpret POST.
qWarning(content);
foreach
(QString pair, post_vars
) { QString key
= pair.
section('=',
0,
0);
qWarning
(QString("%1 => %2").
arg(key
).
arg(val
).
toAscii());
key
= QUrl::fromPercentEncoding (key.
toAscii());
val
= QUrl::fromPercentEncoding (val.
toAscii());
POST[key] = val;
}
if (headers.contains("POST")) {
out << "<h3>POST</h3><table><tbody>\n";
for (QMapIterator<QString,QString> i(POST); i.hasNext(); ) {
i.next();
out << "\t<tr><td>" << i.key()
<< "</td><td>" << i.value() << "</td></tr>\n";
}
out << "</tbody></table>\n";
}
else { // Everything else defaults to GET.
out << "<p><form method=\"post\" action=\"act\">\n"
"\t<input type=\"text\" name=\"input1\" />\n"
"\t<input type=\"text\" name=\"input2\" />\n"
"\t<input type=\"submit\" /></form>\n</p>\n";
}
socket->close();
}
HTTPInterface :: HTTPInterface (QString pass, unsigned int port, QObject * p)
: QTcpServer (p) {
password = pass;
if (!pass.size()) {_ok=false;return;}
connect(this,SIGNAL(newConnection()),
this,SLOT(incoming()) );
_ok = listen (QHostAddress::Any, port);
}
bool HTTPInterface :: ok () const {return _ok;}
void HTTPInterface :: incoming () {
while (QTcpSocket * connection = nextPendingConnection()) {
new HTTPRequest (connection);
}
}
HTTPRequest :: HTTPRequest (QTcpSocket * s) : QObject (s), socket (s) {
connect(s,SIGNAL(readyRead()),
this,SLOT(respond()) );
}
HTTPRequest :: ~HTTPRequest () {
qWarning ("~HTTPRequest");
}
namespace {
QString title = "Remote Administration";
QString page = "http://foo.com";
QString heading =
"<h1>"+title+"</h1>\n"
"<h2><a href=\"" + page + "\">" + page + "</a></h2>\n";
QString stylesheet =
"\n<style type=\"text/css\">\n"
"h1 {\n"
"\tcolor: red;\n"
"}\n"
"</style>\n\n";
QRegExp header_space ("[\\s\\n\\r]+");
QRegExp anything ("[^\\s\\n\\r]");
QRegExp post_var ("([^=]+)=([^&]*)");
};
void HTTPRequest :: respond () {
QTextStream out (socket);
while (socket->canReadLine()) {
QString l = socket -> readLine ();
// Headers end with a blank line.
if (anything.indexIn(l) < 0) {
qWarning("Blank");
// If there's non-header content, read it.
if (headers.contains("Content-Length:")) {
l = headers["Content-Length:"][1];
content = socket -> read(l.toLong());
qWarning(QString("%1 bytes").arg(l.toLong())
.toAscii());
}
continue;
}
// Save each header, indexed by the "FOO:" prefix.
QStringList tokens = l.split (header_space);
foreach (QString t, tokens) {
headers[tokens[0]] = tokens;
}
qWarning(QString("%1:%2")
.arg(tokens[0]).arg(l.size()).toAscii() );
}
qWarning("Headers done\n");
out << "HTTP/1.0 200 Ok\r\n"
"Content-Type: text/html; charset=\"utf-8\"\r\n"
"\r\n"
"<html><head><title>" << title << "</title></head>\n"
"<body>" << stylesheet << heading;
// Interpret POST.
qWarning(content);
QStringList post_vars = QString(content).split('&');
foreach (QString pair, post_vars) {
QString key = pair.section('=',0,0);
QString val = pair.section('=',1);
qWarning(QString("%1 => %2").arg(key).arg(val).toAscii());
key = QUrl::fromPercentEncoding (key.toAscii());
val = QUrl::fromPercentEncoding (val.toAscii());
POST[key] = val;
}
if (headers.contains("POST")) {
out << "<h3>POST</h3><table><tbody>\n";
for (QMapIterator<QString,QString> i(POST); i.hasNext(); ) {
i.next();
out << "\t<tr><td>" << i.key()
<< "</td><td>" << i.value() << "</td></tr>\n";
}
out << "</tbody></table>\n";
}
else { // Everything else defaults to GET.
out << "<p><form method=\"post\" action=\"act\">\n"
"\t<input type=\"text\" name=\"input1\" />\n"
"\t<input type=\"text\" name=\"input2\" />\n"
"\t<input type=\"submit\" /></form>\n</p>\n";
}
socket->close();
}
To copy to clipboard, switch view to plain text mode
Bookmarks