Added safety checks if no args are passed
[ajatus.git] / js / ajatus.utils.js
blobaee74390bd6243e814eed969114706735bf35190
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             }
437             setBase64Str(value);
438             var result = '';
439             var inBuffer = new Array(3);
440             var lineCount = 0;
441             var done = false;
442             while (!done && (inBuffer[0] = readBase64()) != END_OF_INPUT) {
443                 inBuffer[1] = readBase64();
444                 inBuffer[2] = readBase64();
445                 result += ($.ajatus.utils.base64.base64Chars[ inBuffer[0] >> 2 ]);
446                 if (inBuffer[1] != END_OF_INPUT) {
447                     result += ($.ajatus.utils.base64.base64Chars[((inBuffer[0] << 4) & 0x30) | (inBuffer[1] >> 4)]);
448                     if (inBuffer[2] != END_OF_INPUT) {
449                         result += ($.ajatus.utils.base64.base64Chars[((inBuffer[1] << 2) & 0x3c) | (inBuffer[2] >> 6) ]);
450                         result += ($.ajatus.utils.base64.base64Chars[inBuffer[2] & 0x3F]);
451                     } else {
452                         result += ($.ajatus.utils.base64.base64Chars[((inBuffer[1] << 2) & 0x3c)]);
453                         result += ('=');
454                         done = true;
455                     }
456                 } else {
457                     result += ($.ajatus.utils.base64.base64Chars[((inBuffer[0] << 4) & 0x30)]);
458                     result += ('=');
459                     result += ('=');
460                     done = true;
461                 }
462                 lineCount += 4;
463                 if (lineCount >= 76) {
464                     result += ('\n');
465                     lineCount = 0;
466                 }
467             }
468             
469             return result;
470         },
471         decode: function(value) {
472             var base64Str;
473             var base64Count;
474             
475             if ($.ajatus.utils.base64.reverseBase64Chars == null) {
476                 for (var i=0; i < $.ajatus.utils.base64.base64Chars.length; i++) {
477                     $.ajatus.utils.base64.reverseBase64Chars[$.ajatus.utils.base64.base64Chars[i]] = i;
478                 }                
479             }
480             
481             function setBase64Str(str) {
482                 base64Str = str;
483                 base64Count = 0;
484             }
486             function readReverseBase64() {   
487                 if (! base64Str) {
488                     return END_OF_INPUT;
489                 }
490                 
491                 while (true) {
492                     if (base64Count >= base64Str.length) {
493                         return END_OF_INPUT;
494                     }
495                     var nextCharacter = base64Str.charAt(base64Count);
496                     base64Count++;
497                     if ($.ajatus.utils.base64.reverseBase64Chars[nextCharacter]){
498                         return $.ajatus.utils.base64.reverseBase64Chars[nextCharacter];
499                     }
500                     if (nextCharacter == 'A') {
501                         return 0;
502                     }
503                 }
504                 return END_OF_INPUT;
505             }
507             function ntos(n){
508                 n=n.toString(16);
509                 if (n.length == 1) n="0"+n;
510                 n="%"+n;
511                 return unescape(n);
512             }
513             
514             setBase64Str(value);
515             var result = "";
516             var inBuffer = new Array(4);
517             var done = false;
518             while (!done && (inBuffer[0] = readReverseBase64()) != END_OF_INPUT
519                 && (inBuffer[1] = readReverseBase64()) != END_OF_INPUT)
520             {
521                 inBuffer[2] = readReverseBase64();
522                 inBuffer[3] = readReverseBase64();
523                 result += ntos((((inBuffer[0] << 2) & 0xff)| inBuffer[1] >> 4));
524                 if (inBuffer[2] != END_OF_INPUT){
525                     result +=  ntos((((inBuffer[1] << 4) & 0xff)| inBuffer[2] >> 2));
526                     if (inBuffer[3] != END_OF_INPUT){
527                         result +=  ntos((((inBuffer[2] << 6)  & 0xff) | inBuffer[3]));
528                     } else {
529                         done = true;
530                     }
531                 } else {
532                     done = true;
533                 }
534             }
535             
536             return result;            
537         }
538     };
539     
540     /**
541      *
542      * UTF-8 data encode / decode
543      * http://www.webtoolkit.info/
544      *
545      * @returns Encoded/Decoded string
546      * @type String
547      */
548     $.ajatus.utils.utf8 = {
549         encode: function(string) {
550             string = string.replace(/\r\n/g,"\n");
551             var utftext = "";
553             for (var n = 0; n < string.length; n++) {
554                 var c = string.charCodeAt(n);
556                 if (c < 128) {
557                     utftext += String.fromCharCode(c);
558                 } else if (   (c > 127)
559                            && (c < 2048))
560                 {
561                     utftext += String.fromCharCode((c >> 6) | 192);
562                     utftext += String.fromCharCode((c & 63) | 128);
563                 } else {
564                     utftext += String.fromCharCode((c >> 12) | 224);
565                     utftext += String.fromCharCode(((c >> 6) & 63) | 128);
566                     utftext += String.fromCharCode((c & 63) | 128);
567                 }
568             }
570             return utftext;
571         },
572         decode: function(utftext) {
573             var string = "";
574             var i = 0;
575             var c = c1 = c2 = 0;
577             while ( i < utftext.length ) {
578                 c = utftext.charCodeAt(i);
580                 if (c < 128) {
581                     string += String.fromCharCode(c);
582                     i++;
583                 } else if (   (c > 191)
584                            && (c < 224))
585                 {
586                     c2 = utftext.charCodeAt(i+1);
587                     string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
588                     i += 2;
589                 } else {
590                     c2 = utftext.charCodeAt(i+1);
591                     c3 = utftext.charCodeAt(i+2);
592                     string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
593                     i += 3;
594                 }
595             }
597             return string;
598         }
599     };
600     
601     $.ajatus.utils.array = {
602         has_match: function(needles, haystack) {
603             if (   typeof haystack != 'object'
604                 || haystack.length <= 0)
605             {
606                 return false;
607             }
609             if (typeof needles == 'object') {
610                 var matched = false;
611                 $.each(needles, function(i,needle){
612                     if ($.inArray(needle, haystack) != -1) {
613                         matched = true;
614                     }
615                     // if (typeof(haystack[needle]) != 'undefined') {
616                     //                         matched = true;
617                     //                     }
618                 });
619                 return matched;
620             } else if (typeof needles == 'string') {
621                 var matched = false;
622                 if ($.inArray(needles, haystack) != -1) {
623                     matched = true;
624                 }
625                 return matched;
626             }
627             
628             return false;
629         }
630     };
631     
632     $.ajatus.utils.object = {
633         clone: function(obj) {
634             if(obj == null || typeof(obj) != 'object') {
635                 return obj;                
636             }
637             var temp = {};
638             for(var key in obj) {
639                 temp[key] = $.ajatus.utils.object.clone(obj[key]);                
640             }
642             return temp;
643         }
644     };
645     
646     // Put focus on given form element (0 == first) (skips hidden fields)
647     $.fn.set_focus_on = function(eid) {
648         var elem = $('input:visible:not(:hidden)', this).get(eid);
649         var select = $('select:visible', this).get(eid);
651         if (select && elem) {
652             if (select.offsetTop < elem.offsetTop) {
653                 elem = select;
654             }
655         }
657         var textarea = $('textarea:visible', this).get(eid);
658         if (textarea && elem) {
659             if (textarea.offsetTop < elem.offsetTop) {
660                 elem = textarea;
661             }
662         }
664         if (elem) {
665             elem.focus();
666         }
668         return this;
669     }
670     
671     $.ajatus.utils.pause = function(ms) {
672         var date = new Date();
673         var currDate = null;
675         do { currDate = new Date(); }
676         while(currDate - date < ms);
677     }
678     
679     $.ajatus.utils.generate_id = function() {
680         var random_key = Math.floor(Math.random()*4013);
681         return (10016486 + (random_key * 22423));
682     }
683     
684     $.ajatus.utils.get_url_arg = function(name) {
685         var value = null;
686         
687         name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
688         var exp = "[\\?&]"+name+"=([^&#]*)";
689         var regex = new RegExp( exp );
690         var results = regex.exec(window.location.href);
691         if (results != null) {
692             value = results[1];
693         }
694         
695         return value;
696     }
697     
698     $.ajatus.utils.load_script = function(url, callback, cb_args) {
699         $('head').append('<script type="text/javascript" charset="utf-8" src="'+url+'"></script>');
700         if (typeof callback == 'string') {
701             if (   typeof cb_args == 'undefined'
702                 || typeof cb_args != 'object')
703             {
704                 var cb_args = [];
705             }
706             
707             setTimeout('eval("var fn = eval('+callback+'); fn.apply(fn, [\''+cb_args.join("','")+'\']);")', 300);
708         }
709     }
710     
711     $.ajatus.utils.doc_generator = function(prefix, count, type, data, value_tpl) {
712         var doc = {
713             _id: '',
714             value: {
715             }
716         };
717         if (typeof value_tpl != 'undefined') {
718             doc.value = value_tpl;
719         }
720         if (typeof type == 'undefined') {
721             var type = $.ajatus.preferences.client.content_types['note'];
722         }
723         if (typeof data == 'undefined') {
724             var data = {
725             }
726         }
727                 
728         $.each(type.original_schema, function(i,n){
729             doc.value[i] = {
730                 val: n.def_val,
731                 widget: n.widget
732             };
733         });
734         
735         var docs = [];
736         
737         if (typeof prefix == 'undefined') {
738             var prefix = 'ajatus';
739         }
740         if (typeof count == 'undefined') {
741             count = 100;
742         }
743         
744         function prepare_title(title, id) {
745             var full_title = title + " ";
746             full_title += (id).toString();
747             return full_title;
748         }
749         
750         for (var i=0; i<count; i++) {
751             var new_doc = new $.ajatus.document(doc);
752             
753             if (   typeof data.title == 'undefined'
754                 && typeof new_doc.value['title'] != 'undefined')
755             {
756                 new_doc.value['title'].val = $.ajatus.i10n.get("Generated doc title (%s)", [prefix]) + " " + i;
757             }
758             
759             $.each(data, function(x,n){
760                 if (typeof new_doc.value[x] != 'undefined') {
761                     new_doc.value[x].val = n;
762                 }
763             });
765             var now = $.ajatus.formatter.date.js_to_iso8601(new Date());
767             var new_metadata = {
768                 created: now,
769                 creator: $.ajatus.preferences.local.user.email,
770                 revised: now,
771                 revisor: $.ajatus.preferences.local.user.email
772             };
774             new_doc = $.ajatus.document.modify_metadata(new_doc, new_metadata);
775             
776             new_doc._id = prefix + "_gen_doc_" + (i).toString();
777             docs.push($.ajatus.utils.object.clone(new_doc));
778         }
779         
780         return docs;
781     }
782     
783     /**
784      * Following functions are taken from the jquery form plugin.
785      * Plugin can be found from http://www.malsup.com/jquery/form/
786      */
787     $.fieldValue = function(el, successful) {
788         var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
789         if (typeof successful == 'undefined') successful = true;
791         if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
792             (t == 'checkbox' || t == 'radio') && !el.checked ||
793             (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
794             tag == 'select' && el.selectedIndex == -1))
795                 return null;
797         if (tag == 'select') {
798             var index = el.selectedIndex;
799             if (index < 0) return null;
800             var a = [], ops = el.options;
801             var one = (t == 'select-one');
802             var max = (one ? index+1 : ops.length);
803             for(var i=(one ? index : 0); i < max; i++) {
804                 var op = ops[i];
805                 if (op.selected) {
806                     // extra pain for IE...
807                     var v = $.browser.msie && !(op.attributes['value'].specified) ? op.text : op.value;
808                     if (one) return v;
809                     a.push(v);
810                 }
811             }
812             return a;
813         }
814         return el.value;
815     };
816         $.fn.formToArray = function(semantic) {
817         var a = [];
818         if (this.length == 0) return a;
820         var form = this[0];
821         var els = semantic ? form.getElementsByTagName('*') : form.elements;
822         if (!els) return a;
823         for(var i=0, max=els.length; i < max; i++) {
824             var el = els[i];
825             var n = el.name;
826             if (!n) continue;
828             if (semantic && form.clk && el.type == "image") {
829                 // handle image inputs on the fly when semantic == true
830                 if(!el.disabled && form.clk == el)
831                     a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
832                 continue;
833             }
835             var v = $.fieldValue(el, true);
836             if (v && v.constructor == Array) {
837                 for(var j=0, jmax=v.length; j < jmax; j++)
838                     a.push({name: n, value: v[j]});
839             }
840             else if (v !== null && typeof v != 'undefined')
841                 a.push({name: n, value: v});
842         }
844         if (!semantic && form.clk) {
845             // input type=='image' are not found in elements array! handle them here
846             var inputs = form.getElementsByTagName("input");
847             for(var i=0, max=inputs.length; i < max; i++) {
848                 var input = inputs[i];
849                 var n = input.name;
850                 if(n && !input.disabled && input.type == "image" && form.clk == input)
851                     a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
852             }
853         }
854         return a;
855     };
856     /**
857      * Form plugin functions end
858      */
859     
860 })(jQuery);