r9754: Upgrading with the command line utility now works, at least partially (-:
[kai/samba.git] / source4 / scripting / libjs / encoder.js
1 /*
2         server side js functions for encoding/decoding objects into linear strings
3
4         Copyright Andrew Tridgell 2005
5         released under the GNU GPL Version 2 or later
6 */
7 /*
8         usage:
9
10           enc = encodeObject(obj);
11           obj = decodeObject(enc);
12
13        The encoded format of the object is a string that is safe to
14        use in URLs
15
16        Note that only data elements are encoded, not functions
17 */
18
19 function __count_members(o) {
20         var i, count = 0;
21         for (i in o) { 
22                 count++;  
23         }
24         if (o.length != undefined) {
25                 count++;
26         }
27         return count;
28 }
29
30 function __replace(str, old, rep) {
31         var s = string_init();
32         var a = s.split(old, str);
33         var j = s.join(rep, a);
34         return s.join(rep, a);
35 }
36
37 function encodeElement(e, name) {
38         var t = typeof(e);
39         var r;
40         var s = string_init();
41         if (t == 'object' && e == null) {
42                 t = 'null';
43         }
44         if (t == 'object') {
45                 r = s.sprintf("%s:%s:%s", name, t, encodeObject(e));
46         } else if (t == "string") {
47                 var enc = s.encodeURIComponent(e);
48                 var rep = __replace(enc, '%', '#');
49                 r = s.sprintf("%s:%s:%s:", 
50                               name, t, __replace(s.encodeURIComponent(e),'%','#'));
51         } else if (t == "boolean" || t == "number") {
52                 r = s.sprintf("%s:%s:%s:", name, t, "" + e);
53         } else if (t == "undefined" || t == "null") {
54                 r = s.sprintf("%s:%s:", name, t);
55         } else if (t == "pointer") {
56                 r = s.sprintf("%s:string:(POINTER):", name);
57         } else {
58                 println("Unable to linearise type " + t);
59                 r = "";
60         }
61         return r;
62 }
63
64 function encodeObject(o) {
65         var s = string_init();
66         var i, r = s.sprintf("%u:", __count_members(o));
67         for (i in o) {
68                 r = r + encodeElement(o[i], i);
69         }
70         if (o.length != undefined) {
71                 r = r + encodeElement(o.length, 'length');
72         }
73         return r;
74 }
75
76 function decodeObjectArray(a) {
77         var s = string_init();
78         var o = new Object();
79         var i, count = a[a.i]; a.i++;
80         for (i=0;i<count;i++) {
81                 var name  = a[a.i]; a.i++;
82                 var type  = a[a.i]; a.i++;
83                 var value;
84                 if (type == 'object') {
85                         o[name] = decodeObjectArray(a);
86                 } else if (type == "string") {
87                         value = s.decodeURIComponent(__replace(a[a.i],'#','%')); a.i++;
88                         o[name] = value;
89                 } else if (type == "boolean") {
90                         value = a[a.i]; a.i++;
91                         if (value == 'true') {
92                                 o[name] = true;
93                         } else {
94                                 o[name] = false;
95                         }
96                 } else if (type == "undefined") {
97                         o[name] = undefined;
98                 } else if (type == "null") {
99                         o[name] = null;
100                 } else if (type == "number") {
101                         value = a[a.i]; a.i++;
102                         o[name] = value + 0;
103                 } else {
104                         println("Unable to delinearise type " + t);
105                         assert(t == "supported type");
106                 }
107         }
108         return o;
109 }
110
111 function decodeObject(str) {
112         var s = string_init();
113         var a = s.split(':', str);
114         a.i = 0;
115         return decodeObjectArray(a);
116 }