-/* $Id: httpd.js,v 1.58 2005/07/14 00:57:09 mmondor Exp $ */
+/* $Id: httpd.js,v 1.59 2005/07/14 12:42:11 mmondor Exp $ */
/*
* Copyright (c) 2005, Matthew Mondor
* Server identification
*/
SERVER_VERSION = 'mmondor_js_httpd/0.0.1 (NetBSD)';
-SERVER_CVSID = '$Id: httpd.js,v 1.58 2005/07/14 00:57:09 mmondor Exp $';
+SERVER_CVSID = '$Id: httpd.js,v 1.59 2005/07/14 12:42:11 mmondor Exp $';
* method decide if we'll close the connection.
*/
len = 32768 - this.request_data.length;
- if (len < 1)
+ if (len < 1) {
done = true;
- else {
+ close = true;
+ } else {
try {
data = this.read(len);
if (data.length == 0)
}
if ((idx = this.request_data.indexOf("\r\n\r\n")) != -1)
done = true;
- else if (done)
- close = true;
+ else if (!this.checked_old &&
+ (idx = this.request_data.indexOf("\r\n")) != -1) {
+ var w;
- if (done) {
+ this.checked_old = true;
+ if ((w = (this.request_data.substr(0, idx)).split(' ')).
+ length == 2 && w[0] == 'GET') {
+ /*
+ * Old-style HTTP request, we need to respond
+ * immediately in this case without any headers.
+ */
+ done = true;
+ }
+ }
+
+ if (done && !close) {
/*
* Store remaining of buffer after "\r\n" so that we may
* be able to process POST for instance, without needing
this.updateTimeout(time);
/* For process_request()/process_post() */
this.bread_buffer = this.bwrite_buffer = '';
+ /*
+ * Flag used to speed up request parsing related to old HTTP requests
+ */
+ this.checked_old = false;
/*
* Note that fcntl(2) and setsockopt(2) flags applied to the bound
*/
FD.prototype.parseRequest = function(time)
{
- var close = false;
- var valid = false;
+ var close = valid = old = false;
var evil_browser = evil_os = false;
var vhost = '';
var lines;
/* Verify if first line has a request which seems valid */
if (lines.length > 0) {
words = lines[0].split(' ');
- if (words.length == 3) {
+ if (words.length == 2 && words[0] == 'GET') {
+ this.http_method = words[0];
+ this.http_path = words[1];
+ this.http_protocol = 'HTTP/1.1';
+ valid = old = true;
+ } else if (words.length == 3) {
if ((words[0] == 'GET' || words[0] == 'POST' ||
words[0] == 'PUT') && (words[2] == 'HTTP/1.0' ||
words[2] == 'HTTP/1.1')) {
}
}
+ if (old) {
+ /*
+ * We can't send any headers in this case, just error
+ * for now.
+ *
+ * XXX It would be nice to support general requests in the
+ * future, although there are serious limitations to that
+ * old protocol. Maybe static pages only for instance on
+ * the default vhost. The HTTPResult object, as well as the
+ * http_error() function would then need to support a special
+ * flag not to include any headers.
+ */
+ this.bwrite('<html><head>' +
+ '<title>Unsupported Old-Style Request</title></head>' +
+ '<body><h1>Unsupported Old-Style Request</h1><p>' +
+ 'Your browser sent an old-style HTTP request, which ' +
+ 'this server does not support. Use an HTTP/1.0 or ' +
+ 'HTTP/1.1 compliant client to continue.</p></body>' +
+ '</html>' + "\r\n");
+ return true;
+ }
+
/*
* Parse header for interesting lines.
*/
this.http_vhost = vhosts_table[vhost.toLowerCase()];
/*
- * Block out evil Microsoft products
+ * Filter out definitely invalid requests
*/
- if (evil_browser) {
- http_error(this, 666, 'Evil Browser Banished!',
- 'Your browser is evil born.<br>At least ' +
- '<b>upgrade</b> to a <a href="http://mozilla.org">' +
- 'decent</a> browser to survive on these grounds.<br>');
+ if (!valid) {
+ http_error(this, 400, 'Bad Request',
+ 'Your browser sent an invalid HTTP query.');
return true;
}
+
+ /*
+ * Block out evil Microsoft products. Start reporting the OS
+ * so that an unwanted windows user doesn't install another
+ * browser to then realize that his OS is banned nevertheless :)
+ */
if (evil_os) {
http_error(this, 666, 'Evil Operating System Banished!',
'Your Operating System is evil born.<br>At least ' +
'<b>upgrade</b> to a <a href="http://netbsd.org">' +
'decent</a> OS to survive on these grounds.<br>');
return true;
- }
-
- /*
- * Filter out definitely invalid requests
- */
- if (!valid) {
- http_error(this, 400, 'Bad Request',
- 'Your browser sent an invalid HTTP query.');
+ } else if (evil_browser) {
+ http_error(this, 666, 'Evil Browser Banished!',
+ 'Your browser is evil born.<br>At least ' +
+ '<b>upgrade</b> to a <a href="http://mozilla.org">' +
+ 'decent</a> browser to survive on these grounds.<br>');
return true;
}
* Verify if client sent a session cookie, and if it consists of a
* valid one, load session data.
*/
- if ((sessid = this.http_vars_cookies['SessionID']) != undefined &&
+ if (this.http_vhost.scripting &&
+ (sessid = this.http_vars_cookies['SessionID']) != undefined &&
(sess = sessions_table[sessid]) != undefined &&
sess.expires > time) {
this.http_sessid = sessid;
var i;
var t;
+ /*
+ * We need to strip "\n", "\r" and "\r\n" which may be sent by broken
+ * clients.
+ */
this.post_data = this.post_data.replace(/\n/g, '');
this.post_data = this.post_data.replace(/\r/g, '');
+
words = this.post_data.split('&');
for (i in words) {
t = words[i].split('=');
(new Date(sess.expires * 1000)).toGMTString() +
'; path=/');
doc.addContent('<html><head><META HTTP-EQUIV="refresh" ' +
- 'CONTENT="1; URL=' + path.virtual + '"><title>Cookies' +
+ 'CONTENT="5; URL=' + path.virtual + '"><title>Cookies' +
'</title></head><body><h1>Cookies</h1><p>We are ' +
' verifying if your browser supports HTTP cookies. ' +
'These are required to keep persistent session data ' +
- 'among your connections. This page should normally ' +
- 'automatically reload shortly.</p><p>If it doesn\'t, ' +
- 'please ensure that HTTP cookies are enabled on your ' +
- 'HTTP client and are accepted from our site.</p><p>' +
- 'If the page still does not load properly after a few ' +
- 'seconds, please click on <a href="' + path.virtual +
+ 'among your connections. The destination page should ' +
+ 'load automatically in a few seconds.</p>' +
+ ' <p>If it doesn\'t, please ensure that HTTP cookies ' +
+ 'are enabled on your HTTP client and are accepted ' +
+ 'from this server.</p>' +
+ '<p>If the page still does not load properly after a ' +
+ 'few seconds, please click on <a href="' + path.virtual +
'">this link</a>.</p><br><sub>' + SERVER_VERSION +
'<br>' + SERVER_CVSID + '</sub>');
doc.flush(this, null);