diff options
-rw-r--r-- | source4/scripting/libjs/encoder.js | 100 | ||||
-rw-r--r-- | source4/scripting/libjs/server_call.js | 95 |
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; +} + |