Added handling for values
[ajatus.git] / js / ajatus.utils.js
blobefd3ef60791ba10af471bdde3272a63b4b027754
1 /*
2  * This file is part of
3  *
4  * Ajatus - Distributed CRM
5  * @requires jQuery v1.2.1
6  * 
7  * Copyright (c) 2007 Jerry Jalava <jerry.jalava@gmail.com>
8  * Copyright (c) 2007 Nemein Oy <http://nemein.com>
9  * Website: http://ajatus.info
10  * Licensed under the GPL license
11  * http://www.gnu.org/licenses/gpl.html
12  * 
13  */
15 (function($){
16     $.ajatus = $.ajatus || {};
17     
18     $.ajatus.utils = {        
19     };
20     
21     $.ajatus.utils.to_boolean = function(value) {
22         if (typeof value == 'boolean') {
23             return value;
24         }
25         
26         if (typeof value == 'string') {
27             if (value === 'true') {
28                 return true;
29             } else if (value === '1') {
30                 return true;
31             }
32             return false;
33         }
35         if (typeof value == 'number') {
36             if (value === 1) {
37                 return true;
38             }
39             return false;
40         }
41         
42         return false;
43     };
45     /**
46      * Renders pretty printed version from given value
47      * Original pretty_print function by Damien Katz <damien_katz@yahoo.com>
48      * Modified to work with Ajatus by Jerry Jalava <jerry.jalava@gmail.com>
49      * @param {Mixed} val Value to render
50      * @param {Number} indent Current indent level (Default: 4)
51      * @param {String} linesep Line break to be used (Default: "\n")
52      * @param {Number} depth Current line depth (Default: 1)
53      * @returns Pretty printed value
54      * @type String
55      */
56     $.ajatus.utils.pretty_print = function(val, indent, linesep, depth) {
57         var indent = typeof indent != 'undefined' ? indent : 4;
58         var linesep = typeof linesep != 'undefined' ? linesep : "\n";
59         var depth = typeof depth != 'undefined' ? depth : 1;
60         
61         var propsep = linesep.length ? "," + linesep : ", ";
63         var tab = [];
65         for (var i = 0; i < indent * depth; i++) {
66             tab.push("")
67         };
68         tab = tab.join(" ");
70         switch (typeof val) {
71             case "boolean":
72             case "number":
73             case "string":
74                 return $.ajatus.converter.toJSON(val);
75             case "object":
76                 if (val === null) {
77                     return "null";
78                 }
79                 if (val.constructor == Date) {
80                     return $.ajatus.converter.toJSON(val);
81                 }
83                 var buf = [];
84                 if (val.constructor == Array) {
85                     buf.push("[");
86                     for (var index = 0; index < val.length; index++) {
87                         buf.push(index > 0 ? propsep : linesep);
88                         buf.push(
89                             tab, $.ajatus.utils.pretty_print(val[index], indent, linesep, depth + 1)
90                         );
91                     }
92                     
93                     if (index >= 0) {
94                         buf.push(linesep, tab.substr(indent))
95                     };
96                     
97                     buf.push("]");
98                 } else {
99                     buf.push("{");
100                     var index = 0;
101                     for (var key in val) {                        
102                         if (! val.hasOwnProperty(key)) {
103                             continue;
104                         };
105                         
106                         buf.push(index > 0 ? propsep : linesep);
107                         buf.push(
108                             tab, $.ajatus.converter.toJSON(key), ": ",
109                             $.ajatus.utils.pretty_print(val[key], indent, linesep, depth + 1)
110                         );
111                         index++;
112                     }
113                     
114                     if (index >= 0) {
115                         buf.push(linesep, tab.substr(indent));
116                     };
117                     
118                     buf.push("}");
119                 }
120                 
121                 return buf.join("");
122             break;
123         }
124     };
126     /**
127      * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
128      * Digest Algorithm, as defined in RFC 1321.
129      * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
130      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
131      * Distributed under the BSD License
132      * See http://pajhome.org.uk/crypt/md5 for more info.
133      *
134      * Modified to work with Ajatus by Jerry Jalava <jerry.jalava@gmail.com>
135      * @param {Mixed} val Value to render
136      * @param {Number} indent Current indent level (Default: 4)
137      * @param {String} linesep Line break to be used (Default: "\n")
138      * @param {Number} depth Current line depth (Default: 1)
139      * @returns Pretty printed value
140      * @type String
141      */
142     $.ajatus.utils.md5 = {
143         _hexcase: 0,  /* hex output format. 0 - lowercase; 1 - uppercase */
144         _b64pad: "", /* base-64 pad character. "=" for strict RFC compliance */
145         _chrsz: 8,  /* bits per input character. 8 - ASCII; 16 - Unicode */
146         
147         /*
148          * Calculate the MD5 of an array of little-endian words, and a bit length
149          */
150         _core_md5: function(x, len) {
151             /* append padding */
152             x[len >> 5] |= 0x80 << ((len) % 32);
153             x[(((len + 64) >>> 9) << 4) + 14] = len;
155             var a =  1732584193;
156             var b = -271733879;
157             var c = -1732584194;
158             var d =  271733878;
160             for (var i = 0; i < x.length; i += 16) {
161                 var olda = a;
162                 var oldb = b;
163                 var oldc = c;
164                 var oldd = d;
166                 a = $.ajatus.utils.md5._md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
167                 d = $.ajatus.utils.md5._md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
168                 c = $.ajatus.utils.md5._md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
169                 b = $.ajatus.utils.md5._md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
170                 a = $.ajatus.utils.md5._md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
171                 d = $.ajatus.utils.md5._md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
172                 c = $.ajatus.utils.md5._md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
173                 b = $.ajatus.utils.md5._md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
174                 a = $.ajatus.utils.md5._md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
175                 d = $.ajatus.utils.md5._md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
176                 c = $.ajatus.utils.md5._md5_ff(c, d, a, b, x[i+10], 17, -42063);
177                 b = $.ajatus.utils.md5._md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
178                 a = $.ajatus.utils.md5._md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
179                 d = $.ajatus.utils.md5._md5_ff(d, a, b, c, x[i+13], 12, -40341101);
180                 c = $.ajatus.utils.md5._md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
181                 b = $.ajatus.utils.md5._md5_ff(b, c, d, a, x[i+15], 22,  1236535329);
183                 a = $.ajatus.utils.md5._md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
184                 d = $.ajatus.utils.md5._md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
185                 c = $.ajatus.utils.md5._md5_gg(c, d, a, b, x[i+11], 14,  643717713);
186                 b = $.ajatus.utils.md5._md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
187                 a = $.ajatus.utils.md5._md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
188                 d = $.ajatus.utils.md5._md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
189                 c = $.ajatus.utils.md5._md5_gg(c, d, a, b, x[i+15], 14, -660478335);
190                 b = $.ajatus.utils.md5._md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
191                 a = $.ajatus.utils.md5._md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
192                 d = $.ajatus.utils.md5._md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
193                 c = $.ajatus.utils.md5._md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
194                 b = $.ajatus.utils.md5._md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
195                 a = $.ajatus.utils.md5._md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
196                 d = $.ajatus.utils.md5._md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
197                 c = $.ajatus.utils.md5._md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
198                 b = $.ajatus.utils.md5._md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
200                 a = $.ajatus.utils.md5._md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
201                 d = $.ajatus.utils.md5._md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
202                 c = $.ajatus.utils.md5._md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
203                 b = $.ajatus.utils.md5._md5_hh(b, c, d, a, x[i+14], 23, -35309556);
204                 a = $.ajatus.utils.md5._md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
205                 d = $.ajatus.utils.md5._md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
206                 c = $.ajatus.utils.md5._md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
207                 b = $.ajatus.utils.md5._md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
208                 a = $.ajatus.utils.md5._md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
209                 d = $.ajatus.utils.md5._md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
210                 c = $.ajatus.utils.md5._md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
211                 b = $.ajatus.utils.md5._md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
212                 a = $.ajatus.utils.md5._md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
213                 d = $.ajatus.utils.md5._md5_hh(d, a, b, c, x[i+12], 11, -421815835);
214                 c = $.ajatus.utils.md5._md5_hh(c, d, a, b, x[i+15], 16,  530742520);
215                 b = $.ajatus.utils.md5._md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
217                 a = $.ajatus.utils.md5._md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
218                 d = $.ajatus.utils.md5._md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
219                 c = $.ajatus.utils.md5._md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
220                 b = $.ajatus.utils.md5._md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
221                 a = $.ajatus.utils.md5._md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
222                 d = $.ajatus.utils.md5._md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
223                 c = $.ajatus.utils.md5._md5_ii(c, d, a, b, x[i+10], 15, -1051523);
224                 b = $.ajatus.utils.md5._md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
225                 a = $.ajatus.utils.md5._md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
226                 d = $.ajatus.utils.md5._md5_ii(d, a, b, c, x[i+15], 10, -30611744);
227                 c = $.ajatus.utils.md5._md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
228                 b = $.ajatus.utils.md5._md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
229                 a = $.ajatus.utils.md5._md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
230                 d = $.ajatus.utils.md5._md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
231                 c = $.ajatus.utils.md5._md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
232                 b = $.ajatus.utils.md5._md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
234                 a = $.ajatus.utils.md5._safe_add(a, olda);
235                 b = $.ajatus.utils.md5._safe_add(b, oldb);
236                 c = $.ajatus.utils.md5._safe_add(c, oldc);
237                 d = $.ajatus.utils.md5._safe_add(d, oldd);
238             }
239           
240             return Array(a, b, c, d);
241         },
242         
243         /*
244          * These functions implement the four basic operations the algorithm uses.
245          */
246         _md5_cmn: function(q, a, b, x, s, t) {
247             return $.ajatus.utils.md5._safe_add($.ajatus.utils.md5._bit_rol($.ajatus.utils.md5._safe_add($.ajatus.utils.md5._safe_add(a, q), $.ajatus.utils.md5._safe_add(x, t)), s),b);
248         },
249         _md5_ff: function(a, b, c, d, x, s, t) {
250             return $.ajatus.utils.md5._md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
251         },
252         _md5_gg: function(a, b, c, d, x, s, t) {
253             return $.ajatus.utils.md5._md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
254         },
255         _md5_hh: function(a, b, c, d, x, s, t) {
256             return $.ajatus.utils.md5._md5_cmn(b ^ c ^ d, a, b, x, s, t);
257         },
258         _md5_ii: function(a, b, c, d, x, s, t) {
259             return $.ajatus.utils.md5._md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
260         },
261         
262         /*
263          * Calculate the HMAC-MD5, of a key and some data
264          */
265         _core_hmac_md5: function(key, data) {
266             var bkey = $.ajatus.utils.md5._str2binl(key);
267             if(bkey.length > 16) bkey = $.ajatus.utils.md5._core_md5(bkey, key.length * $.ajatus.utils.md5._chrsz);
269             var ipad = Array(16), opad = Array(16);
270             for(var i = 0; i < 16; i++) {
271                 ipad[i] = bkey[i] ^ 0x36363636;
272                 opad[i] = bkey[i] ^ 0x5C5C5C5C;
273             }
275             var hash = $.ajatus.utils.md5._core_md5(ipad.concat($.ajatus.utils.md5._str2binl(data)), 512 + data.length * $.ajatus.utils.md5._chrsz);
277             return $.ajatus.utils.md5._core_md5(opad.concat(hash), 512 + 128);
278         },
279         
280         /*
281          * Add integers, wrapping at 2^32. This uses 16-bit operations internally
282          * to work around bugs in some JS interpreters.
283          */
284         _safe_add: function(x, y) {
285             var lsw = (x & 0xFFFF) + (y & 0xFFFF);
286             var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
287             return (msw << 16) | (lsw & 0xFFFF);
288         },
290         /*
291          * Bitwise rotate a 32-bit number to the left.
292          */
293         _bit_rol: function(num, cnt) {
294             return (num << cnt) | (num >>> (32 - cnt));
295         },
297         /*
298          * Convert a string to an array of little-endian words
299          * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
300          */
301         _str2binl: function(str) {
302             var bin = Array();
303             var mask = (1 << $.ajatus.utils.md5._chrsz) - 1;
304             for (var i = 0; i < str.length * $.ajatus.utils.md5._chrsz; i += $.ajatus.utils.md5._chrsz) {
305                 bin[i>>5] |= (str.charCodeAt(i / $.ajatus.utils.md5._chrsz) & mask) << (i%32);
306             }
307             return bin;
308         },
310         /*
311          * Convert an array of little-endian words to a string
312          */
313         _binl2str: function(bin) {
314             var str = "";
315             var mask = (1 << $.ajatus.utils.md5._chrsz) - 1;
316             for(var i = 0; i < bin.length * 32; i += $.ajatus.utils.md5._chrsz) {
317                 str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);                
318             }
319             return str;
320         },
322         /*
323          * Convert an array of little-endian words to a hex string.
324          */
325         _binl2hex: function(binarray) {
326             var hex_tab = $.ajatus.utils.md5._hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
327             var str = "";
328             for (var i = 0; i < binarray.length * 4; i++) {
329                 str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) + hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
330             }
331             return str;
332         },
334         /*
335          * Convert an array of little-endian words to a base-64 string
336          */
337         _binl2b64: function(binarray) {
338             var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
339             var str = "";
340             for (var i = 0; i < binarray.length * 4; i += 3) {
341                 var triplet = (((binarray[i   >> 2] >> 8 * ( i   %4)) & 0xFF) << 16) | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 ) | ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
342                 for (var j = 0; j < 4; j++) {
343                     if (i * 8 + j * 6 > binarray.length * 32) {
344                         str += $.ajatus.utils.md5._b64pad;
345                     } else {
346                         str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
347                     }
348                 }
349             }
350             return str;
351         },
352         
353         _hex_md5: function(s) {
354             return $.ajatus.utils.md5._binl2hex($.ajatus.utils.md5._core_md5($.ajatus.utils.md5._str2binl(s), s.length * $.ajatus.utils.md5._chrsz));
355         },
356         _b64_md5: function(s) {
357             return $.ajatus.utils.md5._binl2b64($.ajatus.utils.md5._core_md5($.ajatus.utils.md5._str2binl(s), s.length * $.ajatus.utils.md5._chrsz));
358         },
359         _str_md5: function(s) {
360             return $.ajatus.utils.md5._binl2str($.ajatus.utils.md5._core_md5($.ajatus.utils.md5._str2binl(s), s.length * $.ajatus.utils.md5._chrsz));
361         },
362         _hex_hmac_md5: function(key, data) {
363             return $.ajatus.utils.md5._binl2hex($.ajatus.utils.md5._core_hmac_md5(key, data));
364         },
365         _b64_hmac_md5: function(key, data) {
366             return $.ajatus.utils.md5._binl2b64($.ajatus.utils.md5._core_hmac_md5(key, data));
367         },
368         _str_hmac_md5: function(key, data) {
369             return $.ajatus.utils.md5._binl2str($.ajatus.utils.md5._core_hmac_md5(key, data));
370         },
371         
372         encode: function(string, encoding, data) {
373             var encoded_string = '';
374             if (typeof encoding == 'undefined') {
375                 var encoding = 'hex';
376             }
377             
378             switch(encoding) {
379                 case 'b64':
380                     encoded_string = $.ajatus.utils.md5._b64_md5(string);
381                 break;
382                 case 'str':
383                     encoded_string = $.ajatus.utils.md5._str_md5(string);
384                 break;
385                 case 'hex_hmac':
386                     encoded_string = $.ajatus.utils.md5._hex_hmac_md5(string, data);
387                 break;
388                 case 'b64_hmac':
389                     encoded_string = $.ajatus.utils.md5._b64_hmac_md5(string, data);
390                 break;
391                 case 'str_hmac':
392                     encoded_string = $.ajatus.utils.md5._str_hmac_md5(string, data);
393                 break;
394                 case 'hex':
395                 default:
396                     encoded_string = $.ajatus.utils.md5._hex_md5(string);
397                 break;
398             }
399             
400             return encoded_string;
401         },
402         match: function(string, md5, encoding) {
403             var encoded_string = $.ajatus.utils.md5.encode(string, encoding);
404             
405             if (encoded_string === md5) {
406                 return true;
407             }
408             
409             return false;
410         }
411     };
412     
413     $.ajatus.utils.base64 = {
414         END_OF_INPUT: -1,
415         base64Chars: [
416             'A','B','C','D','E','F','G','H',
417             'I','J','K','L','M','N','O','P',
418             'Q','R','S','T','U','V','W','X',
419             'Y','Z','a','b','c','d','e','f',
420             'g','h','i','j','k','l','m','n',
421             'o','p','q','r','s','t','u','v',
422             'w','x','y','z','0','1','2','3',
423             '4','5','6','7','8','9','+','/'
424         ],
425         
426         reverseBase64Chars: null,
428         encode: function(value) {
429             var base64Str;
430             var base64Count;
431             
432             function setBase64Str(str) {
433                 base64Str = str;
434                 base64Count = 0;
435             }
436             
437             function readBase64() {
438                 if (! base64Str) {
439                     return $.ajatus.utils.base64.END_OF_INPUT;
440                 }
441                 if (base64Count >= base64Str.length) {
442                     return $.ajatus.utils.base64.END_OF_INPUT;
443                 }
444                 var c = base64Str.charCodeAt(base64Count) & 0xff;
445                 base64Count++;
446                 
447                 return c;
448             }
450             setBase64Str(value);
451             var result = '';
452             var inBuffer = new Array(3);
453             var lineCount = 0;
454             var done = false;
455             while (!done && (inBuffer[0] = readBase64()) != $.ajatus.utils.base64.END_OF_INPUT) {
456                 inBuffer[1] = readBase64();
457                 inBuffer[2] = readBase64();
458                 result += ($.ajatus.utils.base64.base64Chars[ inBuffer[0] >> 2 ]);
459                 if (inBuffer[1] != $.ajatus.utils.base64.END_OF_INPUT) {
460                     result += ($.ajatus.utils.base64.base64Chars[((inBuffer[0] << 4) & 0x30) | (inBuffer[1] >> 4)]);
461                     if (inBuffer[2] != $.ajatus.utils.base64.END_OF_INPUT) {
462                         result += ($.ajatus.utils.base64.base64Chars[((inBuffer[1] << 2) & 0x3c) | (inBuffer[2] >> 6) ]);
463                         result += ($.ajatus.utils.base64.base64Chars[inBuffer[2] & 0x3F]);
464                     } else {
465                         result += ($.ajatus.utils.base64.base64Chars[((inBuffer[1] << 2) & 0x3c)]);
466                         result += ('=');
467                         done = true;
468                     }
469                 } else {
470                     result += ($.ajatus.utils.base64.base64Chars[((inBuffer[0] << 4) & 0x30)]);
471                     result += ('=');
472                     result += ('=');
473                     done = true;
474                 }
475                 lineCount += 4;
476                 if (lineCount >= 76) {
477                     result += ('\n');
478                     lineCount = 0;
479                 }
480             }
481             
482             return result;
483         },
484         decode: function(value) {
485             var base64Str;
486             var base64Count;
487             
488             if ($.ajatus.utils.base64.reverseBase64Chars == null) {
489                 $.ajatus.utils.base64.reverseBase64Chars = [];
490                 for (var i=0; i < $.ajatus.utils.base64.base64Chars.length; i++) {
491                     $.ajatus.utils.base64.reverseBase64Chars[$.ajatus.utils.base64.base64Chars[i]] = i;
492                 }                
493             }
494             
495             function setBase64Str(str) {
496                 base64Str = str;
497                 base64Count = 0;
498             }
500             function readReverseBase64() {   
501                 if (! base64Str) {
502                     return $.ajatus.utils.base64.END_OF_INPUT;
503                 }
504                 
505                 while (true) {
506                     if (base64Count >= base64Str.length) {
507                         return $.ajatus.utils.base64.END_OF_INPUT;
508                     }
509                     var nextCharacter = base64Str.charAt(base64Count);
510                     base64Count++;
511                     if ($.ajatus.utils.base64.reverseBase64Chars[nextCharacter]){
512                         return $.ajatus.utils.base64.reverseBase64Chars[nextCharacter];
513                     }
514                     if (nextCharacter == 'A') {
515                         return 0;
516                     }
517                 }
518                 return $.ajatus.utils.base64.END_OF_INPUT;
519             }
521             function ntos(n) {
522                 n = n.toString(16);
523                 if (n.length == 1) {
524                     n = "0" + n;
525                 }
526                 n = "%" + n;
527                 
528                 return unescape(n);
529             }
530             
531             setBase64Str(value);
532             var result = "";
533             var inBuffer = new Array(4);
534             var done = false;
535             while (!done && (inBuffer[0] = readReverseBase64()) != $.ajatus.utils.base64.END_OF_INPUT
536                 && (inBuffer[1] = readReverseBase64()) != $.ajatus.utils.base64.END_OF_INPUT)
537             {
538                 inBuffer[2] = readReverseBase64();
539                 inBuffer[3] = readReverseBase64();
540                 result += ntos((((inBuffer[0] << 2) & 0xff)| inBuffer[1] >> 4));
541                 if (inBuffer[2] != $.ajatus.utils.base64.END_OF_INPUT){
542                     result +=  ntos((((inBuffer[1] << 4) & 0xff)| inBuffer[2] >> 2));
543                     if (inBuffer[3] != $.ajatus.utils.base64.END_OF_INPUT){
544                         result +=  ntos((((inBuffer[2] << 6)  & 0xff) | inBuffer[3]));
545                     } else {
546                         done = true;
547                     }
548                 } else {
549                     done = true;
550                 }
551             }
552             
553             return result;            
554         }
555     };
556     
557     /**
558      *
559      * UTF-8 data encode / decode
560      * http://www.webtoolkit.info/
561      *
562      * @returns Encoded/Decoded string
563      * @type String
564      */
565     $.ajatus.utils.utf8 = {
566         encode: function(string) {
567             string = string.replace(/\r\n/g,"\n");
568             var utftext = "";
570             for (var n = 0; n < string.length; n++) {
571                 var c = string.charCodeAt(n);
573                 if (c < 128) {
574                     utftext += String.fromCharCode(c);
575                 } else if (   (c > 127)
576                            && (c < 2048))
577                 {
578                     utftext += String.fromCharCode((c >> 6) | 192);
579                     utftext += String.fromCharCode((c & 63) | 128);
580                 } else {
581                     utftext += String.fromCharCode((c >> 12) | 224);
582                     utftext += String.fromCharCode(((c >> 6) & 63) | 128);
583                     utftext += String.fromCharCode((c & 63) | 128);
584                 }
585             }
587             return utftext;
588         },
589         decode: function(utftext) {
590             var string = "";
591             var i = 0;
592             var c = c1 = c2 = 0;
594             while ( i < utftext.length ) {
595                 c = utftext.charCodeAt(i);
597                 if (c < 128) {
598                     string += String.fromCharCode(c);
599                     i++;
600                 } else if (   (c > 191)
601                            && (c < 224))
602                 {
603                     c2 = utftext.charCodeAt(i+1);
604                     string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
605                     i += 2;
606                 } else {
607                     c2 = utftext.charCodeAt(i+1);
608                     c3 = utftext.charCodeAt(i+2);
609                     string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
610                     i += 3;
611                 }
612             }
614             return string;
615         }
616     };
617     
618     $.ajatus.utils.array = {
619         has_match: function(needles, haystack) {
620             if (   typeof haystack != 'object'
621                 || haystack.length <= 0)
622             {
623                 return false;
624             }
626             if (typeof needles == 'object') {
627                 var matched = false;
628                 $.each(needles, function(i,needle){
629                     if ($.inArray(needle, haystack) != -1) {
630                         matched = true;
631                     }
632                     // if (typeof(haystack[needle]) != 'undefined') {
633                     //                         matched = true;
634                     //                     }
635                 });
636                 return matched;
637             } else if (typeof needles == 'string') {
638                 var matched = false;
639                 if ($.inArray(needles, haystack) != -1) {
640                     matched = true;
641                 }
642                 return matched;
643             }
644             
645             return false;
646         }
647     };
648     
649     $.ajatus.utils.object = {
650         clone: function(obj) {
651             if(obj == null || typeof(obj) != 'object') {
652                 return obj;                
653             }
654             var temp = {};
655             for(var key in obj) {
656                 temp[key] = $.ajatus.utils.object.clone(obj[key]);                
657             }
659             return temp;
660         }
661     };
662     
663     $.ajatus.utils.pause = function(ms) {
664         var date = new Date();
665         var currDate = null;
667         do { currDate = new Date(); }
668         while(currDate - date < ms);
669     };
670         
671     $.ajatus.utils._random_key = 0;
672     $.ajatus.utils.generate_id = function() {
673         $.ajatus.utils._random_key += 1;
674         
675         var date = new Date();
676         var random_key = Math.floor(Math.random()*4013);
677         var random_key2 = Math.floor(Math.random()*3104);
678         
679         return $.ajatus.utils.md5.encode(Math.floor(((date.getTime()/1000)+random_key2) + (10016486 + (random_key * 22423)) * random_key / random_key2).toString() + "_" + $.ajatus.utils._random_key).toString().substr(0,8);
680     };
681     
682     $.ajatus.utils.get_url_arg = function(name) {
683         var value = null;
684         
685         name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
686         var exp = "[\\?&]"+name+"=([^&#]*)";
687         var regex = new RegExp( exp );
688         var results = regex.exec(window.location.href);
689         if (results != null) {
690             value = results[1];
691         }
692         
693         return value;
694     };
695     
696     $.ajatus.utils.load_script = function(url, callback, cb_args) {
697         $('head').append('<script type="text/javascript" charset="utf-8" src="'+url+'"></script>');
698         if (typeof callback == 'string') {
699             if (   typeof cb_args == 'undefined'
700                 || typeof cb_args != 'object')
701             {
702                 var cb_args = [];
703             }
704             
705             setTimeout('eval("var fn = eval('+callback+'); fn.apply(fn, [\''+cb_args.join("','")+'\']);")', 300);
706         }
707     };
708     
709     $.ajatus.utils.doc_generator = function(prefix, count, type, data, value_tpl) {
710         var doc = {
711             _id: '',
712             value: {
713             }
714         };
715         if (typeof value_tpl != 'undefined') {
716             doc.value = value_tpl;
717         }
718         if (typeof type == 'undefined') {
719             var type = $.ajatus.preferences.client.content_types['note'];
720         }
721         if (typeof data == 'undefined') {
722             var data = {
723             }
724         }
725                 
726         $.each(type.original_schema, function(i,n){
727             doc.value[i] = {
728                 val: n.def_val,
729                 widget: n.widget
730             };
731         });
732         
733         var docs = [];
734         
735         if (typeof prefix == 'undefined') {
736             var prefix = 'ajatus';
737         }
738         if (typeof count == 'undefined') {
739             count = 100;
740         }
741         
742         function prepare_title(title, id) {
743             var full_title = title + " ";
744             full_title += (id).toString();
745             return full_title;
746         }
747         
748         for (var i=0; i<count; i++) {
749             var new_doc = new $.ajatus.document(doc);
750             
751             if (   typeof data.title == 'undefined'
752                 && typeof new_doc.value['title'] != 'undefined')
753             {
754                 new_doc.value['title'].val = $.ajatus.i10n.get("Generated doc title (%s)", [prefix]) + " " + i;
755             }
756             
757             $.each(data, function(x,n){
758                 if (typeof new_doc.value[x] != 'undefined') {
759                     new_doc.value[x].val = n;
760                 }
761             });
763             var now = $.ajatus.formatter.date.js_to_iso8601(new Date());
765             var new_metadata = {
766                 created: now,
767                 creator: $.ajatus.preferences.local.user.email,
768                 revised: now,
769                 revisor: $.ajatus.preferences.local.user.email
770             };
772             new_doc = $.ajatus.document.modify_metadata(new_doc, new_metadata);
773             
774             new_doc._id = prefix + "_gen_doc_" + (i).toString();
775             docs.push($.ajatus.utils.object.clone(new_doc));
776         }
777         
778         return docs;
779     };
781     // Put focus on given form element (0 == first) (skips hidden fields)
782     $.fn.set_focus_on = function(eid) {
783         var elem = $('input:visible:not(:hidden)', this).get(eid);
784         var select = $('select:visible', this).get(eid);
786         if (select && elem) {
787             if (select.offsetTop < elem.offsetTop) {
788                 elem = select;
789             }
790         }
792         var textarea = $('textarea:visible', this).get(eid);
793         if (textarea && elem) {
794             if (textarea.offsetTop < elem.offsetTop) {
795                 elem = textarea;
796             }
797         }
799         if (elem) {
800             elem.focus();
801         }
803         return this;
804     };
805     
806     /**
807      * Following functions are taken from the jquery form plugin.
808      * Plugin can be found from http://www.malsup.com/jquery/form/
809      */
810     $.fieldValue = function(el, successful) {
811         var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
812         if (typeof successful == 'undefined') successful = true;
814         if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
815             (t == 'checkbox' || t == 'radio') && !el.checked ||
816             (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
817             tag == 'select' && el.selectedIndex == -1))
818                 return null;
820         if (tag == 'select') {
821             var index = el.selectedIndex;
822             if (index < 0) return null;
823             var a = [], ops = el.options;
824             var one = (t == 'select-one');
825             var max = (one ? index+1 : ops.length);
826             for(var i=(one ? index : 0); i < max; i++) {
827                 var op = ops[i];
828                 if (op.selected) {
829                     // extra pain for IE...
830                     var v = $.browser.msie && !(op.attributes['value'].specified) ? op.text : op.value;
831                     if (one) return v;
832                     a.push(v);
833                 }
834             }
835             return a;
836         }
837         return el.value;
838     };
839         $.fn.formToArray = function(semantic) {
840         var a = [];
841         if (this.length == 0) return a;
843         var form = this[0];
844         var els = semantic ? form.getElementsByTagName('*') : form.elements;
845         if (!els) return a;
846         for(var i=0, max=els.length; i < max; i++) {
847             var el = els[i];
848             var n = el.name;
849             if (!n) continue;
851             if (semantic && form.clk && el.type == "image") {
852                 // handle image inputs on the fly when semantic == true
853                 if(!el.disabled && form.clk == el)
854                     a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
855                 continue;
856             }
858             var v = $.fieldValue(el, true);
859             if (v && v.constructor == Array) {
860                 for(var j=0, jmax=v.length; j < jmax; j++)
861                     a.push({name: n, value: v[j]});
862             }
863             else if (v !== null && typeof v != 'undefined')
864                 a.push({name: n, value: v});
865         }
867         if (!semantic && form.clk) {
868             // input type=='image' are not found in elements array! handle them here
869             var inputs = form.getElementsByTagName("input");
870             for(var i=0, max=inputs.length; i < max; i++) {
871                 var input = inputs[i];
872                 var n = input.name;
873                 if(n && !input.disabled && input.type == "image" && form.clk == input)
874                     a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
875             }
876         }
877         return a;
878     };
879     /**
880      * Form plugin functions end
881      */
882     
883 })(jQuery);