-/* $Id: httpd.js,v 1.32 2006/08/20 02:40:24 mmondor Exp $ */
+/* $Id: httpd.js,v 1.33 2006/08/20 05:32:28 mmondor Exp $ */
/*
* Copyright (c) 2005-2006, Matthew Mondor
* Server identification
*/
const SERVER_VERSION = 'mmondor_js_httpd/0.1.0 (NetBSD)';
-const SERVER_CVSID = '$Id: httpd.js,v 1.32 2006/08/20 02:40:24 mmondor Exp $';
+const SERVER_CVSID = '$Id: httpd.js,v 1.33 2006/08/20 05:32:28 mmondor Exp $';
host_appmatch: function(p)
{
var b, o;
+ var appserv = this.appserv;
b = false;
- if (this.appserv == undefined)
+ if (appserv == undefined)
return b;
- o = this.appserv.paths;
+ o = appserv.paths;
- if (this.paths_cache[p] != undefined)
- return this.paths_cache[p];
+ if (appserv.paths_cache[p] != undefined)
+ return appserv.paths_cache[p];
- if (++this.paths_cache_items == this.paths_cache_max) {
- this.paths_cache = {};
- this.paths_cache_items = 1;
+ if (++appserv.paths_cache_items == appserv.paths_cache_max) {
+ appserv.paths_cache = {};
+ appserv.paths_cache_items = 1;
}
for (i in o) {
- if (h.match(o[i]))
+ if (p.match(o[i]))
b = true;
}
- this.paths_cache[p] = b;
+ appserv.paths_cache[p] = b;
return b;
}
var lines;
var words;
var i;
+ /*
var sessid, sess;
+ */
/* Initial HTTP query state */
this.http_protocol = '';
this.http_agent = '';
this.http_content_length = -1;
this.http_modified_since = undefined;
+ /*
this.http_sessid = undefined;
+ */
this.http_range = undefined;
this.http_old_get = false;
* nothing to do otherwise other than make sure it's valid and be able
* to associate SID->FD
*/
+ /*
if (this.http_vhost.appserver != undefined &&
(sessid = this.http_vars_cookies['SessionID']) != undefined &&
(sess = sessions_table[sessid]) != undefined &&
sess.expires > time)
this.http_sessid = sessid;
+ */
/*
* Fill in associative array with any GET-style supplied
*/
FD.prototype.httpRespond = function(time)
{
- var path, fd, st, res, ext, mimetype, i, sess, size;
+ var path, fd, st, res, ext, mimetype, i, size, appserv_match, error;
+ /*
+ var sess;
+ */
/*
* Verify if requested path is valid
return PSTAT_CLOSE_SUCCESS;
}
+ appserv_match = this.http_vhost.host_appmatch(path.virtual);
+
/*
* General strategy:
- * 1) Verify if path matches appserver, if so jump to appserver
- * forwarding code.
+ * 1) Verify if path matches appserver, if so ensure that client
+ * supports cookies, then proceed with the forwarding code.
* 2) Attempt to open file, return 404 or 403 on failure.
* On success, if it consists of a directory, apply index path,
* match again against appserver paths, close fd and forward to
* appserver also if so. If not, close dir fd and attempt to open
* again after applying index. On failure, return 404 or 403.
- * 3) If file successfully opened, upliad it to client.
+ * 3) If file successfully opened, upload it to client.
* 4) If to forward request to appserver, perform the following:
*
* 1) Verify if session cookie provided. If not, invoke appserver
* keep it open and continue downwards with the stat info already
* filled in.
*/
- fd = new FD();
-
- try {
- fd.open(path.real, FD.O_RDONLY);
- st = fd.fstat();
- } catch (x) {
- http_error(this, 404, 'Not Found',
- path.virtual + ' could not be found.');
- return PSTAT_CLOSE_SUCCESS;
- }
-
- if ((st.st_mode & FD.S_IFDIR) != 0) { /* Directory */
- var error = false;
+ if (!appserv_match) {
+ fd = new FD();
- /*
- * XXX Refit URL to configured index,
- * check if under appserver path and if so process accordingly
- * else check if there's a file under it.
- */
- fd.close();
try {
- fd.open(path.real + '/index.html', FD.O_RDONLY);
+ fd.open(path.real, FD.O_RDONLY);
st = fd.fstat();
- path.real += '/index.html';
- path.virtual += '/index.html';
} catch (x) {
- error = true;
- }
- if (error) {
- http_error(this, 403, 'Permission Denied',
- 'You do not have the permission to access the ' +
- 'resource ' + path.virtual + '.');
+ http_error(this, 404, 'Not Found',
+ path.virtual + ' could not be found.');
return PSTAT_CLOSE_SUCCESS;
}
+
+ if ((st.st_mode & FD.S_IFDIR) != 0) { /* Directory */
+ error = false;
+
+ /*
+ * Refit URL to configured index,
+ * check if under appserver path and if so process
+ * accordingly, else check if there's a file under it.
+ */
+ try {
+ fd.close();
+ } catch (x) {}
+ if (this.http_vhost.index.charAt(1) == '/') {
+ /*
+ * Index points to absolute path, so recompute
+ * path
+ */
+ path = this.http_vhost.htdocs_root.
+ valid_virtual(this.http_vhost.index);
+ if (!path)
+ error = true;
+ } else {
+ /*
+ * We simply need to append the index path and
+ * retry
+ */
+ path.real += this.http_vhost.index;
+ path.virtual += this.http_vhost.index;
+ }
+
+ /*
+ * Verify again if new index matches an appserv path
+ */
+ if (!error) {
+ appserv_match = this.http_vhost.host_appmatch(
+ path.virtual);
+
+ /*
+ * Not under appserv, attempt to reopen file
+ */
+ if (!appserv_match) {
+ try {
+ fd.open(path.real,
+ FD.O_RDONLY);
+ st = fd.fstat();
+ } catch (x) {
+ error = true;
+ }
+ }
+ }
+
+ if (error) {
+ http_error(this, 403, 'Permission Denied',
+ 'You do not have the permission to ' +
+ 'access the resource ' + path.virtual +
+ '.');
+ return PSTAT_CLOSE_SUCCESS;
+ }
+ }
+ }
+
+ /*
+ * If under appserv path, make sure client supports HTTP cookies.
+ * We do this by verifying that we are able to obtain a "cookie=yes"
+ * cookie, without which we send one to the client redirecting to the
+ * same URL.
+ */
+ if (appserv_match && this.http_vars_cookies['cookies'] == undefined) {
+ /* Ensure that client supports HTTP cookies */
+ doc = new HTTPReply(200, "OK",
+ 'text/html; charset=' + options.default_charset);
+ doc.addNoCacheHeaders();
+ doc.addHeader('Set-Cookie: cookies=yes; path=/');
+ doc.addContent('<html><head><META HTTP-EQUIV="refresh" ' +
+ '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. 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></body></html>');
+ doc.flush(this, null);
+
+ return PSTAT_CLOSE_SUCCESS;
}
/*
}
*/
+ /* XXX */
+ if (appserv_match) {
+ http_error(this, 500, 'Internal Server Error',
+ 'You have requested an application server handled path ' +
+ 'which cannot be handled at this time. Please try ' +
+ 'again later.');
+ return PSTAT_CLOSE_SUCCESS;
+ }
+
/*
* Only continue if file is a regular file
*/
- if ((st.st_mode & FD.S_IFREG) == 0) {
+ if (!appserv_match && (st.st_mode & FD.S_IFREG) == 0) {
fd.close();
http_error(this, 403, 'Permission Denied',
'You do not have the permission to access the resource ' +
/*
* Connections limits management
*/
+
function CLimits(maxtotal, maxaddr)
{
this.connections = 0;
*/
function main() {
var i;
+ /*
var sess_gc_secs = 0;
+ */
var fd, e, efd, flush;
/*
* Verify if we should call the session gc, and if so, do so.
* XXX We probably shouldn't do this anymore
*/
+ /*
sess_gc_secs += cur - old;
if (sess_gc_secs >= options.sess_gc_interval) {
sess_gc_secs = 0;
session_gc(cur);
}
+ */
/*
* Run through set of descriptors with pending events