summaryrefslogtreecommitdiff
path: root/swat/scripting
diff options
context:
space:
mode:
Diffstat (limited to 'swat/scripting')
-rw-r--r--swat/scripting/client/call.js118
-rw-r--r--swat/scripting/client/desktop.js121
-rw-r--r--swat/scripting/client/encoder.js84
-rw-r--r--swat/scripting/client/js_scripts.js60
-rw-r--r--swat/scripting/client/regedit.js160
-rw-r--r--swat/scripting/client/status.js40
-rw-r--r--swat/scripting/common.js125
-rw-r--r--swat/scripting/footer_columns.esp7
-rw-r--r--swat/scripting/footer_desktop.esp6
-rw-r--r--swat/scripting/footer_plain.esp7
-rw-r--r--swat/scripting/forms.js112
-rw-r--r--swat/scripting/general_calls.esp25
-rw-r--r--swat/scripting/header_columns.esp85
-rw-r--r--swat/scripting/header_desktop.esp25
-rw-r--r--swat/scripting/header_plain.esp55
-rw-r--r--swat/scripting/menus.js53
-rw-r--r--swat/scripting/preauth.esp48
-rw-r--r--swat/scripting/server/regedit.esp51
-rw-r--r--swat/scripting/server/status.esp27
-rw-r--r--swat/scripting/test.ejs10
-rw-r--r--swat/scripting/test.esp6
21 files changed, 1225 insertions, 0 deletions
diff --git a/swat/scripting/client/call.js b/swat/scripting/client/call.js
new file mode 100644
index 0000000000..2886471db2
--- /dev/null
+++ b/swat/scripting/client/call.js
@@ -0,0 +1,118 @@
+/*
+ client side js functions for remote calls into the server
+
+ Copyright Andrew Tridgell 2005
+ released under the GNU GPL Version 2 or later
+*/
+
+var __call = new Object();
+
+/*
+ we can't use the qooxdoo portability layer for this, as it assumes
+ you are using an XML transport, so instead replicate the portability
+ code for remote calls here. Don't look too closely or you will go
+ blind.
+*/
+__call._activex = window.ActiveXObject && !(new QxClient).isOpera() ? true : false;
+__call._activexobj = null;
+__call._ok = QxXmlHttpLoader._http || QxXmlHttpLoader._activex;
+
+if (__call._activex) {
+ var servers = ["MSXML2", "Microsoft", "MSXML", "MSXML3"];
+ for (var i=0; i<servers.length; i++) {
+ try {
+ var o = new ActiveXObject(servers[i] + ".XMLHTTP");
+ __call._activexobj = servers[i];
+ o = null;
+ } catch(ex) {};
+ };
+};
+
+/*
+ return a http object ready for a remote call
+*/
+function __http_object() {
+ return __call._activex ?
+ new ActiveXObject(__call._activexobj + ".XMLHTTP") :
+ new XMLHttpRequest();
+}
+
+/*
+ usage:
+
+ vserver_call(url, func, callback, args);
+
+ 'func' is a function name to call on the server
+ any additional arguments are passed to func() on the server
+
+ The callback() function is called with the returned
+ object. 'callback' may be null.
+*/
+function vserver_call_url(url, func, callback, args) {
+ var args2 = new Object();
+ args2.length = args.length;
+ var i;
+ for (i=0;i<args.length;i++) {
+ args2[i] = args[i];
+ }
+ var req = __http_object();
+ req.open("POST", url, true);
+ req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
+ req.send("ajaj_func=" + func + "&ajaj_args=" + encodeObject(args2));
+ req.onreadystatechange = function() {
+ if (4 == req.readyState && callback != null) {
+ var o = decodeObject(req.responseText);
+ callback(o.res);
+ }
+ }
+}
+
+
+/*
+ usage:
+
+ server_call_url(url, func, callback, ...);
+
+ 'func' is a function name to call on the server
+ any additional arguments are passed to func() on the server
+
+ The callback() function is called with the returned
+ object. 'callback' may be null.
+*/
+function server_call_url(url, func, callback) {
+ var args = new Object();
+ var i;
+ for (i=3;i<arguments.length;i++) {
+ args[i-3] = arguments[i];
+ }
+ args.length = i-3;
+ vserver_call_url(url, func, callback, args);
+}
+
+
+/*
+ call printf on the server
+*/
+function srv_printf() {
+ vserver_call_url('/scripting/general_calls.esp', 'srv_printf', null, arguments);
+}
+
+/*
+ usage:
+
+ server_call(func, callback, ...);
+
+ 'func' is a function name to call on the server
+ any additional arguments are passed to func() on the server
+
+ The callback() function is called with the returned
+ object. 'callback' may be null.
+*/
+function server_call(func, callback) {
+ var args = new Array(arguments.length-2);
+ var i;
+ for (i=0;i<args.length;i++) {
+ args[i] = arguments[i+1];
+ }
+ vserver_call_url("@request.REQUEST_URI", func, callback, args);
+}
diff --git a/swat/scripting/client/desktop.js b/swat/scripting/client/desktop.js
new file mode 100644
index 0000000000..9e1a342936
--- /dev/null
+++ b/swat/scripting/client/desktop.js
@@ -0,0 +1,121 @@
+/*
+ Windows, tabs, and general widgetry for SWAT.
+
+ Copyright (C) Deryck Hodge 2005
+ released under the GNU GPL Version 2 or later
+*/
+
+/* Qooxdoo's browser sniffer doesn't distinguish IE version.
+We'll cover IE 6 for now, but these checks need to be
+revisited for fuller browser coverage. */
+var browser = QxClient().engine;
+
+// DocX/Y returns the width/height of the page in browser
+function docX()
+{
+ var x;
+ if (browser != "mshtml") {
+ x = window.innerWidth;
+ } else {
+ x = document.documentElement.clientWidth;
+ }
+ return x;
+}
+
+function docY()
+{
+ var y;
+ if (browser != "mshtml") {
+ y = window.innerHeight;
+ } else {
+ y = document.documentElement.clientHeight;
+ }
+ return y;
+}
+
+// If given a number, sizeX/Y returns in pixels a percentage of the browser
+// window. If given a Window object, sizeX/Y returns the size of that object.
+function sizeX(s)
+{
+ var sX;
+
+ if (typeof(s) == 'number') {
+ sX = Math.floor(docX() * s);
+ } else {
+ sX = s.getMinWidth();
+ }
+
+ return sX;
+}
+
+function sizeY(s)
+{
+ var sY;
+ if (typeof(s) == 'number') {
+ sY = Math.floor(docY() * s);
+ } else {
+ sY = s.getMinHeight();
+ }
+
+ return sY;
+}
+
+function getPosX(win)
+{
+ var y = Math.floor( (docY() - sizeY(win)) * Math.random() );
+ return y;
+}
+
+function getPosY(win)
+{
+ var x = Math.floor( (docX() - sizeX(win)) * Math.random() );
+ return x;
+}
+
+function openIn(e)
+{
+ var blank = new Window("New Menu");
+ e.add(blank);
+ blank.setVisible(true);
+}
+
+function Window(h, src, s)
+{
+ this.self = new QxWindow(h);
+
+ // Settings for all windows
+ if (s) {
+ this.self.setMinWidth(sizeX(s));
+ this.self.setMinHeight(sizeY(s));
+ }
+ this.self.setTop(getPosX(this.self));
+ this.self.setLeft(getPosY(this.self));
+
+ this.self.addEventListener("contextmenu", contextMenu);
+
+ return this.self;
+}
+
+function SmallWindow(h, src)
+{
+ this.self = new Window(h, src, .20);
+ return this.self;
+}
+
+function StandardWindow(h, src)
+{
+ this.self = new Window(h, src, .45);
+ return this.self;
+}
+
+function LargeWindow(h, src)
+{
+ this.self = new Window(h, src, .70);
+ return this.self;
+}
+
+Window.small = SmallWindow;
+Window.standard = StandardWindow;
+Window.large = LargeWindow;
+
+
diff --git a/swat/scripting/client/encoder.js b/swat/scripting/client/encoder.js
new file mode 100644
index 0000000000..4aa4cc0954
--- /dev/null
+++ b/swat/scripting/client/encoder.js
@@ -0,0 +1,84 @@
+/*
+ client side js functions for encoding/decoding objects into linear strings
+
+ Copyright Andrew Tridgell 2005
+ released under the GNU GPL Version 2 or later
+*/
+/*
+ usage:
+
+ enc = encodeObject(obj);
+ obj = decodeObject(enc);
+
+ The encoded format of the object is a string that is safe to
+ use in URLs
+
+ Note that only data elements are encoded, not functions
+*/
+
+function count_members(o) {
+ var i, count = 0;
+ for (i in o) {
+ count++;
+ }
+ return count;
+}
+
+function encodeObject(o) {
+ var i, r = count_members(o) + ":";
+ for (i in o) {
+ var t = typeof(o[i]);
+ if (t == 'object') {
+ r = r + "" + i + ":" + t + ":" + encodeObject(o[i]);
+ } else if (t == 'string') {
+ var s = encodeURIComponent(o[i]).replace(/%/g,'#');
+ r = r + "" + i + ":" + t + ":" + s + ":";
+ } else if (t == 'boolean' || t == 'number') {
+ r = r + "" + i + ":" + t + ":" + o[i] + ":";
+ } else if (t == 'undefined' || t == 'null') {
+ r = r + "" + i + ":" + t + ":";
+ } else if (t != 'function') {
+ alert("Unable to encode type " + t);
+ }
+ }
+ return r;
+}
+
+function decodeObjectArray(a) {
+ var o = new Object();
+ var i, count = a[a.i]; a.i++;
+ for (i=0;i<count;i++) {
+ var name = a[a.i]; a.i++;
+ var type = a[a.i]; a.i++;
+ var value;
+ if (type == 'object') {
+ o[name] = decodeObjectArray(a);
+ } else if (type == "string") {
+ value = decodeURIComponent(a[a.i].replace(/#/g,'%')); a.i++;
+ o[name] = value;
+ } else if (type == "boolean") {
+ value = a[a.i]; a.i++;
+ if (value == 'true') {
+ o[name] = true;
+ } else {
+ o[name] = false;
+ }
+ } else if (type == "undefined") {
+ o[name] = undefined;
+ } else if (type == "null") {
+ o[name] = null;
+ } else if (type == "number") {
+ value = a[a.i]; a.i++;
+ o[name] = value * 1;
+ } else {
+ alert("Unable to delinearise type " + type);
+ }
+ }
+ return o;
+}
+
+function decodeObject(str) {
+ var a = str.split(':');
+ a.i = 0;
+ return decodeObjectArray(a);
+}
diff --git a/swat/scripting/client/js_scripts.js b/swat/scripting/client/js_scripts.js
new file mode 100644
index 0000000000..1c6e5806f4
--- /dev/null
+++ b/swat/scripting/client/js_scripts.js
@@ -0,0 +1,60 @@
+/*
+ Beginnnigs of a script manager for SWAT.
+
+ Copyright (C) Deryck Hodge 2005
+ released under the GNU GPL Version 2 or later
+*/
+
+var head = document.getElementsByTagName('head')[0];
+var scripts = document.getElementsByTagName('script');
+
+function __has_js_script(file)
+{
+ var i;
+ for (i=0; i<scripts.length; i++) {
+ if (scripts[i].src.indexOf(file) > -1) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
+
+function __get_js_script(file)
+{
+ var i;
+ for (i=0; i<scripts.length; i++) {
+ if (scripts[i].src.indexOf(file) > -1) {
+ return scripts[i];
+ }
+ }
+}
+
+function __add_js_script(path)
+{
+ // Create a unique ID for this script
+ var srcID = new Date().getTime();
+
+ var script = document.createElement('script');
+ script.type = 'text/javascript';
+ script.id = srcID;
+
+ head.appendChild(script);
+
+ // IE works only with the path set after appending to the document
+ document.getElementById(srcID).src = path;
+}
+
+function __remove_js_script(path)
+{
+ var script = __get_js_script(path);
+ script.parentNode.removeChild(script);
+}
+
+document.js = new Object();
+document.js.scripts = scripts;
+document.js.hasScript = __has_js_script;
+document.js.getScript = __get_js_script;
+document.js.add = __add_js_script;
+document.js.remove = __remove_js_script;
+
diff --git a/swat/scripting/client/regedit.js b/swat/scripting/client/regedit.js
new file mode 100644
index 0000000000..9175017c2e
--- /dev/null
+++ b/swat/scripting/client/regedit.js
@@ -0,0 +1,160 @@
+/*
+ client side js functions for registry editing
+
+ Copyright Andrew Tridgell 2005
+ released under the GNU GPL Version 2 or later
+*/
+
+
+/*
+ callback from the key enumeration call
+*/
+function __folder_keys(fParent, list)
+{
+ var i;
+ if (fParent.working == 1) {
+ fParent.working = 0;
+ fParent.removeAll();
+ }
+ for (i=0;i<list.length;i++) {
+ var fChild;
+ fChild = new QxTreeFolder(list[i]);
+ fParent.add(fChild);
+ fChild.binding = fParent.binding;
+ if (fParent.reg_path == '\\') {
+ fChild.reg_path = list[i];
+ } else {
+ fChild.reg_path = fParent.reg_path + '\\' + list[i];
+ }
+ fChild.working = 1;
+ fChild.add(new QxTreeFolder('Working ...'));
+ fChild.addEventListener("click", function() {
+ var el = this; __folder_click(el);
+ });
+ }
+ fParent.setOpen(1);
+}
+
+/*
+ callback from the key enumeration call
+*/
+function __folder_values(fParent, list)
+{
+ var i;
+ if (list.length == 0) {
+ return;
+ }
+ if (fParent.working == 1) {
+ fParent.working = 0;
+ fParent.removeAll();
+ }
+ for (i=0;i<list.length;i++) {
+ var fChild;
+ fChild = new QxTreeFile(list[i].name);
+ fChild.parent = fParent;
+ fChild.details = list[i];
+ fParent.add(fChild);
+ }
+ fParent.setOpen(1);
+}
+
+/*
+ called when someone clicks on a folder
+*/
+function __folder_click(node)
+{
+ if (!node.populated) {
+ node.populated = true;
+ server_call_url("/scripting/server/regedit.esp", 'enum_keys',
+ function(list) { __folder_keys(node, list); },
+ node.binding, node.reg_path);
+ server_call_url("/scripting/server/regedit.esp", 'enum_values',
+ function(list) { __folder_values(node, list); },
+ node.binding, node.reg_path);
+ }
+}
+
+/* return a registry tree for the given server */
+function __registry_tree(binding)
+{
+ var tree = new QxTree("registry: " + binding);
+ tree.binding = binding;
+ tree.reg_path = "\\";
+ tree.populated = false;
+ with(tree) {
+ setBackgroundColor(255);
+ setBorder(QxBorder.presets.inset);
+ setOverflow("scroll");
+ setStyleProperty("padding", "2px");
+ setWidth("50%");
+ setHeight("90%");
+ setTop("10%");
+ }
+ tree.addEventListener("click", function() {
+ var el = this; __folder_click(el);
+ });
+ return tree;
+}
+
+/*
+ the table of values
+*/
+function __values_table()
+{
+ var headings = new Array("Name", "Type", "Size", "Value");
+ var table = document.createElement('table');
+ table.border = "1";
+ var body = document.createElement('tbody');
+ table.appendChild(body);
+ var th = document.createElement('th');
+ for (var i=0;i<headings.length;i++) {
+ var td = document.createElement('td');
+ td.appendChild(document.createTextNode(headings[i]));
+ th.appendChild(td);
+ }
+ body.appendChild(th);
+ return table;
+}
+
+/*
+ create a registry editing widget and return it as a object
+*/
+function regedit_widget(binding)
+{
+ var fieldSet = new QxFieldSet();
+
+ fieldSet.binding = binding;
+
+ with(fieldSet) {
+ setWidth("100%");
+ setHeight("100%");
+ };
+
+ var gl = new QxGridLayout("auto,auto,auto,auto,auto", "50%,50%");
+ gl.setEdge(0);
+ gl.setCellPaddingTop(3);
+ gl.setCellPaddingBottom(3);
+
+ var t = __registry_tree(fieldSet.binding);
+
+ function change_binding(e) {
+ fieldSet.binding = e.getNewValue();
+ srv_printf("changed binding to %s\\n", fieldSet.binding);
+ gl.remove(t);
+ t = __registry_tree(fieldSet.binding);
+ gl.add(t, { row : 2, col : 1 });
+ }
+
+ var b = new QxTextField(fieldSet.binding);
+ b.addEventListener("changeText", change_binding);
+
+ var values = new __values_table();
+
+ gl.add(b, { row : 1, col : 1 });
+ gl.add(t, { row : 2, col : 1 });
+// gl.add(values, { row : 2, col : 2 });
+
+ fieldSet.add(gl);
+
+ return fieldSet;
+};
diff --git a/swat/scripting/client/status.js b/swat/scripting/client/status.js
new file mode 100644
index 0000000000..31ee31c43b
--- /dev/null
+++ b/swat/scripting/client/status.js
@@ -0,0 +1,40 @@
+/*
+ server status library for SWAT
+
+ released under the GNU GPL Version 2 or later
+*/
+
+
+// Format for a server status table
+var s = [
+ { id : "server",
+ label : "Server",
+ content: "text",
+ defaultValue : "-",
+ width : 100
+ },
+
+ { id : "status",
+ label : "Status",
+ content: "text",
+ defaultValue : "-",
+ width: 100
+ }
+];
+
+function __load_status_table(info, container)
+{
+ var table = new QxListView(s);
+ var i;
+ for (i in info) {
+ table.addData( {server : i, status : info[i]} );
+ }
+ container.add(table);
+ container.setVisible(true);
+}
+
+function getServerStatus(container)
+{
+ server_call_url("/scripting/server/status.esp", 'serverInfo',
+ function(info) { __load_status_table(info, container); });
+}
diff --git a/swat/scripting/common.js b/swat/scripting/common.js
new file mode 100644
index 0000000000..c111089bd8
--- /dev/null
+++ b/swat/scripting/common.js
@@ -0,0 +1,125 @@
+/*
+ js functions and code common to all pages
+*/
+
+/* define some global variables for this request */
+global.page = new Object();
+
+/* fill in some defaults */
+global.page.title = "Samba Web Administration Tool";
+
+libinclude("base.js");
+
+/* to cope with browsers that don't support cookies we append the sessionid
+ to the URI */
+global.SESSIONURI = "";
+if (request['COOKIE_SUPPORT'] != "True") {
+ global.SESSIONURI="?SwatSessionId=" + request['SESSION_ID'];
+}
+
+/*
+ possibly adjust a local URI to have the session id appended
+ used for browsers that don't support cookies
+*/
+function session_uri(uri) {
+ return uri + global.SESSIONURI;
+}
+
+/*
+ like printf, but to the web page
+*/
+function writef()
+{
+ write(vsprintf(arguments));
+}
+
+/*
+ like writef with a <br>
+*/
+function writefln()
+{
+ write(vsprintf(arguments));
+ write("<br/>\n");
+}
+
+
+/* if the browser was too dumb to set the HOST header, then
+ set it now */
+if (headers['HOST'] == undefined) {
+ headers['HOST'] = server['SERVER_HOST'] + ":" + server['SERVER_PORT'];
+}
+
+/*
+ show the page header. page types include "plain" and "column"
+*/
+function page_header(pagetype, title, menu) {
+ global.page.pagetype = pagetype;
+ global.page.title = title;
+ global.page.menu = menu;
+ include("/scripting/header_" + pagetype + ".esp");
+}
+
+/*
+ show the page footer, getting the page type from page.pagetype
+ set in page_header()
+*/
+function page_footer() {
+ include("/scripting/footer_" + global.page.pagetype + ".esp");
+}
+
+
+/*
+ display a table element
+*/
+function table_element(i, o) {
+ write("<tr><td>" + i + "</td><td>");
+ if (typeof(o[i]) == "object") {
+ var j, first;
+ first = true;
+ for (j in o[i]) {
+ if (first == false) {
+ write("<br />");
+ }
+ write(o[i][j]);
+ first = false;
+ }
+ } else {
+ write(o[i]);
+ }
+ write("</td></tr>\n");
+}
+
+/*
+ display a ejs object as a table. The header is optional
+*/
+function simple_table(v) {
+ if (v.length == 0) {
+ return;
+ }
+ write("<table class=\"data\">\n");
+ var r;
+ for (r in v) {
+ table_element(r, v);
+ }
+ write("</table>\n");
+}
+
+/*
+ display an array of objects, with the header for each element from the given
+ attribute
+*/
+function multi_table(array, header) {
+ var i, n;
+ write("<table class=\"data\">\n");
+ for (i=0;i<array.length;i++) {
+ var r, v = array[i];
+ write('<tr><th colspan="2">' + v[header] + "</th></tr>\n");
+ for (r in v) {
+ if (r != header) {
+ table_element(r, v);
+ }
+ }
+ }
+ write("</table>\n");
+}
+
diff --git a/swat/scripting/footer_columns.esp b/swat/scripting/footer_columns.esp
new file mode 100644
index 0000000000..7b5baaf0c8
--- /dev/null
+++ b/swat/scripting/footer_columns.esp
@@ -0,0 +1,7 @@
+<%
+ /* footer for columns page type */
+%>
+</div>
+</div>
+</body>
+</html>
diff --git a/swat/scripting/footer_desktop.esp b/swat/scripting/footer_desktop.esp
new file mode 100644
index 0000000000..5e563dab88
--- /dev/null
+++ b/swat/scripting/footer_desktop.esp
@@ -0,0 +1,6 @@
+<%
+ /* footer for desktop page type */
+%>
+
+</body>
+</html>
diff --git a/swat/scripting/footer_plain.esp b/swat/scripting/footer_plain.esp
new file mode 100644
index 0000000000..31ef8dd4ee
--- /dev/null
+++ b/swat/scripting/footer_plain.esp
@@ -0,0 +1,7 @@
+<%
+ /* footer for plain page type */
+%>
+</div>
+</div>
+</body>
+</html>
diff --git a/swat/scripting/forms.js b/swat/scripting/forms.js
new file mode 100644
index 0000000000..2de9e34462
--- /dev/null
+++ b/swat/scripting/forms.js
@@ -0,0 +1,112 @@
+/*
+ js functions for forms
+*/
+
+
+/*
+ display a simple form from a ejs Form object
+ caller should fill in
+ f.name = form name
+ f.action = action to be taken on submit (optional, defaults to current page)
+ f.class = css class (optional, defaults to 'form')
+ f.submit = an array of submit labels
+ f.add(name, label, [type], [value]) =
+ Add another element
+ f.element[i].label = element label
+ f.element[i].name = element name (defaults to label)
+ f.element[i].type = element type (defaults to text)
+ f.element[i].value = current value (optional, defaults to "")
+ */
+function form_display() {
+ var f = this;
+ var i, size = 20;
+ write('<form name="' + f.name +
+ '" method="post" action="' + f.action +
+ '" class="' + f.class + '">\n');
+ if (f.element.length > 0) {
+ write("<table>\n");
+ }
+ for (i in f.element) {
+ var e = f.element[i];
+ if (e.name == undefined) {
+ e.name = e.label;
+ }
+ if (e.value == undefined) {
+ e.value = "";
+ }
+ if (strlen(e.value) > size) {
+ size = strlen(e.value) + 4;
+ }
+ }
+ for (i in f.element) {
+ var e = f.element[i];
+ write("<tr>");
+ write("<td>" + e.label + "</td>");
+ if (e.type == "select") {
+ write('<td><select name="' + e.name + '">\n');
+ for (s in e.list) {
+ if (e.value == e.list[s]) {
+ write('<option selected=selected>' + e.list[s] + '</option>\n');
+ } else {
+ write('<option>' + e.list[s] + '</option>\n');
+ }
+ }
+ write('</select></td>\n');
+ } else {
+ var sizestr = "";
+ if (e.type == "text" || e.type == "password") {
+ sizestr = sprintf('size="%d"', size);
+ }
+ writef('<td><input name="%s" type="%s" value="%s" %s /></td>\n',
+ e.name, e.type, e.value, sizestr);
+ }
+ write("</tr>");
+ }
+ if (f.element.length > 0) {
+ write("</table>\n");
+ }
+ for (i in f.submit) {
+ write('<input name="submit" type="submit" value="' + f.submit[i] + '" />\n');
+ }
+ write("</form>\n");
+}
+
+function __addMethod(name, label)
+{
+ var f = this;
+ var i = f.element.length;
+ f.element[i] = new Object();
+ f.element[i].name = name;
+ f.element[i].label = label;
+ f.element[i].type = "text";
+ f.element[i].value = "";
+ if (arguments.length > 2) {
+ f.element[i].type = arguments[2];
+ }
+ if (arguments.length > 3) {
+ f.element[i].value = arguments[3];
+ }
+}
+
+/*
+ create a Form object with the defaults filled in, ready for display()
+ */
+function FormObj(name, num_elements, num_submits)
+{
+ var f = new Object();
+ f.name = name;
+ f.element = new Array(num_elements);
+ f.submit = new Array(num_submits);
+ f.action = session_uri(request.REQUEST_URI);
+ f.class = "defaultform";
+ f.add = __addMethod;
+ for (i in f.element) {
+ f.element[i] = new Object();
+ f.element[i].type = "text";
+ f.element[i].value = "";
+ }
+ f.display = form_display;
+
+ return f;
+}
+
diff --git a/swat/scripting/general_calls.esp b/swat/scripting/general_calls.esp
new file mode 100644
index 0000000000..f17c43205a
--- /dev/null
+++ b/swat/scripting/general_calls.esp
@@ -0,0 +1,25 @@
+<%
+/*
+ used for general purpose calls
+*/
+libinclude("server_call.js");
+
+/* register a call for clients to make */
+var call = servCallObj();
+
+/*
+ a remote printf, for displaying stuff on smbd stdout
+*/
+function srv_printf()
+{
+ var s = string_init();
+ print(s.vsprintf(arguments));
+ return undefined;
+}
+
+/* add some basic calls */
+call.add('srv_printf', srv_printf);
+
+/* run the function that was asked for */
+call.run();
+%>
diff --git a/swat/scripting/header_columns.esp b/swat/scripting/header_columns.esp
new file mode 100644
index 0000000000..2fd57c400c
--- /dev/null
+++ b/swat/scripting/header_columns.esp
@@ -0,0 +1,85 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+
+<script type="text/javascript" src="/style/qooxdoo/widgets/qooxdoo.js"></script>
+
+ <title>@@global.page.title</title>
+
+<link rel="stylesheet" href="/style/common.css" type="text/css" media="all" />
+<link rel="stylesheet" href="/style/columns.css" type="text/css" media="all" />
+<link rel="stylesheet" href="/style/swat.css" type="text/css" media="all" />
+<link rel="stylesheet" href="/style/qooxdoo/layouts/application.css" type="text/css" media="all" />
+<link rel="shortcut icon" href="/images/favicon.ico" />
+
+<!--[if gte IE 5.5]>
+ <style type="text/css">
+ /*<![CDATA[*/
+ .logo_hack {
+filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='/images/logo.png',sizingMethod='scale');
+ }
+ /*]]>*/
+ </style>
+<![endif]-->
+
+<!--[if lte IE 5]>
+ <style type="text/css">
+ /*<![CDATA[*/
+ .logo_hack {
+ background-image:url(/images/logo.gif);
+ background-position:center;
+ background-repeat:no-repeat;
+ top:23.5px;
+ left:-10px;
+ }
+ /*]]>*/
+ </style>
+<![endif]-->
+
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta http-equiv="Content-Language" content="en-us" />
+
+</head>
+
+
+<body>
+
+<div id="banner">
+ <div class="stripe"></div>
+ <div class="logout">
+ <b>logged in as @@session.authinfo.username</b>
+ <form method="post" action="/logout.esp@@global.SESSIONURI">
+ <input type="submit" value="Logout" />
+ </form>
+ </div>
+</div>
+
+<div id="logo">
+ <div class="logo_hack"><a href="/@@global.SESSIONURI"><img src="/images/linkpad.gif" alt="SWAT" /></a></div>
+</div>
+
+<div class="slogan">
+ <h4>Samba Web Administration Tool</h4>
+</div>
+
+<div id="nav">
+ <%
+ include("/menu.js");
+ if (form['menu']) {
+ global.page.menu = form['menu'];
+ }
+ swat_menus[global.page.menu].display();
+ if (global.page.menu != "main") {
+ write('<a href="/">Main Menu</a>');
+ }
+ %>
+</div>
+
+<div id="links">
+ <% swat_menus.docs.display(); %>
+</div>
+
+
+<div id="content">
+ <div id="middle" class="center">
diff --git a/swat/scripting/header_desktop.esp b/swat/scripting/header_desktop.esp
new file mode 100644
index 0000000000..9d02ab323b
--- /dev/null
+++ b/swat/scripting/header_desktop.esp
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta http-equiv="Content-Language" content="en-us" />
+
+ <title>@@global.page.title</title>
+
+<link rel="stylesheet" href="/style/qooxdoo/layouts/application.css" type="text/css" media="all" />
+<link rel="shortcut icon" href="/images/favicon.ico" />
+
+<script type="text/javascript" src="/style/qooxdoo/widgets/qooxdoo.js"></script>
+
+<style type="text/css" media="screen">
+body {
+ background-color:#3A6EA5;
+}
+</style>
+
+</head>
+
+<body>
+
diff --git a/swat/scripting/header_plain.esp b/swat/scripting/header_plain.esp
new file mode 100644
index 0000000000..8dd378910e
--- /dev/null
+++ b/swat/scripting/header_plain.esp
@@ -0,0 +1,55 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+
+ <title>@@global.page.title</title>
+
+<link rel="stylesheet" href="/style/common.css" type="text/css" media="all" />
+<link rel="stylesheet" href="/style/columns.css" type="text/css" media="all" />
+<link rel="stylesheet" href="/style/swat.css" type="text/css" media="all" />
+<link rel="shortcut icon" href="/images/favicon.ico" />
+
+<!--[if gte IE 5.5]>
+ <style type="text/css">
+ /*<![CDATA[*/
+ .logo_hack {
+filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='/images/logo.png',sizingMethod='scale');
+ }
+ /*]]>*/
+ </style>
+<![endif]-->
+
+<!--[if lte IE 5]>
+ <style type="text/css">
+ /*<![CDATA[*/
+ .logo_hack {
+ background-image:url(/images/logo.gif);
+ background-position:center;
+ background-repeat:no-repeat;
+ top:23.5px;
+ left:-10px;
+ }
+ /*]]>*/
+ </style>
+<![endif]-->
+
+</head>
+
+
+<body>
+
+<div id="banner">
+ <div class="stripe"></div>
+</div>
+
+<div id="logo">
+ <div class="logo_hack"><a href="/"><img src="/images/linkpad.gif" alt="SWAT" /></a></div>
+</div>
+
+<div class="slogan">
+ <h4>Samba Web Administration Tool</h4>
+</div>
+
+<div id="content">
+ <div class="center">
diff --git a/swat/scripting/menus.js b/swat/scripting/menus.js
new file mode 100644
index 0000000000..ddd97c4ca3
--- /dev/null
+++ b/swat/scripting/menus.js
@@ -0,0 +1,53 @@
+/*
+ menu object for SWAT
+*/
+
+/*
+ display a menu object. Currently only the "simple", "vertical" menu style
+ is supported
+*/
+function menu_display() {
+ var i, m = this;
+ assert(m.style == "simple" && m.orientation == "vertical");
+ write('<div class="' + m.class + '">\n');
+ write("<i>" + m.name + "</i><br /><ul>\n");
+ for (i = 0; i < m.element.length; i++) {
+ var e = m.element[i];
+ write("<li><a href=\"" + e.link + "\">" + e.label + "</a></li>\n");
+ }
+ write("</ul></div>\n");
+}
+
+
+/*
+ create a menu object with the defaults filled in, ready for display_menu()
+ */
+function MenuObj(name, num_elements)
+{
+ var i, o = new Object();
+ o.name = name;
+ o.class = "menu";
+ o.style = "simple";
+ o.orientation = "vertical"
+ o.element = new Array(num_elements);
+ for (i in o.element) {
+ o.element[i] = new Object();
+ }
+ o.display = menu_display;
+ return o;
+}
+
+/*
+ return a menu object created using a title, followed by
+ a set of label/link pairs
+*/
+function simple_menu() {
+ var i, m = MenuObj(arguments[0], (arguments.length-1)/2);
+ for (i=0;i<m.element.length;i++) {
+ var ndx = i*2;
+ m.element[i].label = arguments[ndx+1];
+ m.element[i].link = arguments[ndx+2];
+ }
+ return m;
+}
+
diff --git a/swat/scripting/preauth.esp b/swat/scripting/preauth.esp
new file mode 100644
index 0000000000..e6d04faf8d
--- /dev/null
+++ b/swat/scripting/preauth.esp
@@ -0,0 +1,48 @@
+<%
+include("/scripting/common.js");
+
+/* this script is called on every web request. If it produces any
+ output at all then that output is returned and the requested page
+ is not given or processed.
+*/
+
+/*
+ check if a uri is one of the 'always allowed' pages, even when not logged in
+ This allows the login page to use the same style sheets and images
+*/
+function always_allowed(uri) {
+ var str = string_init();
+
+ /* allow jsonrpc-based applications to do their own authentication */
+ var s = str.split('/', uri);
+ if (s[0] == "" && s[1] == 'index.html') {
+ return true;
+ }
+
+ var s = str.split('.', uri);
+ if (s.length < 2) {
+ return false;
+ }
+
+ var ext = s[s.length-1];
+ var allowed = new Array("ico", "gif", "png","css", "js");
+ for (i in allowed) {
+ if (allowed[i] == ext) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+if (server['SERVER_PROTOCOL'] == "http" &&
+ server['TLS_SUPPORT'] == "True") {
+ write("redirect to https");
+ redirect("https://" + headers['HOST'] + request['REQUEST_URI']);
+} else if (always_allowed(request['REQUEST_URI']) != true &&
+ session['AUTHENTICATED'] == undefined) {
+ /* present the login page */
+ include("/login.esp");
+}
+
+%>
diff --git a/swat/scripting/server/regedit.esp b/swat/scripting/server/regedit.esp
new file mode 100644
index 0000000000..58ba695c47
--- /dev/null
+++ b/swat/scripting/server/regedit.esp
@@ -0,0 +1,51 @@
+<%
+/*
+ server side AJAJ functions for registry editing. These go along
+ with scripting/client/regedit.js
+*/
+libinclude("base.js");
+libinclude("winreg.js");
+libinclude("server_call.js");
+
+/*
+ server side call to return a listing of keys in a winreg path
+*/
+function enum_keys(binding, path) {
+ printf("enum_keys(%s, %s)\n", binding, path);
+ var reg = winregObj();
+
+ reg.credentials = session.authinfo.credentials;
+
+ var status = reg.connect(binding);
+ if (status.is_ok != true) {
+ printVars(status);
+ return undefined;
+ }
+ return reg.enum_path(path);
+}
+
+/*
+ server side call to return a listing of values in a winreg path
+*/
+function enum_values(binding, path) {
+ printf("enum_values(%s, %s)\n", binding, path);
+ var reg = winregObj();
+
+ reg.credentials = session.authinfo.credentials;
+
+ var status = reg.connect(binding);
+ if (status.is_ok != true) {
+ printVars(status);
+ return undefined;
+ }
+ return reg.enum_values(path);
+}
+
+/* register a call for clients to make */
+var call = servCallObj();
+call.add('enum_keys', enum_keys);
+call.add('enum_values', enum_values);
+
+/* run the function that was asked for */
+call.run();
+%>
diff --git a/swat/scripting/server/status.esp b/swat/scripting/server/status.esp
new file mode 100644
index 0000000000..8ca2067d49
--- /dev/null
+++ b/swat/scripting/server/status.esp
@@ -0,0 +1,27 @@
+<%
+
+libinclude("management.js");
+libinclude("server_call.js");
+
+function serverInfo()
+{
+ var info = new Object();
+ info["NBT Server"] = server_status("nbt");
+ info["WINS Server"] = server_status("wins");
+ info["CLDAP Server"] = server_status("cldap");
+ info["Kerberos Server"] = server_status("kdc");
+ info["SMB Server"] = stream_server_status("smb");
+ info["LDAP Server"] = stream_server_status("ldap");
+ info["RPC Server"] = stream_server_status("rpc");
+
+ return info;
+}
+
+/* register a call for clients to make */
+var call = servCallObj();
+call.add('serverInfo', serverInfo);
+
+/* run the function that was asked for */
+call.run();
+
+%>
diff --git a/swat/scripting/test.ejs b/swat/scripting/test.ejs
new file mode 100644
index 0000000000..8e7047f51c
--- /dev/null
+++ b/swat/scripting/test.ejs
@@ -0,0 +1,10 @@
+
+/*
+ some test ejs code
+*/
+function showArray(name, array) {
+ write("<h3>Array: " + name + "</h3>\n");
+ for (v in array) {
+ write(name + "[" + v + "]=" + array[v] + "<br/>\n");
+ }
+}
diff --git a/swat/scripting/test.esp b/swat/scripting/test.esp
new file mode 100644
index 0000000000..614a42410c
--- /dev/null
+++ b/swat/scripting/test.esp
@@ -0,0 +1,6 @@
+<h3>A esp include file</h3>
+<%
+ function testfn(test) {
+ return "the argument was " + test;
+ }
+%>