*** empty log message ***
authorMatthew Mondor <mmondor@pulsar-zone.net>
Thu, 7 Jul 2005 00:11:43 +0000 (00:11 +0000)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Thu, 7 Jul 2005 00:11:43 +0000 (00:11 +0000)
tests/js-test/js/httpd/httpd.js
tests/js-test/js/httpd/root.js [new file with mode: 0644]

index ecce38b..01fa1f2 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: httpd.js,v 1.16 2005/07/06 23:53:54 mmondor Exp $ */
+/* $Id: httpd.js,v 1.17 2005/07/07 00:11:30 mmondor Exp $ */
 
 /*
  * Copyright (c) 2005, Matthew Mondor
@@ -75,7 +75,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.16 2005/07/06 23:53:54 mmondor Exp $';
+SERVER_CVSID   = '$Id: httpd.js,v 1.17 2005/07/07 00:11:30 mmondor Exp $';
 
 
 
@@ -231,16 +231,24 @@ function http_error(fd, code, desc, ldesc)
        var title = new MLTag('title', true);
        title.addContent(code + ' ' + desc);
        head.addContent(title);
+
        var body = new MLTag('body', true);
+
        var h1 = new MLTag('h1', true);
        h1.addContent(code + ' ' + desc);
        body.addContent(h1);
+
        var p = new MLTag('p', true);
        p.addContent(ldesc);
        body.addContent(p);
+
+       body.addContent(fd.httpDebug());
+       body.addContent('<br>');
+
        sub = new MLTag('sub', true);
        sub.addContent(SERVER_VERSION + '<br>' + SERVER_CVSID);
        body.addContent(sub);
+
        html.addContent(head);
        html.addContent(body);
 
@@ -565,7 +573,7 @@ FD.prototype.parseRequest = function()
                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 this holy land.<br>');
+                   'decent</a> browser to survive on these grounds.<br>');
                return true;
        }
 
@@ -755,22 +763,11 @@ FD.prototype.httpRespond = function()
        return false;
 }
 
-/*
-FD.prototype.httpRespond = function()
+FD.prototype.httpDebug = function()
 {
        var res = new HTTPReply(200, 'OK', 'text/html; charset=iso-8859-1');
        res.addNoCacheHeaders();
 
-       var html = new MLTag('html', true);
-       var head = new MLTag('head', true);
-       var title = new MLTag('title', true);
-       title.addContent('Detected!');
-       head.addContent(title);
-       html.addContent(head);
-       var body = new MLTag('body', true);
-       var h1 = new MLTag('h1', true);
-       h1.addContent('Detected!');
-       body.addContent(h1);
        table = new MLTag('table', true);
        table.addAttr('width', '100%');
        table.addAttr('border', '1');
@@ -887,30 +884,8 @@ FD.prototype.httpRespond = function()
        tr.addContent(td);
        table.addContent(tr);
 
-       body.addContent(table);
-
-       p = new MLTag('p', true);
-       p.addContent('Tracing in progress...');
-       body.addContent(p);
-
-       var sub = new MLTag('sub', true);
-       sub.addContent(SERVER_VERSION + '<br>' + SERVER_CVSID);
-       body.addContent(sub);
-
-       html.addContent(body);
-
-       res.addContent(html.toStr(0) + "\n");
-
-       try {
-               res.flush(this, null);
-       } catch (x) {}
-
-       delete html;
-       delete res;
-
-       return true;
+       return table;
 }
-*/
 
 /*
  * Verifies if property name ends with [], which considers it as an array of
diff --git a/tests/js-test/js/httpd/root.js b/tests/js-test/js/httpd/root.js
new file mode 100644 (file)
index 0000000..c46fd2b
--- /dev/null
@@ -0,0 +1,197 @@
+/* $Id: root.js,v 1.1 2005/07/07 00:11:43 mmondor Exp $ */
+
+/*
+ * Copyright (c) 2005, Matthew Mondor
+ * ALL RIGHTS RESERVED.
+ */
+
+/*
+ * Implementation of a virtual chroot(2) system.
+ */
+
+
+
+const PATH_MAX = 255;
+
+
+
+function Root(root)
+{
+
+       if (!(this.root = this.valid_path(root)))
+               throw('Invalid root path "' + root + '"!');
+       this.cwd = '/';
+}
+
+Root.prototype = {
+
+       /*
+        * Quick lookup table of valid characters within pathnames.
+        * Currently 'a'-'z', 'A'-'Z', '0'-'9', '.', '/', '-', '_'
+        */
+       valid_char_table: [
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
+               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+               0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
+               0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+       ],
+
+       /*
+        * Base function to return formatted valid path, or false.
+        * Returned path will always begin with '/' and not have any
+        * trailing '/'.  Multiple '/' are also collapsed into one.
+        */
+       valid_path: function(path)
+       {
+               var i, t, l, p, c, code;
+
+               p = l = '/';
+               for (i = 0, t = path.length; i < t; i++) {
+                       c = path.charAt(i);
+                       if (l == '/') {
+                               /* Collapse multiple '/' */
+                               if (c == '/')
+                                       continue;
+                               /* Prohibit '.' at start of element */
+                               if (c == '.')
+                                       return false;
+                       }
+                       /* Validate chars */
+                       code = c.charCodeAt(0);
+                       if (code != code & 0xff || 
+                           this.valid_char_table[code] == 0)
+                               return false;
+                       p += c;
+                       l = c;
+               }
+               /* Strip last '/' if any, unless only one */
+               if (c == '/' && p.length > 1)
+                       p = p.substr(0, p.length - 1);
+
+               /* If exceeding PATH_MAX, return false */
+               if (p.length > PATH_MAX)
+                       return false;
+
+               return p;
+       },
+
+       /*
+        * Returns version of provided path which points to the parent
+        * directory if possible.  Returns false otherwise.
+        * Should only be used with paths first copied using valid_path().
+        * Can typically be used with the cwd.
+        */
+       parent: function(path)
+       {
+               var i;
+
+               /* First make sure that path starts with '/' */
+               if (path.length < 2 || path.charAt(0) != '/')
+                       return false;
+
+               /* Strip trailing '/' chars */
+               for (i = path.length - 1; i >= 0 && path.charAt(i) == '/';
+                   i--) ;
+               if (i <= path.length)
+                       path = path.substr(0, i + 1);
+
+               /*
+                * Locate previous '/', strip everything after it, including
+                * it, except in the case where it is the only remaining,
+                * where path must remain '/'.
+                */
+               if ((i = path.lastIndexOf('/')) == 0)
+                       i = 1;
+               return path.substring(0, i);
+       },
+
+       /*
+        * This function should always be called when processing user-supplied
+        * paths.  The application should then only trust the object it
+        * returns.  Returns false if the path is invalid.
+        * Otherwise, returns an object, with the following properties:
+        *
+        * <real>       System-wide absolute real fullpath, to be used by the
+        *              application to access the files/directories in
+        *              question.
+        * <virtual>    Virtual root based absolute fullpath, useful to report
+        *              to the user.  Can also be useful to change a Root
+        *              object's cwd to, after verifying that <real> really
+        *              points to an existing directory.
+        */
+       valid_virtual: function(path)
+       {
+               var cwd, c, l, t, o;
+
+               o = {};
+               cwd = this.cwd;
+
+               /*
+                * Look for '~', or '/' in the beginning of the path,
+                * in which case cwd gets cleared to '/'.  Also look for
+                * './' or '.[EOS]', which we simply skip, meaning the
+                * current directory.
+                */
+               if ((l = path.length) > 0) {
+                       c = path.charAt(0);
+                       if (c == '~' || c == '/') {
+                               cwd = '/';
+                               path = path.substr(1);
+                       } else if (c == '.') {
+                               if (l == 1)
+                                       path = '';
+                               else if (l > 1 && path.charAt(1) == '/')
+                                       path = path.substr(2);
+                       }
+               }
+
+               /*
+                * Now process all starting '..' or '../', modifying cwd if
+                * allowed, and stripping them from path.  In case of '../',
+                * also strip any multiple '/'.
+                */
+               for (;;) {
+                       t = false;
+                       l = path.length;
+                       if ((l == 2 && path == '..') ||
+                           (l > 2 && path.substr(0, 2) == '..' &&
+                           (t = (path.charAt(2) == '/')))) {
+                               if (!(cwd = this.parent(cwd)))
+                                       return false;
+                               if (t) {
+                                       for (i = 2; path.charAt(i) == '/';
+                                           i++) ;
+                                       path = path.substr(i);
+                                       continue;
+                               } else {
+                                       path = path.substr(2);
+                                       continue;
+                               }
+                       }
+                       break;
+               }
+
+               /*
+                * Now attempt to fill in our object properties.
+                * this.valid_path() performs necessary sanity checking.
+                */
+               if (!(o.virtual = this.valid_path('/' + cwd + '/' + path)))
+                       return false;
+               o.real = this.root + o.virtual;
+
+               return o;
+       }
+
+};