summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/scripting/libjs/encoder.js100
-rw-r--r--source4/scripting/libjs/server_call.js95
2 files changed, 195 insertions, 0 deletions
diff --git a/source4/scripting/libjs/encoder.js b/source4/scripting/libjs/encoder.js
new file mode 100644
index 0000000000..65b2854d30
--- /dev/null
+++ b/source4/scripting/libjs/encoder.js
@@ -0,0 +1,100 @@
+/*
+ server 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 __replace(str, old, rep) {
+ var s = string_init();
+ var a = s.split(old, str);
+ var j = s.join(rep, a);
+ return s.join(rep, a);
+}
+
+function encodeObject(o) {
+ var s = string_init();
+ var i, r = s.sprintf("%u:", __count_members(o));
+ for (i in o) {
+ var t = typeof(o[i]);
+ if (t == 'object' && o[i] == null) {
+ t = 'null';
+ }
+ if (t == 'object') {
+ r = s.sprintf("%s%s:%s:%s", r, i, t, encodeObject(o[i]));
+ } else if (t == "string") {
+ var enc = s.encodeURIComponent(o[i]);
+ var rep = __replace(enc, '%', '#');
+ r = s.sprintf("%s%s:%s:%s:",
+ r, i, t, __replace(s.encodeURIComponent(o[i]),'%','#'));
+ } else if (t == "boolean" || t == "number") {
+ r = s.sprintf("%s%s:%s:%s:", r, i, t, "" + o[i]);
+ } else if (t == "undefined" || t == "null") {
+ r = s.sprintf("%s%s:%s:", r, i, t);
+ } else {
+ println("Unable to linearise type " + t);
+ }
+ }
+ return r;
+}
+
+function decodeObjectArray(a) {
+ var s = string_init();
+ 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 = s.decodeURIComponent(__replace(a[a.i],'#','%')); 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 + 0;
+ } else {
+ println("Unable to delinearise type " + t);
+ assert(t == "supported type");
+ }
+ }
+ return o;
+}
+
+function decodeObject(str) {
+ var s = string_init();
+ var a = s.split(':', str);
+ a.i = 0;
+ return decodeObjectArray(a);
+}
diff --git a/source4/scripting/libjs/server_call.js b/source4/scripting/libjs/server_call.js
new file mode 100644
index 0000000000..1ed3053206
--- /dev/null
+++ b/source4/scripting/libjs/server_call.js
@@ -0,0 +1,95 @@
+/*
+ server side js functions for handling async calls from js clients
+
+ Copyright Andrew Tridgell 2005
+ released under the GNU GPL Version 2 or later
+*/
+
+libinclude("encoder.js");
+
+/*
+ a remote printf, for displaying stuff on smbd stdout
+*/
+function __server_printf()
+{
+ print(vsprintf(arguments));
+ return undefined;
+}
+
+/*
+ register a new call
+*/
+function __register_call(name, func)
+{
+ var c = this;
+ c.calls[name] = func;
+}
+
+/*
+ run a call sent from the client, and output the returned object (if any)
+*/
+function __run_call() {
+ var c = this;
+ var name = form['func'];
+ if (name == undefined) {
+ println("no function name given in run_call");
+ return;
+ }
+ var args = form['args'];
+ if (args == undefined) {
+ println("no function arguments given in run_call");
+ return;
+ }
+ args = decodeObject(args);
+ if (c.calls[name] == undefined) {
+ println("undefined remote call " + name);
+ return;
+ }
+ var f = c.calls[name];
+ var res;
+ /* oh what a hack - should write a varargs ejs helper */
+ if (args.length == 0) {
+ res = f();
+ } else if (args.length == 1) {
+ res = f(args[0]);
+ } else if (args.length == 2) {
+ res = f(args[0], args[1]);
+ } else if (args.length == 3) {
+ res = f(args[0], args[1], args[2]);
+ } else if (args.length == 4) {
+ res = f(args[0], args[1], args[2], args[3]);
+ } else if (args.length == 5) {
+ res = f(args[0], args[1], args[2], args[3], args[4]);
+ } else if (args.length == 6) {
+ res = f(args[0], args[1], args[2], args[3], args[4], args[5]);
+ } else if (args.length == 7) {
+ res = f(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
+ } else if (args.length == 8) {
+ res = f(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
+ } else {
+ println("too many arguments for remote call: " + name);
+ return;
+ }
+ var repobj = new Object();
+ repobj.res = res;
+ write(encodeObject(repobj));
+}
+
+
+
+/*
+ initialise a server call object
+*/
+function servCallObj()
+{
+ var c = new Object();
+ c.add = __register_call;
+ c.run = __run_call;
+ c.calls = new Object();
+
+ /* add some basic calls */
+ c.add('printf', __server_printf);
+
+ return c;
+}
+