*** empty log message ***
authorMatthew Mondor <mmondor@pulsar-zone.net>
Wed, 6 Jul 2005 23:52:23 +0000 (23:52 +0000)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Wed, 6 Jul 2005 23:52:23 +0000 (23:52 +0000)
tests/js-test/js/httpd/httpd.js

index ff2382d..a557483 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: httpd.js,v 1.14 2005/07/06 20:33:28 mmondor Exp $ */
+/* $Id: httpd.js,v 1.15 2005/07/06 23:52:23 mmondor Exp $ */
 
 /*
  * Copyright (c) 2005, Matthew Mondor
@@ -86,7 +86,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.14 2005/07/06 20:33:28 mmondor Exp $';
+SERVER_CVSID   = '$Id: httpd.js,v 1.15 2005/07/06 23:52:23 mmondor Exp $';
 
 
 
@@ -152,6 +152,14 @@ function VHost(o)
 
 
 /*
+ * For the mime types database
+ */
+
+var mimetypes_table = {};
+
+
+
+/*
  * The HTTPReply object allows to cache addHeader() and addContent() requests,
  * and to eventually flush the whole reply to an arbitrary FD afterwards.
  */
@@ -492,13 +500,14 @@ FD.prototype.parseRequest = function()
        var close = false;
        var valid = false;
        var evil = false;
+       var vhost = '';
        var lines;
        var words;
        var i;
 
        this.http_protocol = '';
        this.http_method = '';
-       this.http_vhost = '';
+       this.http_vhost = undefined;
        this.http_path = '';
        this.http_vars_get = {};
        this.http_vars_post = {};
@@ -541,7 +550,7 @@ FD.prototype.parseRequest = function()
                                        if ((i2 = words[1].indexOf(':')) != -1)
                                                words[1] =
                                                    words[1].substr(0, i2);
-                                       this.http_vhost = words[1];
+                                       vhost = words[1];
                                }
                        } else if (words[0] == 'Cookie:') {
                                words = (lines[i].substr(8)).split('=');
@@ -586,10 +595,9 @@ FD.prototype.parseRequest = function()
         * Also set the name of the vhost to the actual vhost name despite
         * it possibly being resolved through an alias.
         */
-       if (this.http_vhost == '' ||
-           vhosts_table[this.http_vhost] == undefined)
-               this.http_vhost = options.default_vhost;
-       this.http_vhost = vhosts_table[this.http_vhost].name;
+       if (vhost == '' || vhosts_table[vhost] == undefined)
+               vhost = options.default_vhost;
+       this.http_vhost = vhosts_table[vhost];
 
        /*
         * Fill in associative array with any GET-style supplied
@@ -641,23 +649,6 @@ FD.prototype.parseRequest = function()
        if (!close)
                close = this.httpRespond();
 
-       /* XXX Switch state to transfer mode as a test */
-       /*
-       try {
-               this.transfer_src = new FD();
-               this.transfer_src.open('httpd.js', FD.O_RDONLY);
-               var st = this.transfer_src.fstat();
-               this.transfer_dst = this;
-               this.process = process_transfer;
-               this.events = FD.POLLOUT;
-               var res = new HTTPReply(200, 'OK', 'text/plain');
-               res.addNoCacheHeaders();
-               res.flush(this, st.st_size);
-       } catch (x) {
-               err.put(x + "\n");
-       }
-       */
-
        return close;
 }
 
@@ -683,6 +674,101 @@ FD.prototype.parsePost = function()
 
 FD.prototype.httpRespond = function()
 {
+       var path, fd, st, res, ext, mimetype, i, index;
+
+       index = false;
+       for (;;) {
+               path = this.http_vhost.htdocs_root.valid_virtual(
+                   this.http_path);
+               if (!path) {
+                       http_error(this, 403, 'Permission Denied',
+                          'You do not have the permission to access this ' +
+                          'resource.');
+                       return true;
+               }
+
+               fd = new FD();
+               try {
+                       fd.open(path.real, FD.O_RDONLY);
+                       st = fd.fstat();
+               } catch (x) {
+                       if (index) {
+                               http_error(this, 403, 'Permission Denied',
+                                   'You do not have the permission to ' +
+                                   'access this resource.');
+                               return true;
+                       } else {
+                               http_error(this, 404, 'Not Found',
+                                   path.virtual + ' could not be found.');
+                               return true;
+                       }
+               }
+
+               /*
+                * Is file a directory?  If so, attempt to fallback to
+                * index.html inside it.
+                */
+               if (((st.st_mode & FD.S_IFMT) & FD.S_IFDIR) != 0) {
+                       fd.close();
+                       this.http_path += '/index.html';
+                       index = true;
+                       continue;
+               }
+
+               break;
+       }
+
+       /*
+        * Only continue if file is a regular file
+        */
+       if (((st.st_mode & FD.S_IFMT) & FD.S_IFREG) == 0) {
+               fd.close();
+               http_error(this, 403, 'Permission Denied',
+                   'You do not have the permission to access this resource.');
+               return true;
+       }
+
+       /*
+        * 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.
+        */
+       if (this.http_modified_since != undefined &&
+           st.st_mtime <= this.http_modified_since) {
+               fd.close();
+               res = new HTTPReply(304, 'Not Modified', null);
+               res.flush(this, null);
+               return true;
+       }
+
+       /*
+        * We really need to transfer it, so switch to outbound transfer mode.
+        */
+       this.transfer_src = fd;
+       this.transfer_dst = this;
+       this.process = process_transfer;
+       this.events = FD.POLLOUT;
+
+       /*
+        * Obtain mimetype for file and flush HTTP header.
+        * Then return with close=false, to delegate operations to
+        * process_transfer().
+        */
+       mimetype = options.default_mimetype;
+       if ((i = path.virtual.lastIndexOf('.')) != -1) {
+               ext = (path.virtual.substr(i + 1)).toLowerCase();
+               if (ext.lastIndexOf('/') == -1 &&
+                   mimetypes_table[ext] != undefined)
+                       mimetype = mimetypes_table[ext];
+       }
+       res = new HTTPReply(200, 'OK', mimetype);
+       res.flush(this, st.st_size);
+
+       return false;
+}
+
+/*
+FD.prototype.httpRespond = function()
+{
        var res = new HTTPReply(200, 'OK', 'text/html; charset=iso-8859-1');
        res.addNoCacheHeaders();
 
@@ -788,7 +874,7 @@ FD.prototype.httpRespond = function()
        td.addContent('VHost:');
        tr.addContent(td);
        td = new MLTag('td', true);
-       td.addContent(this.http_vhost);
+       td.addContent(this.http_vhost.name);
        tr.addContent(td);
        table.addContent(tr);
 
@@ -835,6 +921,7 @@ FD.prototype.httpRespond = function()
 
        return true;
 }
+*/
 
 /*
  * Verifies if property name ends with [], which considers it as an array of
@@ -927,6 +1014,26 @@ function main() {
        }
 
        /*
+        * Populate mimetypes database.
+        * XXX If this got very large, because the destination strings
+        * are rather large, it might be good to use indexes or references
+        * to them rather than provide the string for each extension.
+        */
+       for (i in mimetypes) {
+               var i2, ext;
+
+               for (i2 in mimetypes[i]) {
+                       ext = mimetypes[i][i2].toLowerCase();
+                       if (mimetypes_table[ext] != undefined) {
+                               err.put('Conflicting mime type ' +
+                                   ext + ' -> ' + i + "\n");
+                               continue;
+                       }
+                       mimetypes_table[ext] = i;
+               }
+       }
+
+       /*
         * Create polling array set
         */
        var set = [];