*** empty log message ***
authorMatthew Mondor <mmondor@pulsar-zone.net>
Thu, 7 Jul 2005 17:09:54 +0000 (17:09 +0000)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Thu, 7 Jul 2005 17:09:54 +0000 (17:09 +0000)
tests/js-test/js/httpd/httpd.js
tests/js-test/js/httpd/options.js

index 798f000..e1df940 100644 (file)
@@ -1,4 +1,4 @@
-/* $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
@@ -12,7 +12,7 @@
  * 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.
  */
 
 
@@ -76,6 +83,7 @@ function file_read(file)
 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 */
 
 
 
@@ -83,7 +91,7 @@ eval(file_read('root.js'));           /* Root object for virtual chroot(2) */
  * 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 $';
 
 
 
@@ -124,14 +132,18 @@ function VHost(o)
         */
        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
@@ -332,7 +344,7 @@ function process_query(time)
                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;
@@ -355,7 +367,7 @@ function process_post(time)
                                close = true;
                }
        } else
-               close = this.parsePost();
+               close = this.parsePost(time);
 
        return close;
 }
@@ -506,7 +518,7 @@ FD.prototype.init = function(time, idx)
  * 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;
@@ -515,6 +527,7 @@ FD.prototype.parseRequest = function()
        var lines;
        var words;
        var i;
+       var sessid, sess;
 
        this.http_protocol = '';
        this.http_method = '';
@@ -656,16 +669,27 @@ FD.prototype.parseRequest = function()
                        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;
@@ -682,12 +706,13 @@ FD.prototype.parsePost = function()
 
        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 (;;) {
@@ -742,6 +767,21 @@ FD.prototype.httpRespond = function()
        }
 
        /*
+        * 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.
         */
@@ -749,6 +789,8 @@ FD.prototype.httpRespond = function()
            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;
        }
@@ -775,6 +817,8 @@ FD.prototype.httpRespond = function()
        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;
@@ -990,6 +1034,7 @@ function counters_dec(fd)
  */
 function main() {
        var i;
+       var sess_gc_secs = 0;
 
        /*
         * Populate vhosts database
@@ -1104,6 +1149,7 @@ function main() {
                 */
                var cur = Date.parse(new Date) / 1000;
                var exp = cur + 3600;
+               var old;
                for (i in set) {
                        var fd;
 
@@ -1153,9 +1199,19 @@ function main() {
                 * 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) {
index 4660a61..123a41e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: options.js,v 1.5 2005/07/07 05:34:14 mmondor Exp $ */
+/* $Id: options.js,v 1.6 2005/07/07 17:09:54 mmondor Exp $ */
 
 var options = {
        /* Maximum number of concurrent clients that we should serve */
@@ -13,7 +13,9 @@ var options = {
        default_vhost:          "hal.xisop",
        /* Default mimetype to use when none matching file extension */
        default_mimetype:       "application/octet-stream",
-       default_charset:        "us-ascii"
+       default_charset:        "us-ascii",
+       default_session_exp:    1800,
+       sess_gc_timeout:        600
 };
 
 /* Address:port combinations to listen to */
@@ -35,7 +37,8 @@ var vhosts = [
                aliases:        [ "hal", "localhost" ],
                root:           "/home/mmondor/jswww/welcome",
                scripts:        true,
-               charset:        'iso-8859-1'
+               charset:        'iso-8859-1',
+               session_exp:    3600
        },
 
        /* Dynamic application virtual host for ascpi.com */