-/* $Id: httpd.js,v 1.23 2005/07/07 07:07:32 mmondor Exp $ */
+/* $Id: httpd.js,v 1.24 2005/07/07 17:09:54 mmondor Exp $ */
/*
* Copyright (c) 2005, Matthew Mondor
* using multiple threads or processes. Must be ran through ../../src/test,
* compiled with ../../src/classes/js_fd.[ch] support.
*
- * Configuration options can be found on options.js
+ * Configuration options can be found in options.js
*
* XXX Possibly that with close var semantics changes or such, we could
* support Keep-Alive for HTTP/1.1 connections. This however is not a
* with a document root to access their http vars...
* - Will also need to take care to never allow uploading js scripts once
* we allow their server-side execution.
+ * - After trying a few tests, it appears that using eval() will be
+ * unpracticeable, and unsafe. I will need to add a new C native object
+ * to allow javascript to load/preload scripts and launch their execution
+ * in a separate context, with the wanted variables attached to the
+ * subcontext's root. In the case of a single embedded dynamic application,
+ * I could eval() in the code to include it once, and invoke its functions
+ * when certain paths are invoked.
*/
eval(file_read('options.js')); /* Configuration */
eval(file_read('ml.js')); /* MLTag object for HTML generation */
eval(file_read('root.js')); /* Root object for virtual chroot(2) */
+eval(file_read('session.js')); /* Sesssion object */
* Server identification
*/
SERVER_VERSION = 'mmondor_js_httpd/0.0.1 (NetBSD)';
-SERVER_CVSID = '$Id: httpd.js,v 1.23 2005/07/07 07:07:32 mmondor Exp $';
+SERVER_CVSID = '$Id: httpd.js,v 1.24 2005/07/07 17:09:54 mmondor Exp $';
*/
try {
this.htdocs_root = new Root(o.root + '/htdocs');
- if (scripts)
+ if (scripts) {
+ this.scripts = true;
this.jsinc_root = new Root(o.root + '/jsinc');
+ }
} catch (x) {
throw (x);
}
if (o.charset != undefined)
this.charset = o.charset;
+ if (o.session_exp != undefined)
+ this.session_exp = o.session_exp;
/*
* Link object to vhosts table
idx += 4;
this.bread_buffer = this.request_data.substr(idx);
this.request_data = this.request_data.substr(0, idx);
- close = this.parseRequest();
+ close = this.parseRequest(time);
}
return close;
close = true;
}
} else
- close = this.parsePost();
+ close = this.parsePost(time);
return close;
}
* To be called once our client request has been read, to decide what action
* to perform and modify state accordingly.
*/
-FD.prototype.parseRequest = function()
+FD.prototype.parseRequest = function(time)
{
var close = false;
var valid = false;
var lines;
var words;
var i;
+ var sessid, sess;
this.http_protocol = '';
this.http_method = '';
this.process = process_post;
return false;
} else
- return this.parsePost();
+ return this.parsePost(time);
+ }
+
+ /*
+ * 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 &&
+ (sess = sessions_table[sessid]) != undefined &&
+ sess.expires < time) {
+ this.http_sessid = sessid;
+ this.http_vars_session = sess.variables;
}
if (!close)
- close = this.httpRespond();
+ close = this.httpRespond(time);
return close;
}
-FD.prototype.parsePost = function()
+FD.prototype.parsePost = function(time)
{
var words;
var i;
delete this.post_data;
- return this.httpRespond();
+ return this.httpRespond(time);
}
-FD.prototype.httpRespond = function()
+FD.prototype.httpRespond = function(time)
{
- var path, fd, st, res, ext, mimetype, i, index;
+ var path, fd, st, res, ext, mimetype, i, index, sess;
+ var cookie = undefined;
index = false;
for (;;) {
}
/*
+ * If no session existed yet for this client, and scripting is allowed
+ * for this vhost, create a session for the client now.
+ */
+ if (this.http_sessid == undefined && this.http_vhost.scripts == true) {
+ sess = new Session(time,
+ (this.http_vhost.session_exp != undefined ?
+ this.http_vhost.session_exp :
+ options.default_session_exp));
+ cookie = 'Set-Cookie: SessionID=' + sess.sessid +
+ '; expires=' +
+ (new Date(sess.expires * 1000)).toGMTString() +
+ '; path=/';
+ }
+
+ /*
* If client only wanted the document if it wasn't modified since
* a certain time, report that it wasn't if it is the case.
*/
st.st_mtime <= this.http_modified_since) {
fd.close();
res = new HTTPReply(304, 'Not Modified', null);
+ if (cookie != undefined)
+ res.addHeader(cookie);
res.flush(this, null);
return true;
}
mimetype += '; charset=' + (this.http_vhost.charset == undefined ?
options.default_charset : this.http_vhost.charset);
res = new HTTPReply(200, 'OK', mimetype);
+ if (cookie != undefined)
+ res.addHeader(cookie);
res.flush(this, st.st_size);
return false;
*/
function main() {
var i;
+ var sess_gc_secs = 0;
/*
* Populate vhosts database
*/
var cur = Date.parse(new Date) / 1000;
var exp = cur + 3600;
+ var old;
for (i in set) {
var fd;
* processing is non-blocking, however. Otherwise we
* would loose track of actual time.
*/
+ old = cur;
cur = (Date.parse(new Date) / 1000);
/*
+ * Verify if we should call the session gc, and if so, do so.
+ */
+ sess_gc_secs += cur - old;
+ if (sess_gc_secs >= options.sess_gc_timeout) {
+ sess_gc_secs = 0;
+ session_gc();
+ }
+
+ /*
* Run through set of descriptors with pending events
*/
for (i in e) {