-/* $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
* 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 $';
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);
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;
}
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');
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
--- /dev/null
+/* $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;
+ }
+
+};