Changeset 1435

Show
Ignore:
Timestamp:
03/15/11 21:32:22 (14 months ago)
Author:
winfried
Message:

- Update JSJaC to the latest version, tigase branch
- Adapt chatstates patch to new version of JSJaC
- Use compressed version of JSJaC as standard version

Location:
HelpIM3/branches/chatgroups/htdocs/lib/jsjac
Files:
3 modified

Legend:

Unmodified
Added
Removed
  • HelpIM3/branches/chatgroups/htdocs/lib/jsjac/JSJaC.js

    r960 r1435  
    3636/*** END CONFIG ***/ 
    3737 
    38 /** 
    39  * @fileoverview Collection of functions to make live easier 
    40  * @author Stefan Strigler 
    41  * @version $Revision: 437 $ 
    42  */ 
    43  
    44 /** 
    45  * Convert special chars to HTML entities 
    46  * @addon 
    47  * @return The string with chars encoded for HTML 
    48  * @type String 
    49  */ 
    50 String.prototype.htmlEnc = function() { 
    51   var str = this.replace(/&/g,"&"); 
    52   str = str.replace(/</g,"&lt;"); 
    53   str = str.replace(/>/g,"&gt;"); 
    54   str = str.replace(/\"/g,"&quot;"); 
    55   str = str.replace(/\n/g,"<br />"); 
    56   return str; 
    57 }; 
    58  
    59 /** 
    60  * Converts from jabber timestamps to JavaScript Date objects 
    61  * @addon 
    62  * @param {String} ts A string representing a jabber datetime timestamp as 
    63  * defined by {@link http://www.xmpp.org/extensions/xep-0082.html XEP-0082} 
    64  * @return A javascript Date object corresponding to the jabber DateTime given 
    65  * @type Date 
    66  */ 
    67 Date.jab2date = function(ts) { 
    68   var date = new Date(Date.UTC(ts.substr(0,4),ts.substr(5,2)-1,ts.substr(8,2),ts.substr(11,2),ts.substr(14,2),ts.substr(17,2))); 
    69   if (ts.substr(ts.length-6,1) != 'Z') { // there's an offset 
    70     var offset = new Date(); 
    71     offset.setTime(0); 
    72     offset.setUTCHours(ts.substr(ts.length-5,2)); 
    73     offset.setUTCMinutes(ts.substr(ts.length-2,2)); 
    74     if (ts.substr(ts.length-6,1) == '+') 
    75       date.setTime(date.getTime() - offset.getTime()); 
    76     else if (ts.substr(ts.length-6,1) == '-') 
    77       date.setTime(date.getTime() + offset.getTime()); 
    78   } 
    79   return date; 
    80 }; 
    81  
    82 /** 
    83  * Takes a timestamp in the form of 2004-08-13T12:07:04+02:00 as argument 
    84  * and converts it to some sort of humane readable format 
    85  * @addon 
    86  */ 
    87 Date.hrTime = function(ts) { 
    88   return Date.jab2date(ts).toLocaleString(); 
    89 }; 
    90  
    91 /** 
    92  * somewhat opposit to {@link #hrTime} 
    93  * expects a javascript Date object as parameter and returns a jabber 
    94  * date string conforming to 
    95  * {@link http://www.xmpp.org/extensions/xep-0082.html XEP-0082} 
    96  * @see #hrTime 
    97  * @return The corresponding jabber DateTime string 
    98  * @type String 
    99  */ 
    100 Date.prototype.jabberDate = function() { 
    101   var padZero = function(i) { 
    102     if (i < 10) return "0" + i; 
    103     return i; 
    104   }; 
    105  
    106   var jDate = this.getUTCFullYear() + "-"; 
    107   jDate += padZero(this.getUTCMonth()+1) + "-"; 
    108   jDate += padZero(this.getUTCDate()) + "T"; 
    109   jDate += padZero(this.getUTCHours()) + ":"; 
    110   jDate += padZero(this.getUTCMinutes()) + ":"; 
    111   jDate += padZero(this.getUTCSeconds()) + "Z"; 
    112  
    113   return jDate; 
    114 }; 
    115  
    116 /** 
    117  * Determines the maximum of two given numbers 
    118  * @addon 
    119  * @param {Number} A a number 
    120  * @param {Number} B another number 
    121  * @return the maximum of A and B 
    122  * @type Number 
    123  */ 
    124 Number.max = function(A, B) { 
    125   return (A > B)? A : B; 
    126 }; 
    127 /* Copyright (c) 1998 - 2007, Paul Johnston & Contributors 
    128  * All rights reserved. 
    129  * 
    130  * Redistribution and use in source and binary forms, with or without 
    131  * modification, are permitted provided that the following conditions 
    132  * are met: 
    133  * 
    134  * Redistributions of source code must retain the above copyright 
    135  * notice, this list of conditions and the following 
    136  * disclaimer. Redistributions in binary form must reproduce the above 
    137  * copyright notice, this list of conditions and the following 
    138  * disclaimer in the documentation and/or other materials provided 
    139  * with the distribution. 
    140  * 
    141  * Neither the name of the author nor the names of its contributors 
    142  * may be used to endorse or promote products derived from this 
    143  * software without specific prior written permission. 
    144  * 
    145  * 
    146  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    147  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
    148  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
    149  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
    150  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
    151  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
    152  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
    153  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
    154  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
    155  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
    156  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
    157  * OF THE POSSIBILITY OF SUCH DAMAGE. 
    158  * 
    159  */ 
    160  
    161 /** 
    162  * @fileoverview Collection of MD5 and SHA1 hashing and encoding 
    163  * methods. 
    164  * @author Stefan Strigler steve@zeank.in-berlin.de 
    165  * @version $Revision: 482 $ 
    166  */ 
    167  
    168 /* 
    169  * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined 
    170  * in FIPS PUB 180-1 
    171  * Version 2.1a Copyright Paul Johnston 2000 - 2002. 
    172  * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet 
    173  * Distributed under the BSD License 
    174  * See http://pajhome.org.uk/crypt/md5 for details. 
    175  */ 
    176  
    177 /* 
    178  * Configurable variables. You may need to tweak these to be compatible with 
    179  * the server-side, but the defaults work in most cases. 
    180  */ 
    181 var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */ 
    182 var b64pad  = "="; /* base-64 pad character. "=" for strict RFC compliance   */ 
    183 var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */ 
    184  
    185 /* 
    186  * These are the functions you'll usually want to call 
    187  * They take string arguments and return either hex or base-64 encoded strings 
    188  */ 
    189 function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));} 
    190 function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));} 
    191 function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));} 
    192 function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));} 
    193 function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));} 
    194 function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));} 
    195  
    196 /* 
    197  * Perform a simple self-test to see if the VM is working 
    198  */ 
     38 
     39String.prototype.htmlEnc=function(){var str=this.replace(/&/g,"&amp;");str=str.replace(/</g,"&lt;");str=str.replace(/>/g,"&gt;");str=str.replace(/\"/g,"&quot;");str=str.replace(/\n/g,"<br />");return str;};Date.jab2date=function(ts){var date=new Date(Date.UTC(ts.substr(0,4),ts.substr(5,2)-1,ts.substr(8,2),ts.substr(11,2),ts.substr(14,2),ts.substr(17,2)));if(ts.substr(ts.length-6,1)!='Z'){var offset=new Date();offset.setTime(0);offset.setUTCHours(ts.substr(ts.length-5,2));offset.setUTCMinutes(ts.substr(ts.length-2,2));if(ts.substr(ts.length-6,1)=='+') 
     40date.setTime(date.getTime()-offset.getTime());else if(ts.substr(ts.length-6,1)=='-') 
     41date.setTime(date.getTime()+offset.getTime());} 
     42return date;};Date.hrTime=function(ts){return Date.jab2date(ts).toLocaleString();};Date.prototype.jabberDate=function(){var padZero=function(i){if(i<10)return"0"+i;return i;};var jDate=this.getUTCFullYear()+"-";jDate+=padZero(this.getUTCMonth()+1)+"-";jDate+=padZero(this.getUTCDate())+"T";jDate+=padZero(this.getUTCHours())+":";jDate+=padZero(this.getUTCMinutes())+":";jDate+=padZero(this.getUTCSeconds())+"Z";return jDate;};Number.max=function(A,B){return(A>B)?A:B;};Number.min=function(A,B){return(A<B)?A:B;};var hexcase=0;var b64pad="=";var chrsz=8;function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length*chrsz));} 
     43function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length*chrsz));} 
     44function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length*chrsz));} 
     45function hex_hmac_sha1(key,data){return binb2hex(core_hmac_sha1(key,data));} 
     46function b64_hmac_sha1(key,data){return binb2b64(core_hmac_sha1(key,data));} 
     47function str_hmac_sha1(key,data){return binb2str(core_hmac_sha1(key,data));} 
    19948function sha1_vm_test() 
    200 { 
    201   return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d"; 
    202 } 
    203  
    204 /* 
    205  * Calculate the SHA-1 of an array of big-endian words, and a bit length 
    206  */ 
    207 function core_sha1(x, len) 
    208 { 
    209   /* append padding */ 
    210   x[len >> 5] |= 0x80 << (24 - len % 32); 
    211   x[((len + 64 >> 9) << 4) + 15] = len; 
    212  
    213   var w = Array(80); 
    214   var a =  1732584193; 
    215   var b = -271733879; 
    216   var c = -1732584194; 
    217   var d =  271733878; 
    218   var e = -1009589776; 
    219  
    220   for(var i = 0; i < x.length; i += 16) 
    221     { 
    222       var olda = a; 
    223       var oldb = b; 
    224       var oldc = c; 
    225       var oldd = d; 
    226       var olde = e; 
    227  
    228       for(var j = 0; j < 80; j++) 
    229         { 
    230           if(j < 16) w[j] = x[i + j]; 
    231           else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1); 
    232           var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), 
    233                            safe_add(safe_add(e, w[j]), sha1_kt(j))); 
    234           e = d; 
    235           d = c; 
    236           c = rol(b, 30); 
    237           b = a; 
    238           a = t; 
    239         } 
    240  
    241       a = safe_add(a, olda); 
    242       b = safe_add(b, oldb); 
    243       c = safe_add(c, oldc); 
    244       d = safe_add(d, oldd); 
    245       e = safe_add(e, olde); 
    246     } 
    247   return Array(a, b, c, d, e); 
    248  
    249 } 
    250  
    251 /* 
    252  * Perform the appropriate triplet combination function for the current 
    253  * iteration 
    254  */ 
    255 function sha1_ft(t, b, c, d) 
    256 { 
    257   if(t < 20) return (b & c) | ((~b) & d); 
    258   if(t < 40) return b ^ c ^ d; 
    259   if(t < 60) return (b & c) | (b & d) | (c & d); 
    260   return b ^ c ^ d; 
    261 } 
    262  
    263 /* 
    264  * Determine the appropriate additive constant for the current iteration 
    265  */ 
     49{return hex_sha1("abc")=="a9993e364706816aba3e25717850c26c9cd0d89d";} 
     50function core_sha1(x,len) 
     51{x[len>>5]|=0x80<<(24-len%32);x[((len+64>>9)<<4)+15]=len;var w=Array(80);var a=1732584193;var b=-271733879;var c=-1732584194;var d=271733878;var e=-1009589776;for(var i=0;i<x.length;i+=16) 
     52{var olda=a;var oldb=b;var oldc=c;var oldd=d;var olde=e;for(var j=0;j<80;j++) 
     53{if(j<16)w[j]=x[i+j];else w[j]=rol(w[j-3]^w[j-8]^w[j-14]^w[j-16],1);var t=safe_add(safe_add(rol(a,5),sha1_ft(j,b,c,d)),safe_add(safe_add(e,w[j]),sha1_kt(j)));e=d;d=c;c=rol(b,30);b=a;a=t;} 
     54a=safe_add(a,olda);b=safe_add(b,oldb);c=safe_add(c,oldc);d=safe_add(d,oldd);e=safe_add(e,olde);} 
     55return Array(a,b,c,d,e);} 
     56function sha1_ft(t,b,c,d) 
     57{if(t<20)return(b&c)|((~b)&d);if(t<40)return b^c^d;if(t<60)return(b&c)|(b&d)|(c&d);return b^c^d;} 
    26658function sha1_kt(t) 
    267 { 
    268   return (t < 20) ?  1518500249 : (t < 40) ?  1859775393 : 
    269     (t < 60) ? -1894007588 : -899497514; 
    270 } 
    271  
    272 /* 
    273  * Calculate the HMAC-SHA1 of a key and some data 
    274  */ 
    275 function core_hmac_sha1(key, data) 
    276 { 
    277   var bkey = str2binb(key); 
    278   if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz); 
    279  
    280   var ipad = Array(16), opad = Array(16); 
    281   for(var i = 0; i < 16; i++) 
    282     { 
    283       ipad[i] = bkey[i] ^ 0x36363636; 
    284       opad[i] = bkey[i] ^ 0x5C5C5C5C; 
    285     } 
    286  
    287   var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz); 
    288   return core_sha1(opad.concat(hash), 512 + 160); 
    289 } 
    290  
    291 /* 
    292  * Bitwise rotate a 32-bit number to the left. 
    293  */ 
    294 function rol(num, cnt) 
    295 { 
    296   return (num << cnt) | (num >>> (32 - cnt)); 
    297 } 
    298  
    299 /* 
    300  * Convert an 8-bit or 16-bit string to an array of big-endian words 
    301  * In 8-bit function, characters >255 have their hi-byte silently ignored. 
    302  */ 
     59{return(t<20)?1518500249:(t<40)?1859775393:(t<60)?-1894007588:-899497514;} 
     60function core_hmac_sha1(key,data) 
     61{var bkey=str2binb(key);if(bkey.length>16)bkey=core_sha1(bkey,key.length*chrsz);var ipad=Array(16),opad=Array(16);for(var i=0;i<16;i++) 
     62{ipad[i]=bkey[i]^0x36363636;opad[i]=bkey[i]^0x5C5C5C5C;} 
     63var hash=core_sha1(ipad.concat(str2binb(data)),512+data.length*chrsz);return core_sha1(opad.concat(hash),512+160);} 
     64function rol(num,cnt) 
     65{return(num<<cnt)|(num>>>(32-cnt));} 
    30366function str2binb(str) 
    304 { 
    305   var bin = Array(); 
    306   var mask = (1 << chrsz) - 1; 
    307   for(var i = 0; i < str.length * chrsz; i += chrsz) 
    308     bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32); 
    309   return bin; 
    310 } 
    311  
    312 /* 
    313  * Convert an array of big-endian words to a string 
    314  */ 
     67{var bin=Array();var mask=(1<<chrsz)-1;for(var i=0;i<str.length*chrsz;i+=chrsz) 
     68bin[i>>5]|=(str.charCodeAt(i/chrsz)&mask)<<(32-chrsz-i%32);return bin;} 
    31569function binb2str(bin) 
    316 { 
    317   var str = ""; 
    318   var mask = (1 << chrsz) - 1; 
    319   for(var i = 0; i < bin.length * 32; i += chrsz) 
    320     str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask); 
    321   return str; 
    322 } 
    323  
    324 /* 
    325  * Convert an array of big-endian words to a hex string. 
    326  */ 
     70{var str="";var mask=(1<<chrsz)-1;for(var i=0;i<bin.length*32;i+=chrsz) 
     71str+=String.fromCharCode((bin[i>>5]>>>(32-chrsz-i%32))&mask);return str;} 
    32772function binb2hex(binarray) 
    328 { 
    329   var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; 
    330   var str = ""; 
    331   for(var i = 0; i < binarray.length * 4; i++) 
    332     { 
    333       str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) + 
    334         hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8  )) & 0xF); 
    335     } 
    336   return str; 
    337 } 
    338  
    339 /* 
    340  * Convert an array of big-endian words to a base-64 string 
    341  */ 
     73{var hex_tab=hexcase?"0123456789ABCDEF":"0123456789abcdef";var str="";for(var i=0;i<binarray.length*4;i++) 
     74{str+=hex_tab.charAt((binarray[i>>2]>>((3-i%4)*8+4))&0xF)+ 
     75hex_tab.charAt((binarray[i>>2]>>((3-i%4)*8))&0xF);} 
     76return str;} 
    34277function binb2b64(binarray) 
    343 { 
    344   var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 
    345   var str = ""; 
    346   for(var i = 0; i < binarray.length * 4; i += 3) 
    347     { 
    348       var triplet = (((binarray[i   >> 2] >> 8 * (3 -  i   %4)) & 0xFF) << 16) 
    349         | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 ) 
    350         |  ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF); 
    351       for(var j = 0; j < 4; j++) 
    352         { 
    353           if(i * 8 + j * 6 > binarray.length * 32) str += b64pad; 
    354           else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F); 
    355         } 
    356     } 
    357   return str.replace(/AAA\=(\=*?)$/,'$1'); // cleans garbage chars at end of string 
    358 } 
    359  
    360 /* 
    361  * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message 
    362  * Digest Algorithm, as defined in RFC 1321. 
    363  * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002. 
    364  * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet 
    365  * Distributed under the BSD License 
    366  * See http://pajhome.org.uk/crypt/md5 for more info. 
    367  */ 
    368  
    369 /* 
    370  * Configurable variables. You may need to tweak these to be compatible with 
    371  * the server-side, but the defaults work in most cases. 
    372  */ 
    373 // var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */ 
    374 // var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */ 
    375 // var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */ 
    376  
    377 /* 
    378  * These are the functions you'll usually want to call 
    379  * They take string arguments and return either hex or base-64 encoded strings 
    380  */ 
    381 function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));} 
    382 function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));} 
    383 function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));} 
    384 function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); } 
    385 function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); } 
    386 function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); } 
    387  
    388 /* 
    389  * Perform a simple self-test to see if the VM is working 
    390  */ 
     78{var tab="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";var str="";for(var i=0;i<binarray.length*4;i+=3) 
     79{var triplet=(((binarray[i>>2]>>8*(3-i%4))&0xFF)<<16)|(((binarray[i+1>>2]>>8*(3-(i+1)%4))&0xFF)<<8)|((binarray[i+2>>2]>>8*(3-(i+2)%4))&0xFF);for(var j=0;j<4;j++) 
     80{if(i*8+j*6>binarray.length*32)str+=b64pad;else str+=tab.charAt((triplet>>6*(3-j))&0x3F);}} 
     81return str.replace(/AAA\=(\=*?)$/,'$1');} 
     82function hex_md5(s){return binl2hex(core_md5(str2binl(s),s.length*chrsz));} 
     83function b64_md5(s){return binl2b64(core_md5(str2binl(s),s.length*chrsz));} 
     84function str_md5(s){return binl2str(core_md5(str2binl(s),s.length*chrsz));} 
     85function hex_hmac_md5(key,data){return binl2hex(core_hmac_md5(key,data));} 
     86function b64_hmac_md5(key,data){return binl2b64(core_hmac_md5(key,data));} 
     87function str_hmac_md5(key,data){return binl2str(core_hmac_md5(key,data));} 
    39188function md5_vm_test() 
    392 { 
    393   return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72"; 
    394 } 
    395  
    396 /* 
    397  * Calculate the MD5 of an array of little-endian words, and a bit length 
    398  */ 
    399 function core_md5(x, len) 
    400 { 
    401   /* append padding */ 
    402   x[len >> 5] |= 0x80 << ((len) % 32); 
    403   x[(((len + 64) >>> 9) << 4) + 14] = len; 
    404  
    405   var a =  1732584193; 
    406   var b = -271733879; 
    407   var c = -1732584194; 
    408   var d =  271733878; 
    409  
    410   for(var i = 0; i < x.length; i += 16) 
    411   { 
    412     var olda = a; 
    413     var oldb = b; 
    414     var oldc = c; 
    415     var oldd = d; 
    416  
    417     a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); 
    418     d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); 
    419     c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819); 
    420     b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); 
    421     a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897); 
    422     d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426); 
    423     c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); 
    424     b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); 
    425     a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416); 
    426     d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); 
    427     c = md5_ff(c, d, a, b, x[i+10], 17, -42063); 
    428     b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162); 
    429     a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682); 
    430     d = md5_ff(d, a, b, c, x[i+13], 12, -40341101); 
    431     c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); 
    432     b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329); 
    433  
    434     a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); 
    435     d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); 
    436     c = md5_gg(c, d, a, b, x[i+11], 14,  643717713); 
    437     b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); 
    438     a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); 
    439     d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083); 
    440     c = md5_gg(c, d, a, b, x[i+15], 14, -660478335); 
    441     b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); 
    442     a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438); 
    443     d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); 
    444     c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); 
    445     b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501); 
    446     a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); 
    447     d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); 
    448     c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473); 
    449     b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734); 
    450  
    451     a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); 
    452     d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); 
    453     c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562); 
    454     b = md5_hh(b, c, d, a, x[i+14], 23, -35309556); 
    455     a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); 
    456     d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353); 
    457     c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); 
    458     b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640); 
    459     a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174); 
    460     d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); 
    461     c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); 
    462     b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189); 
    463     a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); 
    464     d = md5_hh(d, a, b, c, x[i+12], 11, -421815835); 
    465     c = md5_hh(c, d, a, b, x[i+15], 16,  530742520); 
    466     b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); 
    467  
    468     a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); 
    469     d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415); 
    470     c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905); 
    471     b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); 
    472     a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571); 
    473     d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); 
    474     c = md5_ii(c, d, a, b, x[i+10], 15, -1051523); 
    475     b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); 
    476     a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359); 
    477     d = md5_ii(d, a, b, c, x[i+15], 10, -30611744); 
    478     c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); 
    479     b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649); 
    480     a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); 
    481     d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379); 
    482     c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259); 
    483     b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); 
    484  
    485     a = safe_add(a, olda); 
    486     b = safe_add(b, oldb); 
    487     c = safe_add(c, oldc); 
    488     d = safe_add(d, oldd); 
    489   } 
    490   return Array(a, b, c, d); 
    491  
    492 } 
    493  
    494 /* 
    495  * These functions implement the four basic operations the algorithm uses. 
    496  */ 
    497 function md5_cmn(q, a, b, x, s, t) 
    498 { 
    499   return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b); 
    500 } 
    501 function md5_ff(a, b, c, d, x, s, t) 
    502 { 
    503   return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); 
    504 } 
    505 function md5_gg(a, b, c, d, x, s, t) 
    506 { 
    507   return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); 
    508 } 
    509 function md5_hh(a, b, c, d, x, s, t) 
    510 { 
    511   return md5_cmn(b ^ c ^ d, a, b, x, s, t); 
    512 } 
    513 function md5_ii(a, b, c, d, x, s, t) 
    514 { 
    515   return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); 
    516 } 
    517  
    518 /* 
    519  * Calculate the HMAC-MD5, of a key and some data 
    520  */ 
    521 function core_hmac_md5(key, data) 
    522 { 
    523   var bkey = str2binl(key); 
    524   if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz); 
    525  
    526   var ipad = Array(16), opad = Array(16); 
    527   for(var i = 0; i < 16; i++) 
    528   { 
    529     ipad[i] = bkey[i] ^ 0x36363636; 
    530     opad[i] = bkey[i] ^ 0x5C5C5C5C; 
    531   } 
    532  
    533   var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz); 
    534   return core_md5(opad.concat(hash), 512 + 128); 
    535 } 
    536  
    537 /* 
    538  * Add integers, wrapping at 2^32. This uses 16-bit operations internally 
    539  * to work around bugs in some JS interpreters. 
    540  */ 
    541 function safe_add(x, y) 
    542 { 
    543   var lsw = (x & 0xFFFF) + (y & 0xFFFF); 
    544   var msw = (x >> 16) + (y >> 16) + (lsw >> 16); 
    545   return (msw << 16) | (lsw & 0xFFFF); 
    546 } 
    547  
    548 /* 
    549  * Bitwise rotate a 32-bit number to the left. 
    550  */ 
    551 function bit_rol(num, cnt) 
    552 { 
    553   return (num << cnt) | (num >>> (32 - cnt)); 
    554 } 
    555  
    556 /* 
    557  * Convert a string to an array of little-endian words 
    558  * If chrsz is ASCII, characters >255 have their hi-byte silently ignored. 
    559  */ 
     89{return hex_md5("abc")=="900150983cd24fb0d6963f7d28e17f72";} 
     90function core_md5(x,len) 
     91{x[len>>5]|=0x80<<((len)%32);x[(((len+64)>>>9)<<4)+14]=len;var a=1732584193;var b=-271733879;var c=-1732584194;var d=271733878;for(var i=0;i<x.length;i+=16) 
     92{var olda=a;var oldb=b;var oldc=c;var oldd=d;a=md5_ff(a,b,c,d,x[i+0],7,-680876936);d=md5_ff(d,a,b,c,x[i+1],12,-389564586);c=md5_ff(c,d,a,b,x[i+2],17,606105819);b=md5_ff(b,c,d,a,x[i+3],22,-1044525330);a=md5_ff(a,b,c,d,x[i+4],7,-176418897);d=md5_ff(d,a,b,c,x[i+5],12,1200080426);c=md5_ff(c,d,a,b,x[i+6],17,-1473231341);b=md5_ff(b,c,d,a,x[i+7],22,-45705983);a=md5_ff(a,b,c,d,x[i+8],7,1770035416);d=md5_ff(d,a,b,c,x[i+9],12,-1958414417);c=md5_ff(c,d,a,b,x[i+10],17,-42063);b=md5_ff(b,c,d,a,x[i+11],22,-1990404162);a=md5_ff(a,b,c,d,x[i+12],7,1804603682);d=md5_ff(d,a,b,c,x[i+13],12,-40341101);c=md5_ff(c,d,a,b,x[i+14],17,-1502002290);b=md5_ff(b,c,d,a,x[i+15],22,1236535329);a=md5_gg(a,b,c,d,x[i+1],5,-165796510);d=md5_gg(d,a,b,c,x[i+6],9,-1069501632);c=md5_gg(c,d,a,b,x[i+11],14,643717713);b=md5_gg(b,c,d,a,x[i+0],20,-373897302);a=md5_gg(a,b,c,d,x[i+5],5,-701558691);d=md5_gg(d,a,b,c,x[i+10],9,38016083);c=md5_gg(c,d,a,b,x[i+15],14,-660478335);b=md5_gg(b,c,d,a,x[i+4],20,-405537848);a=md5_gg(a,b,c,d,x[i+9],5,568446438);d=md5_gg(d,a,b,c,x[i+14],9,-1019803690);c=md5_gg(c,d,a,b,x[i+3],14,-187363961);b=md5_gg(b,c,d,a,x[i+8],20,1163531501);a=md5_gg(a,b,c,d,x[i+13],5,-1444681467);d=md5_gg(d,a,b,c,x[i+2],9,-51403784);c=md5_gg(c,d,a,b,x[i+7],14,1735328473);b=md5_gg(b,c,d,a,x[i+12],20,-1926607734);a=md5_hh(a,b,c,d,x[i+5],4,-378558);d=md5_hh(d,a,b,c,x[i+8],11,-2022574463);c=md5_hh(c,d,a,b,x[i+11],16,1839030562);b=md5_hh(b,c,d,a,x[i+14],23,-35309556);a=md5_hh(a,b,c,d,x[i+1],4,-1530992060);d=md5_hh(d,a,b,c,x[i+4],11,1272893353);c=md5_hh(c,d,a,b,x[i+7],16,-155497632);b=md5_hh(b,c,d,a,x[i+10],23,-1094730640);a=md5_hh(a,b,c,d,x[i+13],4,681279174);d=md5_hh(d,a,b,c,x[i+0],11,-358537222);c=md5_hh(c,d,a,b,x[i+3],16,-722521979);b=md5_hh(b,c,d,a,x[i+6],23,76029189);a=md5_hh(a,b,c,d,x[i+9],4,-640364487);d=md5_hh(d,a,b,c,x[i+12],11,-421815835);c=md5_hh(c,d,a,b,x[i+15],16,530742520);b=md5_hh(b,c,d,a,x[i+2],23,-995338651);a=md5_ii(a,b,c,d,x[i+0],6,-198630844);d=md5_ii(d,a,b,c,x[i+7],10,1126891415);c=md5_ii(c,d,a,b,x[i+14],15,-1416354905);b=md5_ii(b,c,d,a,x[i+5],21,-57434055);a=md5_ii(a,b,c,d,x[i+12],6,1700485571);d=md5_ii(d,a,b,c,x[i+3],10,-1894986606);c=md5_ii(c,d,a,b,x[i+10],15,-1051523);b=md5_ii(b,c,d,a,x[i+1],21,-2054922799);a=md5_ii(a,b,c,d,x[i+8],6,1873313359);d=md5_ii(d,a,b,c,x[i+15],10,-30611744);c=md5_ii(c,d,a,b,x[i+6],15,-1560198380);b=md5_ii(b,c,d,a,x[i+13],21,1309151649);a=md5_ii(a,b,c,d,x[i+4],6,-145523070);d=md5_ii(d,a,b,c,x[i+11],10,-1120210379);c=md5_ii(c,d,a,b,x[i+2],15,718787259);b=md5_ii(b,c,d,a,x[i+9],21,-343485551);a=safe_add(a,olda);b=safe_add(b,oldb);c=safe_add(c,oldc);d=safe_add(d,oldd);} 
     93return Array(a,b,c,d);} 
     94function md5_cmn(q,a,b,x,s,t) 
     95{return safe_add(bit_rol(safe_add(safe_add(a,q),safe_add(x,t)),s),b);} 
     96function md5_ff(a,b,c,d,x,s,t) 
     97{return md5_cmn((b&c)|((~b)&d),a,b,x,s,t);} 
     98function md5_gg(a,b,c,d,x,s,t) 
     99{return md5_cmn((b&d)|(c&(~d)),a,b,x,s,t);} 
     100function md5_hh(a,b,c,d,x,s,t) 
     101{return md5_cmn(b^c^d,a,b,x,s,t);} 
     102function md5_ii(a,b,c,d,x,s,t) 
     103{return md5_cmn(c^(b|(~d)),a,b,x,s,t);} 
     104function core_hmac_md5(key,data) 
     105{var bkey=str2binl(key);if(bkey.length>16)bkey=core_md5(bkey,key.length*chrsz);var ipad=Array(16),opad=Array(16);for(var i=0;i<16;i++) 
     106{ipad[i]=bkey[i]^0x36363636;opad[i]=bkey[i]^0x5C5C5C5C;} 
     107var hash=core_md5(ipad.concat(str2binl(data)),512+data.length*chrsz);return core_md5(opad.concat(hash),512+128);} 
     108function safe_add(x,y) 
     109{var lsw=(x&0xFFFF)+(y&0xFFFF);var msw=(x>>16)+(y>>16)+(lsw>>16);return(msw<<16)|(lsw&0xFFFF);} 
     110function bit_rol(num,cnt) 
     111{return(num<<cnt)|(num>>>(32-cnt));} 
    560112function str2binl(str) 
    561 { 
    562   var bin = Array(); 
    563   var mask = (1 << chrsz) - 1; 
    564   for(var i = 0; i < str.length * chrsz; i += chrsz) 
    565     bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32); 
    566   return bin; 
    567 } 
    568  
    569 /* 
    570  * Convert an array of little-endian words to a string 
    571  */ 
     113{var bin=Array();var mask=(1<<chrsz)-1;for(var i=0;i<str.length*chrsz;i+=chrsz) 
     114bin[i>>5]|=(str.charCodeAt(i/chrsz)&mask)<<(i%32);return bin;} 
    572115function binl2str(bin) 
    573 { 
    574   var str = ""; 
    575   var mask = (1 << chrsz) - 1; 
    576   for(var i = 0; i < bin.length * 32; i += chrsz) 
    577     str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask); 
    578   return str; 
    579 } 
    580  
    581 /* 
    582  * Convert an array of little-endian words to a hex string. 
    583  */ 
     116{var str="";var mask=(1<<chrsz)-1;for(var i=0;i<bin.length*32;i+=chrsz) 
     117str+=String.fromCharCode((bin[i>>5]>>>(i%32))&mask);return str;} 
    584118function binl2hex(binarray) 
    585 { 
    586   var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; 
    587   var str = ""; 
    588   for(var i = 0; i < binarray.length * 4; i++) 
    589   { 
    590     str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) + 
    591            hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF); 
    592   } 
    593   return str; 
    594 } 
    595  
    596 /* 
    597  * Convert an array of little-endian words to a base-64 string 
    598  */ 
     119{var hex_tab=hexcase?"0123456789ABCDEF":"0123456789abcdef";var str="";for(var i=0;i<binarray.length*4;i++) 
     120{str+=hex_tab.charAt((binarray[i>>2]>>((i%4)*8+4))&0xF)+ 
     121hex_tab.charAt((binarray[i>>2]>>((i%4)*8))&0xF);} 
     122return str;} 
    599123function binl2b64(binarray) 
    600 { 
    601   var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 
    602   var str = ""; 
    603   for(var i = 0; i < binarray.length * 4; i += 3) 
    604   { 
    605     var triplet = (((binarray[i   >> 2] >> 8 * ( i   %4)) & 0xFF) << 16) 
    606                 | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 ) 
    607                 |  ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF); 
    608     for(var j = 0; j < 4; j++) 
    609     { 
    610       if(i * 8 + j * 6 > binarray.length * 32) str += b64pad; 
    611       else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F); 
    612     } 
    613   } 
    614   return str; 
    615 } 
    616  
    617 /* ############################################################################# 
    618    UTF-8 Decoder and Encoder 
    619    base64 Encoder and Decoder 
    620    written by Tobias Kieslich, justdreams 
    621    Contact: tobias@justdreams.de                                http://www.justdreams.de/ 
    622    ############################################################################# */ 
    623  
    624 // returns an array of byterepresenting dezimal numbers which represent the 
    625 // plaintext in an UTF-8 encoded version. Expects a string. 
    626 // This function includes an exception management for those nasty browsers like 
    627 // NN401, which returns negative decimal numbers for chars>128. I hate it!! 
    628 // This handling is unfortunately limited to the user's charset. Anyway, it works 
    629 // in most of the cases! Special signs with an unicode>256 return numbers, which 
    630 // can not be converted to the actual unicode and so not to the valid utf-8 
    631 // representation. Anyway, this function does always return values which can not 
    632 // misinterpretd by RC4 or base64 en- or decoding, because every value is >0 and 
    633 // <255!! 
    634 // Arrays are faster and easier to handle in b64 encoding or encrypting.... 
     124{var tab="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";var str="";for(var i=0;i<binarray.length*4;i+=3) 
     125{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);for(var j=0;j<4;j++) 
     126{if(i*8+j*6>binarray.length*32)str+=b64pad;else str+=tab.charAt((triplet>>6*(3-j))&0x3F);}} 
     127return str;} 
    635128function utf8t2d(t) 
    636 { 
    637   t = t.replace(/\r\n/g,"\n"); 
    638   var d=new Array; var test=String.fromCharCode(237); 
    639   if (test.charCodeAt(0) < 0) 
    640     for(var n=0; n<t.length; n++) 
    641       { 
    642         var c=t.charCodeAt(n); 
    643         if (c>0) 
    644           d[d.length]= c; 
    645         else { 
    646           d[d.length]= (((256+c)>>6)|192); 
    647           d[d.length]= (((256+c)&63)|128);} 
    648       } 
    649   else 
    650     for(var n=0; n<t.length; n++) 
    651       { 
    652         var c=t.charCodeAt(n); 
    653         // all the signs of asci => 1byte 
    654         if (c<128) 
    655           d[d.length]= c; 
    656         // all the signs between 127 and 2047 => 2byte 
    657         else if((c>127) && (c<2048)) { 
    658           d[d.length]= ((c>>6)|192); 
    659           d[d.length]= ((c&63)|128);} 
    660         // all the signs between 2048 and 66536 => 3byte 
    661         else { 
    662           d[d.length]= ((c>>12)|224); 
    663           d[d.length]= (((c>>6)&63)|128); 
    664           d[d.length]= ((c&63)|128);} 
    665       } 
    666   return d; 
    667 } 
    668          
    669 // returns plaintext from an array of bytesrepresenting dezimal numbers, which 
    670 // represent an UTF-8 encoded text; browser which does not understand unicode 
    671 // like NN401 will show "?"-signs instead 
    672 // expects an array of byterepresenting decimals; returns a string 
     129{t=t.replace(/\r\n/g,"\n");var d=new Array;var test=String.fromCharCode(237);if(test.charCodeAt(0)<0) 
     130for(var n=0;n<t.length;n++) 
     131{var c=t.charCodeAt(n);if(c>0) 
     132d[d.length]=c;else{d[d.length]=(((256+c)>>6)|192);d[d.length]=(((256+c)&63)|128);}} 
     133else 
     134for(var n=0;n<t.length;n++) 
     135{var c=t.charCodeAt(n);if(c<128) 
     136d[d.length]=c;else if((c>127)&&(c<2048)){d[d.length]=((c>>6)|192);d[d.length]=((c&63)|128);} 
     137else{d[d.length]=((c>>12)|224);d[d.length]=(((c>>6)&63)|128);d[d.length]=((c&63)|128);}} 
     138return d;} 
    673139function utf8d2t(d) 
    674 { 
    675   var r=new Array; var i=0; 
    676   while(i<d.length) 
    677     { 
    678       if (d[i]<128) { 
    679         r[r.length]= String.fromCharCode(d[i]); i++;} 
    680       else if((d[i]>191) && (d[i]<224)) { 
    681         r[r.length]= String.fromCharCode(((d[i]&31)<<6) | (d[i+1]&63)); i+=2;} 
    682       else { 
    683         r[r.length]= String.fromCharCode(((d[i]&15)<<12) | ((d[i+1]&63)<<6) | (d[i+2]&63)); i+=3;} 
    684     } 
    685   return r.join(""); 
    686 } 
    687  
    688 // included in <body onload="b64arrays"> it creates two arrays which makes base64 
    689 // en- and decoding faster 
    690 // this speed is noticeable especially when coding larger texts (>5k or so) 
    691 function b64arrays() { 
    692   var b64s='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; 
    693   b64 = new Array();f64 =new Array(); 
    694   for (var i=0; i<b64s.length ;i++) { 
    695     b64[i] = b64s.charAt(i); 
    696     f64[b64s.charAt(i)] = i; 
    697   } 
    698 } 
    699  
    700 // creates a base64 encoded text out of an array of byerepresenting dezimals 
    701 // it is really base64 :) this makes serversided handling easier 
    702 // expects an array; returns a string 
    703 function b64d2t(d) { 
    704   var r=new Array; var i=0; var dl=d.length; 
    705   // this is for the padding 
    706   if ((dl%3) == 1) { 
    707     d[d.length] = 0; d[d.length] = 0;} 
    708   if ((dl%3) == 2) 
    709     d[d.length] = 0; 
    710   // from here conversion 
    711   while (i<d.length) 
    712     { 
    713       r[r.length] = b64[d[i]>>2]; 
    714       r[r.length] = b64[((d[i]&3)<<4) | (d[i+1]>>4)]; 
    715       r[r.length] = b64[((d[i+1]&15)<<2) | (d[i+2]>>6)]; 
    716       r[r.length] = b64[d[i+2]&63]; 
    717       i+=3; 
    718     } 
    719   // this is again for the padding 
    720   if ((dl%3) == 1) 
    721     r[r.length-1] = r[r.length-2] = "="; 
    722   if ((dl%3) == 2) 
    723     r[r.length-1] = "="; 
    724   // we join the array to return a textstring 
    725   var t=r.join(""); 
    726   return t; 
    727 } 
    728  
    729 // returns array of byterepresenting numbers created of an base64 encoded text 
    730 // it is still the slowest function in this modul; I hope I can make it faster 
    731 // expects string; returns an array 
    732 function b64t2d(t) { 
    733   var d=new Array; var i=0; 
    734   // here we fix this CRLF sequenz created by MS-OS; arrrgh!!! 
    735   t=t.replace(/\n|\r/g,""); t=t.replace(/=/g,""); 
    736   while (i<t.length) 
    737     { 
    738       d[d.length] = (f64[t.charAt(i)]<<2) | (f64[t.charAt(i+1)]>>4); 
    739       d[d.length] = (((f64[t.charAt(i+1)]&15)<<4) | (f64[t.charAt(i+2)]>>2)); 
    740       d[d.length] = (((f64[t.charAt(i+2)]&3)<<6) | (f64[t.charAt(i+3)])); 
    741       i+=4; 
    742     } 
    743   if (t.length%4 == 2) 
    744     d = d.slice(0, d.length-2); 
    745   if (t.length%4 == 3) 
    746     d = d.slice(0, d.length-1); 
    747   return d; 
    748 } 
    749  
    750 if (typeof(atob) == 'undefined' || typeof(btoa) == 'undefined') 
    751   b64arrays(); 
    752  
    753 if (typeof(atob) == 'undefined') { 
    754   atob = function(s) { 
    755     return utf8d2t(b64t2d(s)); 
    756   } 
    757 } 
    758  
    759 if (typeof(btoa) == 'undefined') { 
    760   btoa = function(s) { 
    761     return b64d2t(utf8t2d(s)); 
    762   } 
    763 } 
    764  
    765 function cnonce(size) { 
    766   var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; 
    767   var cnonce = ''; 
    768   for (var i=0; i<size; i++) { 
    769     cnonce += tab.charAt(Math.round(Math.random(new Date().getTime())*(tab.length-1))); 
    770   } 
    771   return cnonce; 
    772 } 
    773 /* Copyright (c) 2005-2007 Sam Stephenson 
    774  * 
    775  * Permission is hereby granted, free of charge, to any person 
    776  * obtaining a copy of this software and associated documentation 
    777  * files (the "Software"), to deal in the Software without 
    778  * restriction, including without limitation the rights to use, copy, 
    779  * modify, merge, publish, distribute, sublicense, and/or sell copies 
    780  * of the Software, and to permit persons to whom the Software is 
    781  * furnished to do so, subject to the following conditions: 
    782  * 
    783  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
    784  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
    785  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
    786  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 
    787  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
    788  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
    789  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
    790  * SOFTWARE. 
    791  */ 
    792  
    793 /* 
    794   json.js 
    795   taken from prototype.js, made static 
    796 */ 
    797 function JSJaCJSON() {} 
    798 JSJaCJSON.toString = function (obj) { 
    799   var m = { 
    800     '\b': '\\b', 
    801     '\t': '\\t', 
    802     '\n': '\\n', 
    803     '\f': '\\f', 
    804     '\r': '\\r', 
    805     '"' : '\\"', 
    806     '\\': '\\\\' 
    807   }, 
    808   s = { 
    809     array: function (x) { 
    810       var a = ['['], b, f, i, l = x.length, v; 
    811       for (i = 0; i < l; i += 1) { 
    812         v = x[i]; 
    813         f = s[typeof v]; 
    814         if (f) { 
    815           try { 
    816             v = f(v); 
    817             if (typeof v == 'string') { 
    818               if (b) { 
    819                 a[a.length] = ','; 
    820               } 
    821               a[a.length] = v; 
    822               b = true; 
    823             } 
    824           } catch(e) {  
    825           } 
    826         } 
    827       } 
    828       a[a.length] = ']'; 
    829       return a.join(''); 
    830     }, 
    831     'boolean': function (x) { 
    832       return String(x); 
    833     }, 
    834     'null': function (x) { 
    835       return "null"; 
    836     }, 
    837     number: function (x) { 
    838       return isFinite(x) ? String(x) : 'null'; 
    839     }, 
    840     object: function (x) { 
    841       if (x) { 
    842         if (x instanceof Array) { 
    843           return s.array(x); 
    844         } 
    845         var a = ['{'], b, f, i, v; 
    846         for (i in x) { 
    847           if (x.hasOwnProperty(i)) { 
    848             v = x[i]; 
    849             f = s[typeof v]; 
    850             if (f) { 
    851               try { 
    852                 v = f(v); 
    853                 if (typeof v == 'string') { 
    854                   if (b) { 
    855                     a[a.length] = ','; 
    856                   } 
    857                   a.push(s.string(i), ':', v); 
    858                   b = true; 
    859                 } 
    860               } catch(e) { 
    861               } 
    862             } 
    863           } 
    864         } 
    865           
    866         a[a.length] = '}'; 
    867         return a.join(''); 
    868       } 
    869       return 'null'; 
    870     }, 
    871     string: function (x) { 
    872       if (/["\\\x00-\x1f]/.test(x)) { 
    873                     x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) { 
    874           var c = m[b]; 
    875           if (c) { 
    876             return c; 
    877           } 
    878           c = b.charCodeAt(); 
    879           return '\\u00' + 
    880           Math.floor(c / 16).toString(16) + 
    881           (c % 16).toString(16); 
    882         }); 
    883   } 
    884   return '"' + x + '"'; 
    885 } 
    886   }; 
    887  
    888 switch (typeof(obj)) { 
    889  case 'object': 
    890    return s.object(obj); 
    891  case 'array': 
    892    return s.array(obj); 
    893     
    894  } 
    895 }; 
    896  
    897 JSJaCJSON.parse = function (str) { 
    898   try { 
    899     return !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test( 
    900                                                        str.replace(/"(\\.|[^"\\])*"/g, ''))) && 
    901             eval('(' + str + ')'); 
    902     } catch (e) { 
    903         return false; 
    904     } 
    905 }; 
    906  
    907 /* Copyright 2006 Erik Arvidsson 
    908  * 
    909  * Licensed under the Apache License, Version 2.0 (the "License"); you 
    910  * may not use this file except in compliance with the License.  You 
    911  * may obtain a copy of the License at 
    912  * 
    913  * http://www.apache.org/licenses/LICENSE-2.0 
    914  * 
    915  * Unless required by applicable law or agreed to in writing, software 
    916  * distributed under the License is distributed on an "AS IS" BASIS, 
    917  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
    918  * implied.  See the License for the specific language governing 
    919  * permissions and limitations under the License. 
    920  */ 
    921  
    922 /** 
    923  * @fileoverview Wrapper to make working with XmlHttpRequest and the 
    924  * DOM more convenient (cross browser compliance). 
    925  * this code is taken from 
    926  * http://webfx.eae.net/dhtml/xmlextras/xmlextras.html 
    927  * @author Stefan Strigler steve@zeank.in-berlin.de 
    928  * @version $Revision: 499 $ 
    929  */ 
    930  
    931 /** 
    932  * XmlHttp factory 
    933  * @private 
    934  */ 
    935 function XmlHttp() {} 
    936  
    937 /** 
    938  * creates a cross browser compliant XmlHttpRequest object 
    939  */ 
    940 XmlHttp.create = function () { 
    941   try { 
    942     if (window.XMLHttpRequest) { 
    943       var req = new XMLHttpRequest(); 
    944       
    945       // some versions of Moz do not support the readyState property 
    946       // and the onreadystate event so we patch it! 
    947       if (req.readyState == null) { 
    948         req.readyState = 1; 
    949         req.addEventListener("load", function () { 
    950                                req.readyState = 4; 
    951                                if (typeof req.onreadystatechange == "function") 
    952                                  req.onreadystatechange(); 
    953                              }, false); 
    954       } 
    955       
    956       return req; 
    957     } 
    958     if (window.ActiveXObject) { 
    959       return new ActiveXObject(XmlHttp.getPrefix() + ".XmlHttp"); 
    960     } 
    961   } 
    962   catch (ex) {} 
    963   // fell through 
    964   throw new Error("Your browser does not support XmlHttp objects"); 
    965 }; 
    966  
    967 /** 
    968  * used to find the Automation server name 
    969  * @private 
    970  */ 
    971 XmlHttp.getPrefix = function() { 
    972   if (XmlHttp.prefix) // I know what you did last summer 
    973     return XmlHttp.prefix; 
    974   
    975   var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"]; 
    976   var o; 
    977   for (var i = 0; i < prefixes.length; i++) { 
    978     try { 
    979       // try to create the objects 
    980       o = new ActiveXObject(prefixes[i] + ".XmlHttp"); 
    981       return XmlHttp.prefix = prefixes[i]; 
    982     } 
    983     catch (ex) {}; 
    984   } 
    985   
    986   throw new Error("Could not find an installed XML parser"); 
    987 }; 
    988  
    989  
    990 /** 
    991  * XmlDocument factory 
    992  * @private 
    993  */ 
    994 function XmlDocument() {} 
    995  
    996 XmlDocument.create = function (name,ns) { 
    997   name = name || 'foo'; 
    998   ns = ns || ''; 
    999  
    1000   try { 
    1001     var doc; 
    1002     // DOM2 
    1003     if (document.implementation && document.implementation.createDocument) { 
    1004       doc = document.implementation.createDocument(ns, name, null); 
    1005       // some versions of Moz do not support the readyState property 
    1006       // and the onreadystate event so we patch it! 
    1007       if (doc.readyState == null) { 
    1008         doc.readyState = 1; 
    1009         doc.addEventListener("load", function () { 
    1010                                doc.readyState = 4; 
    1011                                if (typeof doc.onreadystatechange == "function") 
    1012                                  doc.onreadystatechange(); 
    1013                              }, false); 
    1014       } 
    1015     } else if (window.ActiveXObject) { 
    1016       doc = new ActiveXObject(XmlDocument.getPrefix() + ".DomDocument"); 
    1017     } 
    1018     
    1019     if (!doc.documentElement || doc.documentElement.tagName != name || 
    1020         (doc.documentElement.namespaceURI && 
    1021          doc.documentElement.namespaceURI != ns)) { 
    1022           try { 
    1023             if (ns != '') 
    1024               doc.appendChild(doc.createElement(name)). 
    1025                 setAttribute('xmlns',ns); 
    1026             else 
    1027               doc.appendChild(doc.createElement(name)); 
    1028           } catch (dex) { 
    1029             doc = document.implementation.createDocument(ns,name,null); 
    1030             
    1031             if (doc.documentElement == null) 
    1032               doc.appendChild(doc.createElement(name)); 
    1033  
    1034              // fix buggy opera 8.5x 
    1035             if (ns != '' && 
    1036                 doc.documentElement.getAttribute('xmlns') != ns) { 
    1037               doc.documentElement.setAttribute('xmlns',ns); 
    1038             } 
    1039           } 
    1040         } 
    1041     
    1042     return doc; 
    1043   } 
    1044   catch (ex) { } 
    1045   throw new Error("Your browser does not support XmlDocument objects"); 
    1046 }; 
    1047  
    1048 /** 
    1049  * used to find the Automation server name 
    1050  * @private 
    1051  */ 
    1052 XmlDocument.getPrefix = function() { 
    1053   if (XmlDocument.prefix) 
    1054     return XmlDocument.prefix; 
    1055  
    1056   var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"]; 
    1057   var o; 
    1058   for (var i = 0; i < prefixes.length; i++) { 
    1059     try { 
    1060       // try to create the objects 
    1061       o = new ActiveXObject(prefixes[i] + ".DomDocument"); 
    1062       return XmlDocument.prefix = prefixes[i]; 
    1063     } 
    1064     catch (ex) {}; 
    1065   } 
    1066   
    1067   throw new Error("Could not find an installed XML parser"); 
    1068 }; 
    1069  
    1070  
    1071 // Create the loadXML method 
    1072 if (typeof(Document) != 'undefined' && window.DOMParser) { 
    1073  
    1074   /** 
    1075    * XMLDocument did not extend the Document interface in some 
    1076    * versions of Mozilla. 
    1077    * @private 
    1078    */ 
    1079   Document.prototype.loadXML = function (s) { 
    1080          
    1081     // parse the string to a new doc 
    1082     var doc2 = (new DOMParser()).parseFromString(s, "text/xml"); 
    1083          
    1084     // remove all initial children 
    1085     while (this.hasChildNodes()) 
    1086       this.removeChild(this.lastChild); 
    1087                  
    1088     // insert and import nodes 
    1089     for (var i = 0; i < doc2.childNodes.length; i++) { 
    1090       this.appendChild(this.importNode(doc2.childNodes[i], true)); 
    1091     } 
    1092   }; 
    1093  } 
    1094  
    1095 // Create xml getter for Mozilla 
    1096 if (window.XMLSerializer && 
    1097     window.Node && Node.prototype && Node.prototype.__defineGetter__) { 
    1098  
    1099   /** 
    1100    * xml getter 
    1101    * 
    1102    * This serializes the DOM tree to an XML String 
    1103    * 
    1104    * Usage: var sXml = oNode.xml 
    1105    * @deprecated 
    1106    * @private 
    1107    */ 
    1108   // XMLDocument did not extend the Document interface in some versions 
    1109   // of Mozilla. Extend both! 
    1110   XMLDocument.prototype.__defineGetter__("xml", function () { 
    1111                                            return (new XMLSerializer()).serializeToString(this); 
    1112                                          }); 
    1113   /** 
    1114    * xml getter 
    1115    * 
    1116    * This serializes the DOM tree to an XML String 
    1117    * 
    1118    * Usage: var sXml = oNode.xml 
    1119    * @deprecated 
    1120    * @private 
    1121    */ 
    1122   Document.prototype.__defineGetter__("xml", function () { 
    1123                                         return (new XMLSerializer()).serializeToString(this); 
    1124                                       }); 
    1125  
    1126   /** 
    1127    * xml getter 
    1128    * 
    1129    * This serializes the DOM tree to an XML String 
    1130    * 
    1131    * Usage: var sXml = oNode.xml 
    1132    * @deprecated 
    1133    * @private 
    1134    */ 
    1135   Node.prototype.__defineGetter__("xml", function () { 
    1136                                     return (new XMLSerializer()).serializeToString(this); 
    1137                                   }); 
    1138  } 
    1139 /* Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) 
    1140  * 
    1141  * Permission is hereby granted, free of charge, to any person 
    1142  * obtaining a copy of this software and associated documentation 
    1143  * files (the "Software"), to deal in the Software without 
    1144  * restriction, including without limitation the rights to use, copy, 
    1145  * modify, merge, publish, distribute, sublicense, and/or sell copies 
    1146  * of the Software, and to permit persons to whom the Software is 
    1147  * furnished to do so, subject to the following conditions: 
    1148  * 
    1149  * The above copyright notice and this permission notice shall be 
    1150  * included in all copies or substantial portions of the Software. 
    1151  * 
    1152  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
    1153  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
    1154  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
    1155  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 
    1156  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
    1157  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
    1158  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
    1159  * SOFTWARE. 
    1160  */ 
    1161  
    1162 /** 
    1163  * @private 
    1164  * This code is taken from {@link 
    1165  * http://wiki.script.aculo.us/scriptaculous/show/Builder 
    1166  * script.aculo.us' Dom Builder} and has been modified to suit our 
    1167  * needs.<br/> 
    1168  * The original parts of the code do have the following 
    1169  * copyright and license notice:<br/> 
    1170  * Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, 
    1171  * http://mir.acu lo.us) <br/> 
    1172  * script.aculo.us is freely distributable under the terms of an 
    1173  * MIT-style license.<br> 
    1174  * For details, see the script.aculo.us web site: 
    1175  * http://script.aculo.us/<br> 
    1176  */ 
    1177 var JSJaCBuilder = { 
    1178   /** 
    1179    * @private 
    1180    */ 
    1181   buildNode: function(doc, elementName) { 
    1182  
    1183     var element, ns = arguments[4]; 
    1184  
    1185     // attributes (or text) 
    1186     if(arguments[2]) 
    1187       if(JSJaCBuilder._isStringOrNumber(arguments[2]) || 
    1188          (arguments[2] instanceof Array)) { 
    1189         element = this._createElement(doc, elementName, ns); 
    1190         JSJaCBuilder._children(doc, element, arguments[2]); 
    1191       } else { 
    1192         ns = arguments[2]['xmlns'] || ns; 
    1193         element = this._createElement(doc, elementName, ns); 
    1194         for(attr in arguments[2]) { 
    1195           if (arguments[2].hasOwnProperty(attr) && attr != 'xmlns') 
    1196             element.setAttribute(attr, arguments[2][attr]); 
    1197         } 
    1198       } 
    1199     else 
    1200       element = this._createElement(doc, elementName, ns); 
    1201     // text, or array of children 
    1202     if(arguments[3]) 
    1203       JSJaCBuilder._children(doc, element, arguments[3], ns); 
    1204  
    1205     return element; 
    1206   }, 
    1207  
    1208   _createElement: function(doc, elementName, ns) { 
    1209     try { 
    1210       if (ns) 
    1211         return doc.createElementNS(ns, elementName); 
    1212     } catch (ex) { } 
    1213  
    1214     var el = doc.createElement(elementName); 
    1215  
    1216     if (ns) 
    1217       el.setAttribute("xmlns", ns); 
    1218  
    1219     return el; 
    1220   }, 
    1221  
    1222   /** 
    1223    * @private 
    1224    */ 
    1225   _text: function(doc, text) { 
    1226     return doc.createTextNode(text); 
    1227   }, 
    1228  
    1229   /** 
    1230    * @private 
    1231    */ 
    1232   _children: function(doc, element, children, ns) { 
    1233     if(typeof children=='object') { // array can hold nodes and text 
    1234       for (var i in children) { 
    1235         if (children.hasOwnProperty(i)) { 
    1236           var e = children[i]; 
    1237           if (typeof e=='object') { 
    1238             if (e instanceof Array) { 
    1239               var node = JSJaCBuilder.buildNode(doc, e[0], e[1], e[2], ns); 
    1240               element.appendChild(node); 
    1241             } else { 
    1242               element.appendChild(e); 
    1243             } 
    1244           } else { 
    1245             if(JSJaCBuilder._isStringOrNumber(e)) { 
    1246               element.appendChild(JSJaCBuilder._text(doc, e)); 
    1247             } 
    1248           } 
    1249         } 
    1250       } 
    1251     } else { 
    1252       if(JSJaCBuilder._isStringOrNumber(children)) { 
    1253         element.appendChild(JSJaCBuilder._text(doc, children)); 
    1254       } 
    1255     } 
    1256   }, 
    1257  
    1258   _attributes: function(attributes) { 
    1259     var attrs = []; 
    1260     for(attribute in attributes) 
    1261       if (attributes.hasOwnProperty(attribute)) 
    1262         attrs.push(attribute + 
    1263           '="' + attributes[attribute].toString().htmlEnc() + '"'); 
    1264     return attrs.join(" "); 
    1265   }, 
    1266  
    1267   _isStringOrNumber: function(param) { 
    1268     return(typeof param=='string' || typeof param=='number'); 
    1269   } 
    1270 }; 
    1271 var NS_DISCO_ITEMS =  "http://jabber.org/protocol/disco#items"; 
    1272 var NS_DISCO_INFO =   "http://jabber.org/protocol/disco#info"; 
    1273 var NS_VCARD =        "vcard-temp"; 
    1274 var NS_AUTH =         "jabber:iq:auth"; 
    1275 var NS_AUTH_ERROR =   "jabber:iq:auth:error"; 
    1276 var NS_REGISTER =     "jabber:iq:register"; 
    1277 var NS_SEARCH =       "jabber:iq:search"; 
    1278 var NS_ROSTER =       "jabber:iq:roster"; 
    1279 var NS_PRIVACY =      "jabber:iq:privacy"; 
    1280 var NS_PRIVATE =      "jabber:iq:private"; 
    1281 var NS_VERSION =      "jabber:iq:version"; 
    1282 var NS_TIME =         "jabber:iq:time"; 
    1283 var NS_LAST =         "jabber:iq:last"; 
    1284 var NS_XDATA =        "jabber:x:data"; 
    1285 var NS_IQDATA =       "jabber:iq:data"; 
    1286 var NS_DELAY =        "jabber:x:delay"; 
    1287 var NS_EXPIRE =       "jabber:x:expire"; 
    1288 var NS_EVENT =        "jabber:x:event"; 
    1289 var NS_XCONFERENCE =  "jabber:x:conference"; 
    1290 var NS_STATS =        "http://jabber.org/protocol/stats"; 
    1291 var NS_MUC =          "http://jabber.org/protocol/muc"; 
    1292 var NS_MUC_USER =     "http://jabber.org/protocol/muc#user"; 
    1293 var NS_MUC_ADMIN =    "http://jabber.org/protocol/muc#admin"; 
    1294 var NS_MUC_OWNER =    "http://jabber.org/protocol/muc#owner"; 
    1295 var NS_PUBSUB =       "http://jabber.org/protocol/pubsub"; 
    1296 var NS_PUBSUB_EVENT = "http://jabber.org/protocol/pubsub#event"; 
    1297 var NS_PUBSUB_OWNER = "http://jabber.org/protocol/pubsub#owner"; 
    1298 var NS_PUBSUB_NMI =   "http://jabber.org/protocol/pubsub#node-meta-info"; 
    1299 var NS_COMMANDS =     "http://jabber.org/protocol/commands"; 
    1300 var NS_STREAM =       "http://etherx.jabber.org/streams"; 
    1301 var NS_CHAT_STATES =  "http://jabber.org/protocol/chatstates"; 
    1302  
    1303 var NS_STANZAS =      "urn:ietf:params:xml:ns:xmpp-stanzas"; 
    1304 var NS_STREAMS =      "urn:ietf:params:xml:ns:xmpp-streams"; 
    1305  
    1306 var NS_TLS =          "urn:ietf:params:xml:ns:xmpp-tls"; 
    1307 var NS_SASL =         "urn:ietf:params:xml:ns:xmpp-sasl"; 
    1308 var NS_SESSION =      "urn:ietf:params:xml:ns:xmpp-session"; 
    1309 var NS_BIND =         "urn:ietf:params:xml:ns:xmpp-bind"; 
    1310  
    1311 var NS_FEATURE_IQAUTH = "http://jabber.org/features/iq-auth"; 
    1312 var NS_FEATURE_IQREGISTER = "http://jabber.org/features/iq-register"; 
    1313 var NS_FEATURE_COMPRESS = "http://jabber.org/features/compress"; 
    1314  
    1315 var NS_COMPRESS =     "http://jabber.org/protocol/compress"; 
    1316  
    1317 function STANZA_ERROR(code, type, cond) { 
    1318   if (window == this) 
    1319     return new STANZA_ERROR(code, type, cond); 
    1320  
    1321   this.code = code; 
    1322   this.type = type; 
    1323   this.cond = cond; 
    1324 } 
    1325  
    1326 var ERR_BAD_REQUEST = 
    1327         STANZA_ERROR("400", "modify", "bad-request"); 
    1328 var ERR_CONFLICT = 
    1329         STANZA_ERROR("409", "cancel", "conflict"); 
    1330 var ERR_FEATURE_NOT_IMPLEMENTED = 
    1331         STANZA_ERROR("501", "cancel", "feature-not-implemented"); 
    1332 var ERR_FORBIDDEN = 
    1333         STANZA_ERROR("403", "auth",   "forbidden"); 
    1334 var ERR_GONE = 
    1335         STANZA_ERROR("302", "modify", "gone"); 
    1336 var ERR_INTERNAL_SERVER_ERROR = 
    1337         STANZA_ERROR("500", "wait",   "internal-server-error"); 
    1338 var ERR_ITEM_NOT_FOUND = 
    1339         STANZA_ERROR("404", "cancel", "item-not-found"); 
    1340 var ERR_JID_MALFORMED = 
    1341         STANZA_ERROR("400", "modify", "jid-malformed"); 
    1342 var ERR_NOT_ACCEPTABLE = 
    1343         STANZA_ERROR("406", "modify", "not-acceptable"); 
    1344 var ERR_NOT_ALLOWED = 
    1345         STANZA_ERROR("405", "cancel", "not-allowed"); 
    1346 var ERR_NOT_AUTHORIZED = 
    1347         STANZA_ERROR("401", "auth",   "not-authorized"); 
    1348 var ERR_PAYMENT_REQUIRED = 
    1349         STANZA_ERROR("402", "auth",   "payment-required"); 
    1350 var ERR_RECIPIENT_UNAVAILABLE = 
    1351         STANZA_ERROR("404", "wait",   "recipient-unavailable"); 
    1352 var ERR_REDIRECT = 
    1353         STANZA_ERROR("302", "modify", "redirect"); 
    1354 var ERR_REGISTRATION_REQUIRED = 
    1355         STANZA_ERROR("407", "auth",   "registration-required"); 
    1356 var ERR_REMOTE_SERVER_NOT_FOUND = 
    1357         STANZA_ERROR("404", "cancel", "remote-server-not-found"); 
    1358 var ERR_REMOTE_SERVER_TIMEOUT = 
    1359         STANZA_ERROR("504", "wait",   "remote-server-timeout"); 
    1360 var ERR_RESOURCE_CONSTRAINT = 
    1361         STANZA_ERROR("500", "wait",   "resource-constraint"); 
    1362 var ERR_SERVICE_UNAVAILABLE = 
    1363         STANZA_ERROR("503", "cancel", "service-unavailable"); 
    1364 var ERR_SUBSCRIPTION_REQUIRED = 
    1365         STANZA_ERROR("407", "auth",   "subscription-required"); 
    1366 var ERR_UNEXPECTED_REQUEST = 
    1367         STANZA_ERROR("400", "wait",   "unexpected-request"); 
    1368  
    1369 /** 
    1370  * @fileoverview Contains Debugger interface for Firebug and Safari 
    1371  * @class Implementation of the Debugger interface for {@link 
    1372  * http://www.getfirebug.com/ Firebug} and Safari 
    1373  * Creates a new debug logger to be passed to jsjac's connection 
    1374  * constructor. Of course you can use it for debugging in your code 
    1375  * too. 
    1376  * @constructor 
    1377  * @param {int} level The maximum level for debugging messages to be 
    1378  * displayed. Thus you can tweak the verbosity of the logger. A value 
    1379  * of 0 means very low traffic whilst a value of 4 makes logging very 
    1380  * verbose about what's going on. 
    1381  */ 
    1382 function JSJaCConsoleLogger(level) { 
    1383   /** 
    1384    * @private 
    1385    */ 
    1386   this.level = level || 4; 
    1387  
    1388   /** 
    1389    * Empty function for API compatibility 
    1390    */ 
    1391   this.start = function() {}; 
    1392   /** 
    1393    * Logs a message to firebug's/safari's console 
    1394    * @param {String} msg The message to be logged. 
    1395    * @param {int} level The message's verbosity level. Importance is 
    1396    * from 0 (very important) to 4 (not so important). A value of 1 
    1397    * denotes an error in the usual protocol flow. 
    1398    */ 
    1399   this.log = function(msg, level) { 
    1400     level = level || 0; 
    1401     if (level > this.level) 
    1402       return; 
    1403     if (typeof(console) == 'undefined') 
    1404       return; 
    1405     try { 
    1406       switch (level) { 
    1407       case 0: 
    1408         console.warn(msg); 
    1409         break; 
    1410       case 1: 
    1411         console.error(msg); 
    1412         break; 
    1413       case 2: 
    1414         console.info(msg); 
    1415         break; 
    1416       case 4: 
    1417         console.debug(msg); 
    1418         break; 
    1419       default: 
    1420         console.log(msg); 
    1421         break; 
    1422       } 
    1423     } catch(e) { try { console.log(msg) } catch(e) {} } 
    1424   }; 
    1425  
    1426   /** 
    1427    * Sets verbosity level. 
    1428    * @param {int} level The maximum level for debugging messages to be 
    1429    * displayed. Thus you can tweak the verbosity of the logger. A 
    1430    * value of 0 means very low traffic whilst a value of 4 makes 
    1431    * logging very verbose about what's going on. 
    1432    * @return This debug logger 
    1433    * @type ConsoleLogger 
    1434    */ 
    1435   this.setLevel = function(level) { this.level = level; return this; }; 
    1436   /** 
    1437    * Gets verbosity level. 
    1438    * @return The level 
    1439    * @type int 
    1440    */ 
    1441   this.getLevel = function() { return this.level; }; 
    1442 } 
    1443 /* Copyright 2003-2006 Peter-Paul Koch 
    1444  *           2006-2008 Stefan Strigler 
    1445  */ 
    1446  
    1447 /** 
    1448  * @fileoverview OO interface to handle cookies. 
    1449  * Taken from {@link http://www.quirksmode.org/js/cookies.html 
    1450  * http://www.quirksmode.org/js/cookies.html} 
    1451  * Regarding licensing of this code the author states: 
    1452  * 
    1453  * "You may copy, tweak, rewrite, sell or lease any code example on 
    1454  * this site, with one single exception." 
    1455  * 
    1456  * @author Stefan Strigler 
    1457  * @version $Revision: 504 $ 
    1458  */ 
    1459  
    1460 /** 
    1461  * Creates a new Cookie 
    1462  * @class Class representing browser cookies for storing small amounts of data 
    1463  * @constructor 
    1464  * @param {String} name   The name of the value to store 
    1465  * @param {String} value  The value to store 
    1466  * @param {int}    secs   Number of seconds until cookie expires (may be empty) 
    1467  * @param {String} domain The domain for the cookie 
    1468  * @param {String} path   The path of cookie 
    1469  */ 
     140{var r=new Array;var i=0;while(i<d.length) 
     141{if(d[i]<128){r[r.length]=String.fromCharCode(d[i]);i++;} 
     142else if((d[i]>191)&&(d[i]<224)){r[r.length]=String.fromCharCode(((d[i]&31)<<6)|(d[i+1]&63));i+=2;} 
     143else{r[r.length]=String.fromCharCode(((d[i]&15)<<12)|((d[i+1]&63)<<6)|(d[i+2]&63));i+=3;}} 
     144return r.join("");} 
     145function b64arrays(){var b64s='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';b64=new Array();f64=new Array();for(var i=0;i<b64s.length;i++){b64[i]=b64s.charAt(i);f64[b64s.charAt(i)]=i;}} 
     146function b64d2t(d){var r=new Array;var i=0;var dl=d.length;if((dl%3)==1){d[d.length]=0;d[d.length]=0;} 
     147if((dl%3)==2) 
     148d[d.length]=0;while(i<d.length) 
     149{r[r.length]=b64[d[i]>>2];r[r.length]=b64[((d[i]&3)<<4)|(d[i+1]>>4)];r[r.length]=b64[((d[i+1]&15)<<2)|(d[i+2]>>6)];r[r.length]=b64[d[i+2]&63];i+=3;} 
     150if((dl%3)==1) 
     151r[r.length-1]=r[r.length-2]="=";if((dl%3)==2) 
     152r[r.length-1]="=";var t=r.join("");return t;} 
     153function b64t2d(t){var d=new Array;var i=0;t=t.replace(/\n|\r/g,"");t=t.replace(/=/g,"");while(i<t.length) 
     154{d[d.length]=(f64[t.charAt(i)]<<2)|(f64[t.charAt(i+1)]>>4);d[d.length]=(((f64[t.charAt(i+1)]&15)<<4)|(f64[t.charAt(i+2)]>>2));d[d.length]=(((f64[t.charAt(i+2)]&3)<<6)|(f64[t.charAt(i+3)]));i+=4;} 
     155if(t.length%4==2) 
     156d=d.slice(0,d.length-2);if(t.length%4==3) 
     157d=d.slice(0,d.length-1);return d;} 
     158if(typeof(atob)=='undefined'||typeof(btoa)=='undefined') 
     159b64arrays();if(typeof(atob)=='undefined'){atob=function(s){return utf8d2t(b64t2d(s));}} 
     160if(typeof(btoa)=='undefined'){btoa=function(s){return b64d2t(utf8t2d(s));}} 
     161function cnonce(size){var tab="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";var cnonce='';for(var i=0;i<size;i++){cnonce+=tab.charAt(Math.round(Math.random(new Date().getTime())*(tab.length-1)));} 
     162return cnonce;} 
     163function JSJaCJSON(){} 
     164JSJaCJSON.toString=function(obj){var m={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},s={array:function(x){var a=['['],b,f,i,l=x.length,v;for(i=0;i<l;i+=1){v=x[i];f=s[typeof v];if(f){try{v=f(v);if(typeof v=='string'){if(b){a[a.length]=',';} 
     165a[a.length]=v;b=true;}}catch(e){}}} 
     166a[a.length]=']';return a.join('');},'boolean':function(x){return String(x);},'null':function(x){return"null";},number:function(x){return isFinite(x)?String(x):'null';},object:function(x){if(x){if(x instanceof Array){return s.array(x);} 
     167var a=['{'],b,f,i,v;for(i in x){if(x.hasOwnProperty(i)){v=x[i];f=s[typeof v];if(f){try{v=f(v);if(typeof v=='string'){if(b){a[a.length]=',';} 
     168a.push(s.string(i),':',v);b=true;}}catch(e){}}}} 
     169a[a.length]='}';return a.join('');} 
     170return'null';},string:function(x){if(/["\\\x00-\x1f]/.test(x)){x=x.replace(/([\x00-\x1f\\"])/g,function(a,b){var c=m[b];if(c){return c;} 
     171c=b.charCodeAt();return'\\u00'+ 
     172Math.floor(c/16).toString(16)+ 
     173(c%16).toString(16);});} 
     174return'"'+x+'"';}};switch(typeof(obj)){case'object':return s.object(obj);case'array':return s.array(obj);}};JSJaCJSON.parse=function(str){try{return!(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(str.replace(/"(\\.|[^"\\])*"/g,'')))&&eval('('+str+')');}catch(e){return false;}};function XmlHttp(){} 
     175XmlHttp.create=function(){try{if(window.XMLHttpRequest){var req=new XMLHttpRequest();if(req.readyState==null){req.readyState=1;req.addEventListener("load",function(){req.readyState=4;if(typeof req.onreadystatechange=="function") 
     176req.onreadystatechange();},false);} 
     177return req;} 
     178if(window.ActiveXObject){return new ActiveXObject(XmlHttp.getPrefix()+".XmlHttp");}} 
     179catch(ex){} 
     180throw new Error("Your browser does not support XmlHttp objects");};XmlHttp.getPrefix=function(){if(XmlHttp.prefix) 
     181return XmlHttp.prefix;var prefixes=["MSXML2","Microsoft","MSXML","MSXML3"];var o;for(var i=0;i<prefixes.length;i++){try{o=new ActiveXObject(prefixes[i]+".XmlHttp");return XmlHttp.prefix=prefixes[i];} 
     182catch(ex){};} 
     183throw new Error("Could not find an installed XML parser");};function XmlDocument(){} 
     184XmlDocument.create=function(name,ns){name=name||'foo';ns=ns||'';try{var doc;if(document.implementation&&document.implementation.createDocument){doc=document.implementation.createDocument(ns,name,null);if(doc.readyState==null){doc.readyState=1;doc.addEventListener("load",function(){doc.readyState=4;if(typeof doc.onreadystatechange=="function") 
     185doc.onreadystatechange();},false);}}else if(window.ActiveXObject){doc=new ActiveXObject(XmlDocument.getPrefix()+".DomDocument");} 
     186if(!doc.documentElement||doc.documentElement.tagName!=name||(doc.documentElement.namespaceURI&&doc.documentElement.namespaceURI!=ns)){try{if(ns!='') 
     187doc.appendChild(doc.createElement(name)).setAttribute('xmlns',ns);else 
     188doc.appendChild(doc.createElement(name));}catch(dex){doc=document.implementation.createDocument(ns,name,null);if(doc.documentElement==null) 
     189doc.appendChild(doc.createElement(name));if(ns!=''&&doc.documentElement.getAttribute('xmlns')!=ns){doc.documentElement.setAttribute('xmlns',ns);}}} 
     190return doc;} 
     191catch(ex){} 
     192throw new Error("Your browser does not support XmlDocument objects");};XmlDocument.getPrefix=function(){if(XmlDocument.prefix) 
     193return XmlDocument.prefix;var prefixes=["MSXML2","Microsoft","MSXML","MSXML3"];var o;for(var i=0;i<prefixes.length;i++){try{o=new ActiveXObject(prefixes[i]+".DomDocument");return XmlDocument.prefix=prefixes[i];} 
     194catch(ex){};} 
     195throw new Error("Could not find an installed XML parser");};if(typeof(Document)!='undefined'&&window.DOMParser){Document.prototype.loadXML=function(s){var doc2=(new DOMParser()).parseFromString(s,"text/xml");while(this.hasChildNodes()) 
     196this.removeChild(this.lastChild);for(var i=0;i<doc2.childNodes.length;i++){this.appendChild(this.importNode(doc2.childNodes[i],true));}};} 
     197if(window.XMLSerializer&&window.Node&&Node.prototype&&Node.prototype.__defineGetter__){XMLDocument.prototype.__defineGetter__("xml",function(){return(new XMLSerializer()).serializeToString(this);});Document.prototype.__defineGetter__("xml",function(){return(new XMLSerializer()).serializeToString(this);});Node.prototype.__defineGetter__("xml",function(){return(new XMLSerializer()).serializeToString(this);});} 
     198var JSJaCBuilder={buildNode:function(doc,elementName){var element,ns=arguments[4];if(arguments[2]) 
     199if(JSJaCBuilder._isStringOrNumber(arguments[2])||(arguments[2]instanceof Array)){element=this._createElement(doc,elementName,ns);JSJaCBuilder._children(doc,element,arguments[2]);}else{ns=arguments[2]['xmlns']||ns;element=this._createElement(doc,elementName,ns);for(attr in arguments[2]){if(arguments[2].hasOwnProperty(attr)&&attr!='xmlns') 
     200element.setAttribute(attr,arguments[2][attr]);}} 
     201else 
     202element=this._createElement(doc,elementName,ns);if(arguments[3]) 
     203JSJaCBuilder._children(doc,element,arguments[3],ns);return element;},_createElement:function(doc,elementName,ns){try{if(ns) 
     204return doc.createElementNS(ns,elementName);}catch(ex){} 
     205var el=doc.createElement(elementName);if(ns) 
     206el.setAttribute("xmlns",ns);return el;},_text:function(doc,text){return doc.createTextNode(text);},_children:function(doc,element,children,ns){if(typeof children=='object'){for(var i in children){if(children.hasOwnProperty(i)){var e=children[i];if(typeof e=='object'){if(e instanceof Array){var node=JSJaCBuilder.buildNode(doc,e[0],e[1],e[2],ns);element.appendChild(node);}else{element.appendChild(e);}}else{if(JSJaCBuilder._isStringOrNumber(e)){element.appendChild(JSJaCBuilder._text(doc,e));}}}}}else{if(JSJaCBuilder._isStringOrNumber(children)){element.appendChild(JSJaCBuilder._text(doc,children));}}},_attributes:function(attributes){var attrs=[];for(attribute in attributes) 
     207if(attributes.hasOwnProperty(attribute)) 
     208attrs.push(attribute+'="'+attributes[attribute].toString().htmlEnc()+'"');return attrs.join(" ");},_isStringOrNumber:function(param){return(typeof param=='string'||typeof param=='number');}};var NS_DISCO_ITEMS="http://jabber.org/protocol/disco#items";var NS_DISCO_INFO="http://jabber.org/protocol/disco#info";var NS_VCARD="vcard-temp";var NS_AUTH="jabber:iq:auth";var NS_AUTH_ERROR="jabber:iq:auth:error";var NS_REGISTER="jabber:iq:register";var NS_SEARCH="jabber:iq:search";var NS_ROSTER="jabber:iq:roster";var NS_PRIVACY="jabber:iq:privacy";var NS_PRIVATE="jabber:iq:private";var NS_VERSION="jabber:iq:version";var NS_TIME="jabber:iq:time";var NS_LAST="jabber:iq:last";var NS_XDATA="jabber:x:data";var NS_IQDATA="jabber:iq:data";var NS_DELAY="jabber:x:delay";var NS_EXPIRE="jabber:x:expire";var NS_EVENT="jabber:x:event";var NS_XCONFERENCE="jabber:x:conference";var NS_STATS="http://jabber.org/protocol/stats";var NS_MUC="http://jabber.org/protocol/muc";var NS_MUC_USER="http://jabber.org/protocol/muc#user";var NS_MUC_ADMIN="http://jabber.org/protocol/muc#admin";var NS_MUC_OWNER="http://jabber.org/protocol/muc#owner";var NS_PUBSUB="http://jabber.org/protocol/pubsub";var NS_PUBSUB_EVENT="http://jabber.org/protocol/pubsub#event";var NS_PUBSUB_OWNER="http://jabber.org/protocol/pubsub#owner";var NS_PUBSUB_NMI="http://jabber.org/protocol/pubsub#node-meta-info";var NS_COMMANDS="http://jabber.org/protocol/commands";var NS_STREAM="http://etherx.jabber.org/streams";var NS_CHAT_STATES="http://jabber.org/protocol/chatstates";var NS_STANZAS="urn:ietf:params:xml:ns:xmpp-stanzas";var NS_STREAMS="urn:ietf:params:xml:ns:xmpp-streams";var NS_TLS="urn:ietf:params:xml:ns:xmpp-tls";var NS_SASL="urn:ietf:params:xml:ns:xmpp-sasl";var NS_SESSION="urn:ietf:params:xml:ns:xmpp-session";var NS_BIND="urn:ietf:params:xml:ns:xmpp-bind";var NS_FEATURE_IQAUTH="http://jabber.org/features/iq-auth";var NS_FEATURE_IQREGISTER="http://jabber.org/features/iq-register";var NS_FEATURE_COMPRESS="http://jabber.org/features/compress";var NS_COMPRESS="http://jabber.org/protocol/compress";function STANZA_ERROR(code,type,cond){if(window==this) 
     209return new STANZA_ERROR(code,type,cond);this.code=code;this.type=type;this.cond=cond;} 
     210var ERR_BAD_REQUEST=STANZA_ERROR("400","modify","bad-request");var ERR_CONFLICT=STANZA_ERROR("409","cancel","conflict");var ERR_FEATURE_NOT_IMPLEMENTED=STANZA_ERROR("501","cancel","feature-not-implemented");var ERR_FORBIDDEN=STANZA_ERROR("403","auth","forbidden");var ERR_GONE=STANZA_ERROR("302","modify","gone");var ERR_INTERNAL_SERVER_ERROR=STANZA_ERROR("500","wait","internal-server-error");var ERR_ITEM_NOT_FOUND=STANZA_ERROR("404","cancel","item-not-found");var ERR_JID_MALFORMED=STANZA_ERROR("400","modify","jid-malformed");var ERR_NOT_ACCEPTABLE=STANZA_ERROR("406","modify","not-acceptable");var ERR_NOT_ALLOWED=STANZA_ERROR("405","cancel","not-allowed");var ERR_NOT_AUTHORIZED=STANZA_ERROR("401","auth","not-authorized");var ERR_PAYMENT_REQUIRED=STANZA_ERROR("402","auth","payment-required");var ERR_RECIPIENT_UNAVAILABLE=STANZA_ERROR("404","wait","recipient-unavailable");var ERR_REDIRECT=STANZA_ERROR("302","modify","redirect");var ERR_REGISTRATION_REQUIRED=STANZA_ERROR("407","auth","registration-required");var ERR_REMOTE_SERVER_NOT_FOUND=STANZA_ERROR("404","cancel","remote-server-not-found");var ERR_REMOTE_SERVER_TIMEOUT=STANZA_ERROR("504","wait","remote-server-timeout");var ERR_RESOURCE_CONSTRAINT=STANZA_ERROR("500","wait","resource-constraint");var ERR_SERVICE_UNAVAILABLE=STANZA_ERROR("503","cancel","service-unavailable");var ERR_SUBSCRIPTION_REQUIRED=STANZA_ERROR("407","auth","subscription-required");var ERR_UNEXPECTED_REQUEST=STANZA_ERROR("400","wait","unexpected-request");function JSJaCConsoleLogger(level){this.level=level||4;this.start=function(){};this.log=function(msg,level){level=level||0;if(level>this.level) 
     211return;if(typeof(console)=='undefined') 
     212return;try{switch(level){case 0:console.warn(msg);break;case 1:console.error(msg);break;case 2:console.info(msg);break;case 4:console.debug(msg);break;default:console.log(msg);break;}}catch(e){try{console.log(msg)}catch(e){}}};this.setLevel=function(level){this.level=level;return this;};this.getLevel=function(){return this.level;};} 
    1470213function JSJaCCookie(name,value,secs,domain,path) 
    1471 { 
    1472   if (window == this) 
    1473     return new JSJaCCookie(name, value, secs, domain, path); 
    1474  
    1475   /** 
    1476    * This cookie's name 
    1477    * @type String 
    1478    */ 
    1479   this.name = name; 
    1480   /** 
    1481    * This cookie's value 
    1482    * @type String 
    1483    */ 
    1484   this.value = value; 
    1485   /** 
    1486    * Time in seconds when cookie expires (thus being delete by 
    1487    * browser). A value of -1 denotes a session cookie which means that 
    1488    * stored data gets lost when browser is being closed.  
    1489    * @type int 
    1490    */ 
    1491   this.secs = secs; 
    1492  
    1493   /** 
    1494    * The cookie's domain 
    1495    * @type string 
    1496    */ 
    1497   this.domain = domain; 
    1498  
    1499   /** 
    1500    * The cookie's path 
    1501    * @type string 
    1502    */ 
    1503   this.path = path; 
    1504  
    1505   /** 
    1506    * Stores this cookie 
    1507    */ 
    1508   this.write = function() { 
    1509     if (this.secs) { 
    1510       var date = new Date(); 
    1511       date.setTime(date.getTime()+(this.secs*1000)); 
    1512       var expires = "; expires="+date.toGMTString(); 
    1513     } else 
    1514       var expires = ""; 
    1515     var domain = this.domain?"; domain="+this.domain:""; 
    1516     var path = this.path?"; path="+this.path:"; path=/"; 
    1517     document.cookie = this.getName()+"="+JSJaCCookie._escape(this.getValue())+ 
    1518       expires+ 
    1519       domain+ 
    1520       path; 
    1521   }; 
    1522   /** 
    1523    * Deletes this cookie 
    1524    */ 
    1525   this.erase = function() { 
    1526     var c = new JSJaCCookie(this.getName(),"",-1); 
    1527     c.write(); 
    1528   }; 
    1529  
    1530   /** 
    1531    * Gets the name of this cookie 
    1532    * @return The name 
    1533    * @type String 
    1534    */ 
    1535   this.getName = function() { 
    1536     return this.name; 
    1537   }; 
    1538   
    1539   /** 
    1540    * Sets the name of this cookie 
    1541    * @param {String} name The name for this cookie 
    1542    * @return This cookie 
    1543    * @type Cookie 
    1544    */ 
    1545   this.setName = function(name) { 
    1546     this.name = name; 
    1547     return this; 
    1548   }; 
    1549  
    1550   /** 
    1551    * Gets the value of this cookie 
    1552    * @return The value 
    1553    * @type String 
    1554    */ 
    1555   this.getValue = function() { 
    1556     return this.value; 
    1557   }; 
    1558   
    1559   /** 
    1560    * Sets the value of this cookie 
    1561    * @param {String} value The value for this cookie 
    1562    * @return This cookie 
    1563    * @type Cookie 
    1564    */ 
    1565   this.setValue = function(value) { 
    1566     this.value = value; 
    1567     return this; 
    1568   }; 
    1569  
    1570   /** 
    1571    * Sets the domain of this cookie 
    1572    * @param {String} domain The value for the domain of the cookie 
    1573    * @return This cookie 
    1574    * @type Cookie 
    1575    */ 
    1576   this.setDomain = function(domain) { 
    1577     this.domain = domain; 
    1578     return this; 
    1579   }; 
    1580  
    1581   /** 
    1582    * Sets the path of this cookie 
    1583    * @param {String} path The value of the path of the cookie 
    1584    * @return This cookie 
    1585    * @type Cookie 
    1586    */ 
    1587   this.setPath = function(path) { 
    1588     this.path = path; 
    1589     return this; 
    1590   }; 
    1591 } 
    1592  
    1593 /** 
    1594  * Reads the value for given <code>name</code> from cookies and return new 
    1595  * <code>Cookie</code> object 
    1596  * @param {String} name The name of the cookie to read 
    1597  * @return A cookie object of the given name 
    1598  * @type Cookie 
    1599  * @throws CookieException when cookie with given name could not be found 
    1600  */ 
    1601 JSJaCCookie.read = function(name) { 
    1602   var nameEQ = name + "="; 
    1603   var ca = document.cookie.split(';'); 
    1604   for(var i=0;i < ca.length;i++) { 
    1605     var c = ca[i]; 
    1606     while (c.charAt(0)==' ') c = c.substring(1,c.length); 
    1607     if (c.indexOf(nameEQ) == 0)  
    1608       return new JSJaCCookie( 
    1609         name,  
    1610         JSJaCCookie._unescape(c.substring(nameEQ.length,c.length))); 
    1611   } 
    1612   throw new JSJaCCookieException("Cookie not found"); 
    1613 }; 
    1614  
    1615 /** 
    1616  * Reads the value for given <code>name</code> from cookies and returns 
    1617  * its valued new 
    1618  * @param {String} name The name of the cookie to read 
    1619  * @return The value of the cookie read 
    1620  * @type String 
    1621  * @throws CookieException when cookie with given name could not be found 
    1622  */ 
    1623 JSJaCCookie.get = function(name) { 
    1624   return JSJaCCookie.read(name).getValue(); 
    1625 }; 
    1626  
    1627 /** 
    1628  * Deletes cookie with given <code>name</code> 
    1629  * @param {String} name The name of the cookie to delete 
    1630  * @throws CookieException when cookie with given name could not be found 
    1631  */ 
    1632 JSJaCCookie.remove = function(name) { 
    1633   JSJaCCookie.read(name).erase(); 
    1634 }; 
    1635  
    1636 /** 
    1637  * @private 
    1638  */ 
    1639 JSJaCCookie._escape = function(str) { 
    1640   return str.replace(/;/g, "%3AB"); 
    1641 } 
    1642  
    1643 /** 
    1644  * @private 
    1645  */ 
    1646 JSJaCCookie._unescape = function(str) { 
    1647   return str.replace(/%3AB/g, ";"); 
    1648 } 
    1649  
    1650 /** 
    1651  * Some exception denoted to dealing with cookies 
    1652  * @constructor 
    1653  * @param {String} msg The message to pass to the exception 
    1654  */ 
    1655 function JSJaCCookieException(msg) { 
    1656   this.message = msg; 
    1657   this.name = "CookieException"; 
    1658 } 
    1659  
    1660 /** 
    1661  * an error packet for internal use 
    1662  * @private 
    1663  * @constructor 
    1664  */ 
    1665 function JSJaCError(code,type,condition) { 
    1666   var xmldoc = XmlDocument.create("error","jsjac"); 
    1667  
    1668   xmldoc.documentElement.setAttribute('code',code); 
    1669   xmldoc.documentElement.setAttribute('type',type); 
    1670   if (condition) 
    1671     xmldoc.documentElement.appendChild(xmldoc.createElement(condition)). 
    1672       setAttribute('xmlns','urn:ietf:params:xml:ns:xmpp-stanzas'); 
    1673   return xmldoc.documentElement; 
    1674 } 
    1675 /** 
    1676  * @fileoverview This file contains all things that make life easier when 
    1677  * dealing with JIDs 
    1678  * @author Stefan Strigler 
    1679  * @version $Revision: 437 $ 
    1680  */ 
    1681  
    1682 /** 
    1683  * list of forbidden chars for nodenames 
    1684  * @private 
    1685  */ 
    1686 var JSJACJID_FORBIDDEN = ['"',' ','&','\'','/',':','<','>','@']; 
    1687  
    1688 /** 
    1689  * Creates a new JSJaCJID object 
    1690  * @class JSJaCJID models xmpp jid objects 
    1691  * @constructor 
    1692  * @param {Object} jid jid may be either of type String or a JID represented 
    1693  * by JSON with fields 'node', 'domain' and 'resource' 
    1694  * @throws JSJaCJIDInvalidException Thrown if jid is not valid 
    1695  * @return a new JSJaCJID object 
    1696  */ 
    1697 function JSJaCJID(jid) { 
    1698   /** 
    1699    *@private 
    1700    */ 
    1701   this._node = ''; 
    1702   /** 
    1703    *@private 
    1704    */ 
    1705   this._domain = ''; 
    1706   /** 
    1707    *@private 
    1708    */ 
    1709   this._resource = ''; 
    1710  
    1711   if (typeof(jid) == 'string') { 
    1712     if (jid.indexOf('@') != -1) { 
    1713         this.setNode(jid.substring(0,jid.indexOf('@'))); 
    1714         jid = jid.substring(jid.indexOf('@')+1); 
    1715     } 
    1716     if (jid.indexOf('/') != -1) { 
    1717       this.setResource(jid.substring(jid.indexOf('/')+1)); 
    1718       jid = jid.substring(0,jid.indexOf('/')); 
    1719     } 
    1720     this.setDomain(jid); 
    1721   } else { 
    1722     this.setNode(jid.node); 
    1723     this.setDomain(jid.domain); 
    1724     this.setResource(jid.resource); 
    1725   } 
    1726 } 
    1727  
    1728  
    1729 /** 
    1730  * Gets the node part of the jid 
    1731  * @return A string representing the node name 
    1732  * @type String 
    1733  */ 
    1734 JSJaCJID.prototype.getNode = function() { return this._node; }; 
    1735  
    1736 /** 
    1737  * Gets the domain part of the jid 
    1738  * @return A string representing the domain name 
    1739  * @type String 
    1740  */ 
    1741 JSJaCJID.prototype.getDomain = function() { return this._domain; }; 
    1742  
    1743 /** 
    1744  * Gets the resource part of the jid 
    1745  * @return A string representing the resource 
    1746  * @type String 
    1747  */ 
    1748 JSJaCJID.prototype.getResource = function() { return this._resource; }; 
    1749  
    1750  
    1751 /** 
    1752  * Sets the node part of the jid 
    1753  * @param {String} node Name of the node 
    1754  * @throws JSJaCJIDInvalidException Thrown if node name contains invalid chars 
    1755  * @return This object 
    1756  * @type JSJaCJID 
    1757  */ 
    1758 JSJaCJID.prototype.setNode = function(node) { 
    1759   JSJaCJID._checkNodeName(node); 
    1760   this._node = node || ''; 
    1761   return this; 
    1762 }; 
    1763  
    1764 /** 
    1765  * Sets the domain part of the jid 
    1766  * @param {String} domain Name of the domain 
    1767  * @throws JSJaCJIDInvalidException Thrown if domain name contains invalid 
    1768  * chars or is empty 
    1769  * @return This object 
    1770  * @type JSJaCJID 
    1771  */ 
    1772 JSJaCJID.prototype.setDomain = function(domain) { 
    1773   if (!domain || domain == '') 
    1774     throw new JSJaCJIDInvalidException("domain name missing"); 
    1775   // chars forbidden for a node are not allowed in domain names 
    1776   // anyway, so let's check 
    1777   JSJaCJID._checkNodeName(domain); 
    1778   this._domain = domain; 
    1779   return this; 
    1780 }; 
    1781  
    1782 /** 
    1783  * Sets the resource part of the jid 
    1784  * @param {String} resource Name of the resource 
    1785  * @return This object 
    1786  * @type JSJaCJID 
    1787  */ 
    1788 JSJaCJID.prototype.setResource = function(resource) { 
    1789   this._resource = resource || ''; 
    1790   return this; 
    1791 }; 
    1792  
    1793 /** 
    1794  * The string representation of the full jid 
    1795  * @return A string representing the jid 
    1796  * @type String 
    1797  */ 
    1798 JSJaCJID.prototype.toString = function() { 
    1799   var jid = ''; 
    1800   if (this.getNode() && this.getNode() != '') 
    1801     jid = this.getNode() + '@'; 
    1802   jid += this.getDomain(); // we always have a domain 
    1803   if (this.getResource() && this.getResource() != "") 
    1804     jid += '/' + this.getResource(); 
    1805   return jid; 
    1806 }; 
    1807  
    1808 /** 
    1809  * Removes the resource part of the jid 
    1810  * @return This object 
    1811  * @type JSJaCJID 
    1812  */ 
    1813 JSJaCJID.prototype.removeResource = function() { 
    1814   return this.setResource(); 
    1815 }; 
    1816  
    1817 /** 
    1818  * creates a copy of this JSJaCJID object 
    1819  * @return A copy of this 
    1820  * @type JSJaCJID 
    1821  */ 
    1822 JSJaCJID.prototype.clone = function() { 
    1823   return new JSJaCJID(this.toString()); 
    1824 }; 
    1825  
    1826 /** 
    1827  * Compares two jids if they belong to the same entity (i.e. w/o resource) 
    1828  * @param {String} jid a jid as string or JSJaCJID object 
    1829  * @return 'true' if jid is same entity as this 
    1830  * @type Boolean 
    1831  */ 
    1832 JSJaCJID.prototype.isEntity = function(jid) { 
    1833   if (typeof jid == 'string') 
    1834           jid = (new JSJaCJID(jid)); 
    1835   jid.removeResource(); 
    1836   return (this.clone().removeResource().toString() === jid.toString()); 
    1837 }; 
    1838  
    1839 /** 
    1840  * Check if node name is valid 
    1841  * @private 
    1842  * @param {String} node A name for a node 
    1843  * @throws JSJaCJIDInvalidException Thrown if name for node is not allowed 
    1844  */ 
    1845 JSJaCJID._checkNodeName = function(nodeprep) { 
    1846     if (!nodeprep || nodeprep == '') 
    1847       return; 
    1848     for (var i=0; i< JSJACJID_FORBIDDEN.length; i++) { 
    1849       if (nodeprep.indexOf(JSJACJID_FORBIDDEN[i]) != -1) { 
    1850         throw new JSJaCJIDInvalidException("forbidden char in nodename: "+JSJACJID_FORBIDDEN[i]); 
    1851       } 
    1852     } 
    1853 }; 
    1854  
    1855 /** 
    1856  * Creates a new Exception of type JSJaCJIDInvalidException 
    1857  * @class Exception to indicate invalid values for a jid 
    1858  * @constructor 
    1859  * @param {String} message The message associated with this Exception 
    1860  */ 
    1861 function JSJaCJIDInvalidException(message) { 
    1862   /** 
    1863    * The exceptions associated message 
    1864    * @type String 
    1865    */ 
    1866   this.message = message; 
    1867   /** 
    1868    * The name of the exception 
    1869    * @type String 
    1870    */ 
    1871   this.name = "JSJaCJIDInvalidException"; 
    1872 } 
    1873  
    1874 /** 
    1875  * Creates a new set of hash keys 
    1876  * @class Reflects a set of sha1/md5 hash keys for securing sessions 
    1877  * @constructor 
    1878  * @param {Function} func The hash function to be used for creating the keys 
    1879  * @param {Debugger} oDbg Reference to debugger implementation [optional] 
    1880  */                                                                       
    1881 function JSJaCKeys(func,oDbg) { 
    1882   var seed = Math.random(); 
    1883  
    1884   /** 
    1885    * @private 
    1886    */ 
    1887   this._k = new Array(); 
    1888   this._k[0] = seed.toString(); 
    1889   if (oDbg) 
    1890     /** 
    1891      * Reference to Debugger 
    1892      * @type Debugger 
    1893      */ 
    1894     this.oDbg = oDbg; 
    1895   else { 
    1896     this.oDbg = {}; 
    1897     this.oDbg.log = function() {}; 
    1898   } 
    1899  
    1900   if (func) { 
    1901     for (var i=1; i<JSJAC_NKEYS; i++) { 
    1902       this._k[i] = func(this._k[i-1]); 
    1903       oDbg.log(i+": "+this._k[i],4); 
    1904     } 
    1905   } 
    1906  
    1907   /** 
    1908    * @private 
    1909    */ 
    1910   this._indexAt = JSJAC_NKEYS-1; 
    1911   /** 
    1912    * Gets next key from stack 
    1913    * @return New hash key 
    1914    * @type String 
    1915    */ 
    1916   this.getKey = function() { 
    1917     return this._k[this._indexAt--]; 
    1918   }; 
    1919   /** 
    1920    * Indicates whether there's only one key left 
    1921    * @return <code>true</code> if there's only one key left, false otherwise 
    1922    * @type boolean 
    1923    */ 
    1924   this.lastKey = function() { return (this._indexAt == 0); }; 
    1925   /** 
    1926    * Returns number of overall/initial stack size 
    1927    * @return Number of keys created 
    1928    * @type int 
    1929    */ 
    1930   this.size = function() { return this._k.length; }; 
    1931  
    1932   /** 
    1933    * @private 
    1934    */ 
    1935   this._getSuspendVars = function() { 
    1936     return ('_k,_indexAt').split(','); 
    1937   } 
    1938 } 
    1939 /** 
    1940  * @fileoverview Contains all Jabber/XMPP packet related classes. 
    1941  * @author Stefan Strigler steve@zeank.in-berlin.de 
    1942  * @version $Revision: 510 $ 
    1943  */ 
    1944  
    1945 var JSJACPACKET_USE_XMLNS = true; 
    1946 var JSJACPACKET_CHAT_STATES = new Array("active", "inactive", "gone", "composing", "paused"); 
    1947  
    1948 /** 
    1949  * Creates a new packet with given root tag name (for internal use) 
    1950  * @class Somewhat abstract base class for all kinds of specialised packets 
    1951  * @param {String} name The root tag name of the packet 
    1952  * (i.e. one of 'message', 'iq' or 'presence') 
    1953  */ 
    1954 function JSJaCPacket(name) { 
    1955   /** 
    1956    * @private 
    1957    */ 
    1958   this.name = name; 
    1959  
    1960   if (typeof(JSJACPACKET_USE_XMLNS) != 'undefined' && JSJACPACKET_USE_XMLNS) 
    1961     /** 
    1962      * @private 
    1963      */ 
    1964     this.doc = XmlDocument.create(name,'jabber:client'); 
    1965   else 
    1966     /** 
    1967      * @private 
    1968      */ 
    1969     this.doc = XmlDocument.create(name,''); 
    1970 } 
    1971  
    1972 /** 
    1973  * Gets the type (name of root element) of this packet, i.e. one of 
    1974  * 'presence', 'message' or 'iq' 
    1975  * @return the top level tag name 
    1976  * @type String 
    1977  */ 
    1978 JSJaCPacket.prototype.pType = function() { return this.name; }; 
    1979  
    1980 /** 
    1981  * Gets the associated Document for this packet. 
    1982  * @type {@link http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#i-Document Document} 
    1983  */ 
    1984 JSJaCPacket.prototype.getDoc = function() { 
    1985   return this.doc; 
    1986 }; 
    1987 /** 
    1988  * Gets the root node of this packet 
    1989  * @type {@link http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247 Node} 
    1990  */ 
    1991 JSJaCPacket.prototype.getNode = function() { 
    1992   if (this.getDoc() && this.getDoc().documentElement) 
    1993     return this.getDoc().documentElement; 
    1994   else 
    1995     return null; 
    1996 }; 
    1997  
    1998 /** 
    1999  * Sets the 'to' attribute of the root node of this packet 
    2000  * @param {String} to 
    2001  * @type JSJaCPacket 
    2002  */ 
    2003 JSJaCPacket.prototype.setTo = function(to) { 
    2004   if (!to || to == '') 
    2005     this.getNode().removeAttribute('to'); 
    2006   else if (typeof(to) == 'string') 
    2007     this.getNode().setAttribute('to',to); 
    2008   else 
    2009     this.getNode().setAttribute('to',to.toString()); 
    2010   return this; 
    2011 }; 
    2012 /** 
    2013  * Sets the 'from' attribute of the root node of this 
    2014  * packet. Usually this is not needed as the server will take care 
    2015  * of this automatically. 
    2016  * @type JSJaCPacket 
    2017  */ 
    2018 JSJaCPacket.prototype.setFrom = function(from) { 
    2019   if (!from || from == '') 
    2020     this.getNode().removeAttribute('from'); 
    2021   else if (typeof(from) == 'string') 
    2022     this.getNode().setAttribute('from',from); 
    2023   else 
    2024     this.getNode().setAttribute('from',from.toString()); 
    2025   return this; 
    2026 }; 
    2027 /** 
    2028  * Sets 'id' attribute of the root node of this packet. 
    2029  * @param {String} id The id of the packet. 
    2030  * @type JSJaCPacket 
    2031  */ 
    2032 JSJaCPacket.prototype.setID = function(id) { 
    2033   if (!id || id == '') 
    2034     this.getNode().removeAttribute('id'); 
    2035   else 
    2036     this.getNode().setAttribute('id',id); 
    2037   return this; 
    2038 }; 
    2039 /** 
    2040  * Sets the 'type' attribute of the root node of this packet. 
    2041  * @param {String} type The type of the packet. 
    2042  * @type JSJaCPacket 
    2043  */ 
    2044 JSJaCPacket.prototype.setType = function(type) { 
    2045   if (!type || type == '') 
    2046     this.getNode().removeAttribute('type'); 
    2047   else 
    2048     this.getNode().setAttribute('type',type); 
    2049   return this; 
    2050 }; 
    2051 /** 
    2052  * Sets 'xml:lang' for this packet 
    2053  * @param {String} xmllang The xml:lang of the packet. 
    2054  * @type JSJaCPacket 
    2055  */ 
    2056 JSJaCPacket.prototype.setXMLLang = function(xmllang) { 
    2057   if (!xmllang || xmllang == '') 
    2058     this.getNode().removeAttribute('xml:lang'); 
    2059   else 
    2060     this.getNode().setAttribute('xml:lang',xmllang); 
    2061   return this; 
    2062 }; 
    2063  
    2064 /** 
    2065  * Gets the 'to' attribute of this packet 
    2066  * @type String 
    2067  */ 
    2068 JSJaCPacket.prototype.getTo = function() { 
    2069   return this.getNode().getAttribute('to'); 
    2070 }; 
    2071 /** 
    2072  * Gets the 'from' attribute of this packet. 
    2073  * @type String 
    2074  */ 
    2075 JSJaCPacket.prototype.getFrom = function() { 
    2076   return this.getNode().getAttribute('from'); 
    2077 }; 
    2078 /** 
    2079  * Gets the 'to' attribute of this packet as a JSJaCJID object 
    2080  * @type JSJaCJID 
    2081  */ 
    2082 JSJaCPacket.prototype.getToJID = function() { 
    2083   return new JSJaCJID(this.getTo()); 
    2084 }; 
    2085 /** 
    2086  * Gets the 'from' attribute of this packet as a JSJaCJID object 
    2087  * @type JSJaCJID 
    2088  */ 
    2089 JSJaCPacket.prototype.getFromJID = function() { 
    2090   return new JSJaCJID(this.getFrom()); 
    2091 }; 
    2092 /** 
    2093  * Gets the 'id' of this packet 
    2094  * @type String 
    2095  */ 
    2096 JSJaCPacket.prototype.getID = function() { 
    2097   return this.getNode().getAttribute('id'); 
    2098 }; 
    2099 /** 
    2100  * Gets the 'type' of this packet 
    2101  * @type String 
    2102  */ 
    2103 JSJaCPacket.prototype.getType = function() { 
    2104   return this.getNode().getAttribute('type'); 
    2105 }; 
    2106 /** 
    2107  * Gets the 'xml:lang' of this packet 
    2108  * @type String 
    2109  */ 
    2110 JSJaCPacket.prototype.getXMLLang = function() { 
    2111   return this.getNode().getAttribute('xml:lang'); 
    2112 }; 
    2113 /** 
    2114  * Gets the 'xmlns' (xml namespace) of the root node of this packet 
    2115  * @type String 
    2116  */ 
    2117 JSJaCPacket.prototype.getXMLNS = function() { 
    2118   return this.getNode().namespaceURI; 
    2119 }; 
    2120  
    2121 /** 
    2122  * Gets a child element of this packet. If no params given returns first child. 
    2123  * @param {String} name Tagname of child to retrieve. Use '*' to match any tag. [optional] 
    2124  * @param {String} ns   Namespace of child. Use '*' to match any ns.[optional] 
    2125  * @return The child node, null if none found 
    2126  * @type {@link http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247 Node} 
    2127  */ 
    2128 JSJaCPacket.prototype.getChild = function(name, ns) { 
    2129   if (!this.getNode()) { 
    2130     return null; 
    2131   } 
    2132   
    2133   name = name || '*'; 
    2134   ns = ns || '*'; 
    2135  
    2136   if (this.getNode().getElementsByTagNameNS) { 
    2137     return this.getNode().getElementsByTagNameNS(ns, name).item(0); 
    2138   } 
    2139  
    2140   // fallback 
    2141   var nodes = this.getNode().getElementsByTagName(name); 
    2142   if (ns != '*') { 
    2143     for (var i=0; i<nodes.length; i++) { 
    2144       if (nodes.item(i).namespaceURI == ns) { 
    2145         return nodes.item(i); 
    2146       } 
    2147     } 
    2148   } else { 
    2149     return nodes.item(0); 
    2150   } 
    2151   return null; // nothing found 
    2152 }; 
    2153  
    2154 /** 
    2155  * Gets the node value of a child element of this packet. 
    2156  * @param {String} name Tagname of child to retrieve. 
    2157  * @param {String} ns   Namespace of child 
    2158  * @return The value of the child node, empty string if none found 
    2159  * @type String 
    2160  */ 
    2161 JSJaCPacket.prototype.getChildVal = function(name, ns) { 
    2162   var node = this.getChild(name, ns); 
    2163   var ret = ''; 
    2164   if (node && node.hasChildNodes()) { 
    2165     // concatenate all values from childNodes 
    2166     for (var i=0; i<node.childNodes.length; i++) 
    2167       if (node.childNodes.item(i).nodeValue) 
    2168         ret += node.childNodes.item(i).nodeValue; 
    2169   } 
    2170   return ret; 
    2171 }; 
    2172  
    2173 /** 
    2174  * Returns a copy of this node 
    2175  * @return a copy of this node 
    2176  * @type JSJaCPacket 
    2177  */ 
    2178 JSJaCPacket.prototype.clone = function() { 
    2179   return JSJaCPacket.wrapNode(this.getNode()); 
    2180 }; 
    2181  
    2182 /** 
    2183  * Checks if packet is of type 'error' 
    2184  * @return 'true' if this packet is of type 'error', 'false' otherwise 
    2185  * @type boolean 
    2186  */ 
    2187 JSJaCPacket.prototype.isError = function() { 
    2188   return (this.getType() == 'error'); 
    2189 }; 
    2190  
    2191 /** 
    2192  * Returns an error condition reply according to {@link http://www.xmpp.org/extensions/xep-0086.html XEP-0086}. Creates a clone of the calling packet with senders and recipient exchanged and error stanza appended. 
    2193  * @param {STANZA_ERROR} stanza_error an error stanza containing error cody, type and condition of the error to be indicated 
    2194  * @return an error reply packet 
    2195  * @type JSJaCPacket 
    2196  */ 
    2197 JSJaCPacket.prototype.errorReply = function(stanza_error) { 
    2198   var rPacket = this.clone(); 
    2199   rPacket.setTo(this.getFrom()); 
    2200   rPacket.setFrom(); 
    2201   rPacket.setType('error'); 
    2202  
    2203   rPacket.appendNode('error', 
    2204                      {code: stanza_error.code, type: stanza_error.type}, 
    2205                      [[stanza_error.cond]]); 
    2206  
    2207   return rPacket; 
    2208 }; 
    2209  
    2210 /** 
    2211  * Returns a string representation of the raw xml content of this packet. 
    2212  * @type String 
    2213  */ 
    2214 JSJaCPacket.prototype.xml = typeof XMLSerializer != 'undefined' ? 
    2215 function() { 
    2216   var r = (new XMLSerializer()).serializeToString(this.getNode()); 
    2217   if (typeof(r) == 'undefined') 
    2218     r = (new XMLSerializer()).serializeToString(this.doc); // oldschool 
    2219   return r 
    2220 } : 
    2221 function() {// IE 
    2222   return this.getDoc().xml 
    2223 }; 
    2224  
    2225  
    2226 // PRIVATE METHODS DOWN HERE 
    2227  
    2228 /** 
    2229  * Gets an attribute of the root element 
    2230  * @private 
    2231  */ 
    2232 JSJaCPacket.prototype._getAttribute = function(attr) { 
    2233   return this.getNode().getAttribute(attr); 
    2234 }; 
    2235  
    2236 /** 
    2237  * Replaces this node with given node 
    2238  * @private 
    2239  */ 
    2240 JSJaCPacket.prototype._replaceNode = function(aNode) { 
    2241   // copy attribs 
    2242   for (var i=0; i<aNode.attributes.length; i++) 
    2243     if (aNode.attributes.item(i).nodeName != 'xmlns') 
    2244       this.getNode().setAttribute(aNode.attributes.item(i).nodeName, 
    2245                                   aNode.attributes.item(i).nodeValue); 
    2246  
    2247   // copy children 
    2248   for (var i=0; i<aNode.childNodes.length; i++) 
    2249     if (this.getDoc().importNode) 
    2250       this.getNode().appendChild(this.getDoc().importNode(aNode. 
    2251                                                           childNodes.item(i), 
    2252                                                           true)); 
    2253     else 
    2254       this.getNode().appendChild(aNode.childNodes.item(i).cloneNode(true)); 
    2255 }; 
    2256   
    2257 /** 
    2258  * Set node value of a child node 
    2259  * @private 
    2260  */ 
    2261 JSJaCPacket.prototype._setChildNode = function(nodeName, nodeValue) { 
    2262   var aNode = this.getChild(nodeName); 
    2263   var tNode = this.getDoc().createTextNode(nodeValue); 
    2264   if (aNode) 
    2265     try { 
    2266       aNode.replaceChild(tNode,aNode.firstChild); 
    2267     } catch (e) { } 
    2268   else { 
    2269     try { 
    2270       aNode = this.getDoc().createElementNS(this.getNode().namespaceURI, 
    2271                                             nodeName); 
    2272     } catch (ex) { 
    2273       aNode = this.getDoc().createElement(nodeName) 
    2274     } 
    2275     this.getNode().appendChild(aNode); 
    2276     aNode.appendChild(tNode); 
    2277   } 
    2278   return aNode; 
    2279 }; 
    2280  
    2281 /** 
    2282  * Create an empty node with the given nodeName and the given xmlns 
    2283  * @private 
    2284  */ 
    2285 JSJaCPacket.prototype._setEmptyChildNode = function(nodeName, xmlns) { 
    2286   var child; 
    2287   try { 
    2288     child = this.getDoc().createElementNS(xmlns,nodeName); 
    2289   } catch (e) { 
    2290     // fallback 
    2291     child = this.getDoc().createElement(nodeName); 
    2292   } 
    2293   if (child && child.getAttribute('xmlns') != xmlns) // fix opera 8.5x 
    2294     child.setAttribute('xmlns',xmlns); 
    2295   this.getNode().appendChild(child); 
    2296   return child; 
    2297 }; 
    2298  
    2299 /** 
    2300  * Builds a node using {@link 
    2301  * http://wiki.script.aculo.us/scriptaculous/show/Builder 
    2302  * script.aculo.us' Dom Builder} notation. 
    2303  * This code is taken from {@link 
    2304  * http://wiki.script.aculo.us/scriptaculous/show/Builder 
    2305  * script.aculo.us' Dom Builder} and has been modified to suit our 
    2306  * needs.<br/> 
    2307  * The original parts of the code do have the following copyright 
    2308  * and license notice:<br/> 
    2309  * Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, 
    2310  * http://mir.acu lo.us) <br/> 
    2311  * script.aculo.us is freely distributable under the terms of an 
    2312  * MIT-style licen se.  // For details, see the script.aculo.us web 
    2313  * site: http://script.aculo.us/<br> 
    2314  * @author Thomas Fuchs 
    2315  * @author Stefan Strigler 
    2316  * @return The newly created node 
    2317  * @type {@link http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247 Node} 
    2318  */ 
    2319 JSJaCPacket.prototype.buildNode = function(elementName) { 
    2320   return JSJaCBuilder.buildNode(this.getDoc(), 
    2321                                 elementName, 
    2322                                 arguments[1], 
    2323                                 arguments[2]); 
    2324 }; 
    2325  
    2326 /** 
    2327  * Appends node created by buildNode to this packets parent node. 
    2328  * @param {@link http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247 Node} element The node to append or 
    2329  * @param {String} element A name plus an object hash with attributes (optional) plus an array of childnodes (optional) 
    2330  * @see #buildNode 
    2331  * @return This packet 
    2332  * @type JSJaCPacket 
    2333  */ 
    2334 JSJaCPacket.prototype.appendNode = function(element) { 
    2335   if (typeof element=='object') { // seems to be a prebuilt node 
    2336     return this.getNode().appendChild(element) 
    2337   } else { // build node 
    2338     return this.getNode().appendChild(this.buildNode(element, 
    2339                                                      arguments[1], 
    2340                                                      arguments[2], 
    2341                                                      null, 
    2342                                                      this.getNode().namespaceURI)); 
    2343   } 
    2344 }; 
    2345  
    2346  
    2347 /** 
    2348  * A jabber/XMPP presence packet 
    2349  * @class Models the XMPP notion of a 'presence' packet 
    2350  * @extends JSJaCPacket 
    2351  */ 
    2352 function JSJaCPresence() { 
    2353   /** 
    2354    * @ignore 
    2355    */ 
    2356   this.base = JSJaCPacket; 
    2357   this.base('presence'); 
    2358 } 
    2359 JSJaCPresence.prototype = new JSJaCPacket; 
    2360  
    2361 /** 
    2362  * Sets the status message for current status. Usually this is set 
    2363  * to some human readable string indicating what the user is 
    2364  * doing/feel like currently. 
    2365  * @param {String} status A status message 
    2366  * @return this 
    2367  * @type JSJaCPacket 
    2368  */ 
    2369 JSJaCPresence.prototype.setStatus = function(status) { 
    2370   this._setChildNode("status", status); 
    2371   return this; 
    2372 }; 
    2373 /** 
    2374  * Sets the online status for this presence packet. 
    2375  * @param {String} show An XMPP complient status indicator. Must 
    2376  * be one of 'chat', 'away', 'xa', 'dnd' 
    2377  * @return this 
    2378  * @type JSJaCPacket 
    2379  */ 
    2380 JSJaCPresence.prototype.setShow = function(show) { 
    2381   if (show == 'chat' || show == 'away' || show == 'xa' || show == 'dnd') 
    2382     this._setChildNode("show",show); 
    2383   return this; 
    2384 }; 
    2385 /** 
    2386  * Sets the priority of the resource bind to with this connection 
    2387  * @param {int} prio The priority to set this resource to 
    2388  * @return this 
    2389  * @type JSJaCPacket 
    2390  */ 
    2391 JSJaCPresence.prototype.setPriority = function(prio) { 
    2392   this._setChildNode("priority", prio); 
    2393   return this; 
    2394 }; 
    2395 /** 
    2396  * Some combined method that allowes for setting show, status and 
    2397  * priority at once 
    2398  * @param {String} show A status message 
    2399  * @param {String} status A status indicator as defined by XMPP 
    2400  * @param {int} prio A priority for this resource 
    2401  * @return this 
    2402  * @type JSJaCPacket 
    2403  */ 
    2404 JSJaCPresence.prototype.setPresence = function(show,status,prio) { 
    2405   if (show) 
    2406     this.setShow(show); 
    2407   if (status) 
    2408     this.setStatus(status); 
    2409   if (prio) 
    2410     this.setPriority(prio); 
    2411   return this; 
    2412 }; 
    2413  
    2414 /** 
    2415  * Gets the status message of this presence 
    2416  * @return The (human readable) status message 
    2417  * @type String 
    2418  */ 
    2419 JSJaCPresence.prototype.getStatus = function() { 
    2420   return this.getChildVal('status'); 
    2421 }; 
    2422 /** 
    2423  * Gets the status of this presence. 
    2424  * Either one of 'chat', 'away', 'xa' or 'dnd' or null. 
    2425  * @return The status indicator as defined by XMPP 
    2426  * @type String 
    2427  */ 
    2428 JSJaCPresence.prototype.getShow = function() { 
    2429   return this.getChildVal('show'); 
    2430 }; 
    2431 /** 
    2432  * Gets the priority of this status message 
    2433  * @return A resource priority 
    2434  * @type int 
    2435  */ 
    2436 JSJaCPresence.prototype.getPriority = function() { 
    2437   return this.getChildVal('priority'); 
    2438 }; 
    2439  
    2440  
    2441 /** 
    2442  * A jabber/XMPP iq packet 
    2443  * @class Models the XMPP notion of an 'iq' packet 
    2444  * @extends JSJaCPacket 
    2445  */ 
    2446 function JSJaCIQ() { 
    2447   /** 
    2448    * @ignore 
    2449    */ 
    2450   this.base = JSJaCPacket; 
    2451   this.base('iq'); 
    2452 } 
    2453 JSJaCIQ.prototype = new JSJaCPacket; 
    2454  
    2455 /** 
    2456  * Some combined method to set 'to', 'type' and 'id' at once 
    2457  * @param {String} to the recepients JID 
    2458  * @param {String} type A XMPP compliant iq type (one of 'set', 'get', 'result' and 'error' 
    2459  * @param {String} id A packet ID 
    2460  * @return this 
    2461  * @type JSJaCIQ 
    2462  */ 
    2463 JSJaCIQ.prototype.setIQ = function(to,type,id) { 
    2464   if (to) 
    2465     this.setTo(to); 
    2466   if (type) 
    2467     this.setType(type); 
    2468   if (id) 
    2469     this.setID(id); 
    2470   return this; 
    2471 }; 
    2472 /** 
    2473  * Creates a 'query' child node with given XMLNS 
    2474  * @param {String} xmlns The namespace for the 'query' node 
    2475  * @return The query node 
    2476  * @type {@link  http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247 Node} 
    2477  */ 
    2478 JSJaCIQ.prototype.setQuery = function(xmlns) { 
    2479   return this._setEmptyChildNode('query', xmlns); 
    2480 }; 
    2481  
    2482 /** 
    2483  * Gets the 'query' node of this packet 
    2484  * @return The query node 
    2485  * @type {@link  http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247 Node} 
    2486  */ 
    2487 JSJaCIQ.prototype.getQuery = function() { 
    2488   return this.getNode().getElementsByTagName('query').item(0); 
    2489 }; 
    2490 /** 
    2491  * Gets the XMLNS of the query node contained within this packet 
    2492  * @return The namespace of the query node 
    2493  * @type String 
    2494  */ 
    2495 JSJaCIQ.prototype.getQueryXMLNS = function() { 
    2496   if (this.getQuery()) 
    2497     return this.getQuery().namespaceURI; 
    2498   else 
    2499     return null; 
    2500 }; 
    2501  
    2502 /** 
    2503  * Creates an IQ reply with type set to 'result'. If given appends payload to first child if IQ. Payload maybe XML as string or a DOM element (or an array of such elements as well). 
    2504  * @param {Element} payload A payload to be appended [optional] 
    2505  * @return An IQ reply packet 
    2506  * @type JSJaCIQ 
    2507  */ 
    2508 JSJaCIQ.prototype.reply = function(payload) { 
    2509   var rIQ = this.clone(); 
    2510   rIQ.setTo(this.getFrom()); 
    2511   rIQ.setFrom(); 
    2512   rIQ.setType('result'); 
    2513   if (payload) { 
    2514     if (typeof payload == 'string') 
    2515       rIQ.getChild().appendChild(rIQ.getDoc().loadXML(payload)); 
    2516     else if (payload.constructor == Array) { 
    2517       var node = rIQ.getChild(); 
    2518       for (var i=0; i<payload.length; i++) 
    2519         if(typeof payload[i] == 'string') 
    2520           node.appendChild(rIQ.getDoc().loadXML(payload[i])); 
    2521         else if (typeof payload[i] == 'object') 
    2522           node.appendChild(payload[i]); 
    2523     } 
    2524     else if (typeof payload == 'object') 
    2525       rIQ.getChild().appendChild(payload); 
    2526   } 
    2527   return rIQ; 
    2528 }; 
    2529  
    2530 /** 
    2531  * A jabber/XMPP message packet 
    2532  * @class Models the XMPP notion of an 'message' packet 
    2533  * @extends JSJaCPacket 
    2534  */ 
    2535 function JSJaCMessage() { 
    2536   /** 
    2537    * @ignore 
    2538    */ 
    2539   this.base = JSJaCPacket; 
    2540   this.base('message'); 
    2541 } 
    2542 JSJaCMessage.prototype = new JSJaCPacket; 
    2543  
    2544 /** 
    2545  * Sets the body of the message 
    2546  * @param {String} body Your message to be sent along 
    2547  * @return this message 
    2548  * @type JSJaCMessage 
    2549  */ 
    2550 JSJaCMessage.prototype.setBody = function(body) { 
    2551   this._setChildNode("body",body); 
    2552   return this; 
    2553 }; 
    2554 /** 
    2555  * Sets the subject of the message 
    2556  * @param {String} subject Your subject to be sent along 
    2557  * @return this message 
    2558  * @type JSJaCMessage 
    2559  */ 
    2560 JSJaCMessage.prototype.setSubject = function(subject) { 
    2561   this._setChildNode("subject",subject); 
    2562   return this; 
    2563 }; 
    2564 /** 
    2565  * Sets the 'tread' attribute for this message. This is used to identify 
    2566  * threads in chat conversations 
    2567  * @param {String} thread Usually a somewhat random hash. 
    2568  * @return this message 
    2569  * @type JSJaCMessage 
    2570  */ 
    2571 JSJaCMessage.prototype.setThread = function(thread) { 
    2572   this._setChildNode("thread", thread); 
    2573   return this; 
    2574 }; 
    2575 /** 
    2576  * Sets a 'chat-state' attribute for this message, 
    2577  * see XEP-0085 
    2578  * @param {String} state to append to this message 
    2579  * @return this message if state is set, otherwise null 
    2580  * @type JSJaCMessage 
    2581  */ 
    2582 JSJaCMessage.prototype.setState = function (state) { 
    2583   var validState = false; 
    2584   for (var i=0; i<JSJACPACKET_CHAT_STATES.length; i++) { 
    2585     if (JSJACPACKET_CHAT_STATES[i] == state) 
    2586       validState = true; 
    2587     if (this.getChild(JSJACPACKET_CHAT_STATES[i])) 
    2588       return null; 
    2589   } 
    2590   if (!validState) 
    2591     return null; 
    2592   this._setEmptyChildNode(state, NS_CHAT_STATES); 
    2593   return this; 
    2594 }; 
    2595 /** 
    2596  * Gets the 'thread' identifier for this message 
    2597  * @return A thread identifier 
    2598  * @type String 
    2599  */ 
    2600 JSJaCMessage.prototype.getThread = function() { 
    2601   return this.getChildVal('thread'); 
    2602 }; 
    2603 /** 
    2604  * Gets the body of this message 
    2605  * @return The body of this message 
    2606  * @type String 
    2607  */ 
    2608 JSJaCMessage.prototype.getBody = function() { 
    2609   return this.getChildVal('body'); 
    2610 }; 
    2611 /** 
    2612  * Gets the subject of this message 
    2613  * @return The subject of this message 
    2614  * @type String 
    2615  */ 
    2616 JSJaCMessage.prototype.getSubject = function() { 
    2617   return this.getChildVal('subject') 
    2618 }; 
    2619 /** 
    2620  * Gets the'chat-state' appended to the message, 
    2621  * see XEP-0085 
    2622  * @return chat state 
    2623  * @type String 
    2624  */ 
    2625 JSJaCMessage.prototype.getState = function () { 
    2626   var state; 
    2627   for (var i=0; i<JSJACPACKET_CHAT_STATES.length; i++) 
    2628     if (this.getChild(JSJACPACKET_CHAT_STATES[i])) 
    2629       return JSJACPACKET_CHAT_STATES[i]; 
    2630   return null; 
    2631 }; 
    2632  
    2633 /** 
    2634  * Tries to transform a w3c DOM node to JSJaC's internal representation 
    2635  * (JSJaCPacket type, one of JSJaCPresence, JSJaCMessage, JSJaCIQ) 
    2636  * @param: {Node 
    2637  * http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247} 
    2638  * node The node to be transformed 
    2639  * @return A JSJaCPacket representing the given node. If node's root 
    2640  * elemenent is not one of 'message', 'presence' or 'iq', 
    2641  * <code>null</code> is being returned. 
    2642  * @type JSJaCPacket 
    2643  */ 
    2644 JSJaCPacket.wrapNode = function(node) { 
    2645   var aNode = null; 
    2646  
    2647   try { 
    2648     switch (node.nodeName.toLowerCase()) { 
    2649     case 'presence': 
    2650       aNode = new JSJaCPresence(); 
    2651       break; 
    2652     case 'message': 
    2653       aNode = new JSJaCMessage(); 
    2654       break; 
    2655     case 'iq': 
    2656       aNode = new JSJaCIQ(); 
    2657       break; 
    2658     } 
    2659  
    2660     aNode._replaceNode(node); 
    2661   } catch(e) { } 
    2662   return aNode; 
    2663 }; 
    2664  
    2665 /** 
    2666  * @fileoverview Contains all things in common for all subtypes of connections 
    2667  * supported. 
    2668  * @author Stefan Strigler steve@zeank.in-berlin.de 
    2669  * @version $Revision: 512 $ 
    2670  */ 
    2671  
    2672 /** 
    2673  * Creates a new Jabber connection (a connection to a jabber server) 
    2674  * @class Somewhat abstract base class for jabber connections. Contains all 
    2675  * of the code in common for all jabber connections 
    2676  * @constructor 
    2677  * @param {JSON http://www.json.org/index} oArg JSON with properties: <br> 
    2678  * * <code>httpbase</code> the http base address of the service to be used for 
    2679  * connecting to jabber<br> 
    2680  * * <code>oDbg</code> (optional) a reference to a debugger interface 
    2681  */ 
    2682 function JSJaCConnection(oArg) { 
    2683    
    2684   if (oArg && oArg.oDbg && oArg.oDbg.log) { 
    2685       /** 
    2686        * Reference to debugger interface 
    2687        * (needs to implement method <code>log</code>) 
    2688        * @type Debugger 
    2689        */ 
    2690     this.oDbg = oArg.oDbg; 
    2691   } else { 
    2692     this.oDbg = new Object(); // always initialise a debugger 
    2693     this.oDbg.log = function() { }; 
    2694   } 
    2695    
    2696   if (oArg && oArg.timerval) 
    2697     this.setPollInterval(oArg.timerval); 
    2698   else  
    2699     this.setPollInterval(JSJAC_TIMERVAL); 
    2700  
    2701   if (oArg && oArg.httpbase) 
    2702       /** 
    2703        * @private 
    2704        */ 
    2705     this._httpbase = oArg.httpbase; 
    2706   
    2707   if (oArg &&oArg.allow_plain) 
    2708       /** 
    2709        * @private 
    2710        */ 
    2711     this.allow_plain = oArg.allow_plain; 
    2712   else 
    2713     this.allow_plain = JSJAC_ALLOW_PLAIN; 
    2714    
    2715   if (oArg && oArg.cookie_prefix) 
    2716       /** 
    2717        * @private 
    2718        */ 
    2719     this._cookie_prefix = oArg.cookie_prefix; 
    2720   else 
    2721     this._cookie_prefix = ""; 
    2722  
    2723   /** 
    2724    * @private 
    2725    */ 
    2726   this._connected = false; 
    2727   /** 
    2728    * @private 
    2729    */ 
    2730   this._events = new Array(); 
    2731   /** 
    2732    * @private 
    2733    */ 
    2734   this._keys = null; 
    2735   /** 
    2736    * @private 
    2737    */ 
    2738   this._ID = 0; 
    2739   /** 
    2740    * @private 
    2741    */ 
    2742   this._inQ = new Array(); 
    2743   /** 
    2744    * @private 
    2745    */ 
    2746   this._pQueue = new Array(); 
    2747   /** 
    2748    * @private 
    2749    */ 
    2750   this._regIDs = new Array(); 
    2751   /** 
    2752    * @private 
    2753    */ 
    2754   this._req = new Array(); 
    2755   /** 
    2756    * @private 
    2757    */ 
    2758   this._status = 'intialized'; 
    2759   /** 
    2760    * @private 
    2761    */ 
    2762   this._errcnt = 0; 
    2763   /** 
    2764    * @private 
    2765    */ 
    2766   this._inactivity = JSJAC_INACTIVITY; 
    2767   /** 
    2768    * @private 
    2769    */ 
    2770   this._sendRawCallbacks = new Array(); 
    2771 } 
    2772  
    2773 JSJaCConnection.prototype.connect = function(oArg) { 
    2774   this._setStatus('connecting'); 
    2775  
    2776   this.domain = oArg.domain || 'localhost'; 
    2777   this.username = oArg.username; 
    2778   this.resource = oArg.resource; 
    2779   this.pass = oArg.pass; 
    2780   this.register = oArg.register; 
    2781  
    2782   this.authhost = oArg.authhost || this.domain; 
    2783   this.authtype = oArg.authtype || 'sasl'; 
    2784  
    2785   if (oArg.xmllang && oArg.xmllang != '') 
    2786     this._xmllang = oArg.xmllang; 
    2787  
    2788   this.host = oArg.host || this.domain; 
    2789   this.port = oArg.port || 5222; 
    2790   if (oArg.secure) 
    2791     this.secure = 'true'; 
    2792   else 
    2793     this.secure = 'false'; 
    2794  
    2795   if (oArg.wait) 
    2796     this._wait = oArg.wait; 
    2797  
    2798   this.jid = this.username + '@' + this.domain; 
    2799   this.fulljid = this.jid + '/' + this.resource; 
    2800  
    2801   this._rid  = Math.round( 100000.5 + ( ( (900000.49999) - (100000.5) ) * Math.random() ) ); 
    2802  
    2803   // setupRequest must be done after rid is created but before first use in reqstr 
    2804   var slot = this._getFreeSlot(); 
    2805   this._req[slot] = this._setupRequest(true); 
    2806  
    2807   var reqstr = this._getInitialRequestString(); 
    2808  
    2809   this.oDbg.log(reqstr,4); 
    2810  
    2811   this._req[slot].r.onreadystatechange =  
    2812   JSJaC.bind(function() { 
    2813                if (this._req[slot].r.readyState == 4) { 
    2814                  this.oDbg.log("async recv: "+this._req[slot].r.responseText,4); 
    2815                  this._handleInitialResponse(slot); // handle response 
    2816                } 
    2817              }, this); 
    2818    
    2819   if (typeof(this._req[slot].r.onerror) != 'undefined') { 
    2820     this._req[slot].r.onerror =  
    2821       JSJaC.bind(function(e) { 
    2822                    this.oDbg.log('XmlHttpRequest error',1); 
    2823                    return false; 
    2824                  }, this); 
    2825   } 
    2826  
    2827   this._req[slot].r.send(reqstr); 
    2828 }; 
    2829  
    2830 /** 
    2831  * Tells whether this connection is connected 
    2832  * @return <code>true</code> if this connections is connected, 
    2833  * <code>false</code> otherwise 
    2834  * @type boolean 
    2835  */ 
    2836 JSJaCConnection.prototype.connected = function() { return this._connected; }; 
    2837  
    2838 /** 
    2839  * Disconnects from jabber server and terminates session (if applicable) 
    2840  */ 
    2841 JSJaCConnection.prototype.disconnect = function() { 
    2842   this._setStatus('disconnecting'); 
    2843  
    2844   if (!this.connected()) 
    2845     return; 
    2846  
    2847   var slot = this._getFreeSlot(); 
    2848   this._req[slot] = this._setupRequest(true); 
    2849   this._req[slot].r.onreadystatechange =  
    2850   JSJaC.bind(function() { 
    2851                if (this._req[slot].r.readyState == 4) { 
    2852                  this.oDbg.log("async recv (disconnect): "+this._req[slot].r.responseText,4); 
    2853                  this._connected = false; 
    2854                  clearInterval(this._interval); 
    2855                  clearInterval(this._inQto); 
    2856                  if (this._timeout) 
    2857                    clearTimeout(this._timeout); // remove timer 
    2858  
    2859                  try { 
    2860                    JSJaCCookie.read(this._cookie_prefix+'JSJaC_State').erase(); 
    2861                  } catch (e) {} 
    2862  
    2863                  this.oDbg.log("Disconnected: "+this._req[slot].r.responseText,2); 
    2864                  this.oDbg.log("Aborting remaining connections",4); 
    2865                  for (var i=0; i<this._hold+1; i++) 
    2866                    if (typeof(this._req[i]) != 'undefined' || typeof(this._req[i].r) != 'undefined' ) 
    2867                      this._req[i].r.abort(); 
    2868                  this._handleEvent('ondisconnect'); 
    2869                } 
    2870              }, this); 
    2871  
    2872   request = this._getRequestString(false, true); 
    2873  
    2874   if (typeof(this._rid) != 'undefined') // remember request id if any 
    2875     this._req[slot].rid = this._rid; 
    2876   this.oDbg.log("Disconnecting: " + request,4); 
    2877   this._req[slot].r.send(request); 
    2878  
    2879 }; 
    2880  
    2881 /** 
    2882  * Gets current value of polling interval 
    2883  * @return Polling interval in milliseconds 
    2884  * @type int 
    2885  */ 
    2886 JSJaCConnection.prototype.getPollInterval = function() { 
    2887   return this._timerval; 
    2888 }; 
    2889  
    2890 /** 
    2891  * Registers an event handler (callback) for this connection. 
    2892  
    2893  * <p>Note: All of the packet handlers for specific packets (like 
    2894  * message_in, presence_in and iq_in) fire only if there's no 
    2895  * callback associated with the id.<br> 
    2896  
    2897  * <p>Example:<br/> 
    2898  * <code>con.registerHandler('iq', 'query', 'jabber:iq:version', handleIqVersion);</code> 
    2899  
    2900  
    2901  * @param {String} event One of 
    2902  
    2903  * <ul> 
    2904  * <li>onConnect - connection has been established and authenticated</li> 
    2905  * <li>onDisconnect - connection has been disconnected</li> 
    2906  * <li>onResume - connection has been resumed</li> 
    2907  
    2908  * <li>onStatusChanged - connection status has changed, current 
    2909  * status as being passed argument to handler. See {@link #status}.</li> 
    2910  
    2911  * <li>onError - an error has occured, error node is supplied as 
    2912  * argument, like this:<br><code>&lt;error code='404' type='cancel'&gt;<br> 
    2913  * &lt;item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/&gt;<br> 
    2914  * &lt;/error&gt;</code></li> 
    2915  
    2916  * <li>packet_in - a packet has been received (argument: the 
    2917  * packet)</li> 
    2918  
    2919  * <li>packet_out - a packet is to be sent(argument: the 
    2920  * packet)</li> 
    2921  
    2922  * <li>message_in | message - a message has been received (argument: 
    2923  * the packet)</li> 
    2924  
    2925  * <li>message_out - a message packet is to be sent (argument: the 
    2926  * packet)</li> 
    2927  
    2928  * <li>presence_in | presence - a presence has been received 
    2929  * (argument: the packet)</li> 
    2930  
    2931  * <li>presence_out - a presence packet is to be sent (argument: the 
    2932  * packet)</li> 
    2933  
    2934  * <li>iq_in | iq - an iq has been received (argument: the packet)</li> 
    2935  * <li>iq_out - an iq is to be sent (argument: the packet)</li> 
    2936  * </ul> 
    2937  
    2938  * @param {String} childName A childnode's name that must occur within a 
    2939  * retrieved packet [optional] 
    2940  
    2941  * @param {String} childNS A childnode's namespace that must occure within 
    2942  * a retrieved packet (works only if childName is given) [optional] 
    2943  
    2944  * @param {String} type The type of the packet to handle (works only if childName and chidNS are given (both may be set to '*' in order to get skipped) [optional] 
    2945  
    2946  * @param {Function} handler The handler to be called when event occurs. If your handler returns 'true' it cancels bubbling of the event. No other registered handlers for this event will be fired. 
    2947  */ 
    2948 JSJaCConnection.prototype.registerHandler = function(event) { 
    2949   event = event.toLowerCase(); // don't be case-sensitive here 
    2950   var eArg = {handler: arguments[arguments.length-1], 
    2951               childName: '*', 
    2952               childNS: '*', 
    2953               type: '*'}; 
    2954   if (arguments.length > 2) 
    2955     eArg.childName = arguments[1]; 
    2956   if (arguments.length > 3) 
    2957     eArg.childNS = arguments[2]; 
    2958   if (arguments.length > 4) 
    2959     eArg.type = arguments[3]; 
    2960   if (!this._events[event]) 
    2961     this._events[event] = new Array(eArg); 
    2962   else 
    2963     this._events[event] = this._events[event].concat(eArg); 
    2964  
    2965   // sort events in order how specific they match criterias thus using 
    2966   // wildcard patterns puts them back in queue when it comes to 
    2967   // bubbling the event 
    2968   this._events[event] = 
    2969   this._events[event].sort(function(a,b) { 
    2970     var aRank = 0; 
    2971     var bRank = 0; 
    2972     with (a) { 
    2973       if (type == '*') 
    2974         aRank++; 
    2975       if (childNS == '*') 
    2976         aRank++; 
    2977       if (childName == '*') 
    2978         aRank++; 
    2979     } 
    2980     with (b) { 
    2981       if (type == '*') 
    2982         bRank++; 
    2983       if (childNS == '*') 
    2984         bRank++; 
    2985       if (childName == '*') 
    2986         bRank++; 
    2987     } 
    2988     if (aRank > bRank) 
    2989       return 1; 
    2990     if (aRank < bRank) 
    2991       return -1; 
    2992     return 0; 
    2993   }); 
    2994   this.oDbg.log("registered handler for event '"+event+"'",2); 
    2995 }; 
    2996  
    2997 JSJaCConnection.prototype.unregisterHandler = function(event,handler) { 
    2998   event = event.toLowerCase(); // don't be case-sensitive here 
    2999  
    3000   if (!this._events[event]) 
    3001     return; 
    3002  
    3003   var arr = this._events[event], res = new Array(); 
    3004   for (var i=0; i<arr.length; i++) 
    3005     if (arr[i].handler != handler) 
    3006       res.push(arr[i]); 
    3007  
    3008   if (arr.length != res.length) { 
    3009     this._events[event] = res; 
    3010     this.oDbg.log("unregistered handler for event '"+event+"'",2); 
    3011   } 
    3012 }; 
    3013  
    3014 /** 
    3015  * Register for iq packets of type 'get'. 
    3016  * @param {String} childName A childnode's name that must occur within a 
    3017  * retrieved packet 
    3018  
    3019  * @param {String} childNS A childnode's namespace that must occure within 
    3020  * a retrieved packet (works only if childName is given) 
    3021  
    3022  * @param {Function} handler The handler to be called when event occurs. If your handler returns 'true' it cancels bubbling of the event. No other registered handlers for this event will be fired. 
    3023  */ 
    3024 JSJaCConnection.prototype.registerIQGet = 
    3025   function(childName, childNS, handler) { 
    3026   this.registerHandler('iq', childName, childNS, 'get', handler); 
    3027 }; 
    3028  
    3029 /** 
    3030  * Register for iq packets of type 'set'. 
    3031  * @param {String} childName A childnode's name that must occur within a 
    3032  * retrieved packet 
    3033  
    3034  * @param {String} childNS A childnode's namespace that must occure within 
    3035  * a retrieved packet (works only if childName is given) 
    3036  
    3037  * @param {Function} handler The handler to be called when event occurs. If your handler returns 'true' it cancels bubbling of the event. No other registered handlers for this event will be fired. 
    3038  */ 
    3039 JSJaCConnection.prototype.registerIQSet = 
    3040   function(childName, childNS, handler) { 
    3041   this.registerHandler('iq', childName, childNS, 'set', handler); 
    3042 }; 
    3043  
    3044 /** 
    3045  * Resumes this connection from saved state (cookie) 
    3046  * @return Whether resume was successful 
    3047  * @type boolean 
    3048  */ 
    3049 JSJaCConnection.prototype.resume = function() { 
    3050   try { 
    3051     var json = JSJaCCookie.read(this._cookie_prefix+'JSJaC_State').getValue();  
    3052     this.oDbg.log('read cookie: '+json,2); 
    3053     JSJaCCookie.read(this._cookie_prefix+'JSJaC_State').erase(); 
    3054  
    3055     return this.resumeFromData(JSJaCJSON.parse(json)); 
    3056   } catch (e) {} 
    3057   return false; // sth went wrong 
    3058 }; 
    3059  
    3060 /** 
    3061  * Resumes BOSH connection from data   
    3062  * @param {Object} serialized jsjac state information 
    3063  * @return Whether resume was successful 
    3064  * @type boolean 
    3065  */ 
    3066 JSJaCConnection.prototype.resumeFromData = function(data) { 
    3067   try { 
    3068     this._setStatus('resuming'); 
    3069  
    3070     for (var i in data) 
    3071       if (data.hasOwnProperty(i)) 
    3072         this[i] = data[i]; 
    3073       
    3074     // copy keys - not being very generic here :-/ 
    3075     if (this._keys) { 
    3076       this._keys2 = new JSJaCKeys(); 
    3077       var u = this._keys2._getSuspendVars(); 
    3078       for (var i=0; i<u.length; i++) 
    3079         this._keys2[u[i]] = this._keys[u[i]]; 
    3080       this._keys = this._keys2; 
    3081     } 
    3082  
    3083     if (this._connected) { 
    3084       // don't poll too fast! 
    3085       this._handleEvent('onresume'); 
    3086       setTimeout(JSJaC.bind(this._resume, this),this.getPollInterval()); 
    3087       this._interval = setInterval(JSJaC.bind(this._checkQueue, this), 
    3088                                    JSJAC_CHECKQUEUEINTERVAL); 
    3089       this._inQto = setInterval(JSJaC.bind(this._checkInQ, this), 
    3090                                 JSJAC_CHECKINQUEUEINTERVAL); 
    3091     } 
    3092  
    3093     return (this._connected === true); 
    3094   } catch (e) { 
    3095     if (e.message) 
    3096       this.oDbg.log("Resume failed: "+e.message, 1); 
    3097     else 
    3098       this.oDbg.log("Resume failed: "+e, 1); 
    3099     return false; 
    3100   } 
    3101 }; 
    3102  
    3103 /** 
    3104  * Sends a JSJaCPacket 
    3105  * @param {JSJaCPacket} packet  The packet to send 
    3106  * @param {Function}    cb      The callback to be called if there's a reply 
    3107  * to this packet (identified by id) [optional] 
    3108  * @param {Object}      arg     Arguments passed to the callback 
    3109  * (additionally to the packet received) [optional] 
    3110  * @return 'true' if sending was successfull, 'false' otherwise 
    3111  * @type boolean 
    3112  */ 
    3113 JSJaCConnection.prototype.send = function(packet,cb,arg) { 
    3114   if (!packet || !packet.pType) { 
    3115     this.oDbg.log("no packet: "+packet, 1); 
    3116     return false; 
    3117   } 
    3118  
    3119   if (!this.connected()) 
    3120     return false; 
    3121  
    3122   // remember id for response if callback present 
    3123   if (cb) { 
    3124     if (!packet.getID()) 
    3125       packet.setID('JSJaCID_'+this._ID++); // generate an ID 
    3126  
    3127     // register callback with id 
    3128     this._registerPID(packet.getID(),cb,arg); 
    3129   } 
    3130  
    3131   try { 
    3132     this._handleEvent(packet.pType()+'_out', packet); 
    3133     this._handleEvent("packet_out", packet); 
    3134     this._pQueue = this._pQueue.concat(packet.xml()); 
    3135   } catch (e) { 
    3136     this.oDbg.log(e.toString(),1); 
    3137     return false; 
    3138   } 
    3139  
    3140   return true; 
    3141 }; 
    3142  
    3143 /** 
    3144  * Sends an IQ packet. Has default handlers for each reply type. 
    3145  * Those maybe overriden by passing an appropriate handler. 
    3146  * @param {JSJaCIQPacket} iq - the iq packet to send 
    3147  * @param {Object} handlers - object with properties 'error_handler', 
    3148  *                            'result_handler' and 'default_handler' 
    3149  *                            with appropriate functions 
    3150  * @param {Object} arg - argument to handlers 
    3151  * @return 'true' if sending was successfull, 'false' otherwise 
    3152  * @type boolean 
    3153  */ 
    3154 JSJaCConnection.prototype.sendIQ = function(iq, handlers, arg) { 
    3155   if (!iq || iq.pType() != 'iq') { 
    3156     return false; 
    3157   } 
    3158  
    3159   handlers = handlers || {}; 
    3160   var error_handler = handlers.error_handler || function(aIq) { 
    3161     this.oDbg.log(aIq.xml(), 1); 
    3162   }; 
    3163   
    3164   var result_handler = handlers.result_handler ||  function(aIq) { 
    3165     this.oDbg.log(aIq.xml(), 2); 
    3166   }; 
    3167   // unsure, what's the use of this? 
    3168   var default_handler = handlers.default_handler || function(aIq) { 
    3169     this.oDbg.log(aIq.xml(), 2); 
    3170   }; 
    3171  
    3172   var iqHandler = function(aIq, arg) { 
    3173     switch (aIq.getType()) { 
    3174       case 'error': 
    3175       error_handler(aIq); 
    3176       break; 
    3177       case 'result': 
    3178       result_handler(aIq, arg); 
    3179       break; 
    3180       default: // may it be? 
    3181       default_handler(aIq, arg); 
    3182     } 
    3183   }; 
    3184   return this.send(iq, iqHandler, arg); 
    3185 }; 
    3186  
    3187 /** 
    3188  * Sets polling interval for this connection 
    3189  * @param {int} millisecs Milliseconds to set timer to 
    3190  * @return effective interval this connection has been set to 
    3191  * @type int 
    3192  */ 
    3193 JSJaCConnection.prototype.setPollInterval = function(timerval) { 
    3194   if (timerval && !isNaN(timerval)) 
    3195     this._timerval = timerval; 
    3196   return this._timerval; 
    3197 }; 
    3198  
    3199 /** 
    3200  * Returns current status of this connection 
    3201  * @return String to denote current state. One of 
    3202  * <ul> 
    3203  * <li>'initializing' ... well 
    3204  * <li>'connecting' if connect() was called 
    3205  * <li>'resuming' if resume() was called 
    3206  * <li>'processing' if it's about to operate as normal 
    3207  * <li>'onerror_fallback' if there was an error with the request object 
    3208  * <li>'protoerror_fallback' if there was an error at the http binding protocol flow (most likely that's where you interested in) 
    3209  * <li>'internal_server_error' in case of an internal server error 
    3210  * <li>'suspending' if suspend() is being called 
    3211  * <li>'aborted' if abort() was called 
    3212  * <li>'disconnecting' if disconnect() has been called 
    3213  * </ul> 
    3214  * @type String 
    3215  */ 
    3216 JSJaCConnection.prototype.status = function() { return this._status; }; 
    3217  
    3218 /** 
    3219  * Suspends this connection (saving state for later resume) 
    3220  * Saves state to cookie 
    3221  * @return Whether suspend (saving to cookie) was successful 
    3222  * @type boolean 
    3223  */ 
    3224 JSJaCConnection.prototype.suspend = function() { 
    3225   var data = this.suspendToData(); 
    3226    
    3227   try { 
    3228     var c = new JSJaCCookie(this._cookie_prefix+'JSJaC_State', JSJaCJSON.toString(data)); 
    3229     this.oDbg.log("writing cookie: "+c.getValue()+"\n"+ 
    3230                   "(length:"+c.getValue().length+")",2); 
    3231     c.write(); 
    3232  
    3233     var c2 = JSJaCCookie.get(this._cookie_prefix+'JSJaC_State'); 
    3234     if (c.getValue() != c2) { 
    3235       this.oDbg.log("Suspend failed writing cookie.\nread: " + c2, 1); 
    3236       c.erase(); 
    3237       return false; 
    3238     } 
    3239     return true; 
    3240   } catch (e) { 
    3241     this.oDbg.log("Failed creating cookie '"+this._cookie_prefix+ 
    3242                   "JSJaC_State': "+e.message,1); 
    3243   } 
    3244   return false; 
    3245 }; 
    3246  
    3247 /** 
    3248  * Suspend connection and return serialized JSJaC connection state 
    3249  * @return JSJaC connection state object 
    3250  * @type Object 
    3251  */ 
    3252 JSJaCConnection.prototype.suspendToData = function() { 
    3253    
    3254   // remove timers 
    3255   clearTimeout(this._timeout); 
    3256   clearInterval(this._interval); 
    3257   clearInterval(this._inQto); 
    3258  
    3259   this._suspend(); 
    3260  
    3261   var u = ('_connected,_keys,_ID,_inQ,_pQueue,_regIDs,_errcnt,_inactivity,domain,username,resource,jid,fulljid,_sid,_httpbase,_timerval,_is_polling').split(','); 
    3262   u = u.concat(this._getSuspendVars()); 
    3263   var s = new Object(); 
    3264  
    3265   for (var i=0; i<u.length; i++) { 
    3266     if (!this[u[i]]) continue; // hu? skip these! 
    3267     if (this[u[i]]._getSuspendVars) { 
    3268       var uo = this[u[i]]._getSuspendVars(); 
    3269       var o = new Object(); 
    3270       for (var j=0; j<uo.length; j++) 
    3271         o[uo[j]] = this[u[i]][uo[j]]; 
    3272     } else 
    3273       var o = this[u[i]]; 
    3274  
    3275     s[u[i]] = o; 
    3276   } 
    3277   this._connected = false; 
    3278   this._setStatus('suspending'); 
    3279   return s; 
    3280 }; 
    3281  
    3282 /** 
    3283  * @private 
    3284  */ 
    3285 JSJaCConnection.prototype._abort = function() { 
    3286   clearTimeout(this._timeout); // remove timer 
    3287  
    3288   clearInterval(this._inQto); 
    3289   clearInterval(this._interval); 
    3290  
    3291   this._connected = false; 
    3292  
    3293   this._setStatus('aborted'); 
    3294  
    3295   this.oDbg.log("Disconnected.",1); 
    3296   this._handleEvent('ondisconnect'); 
    3297   this._handleEvent('onerror', 
    3298                     JSJaCError('500','cancel','service-unavailable')); 
    3299 }; 
    3300  
    3301 /** 
    3302  * @private 
    3303  */ 
    3304 JSJaCConnection.prototype._checkInQ = function() { 
    3305   for (var i=0; i<this._inQ.length && i<10; i++) { 
    3306     var item = this._inQ[0]; 
    3307     this._inQ = this._inQ.slice(1,this._inQ.length); 
    3308     var packet = JSJaCPacket.wrapNode(item); 
    3309  
    3310     if (!packet) 
    3311       return; 
    3312  
    3313     this._handleEvent("packet_in", packet); 
    3314  
    3315     if (packet.pType && !this._handlePID(packet)) { 
    3316       this._handleEvent(packet.pType()+'_in',packet); 
    3317       this._handleEvent(packet.pType(),packet); 
    3318     } 
    3319   } 
    3320 }; 
    3321  
    3322 /** 
    3323  * @private 
    3324  */ 
    3325 JSJaCConnection.prototype._checkQueue = function() { 
    3326   if (this._pQueue.length != 0) 
    3327     this._process(); 
    3328   return true; 
    3329 }; 
    3330  
    3331 /** 
    3332  * @private 
    3333  */ 
    3334 JSJaCConnection.prototype._doAuth = function() { 
    3335   if (this.has_sasl && this.authtype == 'nonsasl') 
    3336     this.oDbg.log("Warning: SASL present but not used", 1); 
    3337  
    3338   if (!this._doSASLAuth() && 
    3339       !this._doLegacyAuth()) { 
    3340     this.oDbg.log("Auth failed for authtype "+this.authtype,1); 
    3341     this.disconnect(); 
    3342     return false; 
    3343   } 
    3344   return true; 
    3345 }; 
    3346  
    3347 /** 
    3348  * @private 
    3349  */ 
    3350 JSJaCConnection.prototype._doInBandReg = function() { 
    3351   if (this.authtype == 'saslanon' || this.authtype == 'anonymous') 
    3352     return; // bullshit - no need to register if anonymous 
    3353  
    3354   /* *** 
    3355    * In-Band Registration see JEP-0077 
    3356    */ 
    3357  
    3358   var iq = new JSJaCIQ(); 
    3359   iq.setType('set'); 
    3360   iq.setID('reg1'); 
    3361   iq.appendNode("query", {xmlns: "jabber:iq:register"}, 
    3362                 [["username", this.username], 
    3363                  ["password", this.pass]]); 
    3364  
    3365   this.send(iq,this._doInBandRegDone); 
    3366 }; 
    3367  
    3368 /** 
    3369  * @private 
    3370  */ 
    3371 JSJaCConnection.prototype._doInBandRegDone = function(iq) { 
    3372   if (iq && iq.getType() == 'error') { // we failed to register 
    3373     this.oDbg.log("registration failed for "+this.username,0); 
    3374     this._handleEvent('onerror',iq.getChild('error')); 
    3375     return; 
    3376   } 
    3377  
    3378   this.oDbg.log(this.username + " registered succesfully",0); 
    3379  
    3380   this._doAuth(); 
    3381 }; 
    3382  
    3383 /** 
    3384  * @private 
    3385  */ 
    3386 JSJaCConnection.prototype._doLegacyAuth = function() { 
    3387   if (this.authtype != 'nonsasl' && this.authtype != 'anonymous') 
    3388     return false; 
    3389  
    3390   /* *** 
    3391    * Non-SASL Authentication as described in JEP-0078 
    3392    */ 
    3393   var iq = new JSJaCIQ(); 
    3394   iq.setIQ(this.server,'get','auth1'); 
    3395   iq.appendNode('query', {xmlns: 'jabber:iq:auth'}, 
    3396                 [['username', this.username]]); 
    3397  
    3398   this.send(iq,this._doLegacyAuth2); 
    3399   return true; 
    3400 }; 
    3401  
    3402 /** 
    3403  * @private 
    3404  */ 
    3405 JSJaCConnection.prototype._doLegacyAuth2 = function(iq) { 
    3406   if (!iq || iq.getType() != 'result') { 
    3407     if (iq && iq.getType() == 'error') 
    3408       this._handleEvent('onerror',iq.getChild('error')); 
    3409     this.disconnect(); 
    3410     return; 
    3411   } 
    3412  
    3413   var use_digest = (iq.getChild('digest') != null); 
    3414  
    3415   /* *** 
    3416    * Send authentication 
    3417    */ 
    3418   var iq = new JSJaCIQ(); 
    3419   iq.setIQ(this.server,'set','auth2'); 
    3420  
    3421   query = iq.appendNode('query', {xmlns: 'jabber:iq:auth'}, 
    3422                         [['username', this.username], 
    3423                          ['resource', this.resource]]); 
    3424  
    3425   if (use_digest) { // digest login 
    3426     query.appendChild(iq.buildNode('digest', {xmlns: 'jabber:iq:auth'}, 
    3427                                    hex_sha1(this.streamid + this.pass))); 
    3428   } else if (this.allow_plain) { // use plaintext auth 
    3429     query.appendChild(iq.buildNode('password', {xmlns: 'jabber:iq:auth'}, 
    3430                                    this.pass)); 
    3431   } else { 
    3432     this.oDbg.log("no valid login mechanism found",1); 
    3433     this.disconnect(); 
    3434     return false; 
    3435   } 
    3436  
    3437   this.send(iq,this._doLegacyAuthDone); 
    3438 }; 
    3439  
    3440 /** 
    3441  * @private 
    3442  */ 
    3443 JSJaCConnection.prototype._doLegacyAuthDone = function(iq) { 
    3444   if (iq.getType() != 'result') { // auth' failed 
    3445     if (iq.getType() == 'error') 
    3446       this._handleEvent('onerror',iq.getChild('error')); 
    3447     this.disconnect(); 
    3448   } else 
    3449     this._handleEvent('onconnect'); 
    3450 }; 
    3451  
    3452 /** 
    3453  * @private 
    3454  */ 
    3455 JSJaCConnection.prototype._doSASLAuth = function() { 
    3456   if (this.authtype == 'nonsasl' || this.authtype == 'anonymous') 
    3457     return false; 
    3458  
    3459   if (this.authtype == 'saslanon') { 
    3460     if (this.mechs['ANONYMOUS']) { 
    3461       this.oDbg.log("SASL using mechanism 'ANONYMOUS'",2); 
    3462       return this._sendRaw("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='ANONYMOUS'/>", 
    3463                            this._doSASLAuthDone); 
    3464     } 
    3465     this.oDbg.log("SASL ANONYMOUS requested but not supported",1); 
    3466   } else { 
    3467     if (this.mechs['DIGEST-MD5']) { 
    3468       this.oDbg.log("SASL using mechanism 'DIGEST-MD5'",2); 
    3469       return this._sendRaw("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='DIGEST-MD5'/>", 
    3470                            this._doSASLAuthDigestMd5S1); 
    3471     } else if (this.allow_plain && this.mechs['PLAIN']) { 
    3472       this.oDbg.log("SASL using mechanism 'PLAIN'",2); 
    3473       var authStr = this.username+'@'+ 
    3474       this.domain+String.fromCharCode(0)+ 
    3475       this.username+String.fromCharCode(0)+ 
    3476       this.pass; 
    3477       this.oDbg.log("authenticating with '"+authStr+"'",2); 
    3478       authStr = btoa(authStr); 
    3479       return this._sendRaw("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>"+authStr+"</auth>", 
    3480                            this._doSASLAuthDone); 
    3481     } 
    3482     this.oDbg.log("No SASL mechanism applied",1); 
    3483     this.authtype = 'nonsasl'; // fallback 
    3484   } 
    3485   return false; 
    3486 }; 
    3487  
    3488 /** 
    3489  * @private 
    3490  */ 
    3491 JSJaCConnection.prototype._doSASLAuthDigestMd5S1 = function(el) { 
    3492   if (el.nodeName != "challenge") { 
    3493     this.oDbg.log("challenge missing",1); 
    3494     this._handleEvent('onerror',JSJaCError('401','auth','not-authorized')); 
    3495     this.disconnect(); 
    3496   } else { 
    3497     var challenge = atob(el.firstChild.nodeValue); 
    3498     this.oDbg.log("got challenge: "+challenge,2); 
    3499     this._nonce = challenge.substring(challenge.indexOf("nonce=")+7); 
    3500     this._nonce = this._nonce.substring(0,this._nonce.indexOf("\"")); 
    3501     this.oDbg.log("nonce: "+this._nonce,2); 
    3502     if (this._nonce == '' || this._nonce.indexOf('\"') != -1) { 
    3503       this.oDbg.log("nonce not valid, aborting",1); 
    3504       this.disconnect(); 
    3505       return; 
    3506     } 
    3507  
    3508     this._digest_uri = "xmpp/"; 
    3509     //     if (typeof(this.host) != 'undefined' && this.host != '') { 
    3510     //       this._digest-uri += this.host; 
    3511     //       if (typeof(this.port) != 'undefined' && this.port) 
    3512     //         this._digest-uri += ":" + this.port; 
    3513     //       this._digest-uri += '/'; 
    3514     //     } 
    3515     this._digest_uri += this.domain; 
    3516  
    3517     this._cnonce = cnonce(14); 
    3518  
    3519     this._nc = '00000001'; 
    3520  
    3521     var A1 = str_md5(this.username+':'+this.domain+':'+this.pass)+ 
    3522     ':'+this._nonce+':'+this._cnonce; 
    3523  
    3524     var A2 = 'AUTHENTICATE:'+this._digest_uri; 
    3525  
    3526     var response = hex_md5(hex_md5(A1)+':'+this._nonce+':'+this._nc+':'+ 
    3527                            this._cnonce+':auth:'+hex_md5(A2)); 
    3528  
    3529     var rPlain = 'username="'+this.username+'",realm="'+this.domain+ 
    3530     '",nonce="'+this._nonce+'",cnonce="'+this._cnonce+'",nc="'+this._nc+ 
    3531     '",qop=auth,digest-uri="'+this._digest_uri+'",response="'+response+ 
    3532     '",charset="utf-8"'; 
    3533     
    3534     this.oDbg.log("response: "+rPlain,2); 
    3535  
    3536     this._sendRaw("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>"+ 
    3537                   binb2b64(str2binb(rPlain))+"</response>", 
    3538                   this._doSASLAuthDigestMd5S2); 
    3539   } 
    3540 }; 
    3541  
    3542 /** 
    3543  * @private 
    3544  */ 
    3545 JSJaCConnection.prototype._doSASLAuthDigestMd5S2 = function(el) { 
    3546   if (el.nodeName == 'failure') { 
    3547     if (el.xml) 
    3548       this.oDbg.log("auth error: "+el.xml,1); 
    3549     else 
    3550       this.oDbg.log("auth error",1); 
    3551     this._handleEvent('onerror',JSJaCError('401','auth','not-authorized')); 
    3552     this.disconnect(); 
    3553     return; 
    3554   } 
    3555  
    3556   var response = atob(el.firstChild.nodeValue); 
    3557   this.oDbg.log("response: "+response,2); 
    3558  
    3559   var rspauth = response.substring(response.indexOf("rspauth=")+8); 
    3560   this.oDbg.log("rspauth: "+rspauth,2); 
    3561  
    3562   var A1 = str_md5(this.username+':'+this.domain+':'+this.pass)+ 
    3563   ':'+this._nonce+':'+this._cnonce; 
    3564  
    3565   var A2 = ':'+this._digest_uri; 
    3566  
    3567   var rsptest = hex_md5(hex_md5(A1)+':'+this._nonce+':'+this._nc+':'+ 
    3568                         this._cnonce+':auth:'+hex_md5(A2)); 
    3569   this.oDbg.log("rsptest: "+rsptest,2); 
    3570  
    3571   if (rsptest != rspauth) { 
    3572     this.oDbg.log("SASL Digest-MD5: server repsonse with wrong rspauth",1); 
    3573     this.disconnect(); 
    3574     return; 
    3575   } 
    3576  
    3577   if (el.nodeName == 'success') 
    3578     this._reInitStream(this.domain, this._doStreamBind); 
    3579   else // some extra turn 
    3580     this._sendRaw("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>", 
    3581                   this._doSASLAuthDone); 
    3582 }; 
    3583  
    3584 /** 
    3585  * @private 
    3586  */ 
    3587 JSJaCConnection.prototype._doSASLAuthDone = function (el) { 
    3588   if (el.nodeName != 'success') { 
    3589     this.oDbg.log("auth failed",1); 
    3590     this._handleEvent('onerror',JSJaCError('401','auth','not-authorized')); 
    3591     this.disconnect(); 
    3592   } else 
    3593     this._reInitStream(this.domain, this._doStreamBind); 
    3594 }; 
    3595  
    3596 /** 
    3597  * @private 
    3598  */ 
    3599 JSJaCConnection.prototype._doStreamBind = function() { 
    3600   var iq = new JSJaCIQ(); 
    3601   iq.setIQ(this.domain,'set','bind_1'); 
    3602   iq.appendNode("bind", {xmlns: "urn:ietf:params:xml:ns:xmpp-bind"}, 
    3603                 [["resource", this.resource]]); 
    3604   this.oDbg.log(iq.xml()); 
    3605   this.send(iq,this._doXMPPSess); 
    3606 }; 
    3607  
    3608 /** 
    3609  * @private 
    3610  */ 
    3611 JSJaCConnection.prototype._doXMPPSess = function(iq) { 
    3612   if (iq.getType() != 'result' || iq.getType() == 'error') { // failed 
    3613     this.disconnect(); 
    3614     if (iq.getType() == 'error') 
    3615       this._handleEvent('onerror',iq.getChild('error')); 
    3616     return; 
    3617   } 
    3618   
    3619   this.fulljid = iq.getChildVal("jid"); 
    3620   this.jid = this.fulljid.substring(0,this.fulljid.lastIndexOf('/')); 
    3621   
    3622   iq = new JSJaCIQ(); 
    3623   iq.setIQ(this.domain,'set','sess_1'); 
    3624   iq.appendNode("session", {xmlns: "urn:ietf:params:xml:ns:xmpp-session"}, 
    3625                 []); 
    3626   this.oDbg.log(iq.xml()); 
    3627   this.send(iq,this._doXMPPSessDone); 
    3628 }; 
    3629  
    3630 /** 
    3631  * @private 
    3632  */ 
    3633 JSJaCConnection.prototype._doXMPPSessDone = function(iq) { 
    3634   if (iq.getType() != 'result' || iq.getType() == 'error') { // failed 
    3635     this.disconnect(); 
    3636     if (iq.getType() == 'error') 
    3637       this._handleEvent('onerror',iq.getChild('error')); 
    3638     return; 
    3639   } else 
    3640     this._handleEvent('onconnect'); 
    3641 }; 
    3642   
    3643 /** 
    3644  * @private 
    3645  */ 
    3646 JSJaCConnection.prototype._handleEvent = function(event,arg) { 
    3647   event = event.toLowerCase(); // don't be case-sensitive here 
    3648   this.oDbg.log("incoming event '"+event+"'",3); 
    3649   if (!this._events[event]) 
    3650     return; 
    3651   this.oDbg.log("handling event '"+event+"'",2); 
    3652   for (var i=0;i<this._events[event].length; i++) { 
    3653     var aEvent = this._events[event][i]; 
    3654     if (typeof aEvent.handler == 'function') { 
    3655       try { 
    3656         if (arg) { 
    3657           if (arg.pType) { // it's a packet 
    3658             if ((!arg.getNode().hasChildNodes() && aEvent.childName != '*') || 
    3659                                 (arg.getNode().hasChildNodes() && 
    3660                                  !arg.getChild(aEvent.childName, aEvent.childNS))) 
    3661               continue; 
    3662             if (aEvent.type != '*' && 
    3663                 arg.getType() != aEvent.type) 
    3664               continue; 
    3665             this.oDbg.log(aEvent.childName+"/"+aEvent.childNS+"/"+aEvent.type+" => match for handler "+aEvent.handler,3); 
    3666           } 
    3667           if (aEvent.handler(arg)) { 
    3668             // handled! 
    3669             break; 
    3670           } 
    3671         } 
    3672         else 
    3673           if (aEvent.handler()) { 
    3674             // handled! 
    3675             break; 
    3676           } 
    3677       } catch (e) {  
    3678  
    3679         if (e.fileName&&e.lineNumber) { 
    3680             this.oDbg.log(aEvent.handler+"\n>>>"+e.name+": "+ e.message+' in '+e.fileName+' line '+e.lineNumber,1);     
    3681         } else { 
    3682             this.oDbg.log(aEvent.handler+"\n>>>"+e.name+": "+ e.message,1);              
    3683         } 
    3684  
    3685       } 
    3686     } 
    3687   } 
    3688 }; 
    3689  
    3690 /** 
    3691  * @private 
    3692  */ 
    3693 JSJaCConnection.prototype._handlePID = function(aJSJaCPacket) { 
    3694   if (!aJSJaCPacket.getID()) 
    3695     return false; 
    3696   for (var i in this._regIDs) { 
    3697     if (this._regIDs.hasOwnProperty(i) && 
    3698         this._regIDs[i] && i == aJSJaCPacket.getID()) { 
    3699       var pID = aJSJaCPacket.getID(); 
    3700       this.oDbg.log("handling "+pID,3); 
    3701       try { 
    3702         if (this._regIDs[i].cb.call(this, aJSJaCPacket,this._regIDs[i].arg) === false) { 
    3703           // don't unregister 
    3704           return false; 
    3705         } else { 
    3706           this._unregisterPID(pID); 
    3707           return true; 
    3708         } 
    3709       } catch (e) { 
    3710         // broken handler? 
    3711         this.oDbg.log(e.name+": "+ e.message); 
    3712         this._unregisterPID(pID); 
    3713         return true; 
    3714       } 
    3715     } 
    3716   } 
    3717   return false; 
    3718 }; 
    3719  
    3720 /** 
    3721  * @private 
    3722  */ 
    3723 JSJaCConnection.prototype._handleResponse = function(req) { 
    3724   var rootEl = this._parseResponse(req); 
    3725  
    3726   if (!rootEl) 
    3727     return; 
    3728  
    3729   for (var i=0; i<rootEl.childNodes.length; i++) { 
    3730     if (this._sendRawCallbacks.length) { 
    3731       var cb = this._sendRawCallbacks[0]; 
    3732       this._sendRawCallbacks = this._sendRawCallbacks.slice(1, this._sendRawCallbacks.length); 
    3733       cb.fn.call(this, rootEl.childNodes.item(i), cb.arg); 
    3734       continue; 
    3735     } 
    3736     this._inQ = this._inQ.concat(rootEl.childNodes.item(i)); 
    3737   } 
    3738 }; 
    3739  
    3740 /** 
    3741  * @private 
    3742  */ 
    3743 JSJaCConnection.prototype._parseStreamFeatures = function(doc) { 
    3744   if (!doc) { 
    3745     this.oDbg.log("nothing to parse ... aborting",1); 
    3746     return false; 
    3747   } 
    3748  
    3749   var errorTag; 
    3750   if (doc.getElementsByTagNameNS) 
    3751     errorTag = doc.getElementsByTagNameNS("http://etherx.jabber.org/streams", "error").item(0); 
    3752   else { 
    3753     var errors = doc.getElementsByTagName("error"); 
    3754     for (var i=0; i<errors.length; i++) 
    3755       if (errors.item(i).namespaceURI == "http://etherx.jabber.org/streams") { 
    3756         errorTag = errors.item(i); 
    3757         break; 
    3758       } 
    3759   } 
    3760  
    3761   if (errorTag) { 
    3762     this._setStatus("internal_server_error"); 
    3763     clearTimeout(this._timeout); // remove timer 
    3764     clearInterval(this._interval); 
    3765     clearInterval(this._inQto); 
    3766     this._handleEvent('onerror',JSJaCError('503','cancel','session-terminate')); 
    3767     this._connected = false; 
    3768     this.oDbg.log("Disconnected.",1); 
    3769     this._handleEvent('ondisconnect'); 
    3770     return false; 
    3771   } 
    3772  
    3773   this.mechs = new Object(); 
    3774   var lMec1 = doc.getElementsByTagName("mechanisms"); 
    3775   this.has_sasl = false; 
    3776   for (var i=0; i<lMec1.length; i++) 
    3777     if (lMec1.item(i).getAttribute("xmlns") == 
    3778         "urn:ietf:params:xml:ns:xmpp-sasl") { 
    3779       this.has_sasl=true; 
    3780       var lMec2 = lMec1.item(i).getElementsByTagName("mechanism"); 
    3781       for (var j=0; j<lMec2.length; j++) 
    3782         this.mechs[lMec2.item(j).firstChild.nodeValue] = true; 
    3783       break; 
    3784     } 
    3785   if (this.has_sasl) 
    3786     this.oDbg.log("SASL detected",2); 
    3787   else { 
    3788     this.oDbg.log("No support for SASL detected",2); 
    3789     return false; 
    3790   } 
    3791  
    3792   /* [TODO] 
    3793    * check if in-band registration available 
    3794    * check for session and bind features 
    3795    */ 
    3796  
    3797   return true; 
    3798 }; 
    3799  
    3800 /** 
    3801  * @private 
    3802  */ 
    3803 JSJaCConnection.prototype._process = function(timerval) { 
    3804   if (!this.connected()) { 
    3805     this.oDbg.log("Connection lost ...",1); 
    3806     if (this._interval) 
    3807       clearInterval(this._interval); 
    3808     return; 
    3809   } 
    3810  
    3811   this.setPollInterval(timerval); 
    3812  
    3813   if (this._timeout) 
    3814     clearTimeout(this._timeout); 
    3815  
    3816   var slot = this._getFreeSlot(); 
    3817  
    3818   if (slot < 0) 
    3819     return; 
    3820  
    3821   if (typeof(this._req[slot]) != 'undefined' && 
    3822       typeof(this._req[slot].r) != 'undefined' && 
    3823       this._req[slot].r.readyState != 4) { 
    3824     this.oDbg.log("Slot "+slot+" is not ready"); 
    3825     return; 
    3826   } 
    3827          
    3828   if (!this.isPolling() && this._pQueue.length == 0 && 
    3829       this._req[(slot+1)%2] && this._req[(slot+1)%2].r.readyState != 4) { 
    3830     this.oDbg.log("all slots busy, standby ...", 2); 
    3831     return; 
    3832   } 
    3833  
    3834   if (!this.isPolling()) 
    3835     this.oDbg.log("Found working slot at "+slot,2); 
    3836  
    3837   this._req[slot] = this._setupRequest(true); 
    3838  
    3839   /* setup onload handler for async send */ 
    3840   this._req[slot].r.onreadystatechange =  
    3841   JSJaC.bind(function() { 
    3842                if (!this.connected()) 
    3843                  return; 
    3844                if (this._req[slot].r.readyState == 4) { 
    3845                  this._setStatus('processing'); 
    3846                  this.oDbg.log("async recv: "+this._req[slot].r.responseText,4); 
    3847                  this._handleResponse(this._req[slot]); 
    3848                  // schedule next tick 
    3849                  if (this._pQueue.length) { 
    3850                    this._timeout = setTimeout(JSJaC.bind(this._process, this),100); 
    3851                  } else { 
    3852                    this.oDbg.log("scheduling next poll in "+this.getPollInterval()+ 
    3853                                  " msec", 4); 
    3854                    this._timeout = setTimeout(JSJaC.bind(this._process, this),this.getPollInterval()); 
    3855                  } 
    3856                } 
    3857              }, this); 
    3858  
    3859   try { 
    3860     this._req[slot].r.onerror =  
    3861       JSJaC.bind(function() { 
    3862                    if (!this.connected()) 
    3863                      return; 
    3864                    this._errcnt++; 
    3865                    this.oDbg.log('XmlHttpRequest error ('+this._errcnt+')',1); 
    3866                    if (this._errcnt > JSJAC_ERR_COUNT) { 
    3867                      // abort 
    3868                      this._abort(); 
    3869                      return false; 
    3870                    } 
    3871                     
    3872                    this._setStatus('onerror_fallback'); 
    3873                          
    3874                    // schedule next tick 
    3875                    setTimeout(JSJaC.bind(this._resume, this),this.getPollInterval()); 
    3876                    return false; 
    3877                  }, this); 
    3878   } catch(e) { } // well ... no onerror property available, maybe we 
    3879   // can catch the error somewhere else ... 
    3880  
    3881   var reqstr = this._getRequestString(); 
    3882  
    3883   if (typeof(this._rid) != 'undefined') // remember request id if any 
    3884     this._req[slot].rid = this._rid; 
    3885  
    3886   this.oDbg.log("sending: " + reqstr,4); 
    3887   this._req[slot].r.send(reqstr); 
    3888 }; 
    3889  
    3890 /** 
    3891  * @private 
    3892  */ 
    3893 JSJaCConnection.prototype._registerPID = function(pID,cb,arg) { 
    3894   if (!pID || !cb) 
    3895     return false; 
    3896   this._regIDs[pID] = new Object(); 
    3897   this._regIDs[pID].cb = cb; 
    3898   if (arg) 
    3899     this._regIDs[pID].arg = arg; 
    3900   this.oDbg.log("registered "+pID,3); 
    3901   return true; 
    3902 }; 
    3903  
    3904 /** 
    3905  * send empty request 
    3906  * waiting for stream id to be able to proceed with authentication 
    3907  * @private 
    3908  */ 
    3909 JSJaCConnection.prototype._sendEmpty = function JSJaCSendEmpty() { 
    3910   var slot = this._getFreeSlot(); 
    3911   this._req[slot] = this._setupRequest(true); 
    3912  
    3913   this._req[slot].r.onreadystatechange =  
    3914   JSJaC.bind(function() { 
    3915                if (this._req[slot].r.readyState == 4) { 
    3916                  this.oDbg.log("async recv: "+this._req[slot].r.responseText,4); 
    3917                  this._getStreamID(slot); // handle response 
    3918                } 
    3919              },this); 
    3920  
    3921   if (typeof(this._req[slot].r.onerror) != 'undefined') { 
    3922     this._req[slot].r.onerror =  
    3923       JSJaC.bind(function(e) { 
    3924                    this.oDbg.log('XmlHttpRequest error',1); 
    3925                    return false; 
    3926                  }, this); 
    3927   } 
    3928  
    3929   var reqstr = this._getRequestString(); 
    3930   this.oDbg.log("sending: " + reqstr,4); 
    3931   this._req[slot].r.send(reqstr); 
    3932 }; 
    3933  
    3934 /** 
    3935  * @private 
    3936  */ 
    3937 JSJaCConnection.prototype._sendRaw = function(xml,cb,arg) { 
    3938   if (cb) 
    3939     this._sendRawCallbacks.push({fn: cb, arg: arg}); 
    3940   
    3941   this._pQueue.push(xml); 
    3942   this._process(); 
    3943  
    3944   return true; 
    3945 }; 
    3946  
    3947 /** 
    3948  * @private 
    3949  */ 
    3950 JSJaCConnection.prototype._setStatus = function(status) { 
    3951   if (!status || status == '') 
    3952     return; 
    3953   if (status != this._status) { // status changed! 
    3954     this._status = status; 
    3955     this._handleEvent('onstatuschanged', status); 
    3956     this._handleEvent('status_changed', status); 
    3957   } 
    3958 }; 
    3959  
    3960 /** 
    3961  * @private 
    3962  */ 
    3963 JSJaCConnection.prototype._unregisterPID = function(pID) { 
    3964   if (!this._regIDs[pID]) 
    3965     return false; 
    3966   this._regIDs[pID] = null; 
    3967   this.oDbg.log("unregistered "+pID,3); 
    3968   return true; 
    3969 }; 
    3970 /** 
    3971  * @fileoverview All stuff related to HTTP Binding 
    3972  * @author Stefan Strigler steve@zeank.in-berlin.de 
    3973  * @version $Revision: 513 $ 
    3974  */ 
    3975  
    3976 /** 
    3977  * Instantiates an HTTP Binding session 
    3978  * @class Implementation of {@link 
    3979  * http://www.xmpp.org/extensions/xep-0206.html XMPP Over BOSH} 
    3980  * formerly known as HTTP Binding. 
    3981  * @extends JSJaCConnection 
    3982  * @constructor 
    3983  */ 
    3984 function JSJaCHttpBindingConnection(oArg) { 
    3985   /** 
    3986    * @ignore 
    3987    */ 
    3988   this.base = JSJaCConnection; 
    3989   this.base(oArg); 
    3990  
    3991   // member vars 
    3992   /** 
    3993    * @private 
    3994    */ 
    3995   this._hold = JSJACHBC_MAX_HOLD; 
    3996   /** 
    3997    * @private 
    3998    */ 
    3999   this._inactivity = 0; 
    4000   /** 
    4001    * @private 
    4002    */ 
    4003   this._last_requests = new Object(); // 'hash' storing hold+1 last requests 
    4004   /** 
    4005    * @private 
    4006    */ 
    4007   this._last_rid = 0;                 // I know what you did last summer 
    4008   /** 
    4009    * @private 
    4010    */ 
    4011   this._min_polling = 0; 
    4012  
    4013   /** 
    4014    * @private 
    4015    */ 
    4016   this._pause = 0; 
    4017   /** 
    4018    * @private 
    4019    */ 
    4020   this._wait = JSJACHBC_MAX_WAIT; 
    4021 } 
    4022 JSJaCHttpBindingConnection.prototype = new JSJaCConnection(); 
    4023  
    4024 /** 
    4025  * Inherit an instantiated HTTP Binding session 
    4026  */ 
    4027 JSJaCHttpBindingConnection.prototype.inherit = function(oArg) { 
    4028   this.domain = oArg.domain || 'localhost'; 
    4029   this.username = oArg.username; 
    4030   this.resource = oArg.resource; 
    4031   this._sid = oArg.sid; 
    4032   this._rid = oArg.rid; 
    4033   this._min_polling = oArg.polling; 
    4034   this._inactivity = oArg.inactivity; 
    4035   this._setHold(oArg.requests-1); 
    4036   this.setPollInterval(this._timerval); 
    4037   if (oArg.wait) 
    4038     this._wait = oArg.wait; // for whatever reason 
    4039  
    4040   this._connected = true; 
    4041  
    4042   this._handleEvent('onconnect'); 
    4043  
    4044   this._interval= setInterval(JSJaC.bind(this._checkQueue, this), 
    4045                               JSJAC_CHECKQUEUEINTERVAL); 
    4046   this._inQto = setInterval(JSJaC.bind(this._checkInQ, this), 
    4047                             JSJAC_CHECKINQUEUEINTERVAL); 
    4048   this._timeout = setTimeout(JSJaC.bind(this._process, this), 
    4049                              this.getPollInterval()); 
    4050 }; 
    4051  
    4052 /** 
    4053  * Sets poll interval 
    4054  * @param {int} timerval the interval in seconds 
    4055  */ 
    4056 JSJaCHttpBindingConnection.prototype.setPollInterval = function(timerval) { 
    4057   if (timerval && !isNaN(timerval)) { 
    4058     if (!this.isPolling()) 
    4059       this._timerval = 100; 
    4060     else if (this._min_polling && timerval < this._min_polling*1000) 
    4061       this._timerval = this._min_polling*1000; 
    4062     else if (this._inactivity && timerval > this._inactivity*1000) 
    4063       this._timerval = this._inactivity*1000; 
    4064     else 
    4065       this._timerval = timerval; 
    4066   } 
    4067   return this._timerval; 
    4068 }; 
    4069  
    4070 /** 
    4071  * whether this session is in polling mode 
    4072  * @type boolean 
    4073  */ 
    4074 JSJaCHttpBindingConnection.prototype.isPolling = function() { return (this._hold == 0) }; 
    4075  
    4076 /** 
    4077  * @private 
    4078  */ 
    4079 JSJaCHttpBindingConnection.prototype._getFreeSlot = function() { 
    4080   for (var i=0; i<this._hold+1; i++) 
    4081     if (typeof(this._req[i]) == 'undefined' || typeof(this._req[i].r) == 'undefined' || this._req[i].r.readyState == 4) 
    4082       return i; 
    4083   return -1; // nothing found 
    4084 }; 
    4085  
    4086 /** 
    4087  * @private 
    4088  */ 
    4089 JSJaCHttpBindingConnection.prototype._getHold = function() { return this._hold; }; 
    4090  
    4091 /** 
    4092  * @private 
    4093  */ 
    4094 JSJaCHttpBindingConnection.prototype._getRequestString = function(raw, last) { 
    4095   raw = raw || ''; 
    4096   var reqstr = ''; 
    4097  
    4098   // check if we're repeating a request 
    4099  
    4100   if (this._rid <= this._last_rid && typeof(this._last_requests[this._rid]) != 'undefined') // repeat! 
    4101     reqstr = this._last_requests[this._rid].xml; 
    4102   else { // grab from queue 
    4103     var xml = ''; 
    4104     while (this._pQueue.length) { 
    4105       var curNode = this._pQueue[0]; 
    4106       xml += curNode; 
    4107       this._pQueue = this._pQueue.slice(1,this._pQueue.length); 
    4108     } 
    4109  
    4110     reqstr = "<body rid='"+this._rid+"' sid='"+this._sid+"' xmlns='http://jabber.org/protocol/httpbind' "; 
    4111     if (JSJAC_HAVEKEYS) { 
    4112       reqstr += "key='"+this._keys.getKey()+"' "; 
    4113       if (this._keys.lastKey()) { 
    4114         this._keys = new JSJaCKeys(hex_sha1,this.oDbg); 
    4115         reqstr += "newkey='"+this._keys.getKey()+"' "; 
    4116       } 
    4117     } 
    4118     if (last) 
    4119       reqstr += "type='terminate'"; 
    4120     else if (this._reinit) { 
    4121       if (JSJACHBC_USE_BOSH_VER)  
    4122         reqstr += "xmpp:restart='true' xmlns:xmpp='urn:xmpp:xbosh'"; 
    4123       this._reinit = false; 
    4124     } 
    4125  
    4126     if (xml != '' || raw != '') { 
    4127       reqstr += ">" + raw + xml + "</body>"; 
    4128     } else { 
    4129       reqstr += "/>"; 
    4130     } 
    4131  
    4132     this._last_requests[this._rid] = new Object(); 
    4133     this._last_requests[this._rid].xml = reqstr; 
    4134     this._last_rid = this._rid; 
    4135  
    4136     for (var i in this._last_requests) 
    4137       if (this._last_requests.hasOwnProperty(i) && 
    4138           i < this._rid-this._hold) 
    4139         delete(this._last_requests[i]); // truncate 
    4140   } 
    4141          
    4142   return reqstr; 
    4143 }; 
    4144  
    4145 /** 
    4146  * @private 
    4147  */ 
    4148 JSJaCHttpBindingConnection.prototype._getInitialRequestString = function() { 
    4149   var reqstr = "<body content='text/xml; charset=utf-8' hold='"+this._hold+"' xmlns='http://jabber.org/protocol/httpbind' to='"+this.authhost+"' wait='"+this._wait+"' rid='"+this._rid+"'"; 
    4150   if (this.host || this.port) 
    4151     reqstr += " route='xmpp:"+this.host+":"+this.port+"'"; 
    4152   if (this.secure) 
    4153     reqstr += " secure='"+this.secure+"'"; 
    4154   if (JSJAC_HAVEKEYS) { 
    4155     this._keys = new JSJaCKeys(hex_sha1,this.oDbg); // generate first set of keys 
    4156     key = this._keys.getKey(); 
    4157     reqstr += " newkey='"+key+"'"; 
    4158   } 
    4159   if (this._xmllang) 
    4160     reqstr += " xml:lang='"+this._xmllang + "'"; 
    4161  
    4162   if (JSJACHBC_USE_BOSH_VER) { 
    4163     reqstr += " ver='" + JSJACHBC_BOSH_VERSION + "'"; 
    4164     reqstr += " xmlns:xmpp='urn:xmpp:xbosh'"; 
    4165     if (this.authtype == 'sasl' || this.authtype == 'saslanon') 
    4166       reqstr += " xmpp:version='1.0'"; 
    4167   } 
    4168   reqstr += "/>"; 
    4169   return reqstr; 
    4170 }; 
    4171  
    4172 /** 
    4173  * @private 
    4174  */ 
    4175 JSJaCHttpBindingConnection.prototype._getStreamID = function(slot) { 
    4176  
    4177   this.oDbg.log(this._req[slot].r.responseText,4); 
    4178  
    4179   if (!this._req[slot].r.responseXML || !this._req[slot].r.responseXML.documentElement) { 
    4180     this._handleEvent('onerror',JSJaCError('503','cancel','service-unavailable')); 
    4181     return; 
    4182   } 
    4183   var body = this._req[slot].r.responseXML.documentElement; 
    4184  
    4185   // extract stream id used for non-SASL authentication 
    4186   if (body.getAttribute('authid')) { 
    4187     this.streamid = body.getAttribute('authid'); 
    4188     this.oDbg.log("got streamid: "+this.streamid,2); 
    4189   } 
    4190  
    4191   if (!this._parseStreamFeatures(body) || !this.streamid) { 
    4192     this._timeout = setTimeout(JSJaC.bind(this._sendEmpty, this), 
    4193                                this.getPollInterval()); 
    4194     return; 
    4195   } 
    4196  
    4197   this._timeout = setTimeout(JSJaC.bind(this._process, this), 
    4198                              this.getPollInterval()); 
    4199  
    4200   if (this.register) 
    4201     this._doInBandReg(); 
    4202   else 
    4203     this._doAuth(); 
    4204 }; 
    4205  
    4206 /** 
    4207  * @private 
    4208  */ 
    4209 JSJaCHttpBindingConnection.prototype._getSuspendVars = function() { 
    4210   return ('host,port,secure,_rid,_last_rid,_wait,_min_polling,_inactivity,_hold,_last_requests,_pause').split(','); 
    4211 }; 
    4212  
    4213 /** 
    4214  * @private 
    4215  */ 
    4216 JSJaCHttpBindingConnection.prototype._handleInitialResponse = function(slot) { 
    4217   try { 
    4218     // This will throw an error on Mozilla when the connection was refused 
    4219     this.oDbg.log(this._req[slot].r.getAllResponseHeaders(),4); 
    4220     this.oDbg.log(this._req[slot].r.responseText,4); 
    4221   } catch(ex) { 
    4222     this.oDbg.log("No response",4); 
    4223   } 
    4224  
    4225   if (this._req[slot].r.status != 200 || !this._req[slot].r.responseXML) { 
    4226     this.oDbg.log("initial response broken (status: "+this._req[slot].r.status+")",1); 
    4227     this._handleEvent('onerror',JSJaCError('503','cancel','service-unavailable')); 
    4228     return; 
    4229   } 
    4230   var body = this._req[slot].r.responseXML.documentElement; 
    4231  
    4232   if (!body || body.tagName != 'body' || body.namespaceURI != 'http://jabber.org/protocol/httpbind') { 
    4233     this.oDbg.log("no body element or incorrect body in initial response",1); 
    4234     this._handleEvent("onerror",JSJaCError("500","wait","internal-service-error")); 
    4235     return; 
    4236   } 
    4237  
    4238   // Check for errors from the server 
    4239   if (body.getAttribute("type") == "terminate") { 
    4240     this.oDbg.log("invalid response:\n" + this._req[slot].r.responseText,1); 
    4241     clearTimeout(this._timeout); // remove timer 
    4242     this._connected = false; 
    4243     this.oDbg.log("Disconnected.",1); 
    4244     this._handleEvent('ondisconnect'); 
    4245     this._handleEvent('onerror',JSJaCError('503','cancel','service-unavailable')); 
    4246     return; 
    4247   } 
    4248  
    4249   // get session ID 
    4250   this._sid = body.getAttribute('sid'); 
    4251   this.oDbg.log("got sid: "+this._sid,2); 
    4252  
    4253   // get attributes from response body 
    4254   if (body.getAttribute('polling')) 
    4255     this._min_polling = body.getAttribute('polling'); 
    4256  
    4257   if (body.getAttribute('inactivity')) 
    4258     this._inactivity = body.getAttribute('inactivity'); 
    4259  
    4260   if (body.getAttribute('requests')) 
    4261     this._setHold(body.getAttribute('requests')-1); 
    4262   this.oDbg.log("set hold to " + this._getHold(),2); 
    4263  
    4264   if (body.getAttribute('ver')) 
    4265     this._bosh_version = body.getAttribute('ver'); 
    4266  
    4267   if (body.getAttribute('maxpause')) 
    4268     this._pause = Number.max(body.getAttribute('maxpause'), JSJACHBC_MAXPAUSE); 
    4269  
    4270   // must be done after response attributes have been collected 
    4271   this.setPollInterval(this._timerval); 
    4272  
    4273   /* start sending from queue for not polling connections */ 
    4274   this._connected = true; 
    4275  
    4276   this._inQto = setInterval(JSJaC.bind(this._checkInQ, this), 
    4277                             JSJAC_CHECKINQUEUEINTERVAL); 
    4278   this._interval= setInterval(JSJaC.bind(this._checkQueue, this), 
    4279                               JSJAC_CHECKQUEUEINTERVAL); 
    4280  
    4281   /* wait for initial stream response to extract streamid needed 
    4282    * for digest auth 
    4283    */ 
    4284   this._getStreamID(slot); 
    4285 }; 
    4286  
    4287 /** 
    4288  * @private 
    4289  */ 
    4290 JSJaCHttpBindingConnection.prototype._parseResponse = function(req) { 
    4291   if (!this.connected() || !req) 
    4292     return null; 
    4293  
    4294   var r = req.r; // the XmlHttpRequest 
    4295  
    4296   try { 
    4297     if (r.status == 404 || r.status == 403) { 
    4298       // connection manager killed session 
    4299       this._abort(); 
    4300       return null; 
    4301     } 
    4302  
    4303     if (r.status != 200 || !r.responseXML) { 
    4304       this._errcnt++; 
    4305       var errmsg = "invalid response ("+r.status+"):\n" + r.getAllResponseHeaders()+"\n"+r.responseText; 
    4306       if (!r.responseXML) 
    4307         errmsg += "\nResponse failed to parse!"; 
    4308       this.oDbg.log(errmsg,1); 
    4309       if (this._errcnt > JSJAC_ERR_COUNT) { 
    4310         // abort 
    4311         this._abort(); 
    4312         return null; 
    4313       } 
    4314       this.oDbg.log("repeating ("+this._errcnt+")",1); 
    4315       
    4316       this._setStatus('proto_error_fallback'); 
    4317       
    4318       // schedule next tick 
    4319       setTimeout(JSJaC.bind(this._resume, this), 
    4320                  this.getPollInterval()); 
    4321       
    4322       return null; 
    4323     } 
    4324   } catch (e) { 
    4325     this.oDbg.log("XMLHttpRequest error: status not available", 1); 
    4326         this._errcnt++; 
    4327         if (this._errcnt > JSJAC_ERR_COUNT) { 
    4328           // abort 
    4329           this._abort(); 
    4330         } else { 
    4331           this.oDbg.log("repeating ("+this._errcnt+")",1); 
    4332       
    4333           this._setStatus('proto_error_fallback'); 
    4334       
    4335           // schedule next tick 
    4336           setTimeout(JSJaC.bind(this._resume, this), 
    4337                      this.getPollInterval());  
    4338     } 
    4339     return null; 
    4340   } 
    4341  
    4342   var body = r.responseXML.documentElement; 
    4343   if (!body || body.tagName != 'body' || 
    4344           body.namespaceURI != 'http://jabber.org/protocol/httpbind') { 
    4345     this.oDbg.log("invalid response:\n" + r.responseText,1); 
    4346  
    4347     clearTimeout(this._timeout); // remove timer 
    4348     clearInterval(this._interval); 
    4349     clearInterval(this._inQto); 
    4350  
    4351     this._connected = false; 
    4352     this.oDbg.log("Disconnected.",1); 
    4353     this._handleEvent('ondisconnect'); 
    4354  
    4355     this._setStatus('internal_server_error'); 
    4356     this._handleEvent('onerror', 
    4357                                           JSJaCError('500','wait','internal-server-error')); 
    4358  
    4359     return null; 
    4360   } 
    4361  
    4362   if (typeof(req.rid) != 'undefined' && this._last_requests[req.rid]) { 
    4363     if (this._last_requests[req.rid].handled) { 
    4364       this.oDbg.log("already handled "+req.rid,2); 
    4365       return null; 
    4366     } else 
    4367       this._last_requests[req.rid].handled = true; 
    4368   } 
    4369  
    4370  
    4371   // Check for errors from the server 
    4372   if (body.getAttribute("type") == "terminate") { 
    4373     this.oDbg.log("session terminated:\n" + r.responseText,1); 
    4374  
    4375     clearTimeout(this._timeout); // remove timer 
    4376     clearInterval(this._interval); 
    4377     clearInterval(this._inQto); 
    4378  
    4379     var condition = body.getAttribute('condition'); 
    4380     if (condition == "remote-stream-error") 
    4381       if (body.getElementsByTagName("conflict").length > 0) 
    4382         this._setStatus("session-terminate-conflict"); 
    4383     if (condition == null) 
    4384       condition = 'session-terminate'; 
    4385     this._handleEvent('onerror',JSJaCError('503','cancel',condition)); 
    4386     this._connected = false; 
    4387     this.oDbg.log("Disconnected.",1); 
    4388     try { 
    4389       JSJaCCookie.read(this._cookie_prefix+'JSJaC_State').erase(); 
    4390     } catch (e) {} 
    4391     this.oDbg.log("Aborting remaining connections",4); 
    4392     for (var i=0; i<this._hold+1; i++) 
    4393       if (typeof(this._req[i]) != 'undefined' || typeof(this._req[i].r) != 'undefined' ) 
    4394         this._req[i].r.abort(); 
    4395     this._handleEvent('ondisconnect'); 
    4396     return null; 
    4397   } 
    4398  
    4399   // no error 
    4400   this._errcnt = 0; 
    4401   return r.responseXML.documentElement; 
    4402 }; 
    4403  
    4404 /** 
    4405  * @private 
    4406  */ 
    4407 JSJaCHttpBindingConnection.prototype._reInitStream = function(to,cb,arg) { 
    4408   /* [TODO] we can't handle 'to' here as this is not (yet) supported 
    4409    * by the protocol 
    4410    */ 
    4411  
    4412   // tell http binding to reinit stream with/before next request 
    4413   this._reinit = true; 
    4414   cb.call(this,arg); // proceed with next callback 
    4415  
    4416   /* [TODO] make sure that we're checking for new stream features when 
    4417    * 'cb' finishes 
    4418    */ 
    4419 }; 
    4420  
    4421 /** 
    4422  * @private 
    4423  */ 
    4424 JSJaCHttpBindingConnection.prototype._resume = function() { 
    4425   /* make sure to repeat last request as we can be sure that 
    4426    * it had failed (only if we're not using the 'pause' attribute 
    4427    */ 
    4428   if (this._pause == 0 && this._rid >= this._last_rid) 
    4429     this._rid = this._last_rid-1; 
    4430  
    4431   this._process(); 
    4432 }; 
    4433  
    4434 /** 
    4435  * @private 
    4436  */ 
    4437 JSJaCHttpBindingConnection.prototype._setHold = function(hold)  { 
    4438   if (!hold || isNaN(hold) || hold < 0) 
    4439     hold = 0; 
    4440   else if (hold > JSJACHBC_MAX_HOLD) 
    4441     hold = JSJACHBC_MAX_HOLD; 
    4442   this._hold = hold; 
    4443   return this._hold; 
    4444 }; 
    4445  
    4446 /** 
    4447  * @private 
    4448  */ 
    4449 JSJaCHttpBindingConnection.prototype._setupRequest = function(async) { 
    4450   var req = new Object(); 
    4451   var r = XmlHttp.create(); 
    4452   try { 
    4453     r.open("POST",this._httpbase,async); 
    4454     r.setRequestHeader('Content-Type','text/xml; charset=utf-8'); 
    4455   } catch(e) { this.oDbg.log(e,1); } 
    4456   req.r = r; 
    4457   this._rid++; 
    4458   req.rid = this._rid; 
    4459   return req; 
    4460 }; 
    4461  
    4462 /** 
    4463  * @private 
    4464  */ 
    4465 JSJaCHttpBindingConnection.prototype._suspend = function() { 
    4466   if (this._pause == 0) 
    4467     return; // got nothing to do 
    4468  
    4469   var slot = this._getFreeSlot(); 
    4470   // Intentionally synchronous 
    4471   this._req[slot] = this._setupRequest(false); 
    4472  
    4473   var reqstr = "<body pause='"+this._pause+"' xmlns='http://jabber.org/protocol/httpbind' sid='"+this._sid+"' rid='"+this._rid+"'"; 
    4474   if (JSJAC_HAVEKEYS) { 
    4475     reqstr += " key='"+this._keys.getKey()+"'"; 
    4476     if (this._keys.lastKey()) { 
    4477       this._keys = new JSJaCKeys(hex_sha1,this.oDbg); 
    4478       reqstr += " newkey='"+this._keys.getKey()+"'"; 
    4479     } 
    4480  
    4481   } 
    4482   reqstr += ">"; 
    4483  
    4484   while (this._pQueue.length) { 
    4485     var curNode = this._pQueue[0]; 
    4486     reqstr += curNode; 
    4487     this._pQueue = this._pQueue.slice(1,this._pQueue.length); 
    4488   } 
    4489  
    4490   //reqstr += "<presence type='unavailable' xmlns='jabber:client'/>"; 
    4491   reqstr += "</body>"; 
    4492  
    4493   this.oDbg.log("Disconnecting: " + reqstr,4); 
    4494   this._req[slot].r.send(reqstr); 
    4495 }; 
    4496 /** 
    4497  * @fileoverview All stuff related to HTTP Polling 
    4498  * @author Stefan Strigler steve@zeank.in-berlin.de 
    4499  * @version $Revision: 511 $ 
    4500  */ 
    4501  
    4502 /** 
    4503  * Instantiates an HTTP Polling session 
    4504  * @class Implementation of {@link 
    4505  * http://www.xmpp.org/extensions/xep-0025.html HTTP Polling} 
    4506  * @extends JSJaCConnection 
    4507  * @constructor 
    4508  */ 
    4509 function JSJaCHttpPollingConnection(oArg) { 
    4510   /** 
    4511    * @ignore 
    4512    */ 
    4513   this.base = JSJaCConnection; 
    4514   this.base(oArg); 
    4515  
    4516   // give hint to JSJaCPacket that we're using HTTP Polling ... 
    4517   JSJACPACKET_USE_XMLNS = false; 
    4518 } 
    4519 JSJaCHttpPollingConnection.prototype = new JSJaCConnection(); 
    4520  
    4521 /** 
    4522  * Tells whether this implementation of JSJaCConnection is polling 
    4523  * Useful if it needs to be decided 
    4524  * whether it makes sense to allow for adjusting or adjust the 
    4525  * polling interval {@link JSJaCConnection#setPollInterval} 
    4526  * @return <code>true</code> if this is a polling connection, 
    4527  * <code>false</code> otherwise. 
    4528  * @type boolean 
    4529  */ 
    4530 JSJaCHttpPollingConnection.prototype.isPolling = function() { return true; }; 
    4531  
    4532 /** 
    4533  * @private 
    4534  */ 
    4535 JSJaCHttpPollingConnection.prototype._getFreeSlot = function() { 
    4536   if (typeof(this._req[0]) == 'undefined' || 
    4537       typeof(this._req[0].r) == 'undefined' || 
    4538       this._req[0].r.readyState == 4) 
    4539     return 0; 
    4540   else 
    4541     return -1; 
    4542 }; 
    4543  
    4544 /** 
    4545  * @private 
    4546  */ 
    4547 JSJaCHttpPollingConnection.prototype._getInitialRequestString = function() { 
    4548   var reqstr = "0"; 
    4549   if (JSJAC_HAVEKEYS) { 
    4550     this._keys = new JSJaCKeys(b64_sha1,this.oDbg); // generate first set of keys 
    4551     key = this._keys.getKey(); 
    4552     reqstr += ";"+key; 
    4553   } 
    4554   var streamto = this.domain; 
    4555   if (this.authhost) 
    4556     streamto = this.authhost; 
    4557  
    4558   reqstr += ",<stream:stream to='"+streamto+"' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'"; 
    4559   if (this.authtype == 'sasl' || this.authtype == 'saslanon') 
    4560     reqstr += " version='1.0'"; 
    4561   reqstr += ">"; 
    4562   return reqstr; 
    4563 }; 
    4564  
    4565 /** 
    4566  * @private 
    4567  */ 
    4568 JSJaCHttpPollingConnection.prototype._getRequestString = function(raw, last) { 
    4569   var reqstr = this._sid; 
    4570   if (JSJAC_HAVEKEYS) { 
    4571     reqstr += ";"+this._keys.getKey(); 
    4572     if (this._keys.lastKey()) { 
    4573       this._keys = new JSJaCKeys(b64_sha1,this.oDbg); 
    4574       reqstr += ';'+this._keys.getKey(); 
    4575     } 
    4576   } 
    4577   reqstr += ','; 
    4578   if (raw) 
    4579     reqstr += raw; 
    4580   while (this._pQueue.length) { 
    4581     reqstr += this._pQueue[0]; 
    4582     this._pQueue = this._pQueue.slice(1,this._pQueue.length); 
    4583   } 
    4584   if (last) 
    4585     reqstr += '</stream:stream>'; 
    4586   return reqstr; 
    4587 }; 
    4588  
    4589 /** 
    4590  * @private 
    4591  */ 
    4592 JSJaCHttpPollingConnection.prototype._getStreamID = function() { 
    4593   if (this._req[0].r.responseText == '') { 
    4594     this.oDbg.log("waiting for stream id",2); 
    4595     this._timeout = setTimeout(JSJaC.bind(this._sendEmpty, this),1000); 
    4596     return; 
    4597   } 
    4598  
    4599   this.oDbg.log(this._req[0].r.responseText,4); 
    4600  
    4601   // extract stream id used for non-SASL authentication 
    4602   if (this._req[0].r.responseText.match(/id=[\'\"]([^\'\"]+)[\'\"]/)) 
    4603     this.streamid = RegExp.$1; 
    4604   this.oDbg.log("got streamid: "+this.streamid,2); 
    4605  
    4606   var doc; 
    4607  
    4608   try { 
    4609     var response = this._req[0].r.responseText; 
    4610     if (!response.match(/<\/stream:stream>\s*$/)) 
    4611       response += '</stream:stream>'; 
    4612  
    4613     doc = XmlDocument.create("doc"); 
    4614     doc.loadXML(response); 
    4615     if (!this._parseStreamFeatures(doc)) { 
    4616       this.authtype = 'nonsasl'; 
    4617       return; 
    4618     } 
    4619   } catch(e) { 
    4620     this.oDbg.log("loadXML: "+e.toString(),1); 
    4621   } 
    4622  
    4623   this._connected = true; 
    4624  
    4625   if (this.register) 
    4626     this._doInBandReg(); 
    4627   else 
    4628     this._doAuth(); 
    4629  
    4630   this._process(this._timerval); // start polling 
    4631 }; 
    4632  
    4633 /** 
    4634  * @private 
    4635  */ 
    4636 JSJaCHttpPollingConnection.prototype._getSuspendVars = function() { 
    4637   return new Array(); 
    4638 }; 
    4639  
    4640 /** 
    4641  * @private 
    4642  */ 
    4643 JSJaCHttpPollingConnection.prototype._handleInitialResponse = function() { 
    4644   // extract session ID 
    4645   this.oDbg.log(this._req[0].r.getAllResponseHeaders(),4); 
    4646   var aPList = this._req[0].r.getResponseHeader('Set-Cookie'); 
    4647   aPList = aPList.split(";"); 
    4648   for (var i=0;i<aPList.length;i++) { 
    4649     aArg = aPList[i].split("="); 
    4650     if (aArg[0] == 'ID') 
    4651       this._sid = aArg[1]; 
    4652   } 
    4653   this.oDbg.log("got sid: "+this._sid,2); 
    4654  
    4655   /* start sending from queue for not polling connections */ 
    4656   this._connected = true; 
    4657  
    4658   this._interval= setInterval(JSJaC.bind(this._checkQueue, this), 
    4659                               JSJAC_CHECKQUEUEINTERVAL); 
    4660   this._inQto = setInterval(JSJaC.bind(this._checkInQ, this), 
    4661                             JSJAC_CHECKINQUEUEINTERVAL); 
    4662  
    4663   /* wait for initial stream response to extract streamid needed 
    4664    * for digest auth 
    4665    */ 
    4666   this._getStreamID(); 
    4667 }; 
    4668  
    4669 /** 
    4670  * @private 
    4671  */ 
    4672 JSJaCHttpPollingConnection.prototype._parseResponse = function(r) { 
    4673   var req = r.r; 
    4674   if (!this.connected()) 
    4675     return null; 
    4676  
    4677   /* handle error */ 
    4678   // proxy error (!) 
    4679   if (req.status != 200) { 
    4680     this.oDbg.log("invalid response ("+req.status+"):" + req.responseText+"\n"+req.getAllResponseHeaders(),1); 
    4681  
    4682     this._setStatus('internal_server_error'); 
    4683  
    4684     clearTimeout(this._timeout); // remove timer 
    4685     clearInterval(this._interval); 
    4686     clearInterval(this._inQto); 
    4687     this._connected = false; 
    4688     this.oDbg.log("Disconnected.",1); 
    4689     this._handleEvent('ondisconnect'); 
    4690     this._handleEvent('onerror',JSJaCError('503','cancel','service-unavailable')); 
    4691     return null; 
    4692   } 
    4693  
    4694   this.oDbg.log(req.getAllResponseHeaders(),4); 
    4695   var sid, aPList = req.getResponseHeader('Set-Cookie'); 
    4696  
    4697   if (aPList == null) 
    4698     sid = "-1:0"; // Generate internal server error 
    4699   else { 
    4700     aPList = aPList.split(";"); 
    4701     var sid; 
    4702     for (var i=0;i<aPList.length;i++) { 
    4703       var aArg = aPList[i].split("="); 
    4704       if (aArg[0] == 'ID') 
    4705         sid = aArg[1]; 
    4706     } 
    4707   } 
    4708  
    4709   // http polling component error 
    4710   if (typeof(sid) != 'undefined' && sid.indexOf(':0') != -1) { 
    4711     switch (sid.substring(0,sid.indexOf(':0'))) { 
    4712     case '0': 
    4713       this.oDbg.log("invalid response:" + req.responseText,1); 
    4714       break; 
    4715     case '-1': 
    4716       this.oDbg.log("Internal Server Error",1); 
    4717       break; 
    4718     case '-2': 
    4719       this.oDbg.log("Bad Request",1); 
    4720       break; 
    4721     case '-3': 
    4722       this.oDbg.log("Key Sequence Error",1); 
    4723       break; 
    4724     } 
    4725  
    4726     this._setStatus('internal_server_error'); 
    4727  
    4728     clearTimeout(this._timeout); // remove timer 
    4729     clearInterval(this._interval); 
    4730     clearInterval(this._inQto); 
    4731     this._handleEvent('onerror',JSJaCError('500','wait','internal-server-error')); 
    4732     this._connected = false; 
    4733     this.oDbg.log("Disconnected.",1); 
    4734     this._handleEvent('ondisconnect'); 
    4735     return null; 
    4736   } 
    4737  
    4738   if (!req.responseText || req.responseText == '') 
    4739     return null; 
    4740  
    4741   try { 
    4742     var response = req.responseText.replace(/\<\?xml.+\?\>/,""); 
    4743     if (response.match(/<stream:stream/)) 
    4744         response += "</stream:stream>"; 
    4745     var doc = JSJaCHttpPollingConnection._parseTree("<body>"+response+"</body>"); 
    4746  
    4747     if (!doc || doc.tagName == 'parsererror') { 
    4748       this.oDbg.log("parsererror",1); 
    4749  
    4750       doc = JSJaCHttpPollingConnection._parseTree("<stream:stream xmlns:stream='http://etherx.jabber.org/streams'>"+req.responseText); 
    4751       if (doc && doc.tagName != 'parsererror') { 
    4752         this.oDbg.log("stream closed",1); 
    4753  
    4754         if (doc.getElementsByTagName('conflict').length > 0) 
    4755           this._setStatus("session-terminate-conflict"); 
    4756                          
    4757         clearTimeout(this._timeout); // remove timer 
    4758         clearInterval(this._interval); 
    4759         clearInterval(this._inQto); 
    4760         this._handleEvent('onerror',JSJaCError('503','cancel','session-terminate')); 
    4761         this._connected = false; 
    4762         this.oDbg.log("Disconnected.",1); 
    4763         this._handleEvent('ondisconnect'); 
    4764       } else 
    4765         this.oDbg.log("parsererror:"+doc,1); 
    4766                  
    4767       return doc; 
    4768     } 
    4769  
    4770     return doc; 
    4771   } catch (e) { 
    4772     this.oDbg.log("parse error:"+e.message,1); 
    4773   } 
    4774   return null;; 
    4775 }; 
    4776  
    4777 /** 
    4778  * @private 
    4779  */ 
    4780 JSJaCHttpPollingConnection.prototype._reInitStream = function(to,cb,arg) { 
    4781   this._sendRaw("<stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client' to='"+to+"' version='1.0'>",cb,arg); 
    4782 }; 
    4783  
    4784 /** 
    4785  * @private 
    4786  */ 
    4787 JSJaCHttpPollingConnection.prototype._resume = function() { 
    4788   this._process(this._timerval); 
    4789 }; 
    4790  
    4791 /** 
    4792  * @private 
    4793  */ 
    4794 JSJaCHttpPollingConnection.prototype._setupRequest = function(async) { 
    4795   var r = XmlHttp.create(); 
    4796   try { 
    4797     r.open("POST",this._httpbase,async); 
    4798     if (r.overrideMimeType) 
    4799       r.overrideMimeType('text/plain; charset=utf-8'); 
    4800     r.setRequestHeader('Content-Type','application/x-www-form-urlencoded'); 
    4801   } catch(e) { this.oDbg.log(e,1); } 
    4802  
    4803   var req = new Object(); 
    4804   req.r = r; 
    4805   return req; 
    4806 }; 
    4807  
    4808 /** 
    4809  * @private 
    4810  */ 
    4811 JSJaCHttpPollingConnection.prototype._suspend = function() {}; 
    4812  
    4813 /*** [static] ***/ 
    4814  
    4815 /** 
    4816  * @private 
    4817  */ 
    4818 JSJaCHttpPollingConnection._parseTree = function(s) { 
    4819   try { 
    4820     var r = XmlDocument.create("body","foo"); 
    4821     if (typeof(r.loadXML) != 'undefined') { 
    4822       r.loadXML(s); 
    4823       return r.documentElement; 
    4824     } else if (window.DOMParser) 
    4825       return (new DOMParser()).parseFromString(s, "text/xml").documentElement; 
    4826   } catch (e) { } 
    4827   return null; 
    4828 }; 
    4829 /** 
    4830  * @fileoverview Magic dependency loading. Taken from script.aculo.us 
    4831  * and modified to break it. 
    4832  * @author Stefan Strigler steve@zeank.in-berlin.de  
    4833  * @version $Revision: 491 $ 
    4834  */ 
    4835  
    4836 var JSJaC = { 
    4837   Version: '$Rev: 491 $', 
    4838   require: function(libraryName) { 
    4839     // inserting via DOM fails in Safari 2.0, so brute force approach 
    4840     document.write('<script type="text/javascript" src="'+libraryName+'"></script>'); 
    4841   }, 
    4842   load: function() { 
    4843     var includes = 
    4844     ['xmlextras', 
    4845      'jsextras', 
    4846      'crypt', 
    4847      'JSJaCConfig', 
    4848      'JSJaCConstants', 
    4849      'JSJaCCookie', 
    4850      'JSJaCJSON', 
    4851      'JSJaCJID', 
    4852      'JSJaCBuilder', 
    4853      'JSJaCPacket', 
    4854      'JSJaCError', 
    4855      'JSJaCKeys', 
    4856      'JSJaCConnection', 
    4857      'JSJaCHttpPollingConnection', 
    4858      'JSJaCHttpBindingConnection', 
    4859      'JSJaCConsoleLogger' 
    4860      ]; 
    4861     var scripts = document.getElementsByTagName("script"); 
    4862     var path = './'; 
    4863     for (var i=0; i<scripts.length; i++) { 
    4864       if (scripts.item(i).src && scripts.item(i).src.match(/JSJaC\.js$/)) { 
    4865         path = scripts.item(i).src.replace(/JSJaC.js$/,''); 
    4866         break; 
    4867       } 
    4868     } 
    4869     for (var i=0; i<includes.length; i++) 
    4870       this.require(path+includes[i]+'.js'); 
    4871   }, 
    4872   bind: function(fn, obj, optArg) { 
    4873     return function(arg) { 
    4874       return fn.apply(obj, [arg, optArg]); 
    4875     }; 
    4876   } 
    4877 }; 
    4878  
    4879 if (typeof JSJaCConnection == 'undefined') 
    4880   JSJaC.load(); 
     214{if(window==this) 
     215return new JSJaCCookie(name,value,secs,domain,path);this.name=name;this.value=value;this.secs=secs;this.domain=domain;this.path=path;this.write=function(){if(this.secs){var date=new Date();date.setTime(date.getTime()+(this.secs*1000));var expires="; expires="+date.toGMTString();}else 
     216var expires="";var domain=this.domain?"; domain="+this.domain:"";var path=this.path?"; path="+this.path:"; path=/";document.cookie=this.getName()+"="+JSJaCCookie._escape(this.getValue())+ 
     217expires+ 
     218domain+ 
     219path;};this.erase=function(){var c=new JSJaCCookie(this.getName(),"",-1);c.write();};this.getName=function(){return this.name;};this.setName=function(name){this.name=name;return this;};this.getValue=function(){return this.value;};this.setValue=function(value){this.value=value;return this;};this.setDomain=function(domain){this.domain=domain;return this;};this.setPath=function(path){this.path=path;return this;};} 
     220JSJaCCookie.read=function(name){var nameEQ=name+"=";var ca=document.cookie.split(';');for(var i=0;i<ca.length;i++){var c=ca[i];while(c.charAt(0)==' ')c=c.substring(1,c.length);if(c.indexOf(nameEQ)==0) 
     221return new JSJaCCookie(name,JSJaCCookie._unescape(c.substring(nameEQ.length,c.length)));} 
     222throw new JSJaCCookieException("Cookie not found");};JSJaCCookie.get=function(name){return JSJaCCookie.read(name).getValue();};JSJaCCookie.remove=function(name){JSJaCCookie.read(name).erase();};JSJaCCookie._escape=function(str){return str.replace(/;/g,"%3AB");} 
     223JSJaCCookie._unescape=function(str){return str.replace(/%3AB/g,";");} 
     224function JSJaCCookieException(msg){this.message=msg;this.name="CookieException";} 
     225function JSJaCError(code,type,condition){var xmldoc=XmlDocument.create("error","jsjac");xmldoc.documentElement.setAttribute('code',code);xmldoc.documentElement.setAttribute('type',type);if(condition) 
     226xmldoc.documentElement.appendChild(xmldoc.createElement(condition)).setAttribute('xmlns','urn:ietf:params:xml:ns:xmpp-stanzas');return xmldoc.documentElement;} 
     227var JSJACJID_FORBIDDEN=['"',' ','&','\'','/',':','<','>','@'];function JSJaCJID(jid){this._node='';this._domain='';this._resource='';if(typeof(jid)=='string'){if(jid.indexOf('@')!=-1){this.setNode(jid.substring(0,jid.indexOf('@')));jid=jid.substring(jid.indexOf('@')+1);} 
     228if(jid.indexOf('/')!=-1){this.setResource(jid.substring(jid.indexOf('/')+1));jid=jid.substring(0,jid.indexOf('/'));} 
     229this.setDomain(jid);}else{this.setNode(jid.node);this.setDomain(jid.domain);this.setResource(jid.resource);}} 
     230JSJaCJID.prototype.getNode=function(){return this._node;};JSJaCJID.prototype.getDomain=function(){return this._domain;};JSJaCJID.prototype.getResource=function(){return this._resource;};JSJaCJID.prototype.setNode=function(node){JSJaCJID._checkNodeName(node);this._node=node||'';return this;};JSJaCJID.prototype.setDomain=function(domain){if(!domain||domain=='') 
     231throw new JSJaCJIDInvalidException("domain name missing");JSJaCJID._checkNodeName(domain);this._domain=domain;return this;};JSJaCJID.prototype.setResource=function(resource){this._resource=resource||'';return this;};JSJaCJID.prototype.toString=function(){var jid='';if(this.getNode()&&this.getNode()!='') 
     232jid=this.getNode()+'@';jid+=this.getDomain();if(this.getResource()&&this.getResource()!="") 
     233jid+='/'+this.getResource();return jid;};JSJaCJID.prototype.removeResource=function(){return this.setResource();};JSJaCJID.prototype.clone=function(){return new JSJaCJID(this.toString());};JSJaCJID.prototype.isEntity=function(jid){if(typeof jid=='string') 
     234jid=(new JSJaCJID(jid));jid.removeResource();return(this.clone().removeResource().toString()===jid.toString());};JSJaCJID._checkNodeName=function(nodeprep){if(!nodeprep||nodeprep=='') 
     235return;for(var i=0;i<JSJACJID_FORBIDDEN.length;i++){if(nodeprep.indexOf(JSJACJID_FORBIDDEN[i])!=-1){throw new JSJaCJIDInvalidException("forbidden char in nodename: "+JSJACJID_FORBIDDEN[i]);}}};function JSJaCJIDInvalidException(message){this.message=message;this.name="JSJaCJIDInvalidException";} 
     236function JSJaCKeys(func,oDbg){var seed=Math.random();this._k=new Array();this._k[0]=seed.toString();if(oDbg) 
     237this.oDbg=oDbg;else{this.oDbg={};this.oDbg.log=function(){};} 
     238if(func){for(var i=1;i<JSJAC_NKEYS;i++){this._k[i]=func(this._k[i-1]);oDbg.log(i+": "+this._k[i],4);}} 
     239this._indexAt=JSJAC_NKEYS-1;this.getKey=function(){return this._k[this._indexAt--];};this.lastKey=function(){return(this._indexAt==0);};this.size=function(){return this._k.length;};this._getSuspendVars=function(){return('_k,_indexAt').split(',');}} 
     240var JSJACPACKET_USE_XMLNS=true;var JSJACPACKET_CHAT_STATES=new Array("active","inactive","gone","composing","paused");function JSJaCPacket(name){this.name=name;if(typeof(JSJACPACKET_USE_XMLNS)!='undefined'&&JSJACPACKET_USE_XMLNS) 
     241this.doc=XmlDocument.create(name,'jabber:client');else 
     242this.doc=XmlDocument.create(name,'');} 
     243JSJaCPacket.prototype.pType=function(){return this.name;};JSJaCPacket.prototype.getDoc=function(){return this.doc;};JSJaCPacket.prototype.getNode=function(){if(this.getDoc()&&this.getDoc().documentElement) 
     244return this.getDoc().documentElement;else 
     245return null;};JSJaCPacket.prototype.setTo=function(to){if(!to||to=='') 
     246this.getNode().removeAttribute('to');else if(typeof(to)=='string') 
     247this.getNode().setAttribute('to',to);else 
     248this.getNode().setAttribute('to',to.toString());return this;};JSJaCPacket.prototype.setFrom=function(from){if(!from||from=='') 
     249this.getNode().removeAttribute('from');else if(typeof(from)=='string') 
     250this.getNode().setAttribute('from',from);else 
     251this.getNode().setAttribute('from',from.toString());return this;};JSJaCPacket.prototype.setID=function(id){if(!id||id=='') 
     252this.getNode().removeAttribute('id');else 
     253this.getNode().setAttribute('id',id);return this;};JSJaCPacket.prototype.setType=function(type){if(!type||type=='') 
     254this.getNode().removeAttribute('type');else 
     255this.getNode().setAttribute('type',type);return this;};JSJaCPacket.prototype.setXMLLang=function(xmllang){if(!xmllang||xmllang=='') 
     256this.getNode().removeAttribute('xml:lang');else 
     257this.getNode().setAttribute('xml:lang',xmllang);return this;};JSJaCPacket.prototype.getTo=function(){return this.getNode().getAttribute('to');};JSJaCPacket.prototype.getFrom=function(){return this.getNode().getAttribute('from');};JSJaCPacket.prototype.getToJID=function(){return new JSJaCJID(this.getTo());};JSJaCPacket.prototype.getFromJID=function(){return new JSJaCJID(this.getFrom());};JSJaCPacket.prototype.getID=function(){return this.getNode().getAttribute('id');};JSJaCPacket.prototype.getType=function(){return this.getNode().getAttribute('type');};JSJaCPacket.prototype.getXMLLang=function(){return this.getNode().getAttribute('xml:lang');};JSJaCPacket.prototype.getXMLNS=function(){return this.getNode().namespaceURI||this.getNode().getAttribute('xmlns');};JSJaCPacket.prototype.getChild=function(name,ns){if(!this.getNode()){return null;} 
     258name=name||'*';ns=ns||'*';if(this.getNode().getElementsByTagNameNS){return this.getNode().getElementsByTagNameNS(ns,name).item(0);} 
     259var nodes=this.getNode().getElementsByTagName(name);if(ns!='*'){for(var i=0;i<nodes.length;i++){if(nodes.item(i).namespaceURI==ns||nodes.item(i).getAttribute('xmlns')==ns){return nodes.item(i);}}}else{return nodes.item(0);} 
     260return null;};JSJaCPacket.prototype.getChildVal=function(name,ns){var node=this.getChild(name,ns);var ret='';if(node&&node.hasChildNodes()){for(var i=0;i<node.childNodes.length;i++) 
     261if(node.childNodes.item(i).nodeValue) 
     262ret+=node.childNodes.item(i).nodeValue;} 
     263return ret;};JSJaCPacket.prototype.clone=function(){return JSJaCPacket.wrapNode(this.getNode());};JSJaCPacket.prototype.isError=function(){return(this.getType()=='error');};JSJaCPacket.prototype.errorReply=function(stanza_error){var rPacket=this.clone();rPacket.setTo(this.getFrom());rPacket.setFrom();rPacket.setType('error');rPacket.appendNode('error',{code:stanza_error.code,type:stanza_error.type},[[stanza_error.cond]]);return rPacket;};JSJaCPacket.prototype.xml=typeof XMLSerializer!='undefined'?function(){var r=(new XMLSerializer()).serializeToString(this.getNode());if(typeof(r)=='undefined') 
     264r=(new XMLSerializer()).serializeToString(this.doc);return r}:function(){return this.getDoc().xml};JSJaCPacket.prototype._getAttribute=function(attr){return this.getNode().getAttribute(attr);};if(document.ELEMENT_NODE==null){document.ELEMENT_NODE=1;document.ATTRIBUTE_NODE=2;document.TEXT_NODE=3;document.CDATA_SECTION_NODE=4;document.ENTITY_REFERENCE_NODE=5;document.ENTITY_NODE=6;document.PROCESSING_INSTRUCTION_NODE=7;document.COMMENT_NODE=8;document.DOCUMENT_NODE=9;document.DOCUMENT_TYPE_NODE=10;document.DOCUMENT_FRAGMENT_NODE=11;document.NOTATION_NODE=12;} 
     265JSJaCPacket.prototype._importNode=function(node,allChildren){switch(node.nodeType){case document.ELEMENT_NODE:if(this.getDoc().createElementNS){var newNode=this.getDoc().createElementNS(node.namespaceURI,node.nodeName);}else{var newNode=this.getDoc().createElement(node.nodeName);} 
     266if(node.attributes&&node.attributes.length>0) 
     267for(var i=0,il=node.attributes.length;i<il;i++){var attr=node.attributes.item(i);if(attr.nodeName=='xmlns'&&newNode.getAttribute('xmlns')!=null)continue;if(newNode.setAttributeNS&&attr.namespaceURI){newNode.setAttributeNS(attr.namespaceURI,attr.nodeName,attr.nodeValue);}else{newNode.setAttribute(attr.nodeName,attr.nodeValue);}} 
     268if(allChildren&&node.childNodes&&node.childNodes.length>0){for(var i=0,il=node.childNodes.length;i<il;i++){newNode.appendChild(this._importNode(node.childNodes.item(i),allChildren));}} 
     269return newNode;break;case document.TEXT_NODE:case document.CDATA_SECTION_NODE:case document.COMMENT_NODE:return this.getDoc().createTextNode(node.nodeValue);break;}};JSJaCPacket.prototype._setChildNode=function(nodeName,nodeValue){var aNode=this.getChild(nodeName);var tNode=this.getDoc().createTextNode(nodeValue);if(aNode) 
     270try{aNode.replaceChild(tNode,aNode.firstChild);}catch(e){} 
     271else{try{aNode=this.getDoc().createElementNS(this.getNode().namespaceURI,nodeName);}catch(ex){aNode=this.getDoc().createElement(nodeName)} 
     272this.getNode().appendChild(aNode);aNode.appendChild(tNode);} 
     273return aNode;};JSJaCPacket.prototype.buildNode=function(elementName){return JSJaCBuilder.buildNode(this.getDoc(),elementName,arguments[1],arguments[2]);};JSJaCPacket.prototype.appendNode=function(element){if(typeof element=='object'){return this.getNode().appendChild(element)}else{return this.getNode().appendChild(this.buildNode(element,arguments[1],arguments[2],null,this.getNode().namespaceURI));}};function JSJaCPresence(){this.base=JSJaCPacket;this.base('presence');} 
     274JSJaCPresence.prototype=new JSJaCPacket;JSJaCPresence.prototype.setStatus=function(status){this._setChildNode("status",status);return this;};JSJaCPresence.prototype.setShow=function(show){if(show=='chat'||show=='away'||show=='xa'||show=='dnd') 
     275this._setChildNode("show",show);return this;};JSJaCPresence.prototype.setPriority=function(prio){this._setChildNode("priority",prio);return this;};JSJaCPresence.prototype.setPresence=function(show,status,prio){if(show) 
     276this.setShow(show);if(status) 
     277this.setStatus(status);if(prio) 
     278this.setPriority(prio);return this;};JSJaCPresence.prototype.getStatus=function(){return this.getChildVal('status');};JSJaCPresence.prototype.getShow=function(){return this.getChildVal('show');};JSJaCPresence.prototype.getPriority=function(){return this.getChildVal('priority');};function JSJaCIQ(){this.base=JSJaCPacket;this.base('iq');} 
     279JSJaCIQ.prototype=new JSJaCPacket;JSJaCIQ.prototype.setIQ=function(to,type,id){if(to) 
     280this.setTo(to);if(type) 
     281this.setType(type);if(id) 
     282this.setID(id);return this;};JSJaCIQ.prototype.setQuery=function(xmlns){var query;try{query=this.getDoc().createElementNS(xmlns,'query');}catch(e){query=this.getDoc().createElement('query');query.setAttribute('xmlns',xmlns);} 
     283this.getNode().appendChild(query);return query;};JSJaCIQ.prototype.getQuery=function(){return this.getNode().getElementsByTagName('query').item(0);};JSJaCIQ.prototype.getQueryXMLNS=function(){if(this.getQuery()){return this.getQuery().namespaceURI||this.getQuery().getAttribute('xmlns');}else{return null;}};JSJaCIQ.prototype.reply=function(payload){var rIQ=this.clone();rIQ.setTo(this.getFrom());rIQ.setFrom();rIQ.setType('result');if(payload){if(typeof payload=='string') 
     284rIQ.getChild().appendChild(rIQ.getDoc().loadXML(payload));else if(payload.constructor==Array){var node=rIQ.getChild();for(var i=0;i<payload.length;i++) 
     285if(typeof payload[i]=='string') 
     286node.appendChild(rIQ.getDoc().loadXML(payload[i]));else if(typeof payload[i]=='object') 
     287node.appendChild(payload[i]);} 
     288else if(typeof payload=='object') 
     289rIQ.getChild().appendChild(payload);} 
     290return rIQ;};function JSJaCMessage(){this.base=JSJaCPacket;this.base('message');} 
     291JSJaCMessage.prototype=new JSJaCPacket;JSJaCMessage.prototype.setBody=function(body){this._setChildNode("body",body);return this;};JSJaCMessage.prototype.setSubject=function(subject){this._setChildNode("subject",subject);return this;};JSJaCMessage.prototype.setThread=function(thread){this._setChildNode("thread",thread);return this;};JSJaCMessage.prototype.getThread=function(){return this.getChildVal('thread');};JSJaCMessage.prototype.getBody=function(){return this.getChildVal('body');};JSJaCMessage.prototype.getSubject=function(){return this.getChildVal('subject')};JSJaCPacket.wrapNode=function(node){var oPacket=null;switch(node.nodeName.toLowerCase()){case'presence':oPacket=new JSJaCPresence();break;case'message':oPacket=new JSJaCMessage();break;case'iq':oPacket=new JSJaCIQ();break;} 
     292if(oPacket){oPacket.getDoc().replaceChild(oPacket._importNode(node,true),oPacket.getNode());} 
     293return oPacket;};JSJaCMessage.prototype.getState=function(){var stateEl=this.getChild('*',NS_CHAT_STATES);if(stateEl) 
     294return stateEl.tagName;else 
     295return null;};JSJaCMessage.prototype.setState=function(state){if(this.getChild('*',NS_CHAT_STATES)) 
     296return null;var validState=false;for(var i=0;i<JSJACPACKET_CHAT_STATES.length;i++){if(JSJACPACKET_CHAT_STATES[i]==state) 
     297validState=true;} 
     298if(!validState) 
     299return null;this.appendNode(state,{xmlns:NS_CHAT_STATES});return this;};function JSJaCConnection(oArg){if(oArg&&oArg.oDbg&&oArg.oDbg.log){this.oDbg=oArg.oDbg;}else{this.oDbg=new Object();this.oDbg.log=function(){};} 
     300if(oArg&&oArg.timerval) 
     301this.setPollInterval(oArg.timerval);else 
     302this.setPollInterval(JSJAC_TIMERVAL);if(oArg&&oArg.httpbase) 
     303this._httpbase=oArg.httpbase;if(oArg&&oArg.allow_plain) 
     304this.allow_plain=oArg.allow_plain;else 
     305this.allow_plain=JSJAC_ALLOW_PLAIN;if(oArg&&oArg.cookie_prefix) 
     306this._cookie_prefix=oArg.cookie_prefix;else 
     307this._cookie_prefix="";this._connected=false;this._events=new Array();this._keys=null;this._ID=0;this._inQ=new Array();this._pQueue=new Array();this._regIDs=new Array();this._req=new Array();this._status='intialized';this._errcnt=0;this._inactivity=JSJAC_INACTIVITY;this._sendRawCallbacks=new Array();} 
     308JSJaCConnection.prototype.connect=function(oArg){this._setStatus('connecting');this.domain=oArg.domain||'localhost';this.username=oArg.username;this.resource=oArg.resource;this.pass=oArg.pass;this.register=oArg.register;this.authhost=oArg.authhost||this.domain;this.authtype=oArg.authtype||'sasl';if(oArg.xmllang&&oArg.xmllang!='') 
     309this._xmllang=oArg.xmllang;this.host=oArg.host||this.domain;this.port=oArg.port||5222;if(oArg.secure) 
     310this.secure='true';else 
     311this.secure='false';if(oArg.wait) 
     312this._wait=oArg.wait;this.jid=this.username+'@'+this.domain;this.fulljid=this.jid+'/'+this.resource;this._rid=Math.round(100000.5+(((900000.49999)-(100000.5))*Math.random()));var slot=this._getFreeSlot();this._req[slot]=this._setupRequest(true);var reqstr=this._getInitialRequestString();this.oDbg.log(reqstr,4);this._req[slot].r.onreadystatechange=JSJaC.bind(function(){if(this._req[slot].r.readyState==4){this.oDbg.log("async recv: "+this._req[slot].r.responseText,4);this._handleInitialResponse(slot);}},this);if(typeof(this._req[slot].r.onerror)!='undefined'){this._req[slot].r.onerror=JSJaC.bind(function(e){this.oDbg.log('XmlHttpRequest error',1);return false;},this);} 
     313this._req[slot].r.send(reqstr);};JSJaCConnection.prototype.connected=function(){return this._connected;};JSJaCConnection.prototype.disconnect=function(){this._setStatus('disconnecting');if(!this.connected()) 
     314return;var slot=this._getFreeSlot();this._req[slot]=this._setupRequest(true);this._req[slot].r.onreadystatechange=JSJaC.bind(function(){try{if(this._req[slot].r.readyState==4){this.oDbg.log("async recv: "+this._req[slot].r.responseText,4);this._handleResponse(this._req[slot]);}}catch(e){this.oDbg.log(e,1);}},this);request=this._getRequestString(false,true);this.oDbg.log("Disconnecting: "+request,4);this._req[slot].r.send(request);};JSJaCConnection.prototype.getPollInterval=function(){return this._timerval;};JSJaCConnection.prototype.registerHandler=function(event){event=event.toLowerCase();var eArg={handler:arguments[arguments.length-1],childName:'*',childNS:'*',type:'*'};if(arguments.length>2) 
     315eArg.childName=arguments[1];if(arguments.length>3) 
     316eArg.childNS=arguments[2];if(arguments.length>4) 
     317eArg.type=arguments[3];if(!this._events[event]) 
     318this._events[event]=new Array(eArg);else 
     319this._events[event]=this._events[event].concat(eArg);this._events[event]=this._events[event].sort(function(a,b){var aRank=0;var bRank=0;with(a){if(type=='*') 
     320aRank++;if(childNS=='*') 
     321aRank++;if(childName=='*') 
     322aRank++;} 
     323with(b){if(type=='*') 
     324bRank++;if(childNS=='*') 
     325bRank++;if(childName=='*') 
     326bRank++;} 
     327if(aRank>bRank) 
     328return 1;if(aRank<bRank) 
     329return-1;return 0;});this.oDbg.log("registered handler for event '"+event+"'",2);};JSJaCConnection.prototype.unregisterHandler=function(event,handler){event=event.toLowerCase();if(!this._events[event]) 
     330return;var arr=this._events[event],res=new Array();for(var i=0;i<arr.length;i++) 
     331if(arr[i].handler!=handler) 
     332res.push(arr[i]);if(arr.length!=res.length){this._events[event]=res;this.oDbg.log("unregistered handler for event '"+event+"'",2);}};JSJaCConnection.prototype.registerIQGet=function(childName,childNS,handler){this.registerHandler('iq',childName,childNS,'get',handler);};JSJaCConnection.prototype.registerIQSet=function(childName,childNS,handler){this.registerHandler('iq',childName,childNS,'set',handler);};JSJaCConnection.prototype.resume=function(){try{var json=JSJaCCookie.read(this._cookie_prefix+'JSJaC_State').getValue();this.oDbg.log('read cookie: '+json,2);JSJaCCookie.read(this._cookie_prefix+'JSJaC_State').erase();return this.resumeFromData(JSJaCJSON.parse(json));}catch(e){} 
     333return false;};JSJaCConnection.prototype.resumeFromData=function(data){try{this._setStatus('resuming');for(var i in data) 
     334if(data.hasOwnProperty(i)) 
     335this[i]=data[i];if(this._keys){this._keys2=new JSJaCKeys();var u=this._keys2._getSuspendVars();for(var i=0;i<u.length;i++) 
     336this._keys2[u[i]]=this._keys[u[i]];this._keys=this._keys2;} 
     337if(this._connected){this._handleEvent('onresume');setTimeout(JSJaC.bind(this._resume,this),this.getPollInterval());this._interval=setInterval(JSJaC.bind(this._checkQueue,this),JSJAC_CHECKQUEUEINTERVAL);this._inQto=setInterval(JSJaC.bind(this._checkInQ,this),JSJAC_CHECKINQUEUEINTERVAL);} 
     338return(this._connected===true);}catch(e){if(e.message) 
     339this.oDbg.log("Resume failed: "+e.message,1);else 
     340this.oDbg.log("Resume failed: "+e,1);return false;}};JSJaCConnection.prototype.send=function(packet,cb,arg){if(!packet||!packet.pType){this.oDbg.log("no packet: "+packet,1);return false;} 
     341if(!this.connected()) 
     342return false;if(cb){if(!packet.getID()) 
     343packet.setID('JSJaCID_'+this._ID++);this._registerPID(packet.getID(),cb,arg);} 
     344try{this._handleEvent(packet.pType()+'_out',packet);this._handleEvent("packet_out",packet);this._pQueue=this._pQueue.concat(packet.xml());}catch(e){this.oDbg.log(e.toString(),1);return false;} 
     345return true;};JSJaCConnection.prototype.sendIQ=function(iq,handlers,arg){if(!iq||iq.pType()!='iq'){return false;} 
     346handlers=handlers||{};var error_handler=handlers.error_handler||JSJaC.bind(function(aIq){this.oDbg.log(aIq.xml(),1);},this);var result_handler=handlers.result_handler||JSJaC.bind(function(aIq){this.oDbg.log(aIq.xml(),2);},this);var iqHandler=function(aIq,arg){switch(aIq.getType()){case'error':error_handler(aIq);break;case'result':result_handler(aIq,arg);break;}};return this.send(iq,iqHandler,arg);};JSJaCConnection.prototype.setPollInterval=function(timerval){if(timerval&&!isNaN(timerval)) 
     347this._timerval=timerval;return this._timerval;};JSJaCConnection.prototype.status=function(){return this._status;};JSJaCConnection.prototype.suspend=function(){var data=this.suspendToData();try{var c=new JSJaCCookie(this._cookie_prefix+'JSJaC_State',JSJaCJSON.toString(data));this.oDbg.log("writing cookie: "+c.getValue()+"\n"+"(length:"+c.getValue().length+")",2);c.write();var c2=JSJaCCookie.get(this._cookie_prefix+'JSJaC_State');if(c.getValue()!=c2){this.oDbg.log("Suspend failed writing cookie.\nread: "+c2,1);c.erase();return false;} 
     348return true;}catch(e){this.oDbg.log("Failed creating cookie '"+this._cookie_prefix+"JSJaC_State': "+e.message,1);} 
     349return false;};JSJaCConnection.prototype.suspendToData=function(){clearTimeout(this._timeout);clearInterval(this._interval);clearInterval(this._inQto);this._suspend();var u=('_connected,_keys,_ID,_inQ,_pQueue,_regIDs,_errcnt,_inactivity,domain,username,resource,jid,fulljid,_sid,_httpbase,_timerval,_is_polling').split(',');u=u.concat(this._getSuspendVars());var s=new Object();for(var i=0;i<u.length;i++){if(!this[u[i]])continue;if(this[u[i]]._getSuspendVars){var uo=this[u[i]]._getSuspendVars();var o=new Object();for(var j=0;j<uo.length;j++) 
     350o[uo[j]]=this[u[i]][uo[j]];}else 
     351var o=this[u[i]];s[u[i]]=o;} 
     352this._connected=false;this._setStatus('suspending');return s;};JSJaCConnection.prototype._abort=function(){clearTimeout(this._timeout);clearInterval(this._inQto);clearInterval(this._interval);this._connected=false;this._setStatus('aborted');this.oDbg.log("Disconnected.",1);this._handleEvent('ondisconnect');this._handleEvent('onerror',JSJaCError('500','cancel','service-unavailable'));};JSJaCConnection.prototype._checkInQ=function(){for(var i=0;i<this._inQ.length&&i<10;i++){var item=this._inQ[0];this._inQ=this._inQ.slice(1,this._inQ.length);var packet=JSJaCPacket.wrapNode(item);if(!packet) 
     353return;this._handleEvent("packet_in",packet);if(packet.pType&&!this._handlePID(packet)){this._handleEvent(packet.pType()+'_in',packet);this._handleEvent(packet.pType(),packet);}}};JSJaCConnection.prototype._checkQueue=function(){if(this._pQueue.length!=0) 
     354this._process();return true;};JSJaCConnection.prototype._doAuth=function(){if(this.has_sasl&&this.authtype=='nonsasl') 
     355this.oDbg.log("Warning: SASL present but not used",1);if(!this._doSASLAuth()&&!this._doLegacyAuth()){this.oDbg.log("Auth failed for authtype "+this.authtype,1);this.disconnect();return false;} 
     356return true;};JSJaCConnection.prototype._doInBandReg=function(){if(this.authtype=='saslanon'||this.authtype=='anonymous') 
     357return;var iq=new JSJaCIQ();iq.setType('set');iq.setID('reg1');iq.appendNode("query",{xmlns:"jabber:iq:register"},[["username",this.username],["password",this.pass]]);this.send(iq,this._doInBandRegDone);};JSJaCConnection.prototype._doInBandRegDone=function(iq){if(iq&&iq.getType()=='error'){this.oDbg.log("registration failed for "+this.username,0);this._handleEvent('onerror',iq.getChild('error'));return;} 
     358this.oDbg.log(this.username+" registered succesfully",0);this._doAuth();};JSJaCConnection.prototype._doLegacyAuth=function(){if(this.authtype!='nonsasl'&&this.authtype!='anonymous') 
     359return false;var iq=new JSJaCIQ();iq.setIQ(this.server,'get','auth1');iq.appendNode('query',{xmlns:'jabber:iq:auth'},[['username',this.username]]);this.send(iq,this._doLegacyAuth2);return true;};JSJaCConnection.prototype._doLegacyAuth2=function(iq){if(!iq||iq.getType()!='result'){if(iq&&iq.getType()=='error') 
     360this._handleEvent('onerror',iq.getChild('error'));this.disconnect();return;} 
     361var use_digest=(iq.getChild('digest')!=null);var iq=new JSJaCIQ();iq.setIQ(this.server,'set','auth2');query=iq.appendNode('query',{xmlns:'jabber:iq:auth'},[['username',this.username],['resource',this.resource]]);if(use_digest){query.appendChild(iq.buildNode('digest',{xmlns:'jabber:iq:auth'},hex_sha1(this.streamid+this.pass)));}else if(this.allow_plain){query.appendChild(iq.buildNode('password',{xmlns:'jabber:iq:auth'},this.pass));}else{this.oDbg.log("no valid login mechanism found",1);this.disconnect();return false;} 
     362this.send(iq,this._doLegacyAuthDone);};JSJaCConnection.prototype._doLegacyAuthDone=function(iq){if(iq.getType()!='result'){if(iq.getType()=='error') 
     363this._handleEvent('onerror',iq.getChild('error'));this.disconnect();}else 
     364this._handleEvent('onconnect');};JSJaCConnection.prototype._doSASLAuth=function(){if(this.authtype=='nonsasl'||this.authtype=='anonymous') 
     365return false;if(this.authtype=='saslanon'){if(this.mechs['ANONYMOUS']){this.oDbg.log("SASL using mechanism 'ANONYMOUS'",2);return this._sendRaw("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='ANONYMOUS'/>",this._doSASLAuthDone);} 
     366this.oDbg.log("SASL ANONYMOUS requested but not supported",1);}else{if(this.mechs['DIGEST-MD5']){this.oDbg.log("SASL using mechanism 'DIGEST-MD5'",2);return this._sendRaw("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='DIGEST-MD5'/>",this._doSASLAuthDigestMd5S1);}else if(this.allow_plain&&this.mechs['PLAIN']){this.oDbg.log("SASL using mechanism 'PLAIN'",2);var authStr=this.username+'@'+ 
     367this.domain+String.fromCharCode(0)+ 
     368this.username+String.fromCharCode(0)+ 
     369this.pass;this.oDbg.log("authenticating with '"+authStr+"'",2);authStr=btoa(authStr);return this._sendRaw("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>"+authStr+"</auth>",this._doSASLAuthDone);} 
     370this.oDbg.log("No SASL mechanism applied",1);this.authtype='nonsasl';} 
     371return false;};JSJaCConnection.prototype._doSASLAuthDigestMd5S1=function(el){if(el.nodeName!="challenge"){this.oDbg.log("challenge missing",1);this._handleEvent('onerror',JSJaCError('401','auth','not-authorized'));this.disconnect();}else{var challenge=atob(el.firstChild.nodeValue);this.oDbg.log("got challenge: "+challenge,2);this._nonce=challenge.substring(challenge.indexOf("nonce=")+7);this._nonce=this._nonce.substring(0,this._nonce.indexOf("\""));this.oDbg.log("nonce: "+this._nonce,2);if(this._nonce==''||this._nonce.indexOf('\"')!=-1){this.oDbg.log("nonce not valid, aborting",1);this.disconnect();return;} 
     372this._digest_uri="xmpp/";this._digest_uri+=this.domain;this._cnonce=cnonce(14);this._nc='00000001';var A1=str_md5(this.username+':'+this.domain+':'+this.pass)+':'+this._nonce+':'+this._cnonce;var A2='AUTHENTICATE:'+this._digest_uri;var response=hex_md5(hex_md5(A1)+':'+this._nonce+':'+this._nc+':'+ 
     373this._cnonce+':auth:'+hex_md5(A2));var rPlain='username="'+this.username+'",realm="'+this.domain+'",nonce="'+this._nonce+'",cnonce="'+this._cnonce+'",nc="'+this._nc+'",qop=auth,digest-uri="'+this._digest_uri+'",response="'+response+'",charset="utf-8"';this.oDbg.log("response: "+rPlain,2);this._sendRaw("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>"+ 
     374binb2b64(str2binb(rPlain))+"</response>",this._doSASLAuthDigestMd5S2);}};JSJaCConnection.prototype._doSASLAuthDigestMd5S2=function(el){if(el.nodeName=='failure'){if(el.xml) 
     375this.oDbg.log("auth error: "+el.xml,1);else 
     376this.oDbg.log("auth error",1);this._handleEvent('onerror',JSJaCError('401','auth','not-authorized'));this.disconnect();return;} 
     377var response=atob(el.firstChild.nodeValue);this.oDbg.log("response: "+response,2);var rspauth=response.substring(response.indexOf("rspauth=")+8);this.oDbg.log("rspauth: "+rspauth,2);var A1=str_md5(this.username+':'+this.domain+':'+this.pass)+':'+this._nonce+':'+this._cnonce;var A2=':'+this._digest_uri;var rsptest=hex_md5(hex_md5(A1)+':'+this._nonce+':'+this._nc+':'+ 
     378this._cnonce+':auth:'+hex_md5(A2));this.oDbg.log("rsptest: "+rsptest,2);if(rsptest!=rspauth){this.oDbg.log("SASL Digest-MD5: server repsonse with wrong rspauth",1);this.disconnect();return;} 
     379if(el.nodeName=='success') 
     380this._reInitStream(this.domain,this._doStreamBind);else 
     381this._sendRaw("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>",this._doSASLAuthDone);};JSJaCConnection.prototype._doSASLAuthDone=function(el){if(el.nodeName!='success'){this.oDbg.log("auth failed",1);this._handleEvent('onerror',JSJaCError('401','auth','not-authorized'));this.disconnect();}else 
     382this._reInitStream(this.domain,this._doStreamBind);};JSJaCConnection.prototype._doStreamBind=function(){var iq=new JSJaCIQ();iq.setIQ(null,'set','bind_1');iq.appendNode("bind",{xmlns:"urn:ietf:params:xml:ns:xmpp-bind"},[["resource",this.resource]]);this.oDbg.log(iq.xml());this.send(iq,this._doXMPPSess);};JSJaCConnection.prototype._doXMPPSess=function(iq){if(iq.getType()!='result'||iq.getType()=='error'){this.disconnect();if(iq.getType()=='error') 
     383this._handleEvent('onerror',iq.getChild('error'));return;} 
     384this.fulljid=iq.getChildVal("jid");this.jid=this.fulljid.substring(0,this.fulljid.lastIndexOf('/'));iq=new JSJaCIQ();iq.setIQ(this.domain,'set','sess_1');iq.appendNode("session",{xmlns:"urn:ietf:params:xml:ns:xmpp-session"},[]);this.oDbg.log(iq.xml());this.send(iq,this._doXMPPSessDone);};JSJaCConnection.prototype._doXMPPSessDone=function(iq){if(iq.getType()!='result'||iq.getType()=='error'){this.disconnect();if(iq.getType()=='error') 
     385this._handleEvent('onerror',iq.getChild('error'));return;}else 
     386this._handleEvent('onconnect');};JSJaCConnection.prototype._handleEvent=function(event,arg){event=event.toLowerCase();this.oDbg.log("incoming event '"+event+"'",3);if(!this._events[event]) 
     387return;this.oDbg.log("handling event '"+event+"'",2);for(var i=0;i<this._events[event].length;i++){var aEvent=this._events[event][i];if(typeof aEvent.handler=='function'){try{if(arg){if(arg.pType){if((!arg.getNode().hasChildNodes()&&aEvent.childName!='*')||(arg.getNode().hasChildNodes()&&!arg.getChild(aEvent.childName,aEvent.childNS))) 
     388continue;if(aEvent.type!='*'&&arg.getType()!=aEvent.type) 
     389continue;this.oDbg.log(aEvent.childName+"/"+aEvent.childNS+"/"+aEvent.type+" => match for handler "+aEvent.handler,3);} 
     390if(aEvent.handler(arg)){break;}} 
     391else 
     392if(aEvent.handler()){break;}}catch(e){if(e.fileName&&e.lineNumber){this.oDbg.log(aEvent.handler+"\n>>>"+e.name+": "+e.message+' in '+e.fileName+' line '+e.lineNumber,1);}else{this.oDbg.log(aEvent.handler+"\n>>>"+e.name+": "+e.message,1);}}}}};JSJaCConnection.prototype._handlePID=function(aJSJaCPacket){if(!aJSJaCPacket.getID()) 
     393return false;for(var i in this._regIDs){if(this._regIDs.hasOwnProperty(i)&&this._regIDs[i]&&i==aJSJaCPacket.getID()){var pID=aJSJaCPacket.getID();this.oDbg.log("handling "+pID,3);try{if(this._regIDs[i].cb.call(this,aJSJaCPacket,this._regIDs[i].arg)===false){return false;}else{this._unregisterPID(pID);return true;}}catch(e){this.oDbg.log(e.name+": "+e.message,1);this._unregisterPID(pID);return true;}}} 
     394return false;};JSJaCConnection.prototype._handleResponse=function(req){var rootEl=this._parseResponse(req);if(!rootEl) 
     395return;for(var i=0;i<rootEl.childNodes.length;i++){if(this._sendRawCallbacks.length){var cb=this._sendRawCallbacks[0];this._sendRawCallbacks=this._sendRawCallbacks.slice(1,this._sendRawCallbacks.length);cb.fn.call(this,rootEl.childNodes.item(i),cb.arg);continue;} 
     396this._inQ=this._inQ.concat(rootEl.childNodes.item(i));}};JSJaCConnection.prototype._parseStreamFeatures=function(doc){if(!doc){this.oDbg.log("nothing to parse ... aborting",1);return false;} 
     397var errorTag;if(doc.getElementsByTagNameNS) 
     398errorTag=doc.getElementsByTagNameNS("http://etherx.jabber.org/streams","error").item(0);else{var errors=doc.getElementsByTagName("error");for(var i=0;i<errors.length;i++) 
     399if(errors.item(i).namespaceURI=="http://etherx.jabber.org/streams"){errorTag=errors.item(i);break;}} 
     400if(errorTag){this._setStatus("internal_server_error");clearTimeout(this._timeout);clearInterval(this._interval);clearInterval(this._inQto);this._handleEvent('onerror',JSJaCError('503','cancel','session-terminate'));this._connected=false;this.oDbg.log("Disconnected.",1);this._handleEvent('ondisconnect');return false;} 
     401this.mechs=new Object();var lMec1=doc.getElementsByTagName("mechanisms");this.has_sasl=false;for(var i=0;i<lMec1.length;i++) 
     402if(lMec1.item(i).getAttribute("xmlns")=="urn:ietf:params:xml:ns:xmpp-sasl"){this.has_sasl=true;var lMec2=lMec1.item(i).getElementsByTagName("mechanism");for(var j=0;j<lMec2.length;j++) 
     403this.mechs[lMec2.item(j).firstChild.nodeValue]=true;break;} 
     404if(this.has_sasl) 
     405this.oDbg.log("SASL detected",2);else{this.oDbg.log("No support for SASL detected",2);return false;} 
     406return true;};JSJaCConnection.prototype._process=function(timerval){if(!this.connected()){this.oDbg.log("Connection lost ...",1);if(this._interval) 
     407clearInterval(this._interval);return;} 
     408this.setPollInterval(timerval);if(this._timeout) 
     409clearTimeout(this._timeout);var slot=this._getFreeSlot();if(slot<0) 
     410return;if(typeof(this._req[slot])!='undefined'&&typeof(this._req[slot].r)!='undefined'&&this._req[slot].r.readyState!=4){this.oDbg.log("Slot "+slot+" is not ready");return;} 
     411if(!this.isPolling()&&this._pQueue.length==0&&this._req[(slot+1)%2]&&this._req[(slot+1)%2].r.readyState!=4){this.oDbg.log("all slots busy, standby ...",2);return;} 
     412if(!this.isPolling()) 
     413this.oDbg.log("Found working slot at "+slot,2);this._req[slot]=this._setupRequest(true);this._req[slot].r.onreadystatechange=JSJaC.bind(function(){if(this._req[slot].r.readyState==4){this._setStatus('processing');this.oDbg.log("async recv: "+this._req[slot].r.responseText,4);this._handleResponse(this._req[slot]);if(!this.connected()) 
     414return;if(this._pQueue.length){this._timeout=setTimeout(JSJaC.bind(this._process,this),100);}else{this.oDbg.log("scheduling next poll in "+this.getPollInterval()+" msec",4);this._timeout=setTimeout(JSJaC.bind(this._process,this),this.getPollInterval());}}},this);try{this._req[slot].r.onerror=JSJaC.bind(function(){if(!this.connected()) 
     415return;this._errcnt++;this.oDbg.log('XmlHttpRequest error ('+this._errcnt+')',1);if(this._errcnt>JSJAC_ERR_COUNT){this._abort();return false;} 
     416this._setStatus('onerror_fallback');setTimeout(JSJaC.bind(this._resume,this),this.getPollInterval());return false;},this);}catch(e){} 
     417var reqstr=this._getRequestString();if(typeof(this._rid)!='undefined') 
     418this._req[slot].rid=this._rid;this.oDbg.log("sending: "+reqstr,4);this._req[slot].r.send(reqstr);};JSJaCConnection.prototype._registerPID=function(pID,cb,arg){if(!pID||!cb) 
     419return false;this._regIDs[pID]=new Object();this._regIDs[pID].cb=cb;if(arg) 
     420this._regIDs[pID].arg=arg;this.oDbg.log("registered "+pID,3);return true;};JSJaCConnection.prototype._sendEmpty=function JSJaCSendEmpty(){var slot=this._getFreeSlot();this._req[slot]=this._setupRequest(true);this._req[slot].r.onreadystatechange=JSJaC.bind(function(){if(this._req[slot].r.readyState==4){this.oDbg.log("async recv: "+this._req[slot].r.responseText,4);this._getStreamID(slot);}},this);if(typeof(this._req[slot].r.onerror)!='undefined'){this._req[slot].r.onerror=JSJaC.bind(function(e){this.oDbg.log('XmlHttpRequest error',1);return false;},this);} 
     421var reqstr=this._getRequestString();this.oDbg.log("sending: "+reqstr,4);this._req[slot].r.send(reqstr);};JSJaCConnection.prototype._sendRaw=function(xml,cb,arg){if(cb) 
     422this._sendRawCallbacks.push({fn:cb,arg:arg});this._pQueue.push(xml);this._process();return true;};JSJaCConnection.prototype._setStatus=function(status){if(!status||status=='') 
     423return;if(status!=this._status){this._status=status;this._handleEvent('onstatuschanged',status);this._handleEvent('status_changed',status);}};JSJaCConnection.prototype._unregisterPID=function(pID){if(!this._regIDs[pID]) 
     424return false;this._regIDs[pID]=null;this.oDbg.log("unregistered "+pID,3);return true;};function JSJaCHttpBindingConnection(oArg){this.base=JSJaCConnection;this.base(oArg);this._hold=JSJACHBC_MAX_HOLD;this._inactivity=0;this._last_requests=new Object();this._last_rid=0;this._min_polling=0;this._pause=0;this._wait=JSJACHBC_MAX_WAIT;} 
     425JSJaCHttpBindingConnection.prototype=new JSJaCConnection();JSJaCHttpBindingConnection.prototype.inherit=function(oArg){if(oArg.jid){var oJid=new JSJaCJID(oArg.jid);this.domain=oJid.getDomain();this.username=oJid.getNode();this.resource=oJid.getResource();}else{this.domain=oArg.domain||'localhost';this.username=oArg.username;this.resource=oArg.resource;} 
     426this._sid=oArg.sid;this._rid=oArg.rid;this._min_polling=oArg.polling;this._inactivity=oArg.inactivity;this._setHold(oArg.requests-1);this.setPollInterval(this._timerval);if(oArg.wait) 
     427this._wait=oArg.wait;this._connected=true;this._handleEvent('onconnect');this._interval=setInterval(JSJaC.bind(this._checkQueue,this),JSJAC_CHECKQUEUEINTERVAL);this._inQto=setInterval(JSJaC.bind(this._checkInQ,this),JSJAC_CHECKINQUEUEINTERVAL);this._timeout=setTimeout(JSJaC.bind(this._process,this),this.getPollInterval());};JSJaCHttpBindingConnection.prototype.setPollInterval=function(timerval){if(timerval&&!isNaN(timerval)){if(!this.isPolling()) 
     428this._timerval=100;else if(this._min_polling&&timerval<this._min_polling*1000) 
     429this._timerval=this._min_polling*1000;else if(this._inactivity&&timerval>this._inactivity*1000) 
     430this._timerval=this._inactivity*1000;else 
     431this._timerval=timerval;} 
     432return this._timerval;};JSJaCHttpBindingConnection.prototype.isPolling=function(){return(this._hold==0)};JSJaCHttpBindingConnection.prototype._getFreeSlot=function(){for(var i=0;i<this._hold+1;i++) 
     433if(typeof(this._req[i])=='undefined'||typeof(this._req[i].r)=='undefined'||this._req[i].r.readyState==4) 
     434return i;return-1;};JSJaCHttpBindingConnection.prototype._getHold=function(){return this._hold;};JSJaCHttpBindingConnection.prototype._getRequestString=function(raw,last){raw=raw||'';var reqstr='';if(this._rid<=this._last_rid&&typeof(this._last_requests[this._rid])!='undefined') 
     435reqstr=this._last_requests[this._rid].xml;else{var xml='';while(this._pQueue.length){var curNode=this._pQueue[0];xml+=curNode;this._pQueue=this._pQueue.slice(1,this._pQueue.length);} 
     436reqstr="<body rid='"+this._rid+"' sid='"+this._sid+"' xmlns='http://jabber.org/protocol/httpbind' ";if(JSJAC_HAVEKEYS){reqstr+="key='"+this._keys.getKey()+"' ";if(this._keys.lastKey()){this._keys=new JSJaCKeys(hex_sha1,this.oDbg);reqstr+="newkey='"+this._keys.getKey()+"' ";}} 
     437if(last) 
     438reqstr+="type='terminate'";else if(this._reinit){if(JSJACHBC_USE_BOSH_VER) 
     439reqstr+="xmpp:restart='true' xmlns:xmpp='urn:xmpp:xbosh'";this._reinit=false;} 
     440if(xml!=''||raw!=''){reqstr+=">"+raw+xml+"</body>";}else{reqstr+="/>";} 
     441this._last_requests[this._rid]=new Object();this._last_requests[this._rid].xml=reqstr;this._last_rid=this._rid;for(var i in this._last_requests) 
     442if(this._last_requests.hasOwnProperty(i)&&i<this._rid-this._hold) 
     443delete(this._last_requests[i]);} 
     444return reqstr;};JSJaCHttpBindingConnection.prototype._getInitialRequestString=function(){var reqstr="<body content='text/xml; charset=utf-8' hold='"+this._hold+"' xmlns='http://jabber.org/protocol/httpbind' to='"+this.authhost+"' wait='"+this._wait+"' rid='"+this._rid+"'";if(this.host||this.port) 
     445reqstr+=" route='xmpp:"+this.host+":"+this.port+"'";if(this.secure) 
     446reqstr+=" secure='"+this.secure+"'";if(JSJAC_HAVEKEYS){this._keys=new JSJaCKeys(hex_sha1,this.oDbg);key=this._keys.getKey();reqstr+=" newkey='"+key+"'";} 
     447if(this._xmllang) 
     448reqstr+=" xml:lang='"+this._xmllang+"'";if(JSJACHBC_USE_BOSH_VER){reqstr+=" ver='"+JSJACHBC_BOSH_VERSION+"'";reqstr+=" xmlns:xmpp='urn:xmpp:xbosh'";if(this.authtype=='sasl'||this.authtype=='saslanon') 
     449reqstr+=" xmpp:version='1.0'";} 
     450reqstr+="/>";return reqstr;};JSJaCHttpBindingConnection.prototype._getStreamID=function(slot){this.oDbg.log(this._req[slot].r.responseText,4);if(!this._req[slot].r.responseXML||!this._req[slot].r.responseXML.documentElement){this._handleEvent('onerror',JSJaCError('503','cancel','service-unavailable'));return;} 
     451var body=this._req[slot].r.responseXML.documentElement;if(body.getAttribute('authid')){this.streamid=body.getAttribute('authid');this.oDbg.log("got streamid: "+this.streamid,2);} 
     452if(!this._parseStreamFeatures(body)||!this.streamid){this._timeout=setTimeout(JSJaC.bind(this._sendEmpty,this),this.getPollInterval());return;} 
     453this._timeout=setTimeout(JSJaC.bind(this._process,this),this.getPollInterval());if(this.register) 
     454this._doInBandReg();else 
     455this._doAuth();};JSJaCHttpBindingConnection.prototype._getSuspendVars=function(){return('host,port,secure,_rid,_last_rid,_wait,_min_polling,_inactivity,_hold,_last_requests,_pause').split(',');};JSJaCHttpBindingConnection.prototype._handleInitialResponse=function(slot){try{this.oDbg.log(this._req[slot].r.getAllResponseHeaders(),4);this.oDbg.log(this._req[slot].r.responseText,4);}catch(ex){this.oDbg.log("No response",4);} 
     456if(this._req[slot].r.status!=200||!this._req[slot].r.responseXML){this.oDbg.log("initial response broken (status: "+this._req[slot].r.status+")",1);this._handleEvent('onerror',JSJaCError('503','cancel','service-unavailable'));return;} 
     457var body=this._req[slot].r.responseXML.documentElement;if(!body||body.tagName!='body'||body.namespaceURI!='http://jabber.org/protocol/httpbind'){this.oDbg.log("no body element or incorrect body in initial response",1);this._handleEvent("onerror",JSJaCError("500","wait","internal-service-error"));return;} 
     458if(body.getAttribute("type")=="terminate"){this.oDbg.log("invalid response:\n"+this._req[slot].r.responseText,1);clearTimeout(this._timeout);this._connected=false;this.oDbg.log("Disconnected.",1);this._handleEvent('ondisconnect');this._handleEvent('onerror',JSJaCError('503','cancel','service-unavailable'));return;} 
     459this._sid=body.getAttribute('sid');this.oDbg.log("got sid: "+this._sid,2);if(body.getAttribute('polling')) 
     460this._min_polling=body.getAttribute('polling');if(body.getAttribute('inactivity')) 
     461this._inactivity=body.getAttribute('inactivity');if(body.getAttribute('requests')) 
     462this._setHold(body.getAttribute('requests')-1);this.oDbg.log("set hold to "+this._getHold(),2);if(body.getAttribute('ver')) 
     463this._bosh_version=body.getAttribute('ver');if(body.getAttribute('maxpause')) 
     464this._pause=Number.min(body.getAttribute('maxpause'),JSJACHBC_MAXPAUSE);this.setPollInterval(this._timerval);this._connected=true;this._inQto=setInterval(JSJaC.bind(this._checkInQ,this),JSJAC_CHECKINQUEUEINTERVAL);this._interval=setInterval(JSJaC.bind(this._checkQueue,this),JSJAC_CHECKQUEUEINTERVAL);this._getStreamID(slot);};JSJaCHttpBindingConnection.prototype._parseResponse=function(req){if(!this.connected()||!req) 
     465return null;var r=req.r;try{if(r.status==404||r.status==403){this._abort();return null;} 
     466if(r.status!=200||!r.responseXML){this._errcnt++;var errmsg="invalid response ("+r.status+"):\n"+r.getAllResponseHeaders()+"\n"+r.responseText;if(!r.responseXML) 
     467errmsg+="\nResponse failed to parse!";this.oDbg.log(errmsg,1);if(this._errcnt>JSJAC_ERR_COUNT){this._abort();return null;} 
     468if(this.connected()){this.oDbg.log("repeating ("+this._errcnt+")",1);this._setStatus('proto_error_fallback');setTimeout(JSJaC.bind(this._resume,this),this.getPollInterval());} 
     469return null;}}catch(e){this.oDbg.log("XMLHttpRequest error: status not available",1);this._errcnt++;if(this._errcnt>JSJAC_ERR_COUNT){this._abort();}else{if(this.connected()){this.oDbg.log("repeating ("+this._errcnt+")",1);this._setStatus('proto_error_fallback');setTimeout(JSJaC.bind(this._resume,this),this.getPollInterval());}} 
     470return null;} 
     471var body=r.responseXML.documentElement;if(!body||body.tagName!='body'||body.namespaceURI!='http://jabber.org/protocol/httpbind'){this.oDbg.log("invalid response:\n"+r.responseText,1);clearTimeout(this._timeout);clearInterval(this._interval);clearInterval(this._inQto);this._connected=false;this.oDbg.log("Disconnected.",1);this._handleEvent('ondisconnect');this._setStatus('internal_server_error');this._handleEvent('onerror',JSJaCError('500','wait','internal-server-error'));return null;} 
     472if(typeof(req.rid)!='undefined'&&this._last_requests[req.rid]){if(this._last_requests[req.rid].handled){this.oDbg.log("already handled "+req.rid,2);return null;}else 
     473this._last_requests[req.rid].handled=true;} 
     474if(body.getAttribute("type")=="terminate"){this.oDbg.log("session terminated:\n"+r.responseText,1);clearTimeout(this._timeout);clearInterval(this._interval);clearInterval(this._inQto);try{JSJaCCookie.read(this._cookie_prefix+'JSJaC_State').erase();}catch(e){} 
     475this._connected=false;var condition=body.getAttribute('condition');if(condition=="remote-stream-error") 
     476if(body.getElementsByTagName("conflict").length>0) 
     477this._setStatus("session-terminate-conflict");if(condition==null) 
     478condition='session-terminate';this._handleEvent('onerror',JSJaCError('503','cancel',condition));this.oDbg.log("Aborting remaining connections",4);for(var i=0;i<this._hold+1;i++){try{this._req[i].r.abort();}catch(e){this.oDbg.log(e,1);}} 
     479this.oDbg.log("parseResponse done with terminating",3);this.oDbg.log("Disconnected.",1);this._handleEvent('ondisconnect');return null;} 
     480this._errcnt=0;return r.responseXML.documentElement;};JSJaCHttpBindingConnection.prototype._reInitStream=function(to,cb,arg){this._reinit=true;cb.call(this,arg);};JSJaCHttpBindingConnection.prototype._resume=function(){if(this._pause==0&&this._rid>=this._last_rid) 
     481this._rid=this._last_rid-1;this._process();};JSJaCHttpBindingConnection.prototype._setHold=function(hold){if(!hold||isNaN(hold)||hold<0) 
     482hold=0;else if(hold>JSJACHBC_MAX_HOLD) 
     483hold=JSJACHBC_MAX_HOLD;this._hold=hold;return this._hold;};JSJaCHttpBindingConnection.prototype._setupRequest=function(async){var req=new Object();var r=XmlHttp.create();try{r.open("POST",this._httpbase,async);r.setRequestHeader('Content-Type','text/xml; charset=utf-8');}catch(e){this.oDbg.log(e,1);} 
     484req.r=r;this._rid++;req.rid=this._rid;return req;};JSJaCHttpBindingConnection.prototype._suspend=function(){if(this._pause==0) 
     485return;var slot=this._getFreeSlot();this._req[slot]=this._setupRequest(false);var reqstr="<body pause='"+this._pause+"' xmlns='http://jabber.org/protocol/httpbind' sid='"+this._sid+"' rid='"+this._rid+"'";if(JSJAC_HAVEKEYS){reqstr+=" key='"+this._keys.getKey()+"'";if(this._keys.lastKey()){this._keys=new JSJaCKeys(hex_sha1,this.oDbg);reqstr+=" newkey='"+this._keys.getKey()+"'";}} 
     486reqstr+=">";while(this._pQueue.length){var curNode=this._pQueue[0];reqstr+=curNode;this._pQueue=this._pQueue.slice(1,this._pQueue.length);} 
     487reqstr+="</body>";this.oDbg.log("Disconnecting: "+reqstr,4);this._req[slot].r.send(reqstr);};function JSJaCHttpPollingConnection(oArg){this.base=JSJaCConnection;this.base(oArg);JSJACPACKET_USE_XMLNS=false;} 
     488JSJaCHttpPollingConnection.prototype=new JSJaCConnection();JSJaCHttpPollingConnection.prototype.isPolling=function(){return true;};JSJaCHttpPollingConnection.prototype._getFreeSlot=function(){if(typeof(this._req[0])=='undefined'||typeof(this._req[0].r)=='undefined'||this._req[0].r.readyState==4) 
     489return 0;else 
     490return-1;};JSJaCHttpPollingConnection.prototype._getInitialRequestString=function(){var reqstr="0";if(JSJAC_HAVEKEYS){this._keys=new JSJaCKeys(b64_sha1,this.oDbg);key=this._keys.getKey();reqstr+=";"+key;} 
     491var streamto=this.domain;if(this.authhost) 
     492streamto=this.authhost;reqstr+=",<stream:stream to='"+streamto+"' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'";if(this.authtype=='sasl'||this.authtype=='saslanon') 
     493reqstr+=" version='1.0'";reqstr+=">";return reqstr;};JSJaCHttpPollingConnection.prototype._getRequestString=function(raw,last){var reqstr=this._sid;if(JSJAC_HAVEKEYS){reqstr+=";"+this._keys.getKey();if(this._keys.lastKey()){this._keys=new JSJaCKeys(b64_sha1,this.oDbg);reqstr+=';'+this._keys.getKey();}} 
     494reqstr+=',';if(raw) 
     495reqstr+=raw;while(this._pQueue.length){reqstr+=this._pQueue[0];this._pQueue=this._pQueue.slice(1,this._pQueue.length);} 
     496if(last) 
     497reqstr+='</stream:stream>';return reqstr;};JSJaCHttpPollingConnection.prototype._getStreamID=function(){if(this._req[0].r.responseText==''){this.oDbg.log("waiting for stream id",2);this._timeout=setTimeout(JSJaC.bind(this._sendEmpty,this),1000);return;} 
     498this.oDbg.log(this._req[0].r.responseText,4);if(this._req[0].r.responseText.match(/id=[\'\"]([^\'\"]+)[\'\"]/)) 
     499this.streamid=RegExp.$1;this.oDbg.log("got streamid: "+this.streamid,2);var doc;try{var response=this._req[0].r.responseText;if(!response.match(/<\/stream:stream>\s*$/)) 
     500response+='</stream:stream>';doc=XmlDocument.create("doc");doc.loadXML(response);if(!this._parseStreamFeatures(doc)){this.authtype='nonsasl';return;}}catch(e){this.oDbg.log("loadXML: "+e.toString(),1);} 
     501this._connected=true;if(this.register) 
     502this._doInBandReg();else 
     503this._doAuth();this._process(this._timerval);};JSJaCHttpPollingConnection.prototype._getSuspendVars=function(){return new Array();};JSJaCHttpPollingConnection.prototype._handleInitialResponse=function(){this.oDbg.log(this._req[0].r.getAllResponseHeaders(),4);var aPList=this._req[0].r.getResponseHeader('Set-Cookie');aPList=aPList.split(";");for(var i=0;i<aPList.length;i++){aArg=aPList[i].split("=");if(aArg[0]=='ID') 
     504this._sid=aArg[1];} 
     505this.oDbg.log("got sid: "+this._sid,2);this._connected=true;this._interval=setInterval(JSJaC.bind(this._checkQueue,this),JSJAC_CHECKQUEUEINTERVAL);this._inQto=setInterval(JSJaC.bind(this._checkInQ,this),JSJAC_CHECKINQUEUEINTERVAL);this._getStreamID();};JSJaCHttpPollingConnection.prototype._parseResponse=function(r){var req=r.r;if(!this.connected()) 
     506return null;if(req.status!=200){this.oDbg.log("invalid response ("+req.status+"):"+req.responseText+"\n"+req.getAllResponseHeaders(),1);this._setStatus('internal_server_error');clearTimeout(this._timeout);clearInterval(this._interval);clearInterval(this._inQto);this._connected=false;this.oDbg.log("Disconnected.",1);this._handleEvent('ondisconnect');this._handleEvent('onerror',JSJaCError('503','cancel','service-unavailable'));return null;} 
     507this.oDbg.log(req.getAllResponseHeaders(),4);var sid,aPList=req.getResponseHeader('Set-Cookie');if(aPList==null) 
     508sid="-1:0";else{aPList=aPList.split(";");var sid;for(var i=0;i<aPList.length;i++){var aArg=aPList[i].split("=");if(aArg[0]=='ID') 
     509sid=aArg[1];}} 
     510if(typeof(sid)!='undefined'&&sid.indexOf(':0')!=-1){switch(sid.substring(0,sid.indexOf(':0'))){case'0':this.oDbg.log("invalid response:"+req.responseText,1);break;case'-1':this.oDbg.log("Internal Server Error",1);break;case'-2':this.oDbg.log("Bad Request",1);break;case'-3':this.oDbg.log("Key Sequence Error",1);break;} 
     511this._setStatus('internal_server_error');clearTimeout(this._timeout);clearInterval(this._interval);clearInterval(this._inQto);this._handleEvent('onerror',JSJaCError('500','wait','internal-server-error'));this._connected=false;this.oDbg.log("Disconnected.",1);this._handleEvent('ondisconnect');return null;} 
     512if(!req.responseText||req.responseText=='') 
     513return null;try{var response=req.responseText.replace(/\<\?xml.+\?\>/,"");if(response.match(/<stream:stream/)) 
     514response+="</stream:stream>";var doc=JSJaCHttpPollingConnection._parseTree("<body>"+response+"</body>");if(!doc||doc.tagName=='parsererror'){this.oDbg.log("parsererror",1);doc=JSJaCHttpPollingConnection._parseTree("<stream:stream xmlns:stream='http://etherx.jabber.org/streams'>"+req.responseText);if(doc&&doc.tagName!='parsererror'){this.oDbg.log("stream closed",1);if(doc.getElementsByTagName('conflict').length>0) 
     515this._setStatus("session-terminate-conflict");clearTimeout(this._timeout);clearInterval(this._interval);clearInterval(this._inQto);this._handleEvent('onerror',JSJaCError('503','cancel','session-terminate'));this._connected=false;this.oDbg.log("Disconnected.",1);this._handleEvent('ondisconnect');}else 
     516this.oDbg.log("parsererror:"+doc,1);return doc;} 
     517return doc;}catch(e){this.oDbg.log("parse error:"+e.message,1);} 
     518return null;;};JSJaCHttpPollingConnection.prototype._reInitStream=function(to,cb,arg){this._sendRaw("<stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client' to='"+to+"' version='1.0'>",cb,arg);};JSJaCHttpPollingConnection.prototype._resume=function(){this._process(this._timerval);};JSJaCHttpPollingConnection.prototype._setupRequest=function(async){var r=XmlHttp.create();try{r.open("POST",this._httpbase,async);if(r.overrideMimeType) 
     519r.overrideMimeType('text/plain; charset=utf-8');r.setRequestHeader('Content-Type','application/x-www-form-urlencoded');}catch(e){this.oDbg.log(e,1);} 
     520var req=new Object();req.r=r;return req;};JSJaCHttpPollingConnection.prototype._suspend=function(){};JSJaCHttpPollingConnection._parseTree=function(s){try{var r=XmlDocument.create("body","foo");if(typeof(r.loadXML)!='undefined'){r.loadXML(s);return r.documentElement;}else if(window.DOMParser) 
     521return(new DOMParser()).parseFromString(s,"text/xml").documentElement;}catch(e){} 
     522return null;};var JSJaC={Version:'$Rev$',require:function(libraryName){document.write('<script type="text/javascript" src="'+libraryName+'"></script>');},load:function(){var includes=['xmlextras','jsextras','crypt','JSJaCConfig','JSJaCConstants','JSJaCCookie','JSJaCJSON','JSJaCJID','JSJaCBuilder','JSJaCPacket','JSJaCError','JSJaCKeys','JSJaCConnection','JSJaCHttpPollingConnection','JSJaCHttpBindingConnection','JSJaCConsoleLogger'];var scripts=document.getElementsByTagName("script");var path='./';for(var i=0;i<scripts.length;i++){if(scripts.item(i).src&&scripts.item(i).src.match(/JSJaC\.js$/)){path=scripts.item(i).src.replace(/JSJaC.js$/,'');break;}} 
     523for(var i=0;i<includes.length;i++) 
     524this.require(path+includes[i]+'.js');},bind:function(fn,obj,optArg){return function(arg){return fn.apply(obj,[arg,optArg]);};}};if(typeof JSJaCConnection=='undefined') 
     525JSJaC.load(); 
  • HelpIM3/branches/chatgroups/htdocs/lib/jsjac/jsjac.compressed.js

    r960 r1435  
    4040date.setTime(date.getTime()-offset.getTime());else if(ts.substr(ts.length-6,1)=='-') 
    4141date.setTime(date.getTime()+offset.getTime());} 
    42 return date;};Date.hrTime=function(ts){return Date.jab2date(ts).toLocaleString();};Date.prototype.jabberDate=function(){var padZero=function(i){if(i<10)return"0"+i;return i;};var jDate=this.getUTCFullYear()+"-";jDate+=padZero(this.getUTCMonth()+1)+"-";jDate+=padZero(this.getUTCDate())+"T";jDate+=padZero(this.getUTCHours())+":";jDate+=padZero(this.getUTCMinutes())+":";jDate+=padZero(this.getUTCSeconds())+"Z";return jDate;};Number.max=function(A,B){return(A>B)?A:B;};var hexcase=0;var b64pad="=";var chrsz=8;function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length*chrsz));} 
     42return date;};Date.hrTime=function(ts){return Date.jab2date(ts).toLocaleString();};Date.prototype.jabberDate=function(){var padZero=function(i){if(i<10)return"0"+i;return i;};var jDate=this.getUTCFullYear()+"-";jDate+=padZero(this.getUTCMonth()+1)+"-";jDate+=padZero(this.getUTCDate())+"T";jDate+=padZero(this.getUTCHours())+":";jDate+=padZero(this.getUTCMinutes())+":";jDate+=padZero(this.getUTCSeconds())+"Z";return jDate;};Number.max=function(A,B){return(A>B)?A:B;};Number.min=function(A,B){return(A<B)?A:B;};var hexcase=0;var b64pad="=";var chrsz=8;function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length*chrsz));} 
    4343function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length*chrsz));} 
    4444function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length*chrsz));} 
     
    255255this.getNode().setAttribute('type',type);return this;};JSJaCPacket.prototype.setXMLLang=function(xmllang){if(!xmllang||xmllang=='') 
    256256this.getNode().removeAttribute('xml:lang');else 
    257 this.getNode().setAttribute('xml:lang',xmllang);return this;};JSJaCPacket.prototype.getTo=function(){return this.getNode().getAttribute('to');};JSJaCPacket.prototype.getFrom=function(){return this.getNode().getAttribute('from');};JSJaCPacket.prototype.getToJID=function(){return new JSJaCJID(this.getTo());};JSJaCPacket.prototype.getFromJID=function(){return new JSJaCJID(this.getFrom());};JSJaCPacket.prototype.getID=function(){return this.getNode().getAttribute('id');};JSJaCPacket.prototype.getType=function(){return this.getNode().getAttribute('type');};JSJaCPacket.prototype.getXMLLang=function(){return this.getNode().getAttribute('xml:lang');};JSJaCPacket.prototype.getXMLNS=function(){return this.getNode().namespaceURI;};JSJaCPacket.prototype.getChild=function(name,ns){if(!this.getNode()){return null;} 
     257this.getNode().setAttribute('xml:lang',xmllang);return this;};JSJaCPacket.prototype.getTo=function(){return this.getNode().getAttribute('to');};JSJaCPacket.prototype.getFrom=function(){return this.getNode().getAttribute('from');};JSJaCPacket.prototype.getToJID=function(){return new JSJaCJID(this.getTo());};JSJaCPacket.prototype.getFromJID=function(){return new JSJaCJID(this.getFrom());};JSJaCPacket.prototype.getID=function(){return this.getNode().getAttribute('id');};JSJaCPacket.prototype.getType=function(){return this.getNode().getAttribute('type');};JSJaCPacket.prototype.getXMLLang=function(){return this.getNode().getAttribute('xml:lang');};JSJaCPacket.prototype.getXMLNS=function(){return this.getNode().namespaceURI||this.getNode().getAttribute('xmlns');};JSJaCPacket.prototype.getChild=function(name,ns){if(!this.getNode()){return null;} 
    258258name=name||'*';ns=ns||'*';if(this.getNode().getElementsByTagNameNS){return this.getNode().getElementsByTagNameNS(ns,name).item(0);} 
    259 var nodes=this.getNode().getElementsByTagName(name);if(ns!='*'){for(var i=0;i<nodes.length;i++){if(nodes.item(i).namespaceURI==ns){return nodes.item(i);}}}else{return nodes.item(0);} 
     259var nodes=this.getNode().getElementsByTagName(name);if(ns!='*'){for(var i=0;i<nodes.length;i++){if(nodes.item(i).namespaceURI==ns||nodes.item(i).getAttribute('xmlns')==ns){return nodes.item(i);}}}else{return nodes.item(0);} 
    260260return null;};JSJaCPacket.prototype.getChildVal=function(name,ns){var node=this.getChild(name,ns);var ret='';if(node&&node.hasChildNodes()){for(var i=0;i<node.childNodes.length;i++) 
    261261if(node.childNodes.item(i).nodeValue) 
    262262ret+=node.childNodes.item(i).nodeValue;} 
    263263return ret;};JSJaCPacket.prototype.clone=function(){return JSJaCPacket.wrapNode(this.getNode());};JSJaCPacket.prototype.isError=function(){return(this.getType()=='error');};JSJaCPacket.prototype.errorReply=function(stanza_error){var rPacket=this.clone();rPacket.setTo(this.getFrom());rPacket.setFrom();rPacket.setType('error');rPacket.appendNode('error',{code:stanza_error.code,type:stanza_error.type},[[stanza_error.cond]]);return rPacket;};JSJaCPacket.prototype.xml=typeof XMLSerializer!='undefined'?function(){var r=(new XMLSerializer()).serializeToString(this.getNode());if(typeof(r)=='undefined') 
    264 r=(new XMLSerializer()).serializeToString(this.doc);return r}:function(){return this.getDoc().xml};JSJaCPacket.prototype._getAttribute=function(attr){return this.getNode().getAttribute(attr);};JSJaCPacket.prototype._replaceNode=function(aNode){for(var i=0;i<aNode.attributes.length;i++) 
    265 if(aNode.attributes.item(i).nodeName!='xmlns') 
    266 this.getNode().setAttribute(aNode.attributes.item(i).nodeName,aNode.attributes.item(i).nodeValue);for(var i=0;i<aNode.childNodes.length;i++) 
    267 if(this.getDoc().importNode) 
    268 this.getNode().appendChild(this.getDoc().importNode(aNode.childNodes.item(i),true));else 
    269 this.getNode().appendChild(aNode.childNodes.item(i).cloneNode(true));};JSJaCPacket.prototype._setChildNode=function(nodeName,nodeValue){var aNode=this.getChild(nodeName);var tNode=this.getDoc().createTextNode(nodeValue);if(aNode) 
     264r=(new XMLSerializer()).serializeToString(this.doc);return r}:function(){return this.getDoc().xml};JSJaCPacket.prototype._getAttribute=function(attr){return this.getNode().getAttribute(attr);};if(document.ELEMENT_NODE==null){document.ELEMENT_NODE=1;document.ATTRIBUTE_NODE=2;document.TEXT_NODE=3;document.CDATA_SECTION_NODE=4;document.ENTITY_REFERENCE_NODE=5;document.ENTITY_NODE=6;document.PROCESSING_INSTRUCTION_NODE=7;document.COMMENT_NODE=8;document.DOCUMENT_NODE=9;document.DOCUMENT_TYPE_NODE=10;document.DOCUMENT_FRAGMENT_NODE=11;document.NOTATION_NODE=12;} 
     265JSJaCPacket.prototype._importNode=function(node,allChildren){switch(node.nodeType){case document.ELEMENT_NODE:if(this.getDoc().createElementNS){var newNode=this.getDoc().createElementNS(node.namespaceURI,node.nodeName);}else{var newNode=this.getDoc().createElement(node.nodeName);} 
     266if(node.attributes&&node.attributes.length>0) 
     267for(var i=0,il=node.attributes.length;i<il;i++){var attr=node.attributes.item(i);if(attr.nodeName=='xmlns'&&newNode.getAttribute('xmlns')!=null)continue;if(newNode.setAttributeNS&&attr.namespaceURI){newNode.setAttributeNS(attr.namespaceURI,attr.nodeName,attr.nodeValue);}else{newNode.setAttribute(attr.nodeName,attr.nodeValue);}} 
     268if(allChildren&&node.childNodes&&node.childNodes.length>0){for(var i=0,il=node.childNodes.length;i<il;i++){newNode.appendChild(this._importNode(node.childNodes.item(i),allChildren));}} 
     269return newNode;break;case document.TEXT_NODE:case document.CDATA_SECTION_NODE:case document.COMMENT_NODE:return this.getDoc().createTextNode(node.nodeValue);break;}};JSJaCPacket.prototype._setChildNode=function(nodeName,nodeValue){var aNode=this.getChild(nodeName);var tNode=this.getDoc().createTextNode(nodeValue);if(aNode) 
    270270try{aNode.replaceChild(tNode,aNode.firstChild);}catch(e){} 
    271271else{try{aNode=this.getDoc().createElementNS(this.getNode().namespaceURI,nodeName);}catch(ex){aNode=this.getDoc().createElement(nodeName)} 
    272272this.getNode().appendChild(aNode);aNode.appendChild(tNode);} 
    273 return aNode;};JSJaCPacket.prototype._setEmptyChildNode=function(nodeName,xmlns){var child;try{child=this.getDoc().createElementNS(xmlns,nodeName);}catch(e){child=this.getDoc().createElement(nodeName);} 
    274 if(child&&child.getAttribute('xmlns')!=xmlns) 
    275 child.setAttribute('xmlns',xmlns);this.getNode().appendChild(child);return child;};JSJaCPacket.prototype.buildNode=function(elementName){return JSJaCBuilder.buildNode(this.getDoc(),elementName,arguments[1],arguments[2]);};JSJaCPacket.prototype.appendNode=function(element){if(typeof element=='object'){return this.getNode().appendChild(element)}else{return this.getNode().appendChild(this.buildNode(element,arguments[1],arguments[2],null,this.getNode().namespaceURI));}};function JSJaCPresence(){this.base=JSJaCPacket;this.base('presence');} 
     273return aNode;};JSJaCPacket.prototype.buildNode=function(elementName){return JSJaCBuilder.buildNode(this.getDoc(),elementName,arguments[1],arguments[2]);};JSJaCPacket.prototype.appendNode=function(element){if(typeof element=='object'){return this.getNode().appendChild(element)}else{return this.getNode().appendChild(this.buildNode(element,arguments[1],arguments[2],null,this.getNode().namespaceURI));}};function JSJaCPresence(){this.base=JSJaCPacket;this.base('presence');} 
    276274JSJaCPresence.prototype=new JSJaCPacket;JSJaCPresence.prototype.setStatus=function(status){this._setChildNode("status",status);return this;};JSJaCPresence.prototype.setShow=function(show){if(show=='chat'||show=='away'||show=='xa'||show=='dnd') 
    277275this._setChildNode("show",show);return this;};JSJaCPresence.prototype.setPriority=function(prio){this._setChildNode("priority",prio);return this;};JSJaCPresence.prototype.setPresence=function(show,status,prio){if(show) 
     
    282280this.setTo(to);if(type) 
    283281this.setType(type);if(id) 
    284 this.setID(id);return this;};JSJaCIQ.prototype.setQuery=function(xmlns){return this._setEmptyChildNode('query',xmlns);};JSJaCIQ.prototype.getQuery=function(){return this.getNode().getElementsByTagName('query').item(0);};JSJaCIQ.prototype.getQueryXMLNS=function(){if(this.getQuery()) 
    285 return this.getQuery().namespaceURI;else 
    286 return null;};JSJaCIQ.prototype.reply=function(payload){var rIQ=this.clone();rIQ.setTo(this.getFrom());rIQ.setFrom();rIQ.setType('result');if(payload){if(typeof payload=='string') 
     282this.setID(id);return this;};JSJaCIQ.prototype.setQuery=function(xmlns){var query;try{query=this.getDoc().createElementNS(xmlns,'query');}catch(e){query=this.getDoc().createElement('query');query.setAttribute('xmlns',xmlns);} 
     283this.getNode().appendChild(query);return query;};JSJaCIQ.prototype.getQuery=function(){return this.getNode().getElementsByTagName('query').item(0);};JSJaCIQ.prototype.getQueryXMLNS=function(){if(this.getQuery()){return this.getQuery().namespaceURI||this.getQuery().getAttribute('xmlns');}else{return null;}};JSJaCIQ.prototype.reply=function(payload){var rIQ=this.clone();rIQ.setTo(this.getFrom());rIQ.setFrom();rIQ.setType('result');if(payload){if(typeof payload=='string') 
    287284rIQ.getChild().appendChild(rIQ.getDoc().loadXML(payload));else if(payload.constructor==Array){var node=rIQ.getChild();for(var i=0;i<payload.length;i++) 
    288285if(typeof payload[i]=='string') 
     
    292289rIQ.getChild().appendChild(payload);} 
    293290return rIQ;};function JSJaCMessage(){this.base=JSJaCPacket;this.base('message');} 
    294 JSJaCMessage.prototype=new JSJaCPacket;JSJaCMessage.prototype.setBody=function(body){this._setChildNode("body",body);return this;};JSJaCMessage.prototype.setSubject=function(subject){this._setChildNode("subject",subject);return this;};JSJaCMessage.prototype.setThread=function(thread){this._setChildNode("thread",thread);return this;};JSJaCMessage.prototype.setState=function(state){var validState=false;for(var i=0;i<JSJACPACKET_CHAT_STATES.length;i++){if(JSJACPACKET_CHAT_STATES[i]==state) 
    295 validState=true;if(this.getChild(JSJACPACKET_CHAT_STATES[i])) 
    296 return null;} 
     291JSJaCMessage.prototype=new JSJaCPacket;JSJaCMessage.prototype.setBody=function(body){this._setChildNode("body",body);return this;};JSJaCMessage.prototype.setSubject=function(subject){this._setChildNode("subject",subject);return this;};JSJaCMessage.prototype.setThread=function(thread){this._setChildNode("thread",thread);return this;};JSJaCMessage.prototype.getThread=function(){return this.getChildVal('thread');};JSJaCMessage.prototype.getBody=function(){return this.getChildVal('body');};JSJaCMessage.prototype.getSubject=function(){return this.getChildVal('subject')};JSJaCPacket.wrapNode=function(node){var oPacket=null;switch(node.nodeName.toLowerCase()){case'presence':oPacket=new JSJaCPresence();break;case'message':oPacket=new JSJaCMessage();break;case'iq':oPacket=new JSJaCIQ();break;} 
     292if(oPacket){oPacket.getDoc().replaceChild(oPacket._importNode(node,true),oPacket.getNode());} 
     293return oPacket;};JSJaCMessage.prototype.getState=function(){var stateEl=this.getChild('*',NS_CHAT_STATES);if(stateEl) 
     294return stateEl.tagName;else 
     295return null;};JSJaCMessage.prototype.setState=function(state){if(this.getChild('*',NS_CHAT_STATES)) 
     296return null;var validState=false;for(var i=0;i<JSJACPACKET_CHAT_STATES.length;i++){if(JSJACPACKET_CHAT_STATES[i]==state) 
     297validState=true;} 
    297298if(!validState) 
    298 return null;this._setEmptyChildNode(state,NS_CHAT_STATES);return this;};JSJaCMessage.prototype.getThread=function(){return this.getChildVal('thread');};JSJaCMessage.prototype.getBody=function(){return this.getChildVal('body');};JSJaCMessage.prototype.getSubject=function(){return this.getChildVal('subject')};JSJaCMessage.prototype.getState=function(){var state;for(var i=0;i<JSJACPACKET_CHAT_STATES.length;i++) 
    299 if(this.getChild(JSJACPACKET_CHAT_STATES[i])) 
    300 return JSJACPACKET_CHAT_STATES[i];return null;};JSJaCPacket.wrapNode=function(node){var aNode=null;try{switch(node.nodeName.toLowerCase()){case'presence':aNode=new JSJaCPresence();break;case'message':aNode=new JSJaCMessage();break;case'iq':aNode=new JSJaCIQ();break;} 
    301 aNode._replaceNode(node);}catch(e){} 
    302 return aNode;};function JSJaCConnection(oArg){if(oArg&&oArg.oDbg&&oArg.oDbg.log){this.oDbg=oArg.oDbg;}else{this.oDbg=new Object();this.oDbg.log=function(){};} 
     299return null;this.appendNode(state,{xmlns:NS_CHAT_STATES});return this;};function JSJaCConnection(oArg){if(oArg&&oArg.oDbg&&oArg.oDbg.log){this.oDbg=oArg.oDbg;}else{this.oDbg=new Object();this.oDbg.log=function(){};} 
    303300if(oArg&&oArg.timerval) 
    304301this.setPollInterval(oArg.timerval);else 
     
    315312this._wait=oArg.wait;this.jid=this.username+'@'+this.domain;this.fulljid=this.jid+'/'+this.resource;this._rid=Math.round(100000.5+(((900000.49999)-(100000.5))*Math.random()));var slot=this._getFreeSlot();this._req[slot]=this._setupRequest(true);var reqstr=this._getInitialRequestString();this.oDbg.log(reqstr,4);this._req[slot].r.onreadystatechange=JSJaC.bind(function(){if(this._req[slot].r.readyState==4){this.oDbg.log("async recv: "+this._req[slot].r.responseText,4);this._handleInitialResponse(slot);}},this);if(typeof(this._req[slot].r.onerror)!='undefined'){this._req[slot].r.onerror=JSJaC.bind(function(e){this.oDbg.log('XmlHttpRequest error',1);return false;},this);} 
    316313this._req[slot].r.send(reqstr);};JSJaCConnection.prototype.connected=function(){return this._connected;};JSJaCConnection.prototype.disconnect=function(){this._setStatus('disconnecting');if(!this.connected()) 
    317 return;this._connected=false;clearInterval(this._interval);clearInterval(this._inQto);if(this._timeout) 
    318 clearTimeout(this._timeout);var slot=this._getFreeSlot();this._req[slot]=this._setupRequest(false);request=this._getRequestString(false,true);this.oDbg.log("Disconnecting: "+request,4);try{this._req[slot].r.send(request);}catch(e){} 
    319 try{JSJaCCookie.read(this._cookie_prefix+'JSJaC_State').erase();}catch(e){} 
    320 this.oDbg.log("Disconnected: "+this._req[slot].r.responseText,2);this._handleEvent('ondisconnect');};JSJaCConnection.prototype.getPollInterval=function(){return this._timerval;};JSJaCConnection.prototype.registerHandler=function(event){event=event.toLowerCase();var eArg={handler:arguments[arguments.length-1],childName:'*',childNS:'*',type:'*'};if(arguments.length>2) 
     314return;var slot=this._getFreeSlot();this._req[slot]=this._setupRequest(true);this._req[slot].r.onreadystatechange=JSJaC.bind(function(){try{if(this._req[slot].r.readyState==4){this.oDbg.log("async recv: "+this._req[slot].r.responseText,4);this._handleResponse(this._req[slot]);}}catch(e){this.oDbg.log(e,1);}},this);request=this._getRequestString(false,true);this.oDbg.log("Disconnecting: "+request,4);this._req[slot].r.send(request);};JSJaCConnection.prototype.getPollInterval=function(){return this._timerval;};JSJaCConnection.prototype.registerHandler=function(event){event=event.toLowerCase();var eArg={handler:arguments[arguments.length-1],childName:'*',childNS:'*',type:'*'};if(arguments.length>2) 
    321315eArg.childName=arguments[1];if(arguments.length>3) 
    322316eArg.childNS=arguments[2];if(arguments.length>4) 
     
    350344try{this._handleEvent(packet.pType()+'_out',packet);this._handleEvent("packet_out",packet);this._pQueue=this._pQueue.concat(packet.xml());}catch(e){this.oDbg.log(e.toString(),1);return false;} 
    351345return true;};JSJaCConnection.prototype.sendIQ=function(iq,handlers,arg){if(!iq||iq.pType()!='iq'){return false;} 
    352 handlers=handlers||{};var error_handler=handlers.error_handler||function(aIq){this.oDbg.log(aIq.xml(),1);};var result_handler=handlers.result_handler||function(aIq){this.oDbg.log(aIq.xml(),2);};var default_handler=handlers.default_handler||function(aIq){this.oDbg.log(aIq.xml(),2);};var iqHandler=function(aIq,arg){switch(aIq.getType()){case'error':error_handler(aIq);break;case'result':result_handler(aIq,arg);break;default:default_handler(aIq,arg);}};return this.send(iq,iqHandler,arg);};JSJaCConnection.prototype.setPollInterval=function(timerval){if(timerval&&!isNaN(timerval)) 
     346handlers=handlers||{};var error_handler=handlers.error_handler||JSJaC.bind(function(aIq){this.oDbg.log(aIq.xml(),1);},this);var result_handler=handlers.result_handler||JSJaC.bind(function(aIq){this.oDbg.log(aIq.xml(),2);},this);var iqHandler=function(aIq,arg){switch(aIq.getType()){case'error':error_handler(aIq);break;case'result':result_handler(aIq,arg);break;}};return this.send(iq,iqHandler,arg);};JSJaCConnection.prototype.setPollInterval=function(timerval){if(timerval&&!isNaN(timerval)) 
    353347this._timerval=timerval;return this._timerval;};JSJaCConnection.prototype.status=function(){return this._status;};JSJaCConnection.prototype.suspend=function(){var data=this.suspendToData();try{var c=new JSJaCCookie(this._cookie_prefix+'JSJaC_State',JSJaCJSON.toString(data));this.oDbg.log("writing cookie: "+c.getValue()+"\n"+"(length:"+c.getValue().length+")",2);c.write();var c2=JSJaCCookie.get(this._cookie_prefix+'JSJaC_State');if(c.getValue()!=c2){this.oDbg.log("Suspend failed writing cookie.\nread: "+c2,1);c.erase();return false;} 
    354348return true;}catch(e){this.oDbg.log("Failed creating cookie '"+this._cookie_prefix+"JSJaC_State': "+e.message,1);} 
     
    386380this._reInitStream(this.domain,this._doStreamBind);else 
    387381this._sendRaw("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>",this._doSASLAuthDone);};JSJaCConnection.prototype._doSASLAuthDone=function(el){if(el.nodeName!='success'){this.oDbg.log("auth failed",1);this._handleEvent('onerror',JSJaCError('401','auth','not-authorized'));this.disconnect();}else 
    388 this._reInitStream(this.domain,this._doStreamBind);};JSJaCConnection.prototype._doStreamBind=function(){var iq=new JSJaCIQ();iq.setIQ(this.domain,'set','bind_1');iq.appendNode("bind",{xmlns:"urn:ietf:params:xml:ns:xmpp-bind"},[["resource",this.resource]]);this.oDbg.log(iq.xml());this.send(iq,this._doXMPPSess);};JSJaCConnection.prototype._doXMPPSess=function(iq){if(iq.getType()!='result'||iq.getType()=='error'){this.disconnect();if(iq.getType()=='error') 
     382this._reInitStream(this.domain,this._doStreamBind);};JSJaCConnection.prototype._doStreamBind=function(){var iq=new JSJaCIQ();iq.setIQ(null,'set','bind_1');iq.appendNode("bind",{xmlns:"urn:ietf:params:xml:ns:xmpp-bind"},[["resource",this.resource]]);this.oDbg.log(iq.xml());this.send(iq,this._doXMPPSess);};JSJaCConnection.prototype._doXMPPSess=function(iq){if(iq.getType()!='result'||iq.getType()=='error'){this.disconnect();if(iq.getType()=='error') 
    389383this._handleEvent('onerror',iq.getChild('error'));return;} 
    390384this.fulljid=iq.getChildVal("jid");this.jid=this.fulljid.substring(0,this.fulljid.lastIndexOf('/'));iq=new JSJaCIQ();iq.setIQ(this.domain,'set','sess_1');iq.appendNode("session",{xmlns:"urn:ietf:params:xml:ns:xmpp-session"},[]);this.oDbg.log(iq.xml());this.send(iq,this._doXMPPSessDone);};JSJaCConnection.prototype._doXMPPSessDone=function(iq){if(iq.getType()!='result'||iq.getType()=='error'){this.disconnect();if(iq.getType()=='error') 
     
    397391else 
    398392if(aEvent.handler()){break;}}catch(e){if(e.fileName&&e.lineNumber){this.oDbg.log(aEvent.handler+"\n>>>"+e.name+": "+e.message+' in '+e.fileName+' line '+e.lineNumber,1);}else{this.oDbg.log(aEvent.handler+"\n>>>"+e.name+": "+e.message,1);}}}}};JSJaCConnection.prototype._handlePID=function(aJSJaCPacket){if(!aJSJaCPacket.getID()) 
    399 return false;for(var i in this._regIDs){if(this._regIDs.hasOwnProperty(i)&&this._regIDs[i]&&i==aJSJaCPacket.getID()){var pID=aJSJaCPacket.getID();this.oDbg.log("handling "+pID,3);try{if(this._regIDs[i].cb.call(this,aJSJaCPacket,this._regIDs[i].arg)===false){return false;}else{this._unregisterPID(pID);return true;}}catch(e){this.oDbg.log(e.name+": "+e.message);this._unregisterPID(pID);return true;}}} 
     393return false;for(var i in this._regIDs){if(this._regIDs.hasOwnProperty(i)&&this._regIDs[i]&&i==aJSJaCPacket.getID()){var pID=aJSJaCPacket.getID();this.oDbg.log("handling "+pID,3);try{if(this._regIDs[i].cb.call(this,aJSJaCPacket,this._regIDs[i].arg)===false){return false;}else{this._unregisterPID(pID);return true;}}catch(e){this.oDbg.log(e.name+": "+e.message,1);this._unregisterPID(pID);return true;}}} 
    400394return false;};JSJaCConnection.prototype._handleResponse=function(req){var rootEl=this._parseResponse(req);if(!rootEl) 
    401395return;for(var i=0;i<rootEl.childNodes.length;i++){if(this._sendRawCallbacks.length){var cb=this._sendRawCallbacks[0];this._sendRawCallbacks=this._sendRawCallbacks.slice(1,this._sendRawCallbacks.length);cb.fn.call(this,rootEl.childNodes.item(i),cb.arg);continue;} 
     
    417411if(!this.isPolling()&&this._pQueue.length==0&&this._req[(slot+1)%2]&&this._req[(slot+1)%2].r.readyState!=4){this.oDbg.log("all slots busy, standby ...",2);return;} 
    418412if(!this.isPolling()) 
    419 this.oDbg.log("Found working slot at "+slot,2);this._req[slot]=this._setupRequest(true);this._req[slot].r.onreadystatechange=JSJaC.bind(function(){if(!this.connected()) 
    420 return;if(this._req[slot].r.readyState==4){this._setStatus('processing');this.oDbg.log("async recv: "+this._req[slot].r.responseText,4);this._handleResponse(this._req[slot]);if(this._pQueue.length){this._timeout=setTimeout(JSJaC.bind(this._process,this),100);}else{this.oDbg.log("scheduling next poll in "+this.getPollInterval()+" msec",4);this._timeout=setTimeout(JSJaC.bind(this._process,this),this.getPollInterval());}}},this);try{this._req[slot].r.onerror=JSJaC.bind(function(){if(!this.connected()) 
     413this.oDbg.log("Found working slot at "+slot,2);this._req[slot]=this._setupRequest(true);this._req[slot].r.onreadystatechange=JSJaC.bind(function(){if(this._req[slot].r.readyState==4){this._setStatus('processing');this.oDbg.log("async recv: "+this._req[slot].r.responseText,4);this._handleResponse(this._req[slot]);if(!this.connected()) 
     414return;if(this._pQueue.length){this._timeout=setTimeout(JSJaC.bind(this._process,this),100);}else{this.oDbg.log("scheduling next poll in "+this.getPollInterval()+" msec",4);this._timeout=setTimeout(JSJaC.bind(this._process,this),this.getPollInterval());}}},this);try{this._req[slot].r.onerror=JSJaC.bind(function(){if(!this.connected()) 
    421415return;this._errcnt++;this.oDbg.log('XmlHttpRequest error ('+this._errcnt+')',1);if(this._errcnt>JSJAC_ERR_COUNT){this._abort();return false;} 
    422416this._setStatus('onerror_fallback');setTimeout(JSJaC.bind(this._resume,this),this.getPollInterval());return false;},this);}catch(e){} 
     
    429423return;if(status!=this._status){this._status=status;this._handleEvent('onstatuschanged',status);this._handleEvent('status_changed',status);}};JSJaCConnection.prototype._unregisterPID=function(pID){if(!this._regIDs[pID]) 
    430424return false;this._regIDs[pID]=null;this.oDbg.log("unregistered "+pID,3);return true;};function JSJaCHttpBindingConnection(oArg){this.base=JSJaCConnection;this.base(oArg);this._hold=JSJACHBC_MAX_HOLD;this._inactivity=0;this._last_requests=new Object();this._last_rid=0;this._min_polling=0;this._pause=0;this._wait=JSJACHBC_MAX_WAIT;} 
    431 JSJaCHttpBindingConnection.prototype=new JSJaCConnection();JSJaCHttpBindingConnection.prototype.inherit=function(oArg){this.domain=oArg.domain||'localhost';this.username=oArg.username;this.resource=oArg.resource;this._sid=oArg.sid;this._rid=oArg.rid;this._min_polling=oArg.polling;this._inactivity=oArg.inactivity;this._setHold(oArg.requests-1);this.setPollInterval(this._timerval);if(oArg.wait) 
     425JSJaCHttpBindingConnection.prototype=new JSJaCConnection();JSJaCHttpBindingConnection.prototype.inherit=function(oArg){if(oArg.jid){var oJid=new JSJaCJID(oArg.jid);this.domain=oJid.getDomain();this.username=oJid.getNode();this.resource=oJid.getResource();}else{this.domain=oArg.domain||'localhost';this.username=oArg.username;this.resource=oArg.resource;} 
     426this._sid=oArg.sid;this._rid=oArg.rid;this._min_polling=oArg.polling;this._inactivity=oArg.inactivity;this._setHold(oArg.requests-1);this.setPollInterval(this._timerval);if(oArg.wait) 
    432427this._wait=oArg.wait;this._connected=true;this._handleEvent('onconnect');this._interval=setInterval(JSJaC.bind(this._checkQueue,this),JSJAC_CHECKQUEUEINTERVAL);this._inQto=setInterval(JSJaC.bind(this._checkInQ,this),JSJAC_CHECKINQUEUEINTERVAL);this._timeout=setTimeout(JSJaC.bind(this._process,this),this.getPollInterval());};JSJaCHttpBindingConnection.prototype.setPollInterval=function(timerval){if(timerval&&!isNaN(timerval)){if(!this.isPolling()) 
    433428this._timerval=100;else if(this._min_polling&&timerval<this._min_polling*1000) 
     
    467462this._setHold(body.getAttribute('requests')-1);this.oDbg.log("set hold to "+this._getHold(),2);if(body.getAttribute('ver')) 
    468463this._bosh_version=body.getAttribute('ver');if(body.getAttribute('maxpause')) 
    469 this._pause=Number.max(body.getAttribute('maxpause'),JSJACHBC_MAXPAUSE);this.setPollInterval(this._timerval);this._connected=true;this._inQto=setInterval(JSJaC.bind(this._checkInQ,this),JSJAC_CHECKINQUEUEINTERVAL);this._interval=setInterval(JSJaC.bind(this._checkQueue,this),JSJAC_CHECKQUEUEINTERVAL);this._getStreamID(slot);};JSJaCHttpBindingConnection.prototype._parseResponse=function(req){if(!this.connected()||!req) 
     464this._pause=Number.min(body.getAttribute('maxpause'),JSJACHBC_MAXPAUSE);this.setPollInterval(this._timerval);this._connected=true;this._inQto=setInterval(JSJaC.bind(this._checkInQ,this),JSJAC_CHECKINQUEUEINTERVAL);this._interval=setInterval(JSJaC.bind(this._checkQueue,this),JSJAC_CHECKQUEUEINTERVAL);this._getStreamID(slot);};JSJaCHttpBindingConnection.prototype._parseResponse=function(req){if(!this.connected()||!req) 
    470465return null;var r=req.r;try{if(r.status==404||r.status==403){this._abort();return null;} 
    471466if(r.status!=200||!r.responseXML){this._errcnt++;var errmsg="invalid response ("+r.status+"):\n"+r.getAllResponseHeaders()+"\n"+r.responseText;if(!r.responseXML) 
    472467errmsg+="\nResponse failed to parse!";this.oDbg.log(errmsg,1);if(this._errcnt>JSJAC_ERR_COUNT){this._abort();return null;} 
    473 this.oDbg.log("repeating ("+this._errcnt+")",1);this._setStatus('proto_error_fallback');setTimeout(JSJaC.bind(this._resume,this),this.getPollInterval());return null;}}catch(e){this.oDbg.log("XMLHttpRequest error: status not available",1);this._errcnt++;if(this._errcnt>JSJAC_ERR_COUNT){this._abort();}else{this.oDbg.log("repeating ("+this._errcnt+")",1);this._setStatus('proto_error_fallback');setTimeout(JSJaC.bind(this._resume,this),this.getPollInterval());} 
     468if(this.connected()){this.oDbg.log("repeating ("+this._errcnt+")",1);this._setStatus('proto_error_fallback');setTimeout(JSJaC.bind(this._resume,this),this.getPollInterval());} 
     469return null;}}catch(e){this.oDbg.log("XMLHttpRequest error: status not available",1);this._errcnt++;if(this._errcnt>JSJAC_ERR_COUNT){this._abort();}else{if(this.connected()){this.oDbg.log("repeating ("+this._errcnt+")",1);this._setStatus('proto_error_fallback');setTimeout(JSJaC.bind(this._resume,this),this.getPollInterval());}} 
    474470return null;} 
    475471var body=r.responseXML.documentElement;if(!body||body.tagName!='body'||body.namespaceURI!='http://jabber.org/protocol/httpbind'){this.oDbg.log("invalid response:\n"+r.responseText,1);clearTimeout(this._timeout);clearInterval(this._interval);clearInterval(this._inQto);this._connected=false;this.oDbg.log("Disconnected.",1);this._handleEvent('ondisconnect');this._setStatus('internal_server_error');this._handleEvent('onerror',JSJaCError('500','wait','internal-server-error'));return null;} 
    476472if(typeof(req.rid)!='undefined'&&this._last_requests[req.rid]){if(this._last_requests[req.rid].handled){this.oDbg.log("already handled "+req.rid,2);return null;}else 
    477473this._last_requests[req.rid].handled=true;} 
    478 if(body.getAttribute("type")=="terminate"){this.oDbg.log("session terminated:\n"+r.responseText,1);clearTimeout(this._timeout);clearInterval(this._interval);clearInterval(this._inQto);var condition=body.getAttribute('condition');if(condition=="remote-stream-error") 
     474if(body.getAttribute("type")=="terminate"){this.oDbg.log("session terminated:\n"+r.responseText,1);clearTimeout(this._timeout);clearInterval(this._interval);clearInterval(this._inQto);try{JSJaCCookie.read(this._cookie_prefix+'JSJaC_State').erase();}catch(e){} 
     475this._connected=false;var condition=body.getAttribute('condition');if(condition=="remote-stream-error") 
    479476if(body.getElementsByTagName("conflict").length>0) 
    480477this._setStatus("session-terminate-conflict");if(condition==null) 
    481 condition='session-terminate';this._handleEvent('onerror',JSJaCError('503','cancel',condition));this._connected=false;this.oDbg.log("Disconnected.",1);this._handleEvent('ondisconnect');return null;} 
     478condition='session-terminate';this._handleEvent('onerror',JSJaCError('503','cancel',condition));this.oDbg.log("Aborting remaining connections",4);for(var i=0;i<this._hold+1;i++){try{this._req[i].r.abort();}catch(e){this.oDbg.log(e,1);}} 
     479this.oDbg.log("parseResponse done with terminating",3);this.oDbg.log("Disconnected.",1);this._handleEvent('ondisconnect');return null;} 
    482480this._errcnt=0;return r.responseXML.documentElement;};JSJaCHttpBindingConnection.prototype._reInitStream=function(to,cb,arg){this._reinit=true;cb.call(this,arg);};JSJaCHttpBindingConnection.prototype._resume=function(){if(this._pause==0&&this._rid>=this._last_rid) 
    483481this._rid=this._last_rid-1;this._process();};JSJaCHttpBindingConnection.prototype._setHold=function(hold){if(!hold||isNaN(hold)||hold<0) 
     
    522520var req=new Object();req.r=r;return req;};JSJaCHttpPollingConnection.prototype._suspend=function(){};JSJaCHttpPollingConnection._parseTree=function(s){try{var r=XmlDocument.create("body","foo");if(typeof(r.loadXML)!='undefined'){r.loadXML(s);return r.documentElement;}else if(window.DOMParser) 
    523521return(new DOMParser()).parseFromString(s,"text/xml").documentElement;}catch(e){} 
    524 return null;};var JSJaC={Version:'$Rev: 491 $',require:function(libraryName){document.write('<script type="text/javascript" src="'+libraryName+'"></script>');},load:function(){var includes=['xmlextras','jsextras','crypt','JSJaCConfig','JSJaCConstants','JSJaCCookie','JSJaCJSON','JSJaCJID','JSJaCBuilder','JSJaCPacket','JSJaCError','JSJaCKeys','JSJaCConnection','JSJaCHttpPollingConnection','JSJaCHttpBindingConnection','JSJaCConsoleLogger'];var scripts=document.getElementsByTagName("script");var path='./';for(var i=0;i<scripts.length;i++){if(scripts.item(i).src&&scripts.item(i).src.match(/JSJaC\.js$/)){path=scripts.item(i).src.replace(/JSJaC.js$/,'');break;}} 
     522return null;};var JSJaC={Version:'$Rev$',require:function(libraryName){document.write('<script type="text/javascript" src="'+libraryName+'"></script>');},load:function(){var includes=['xmlextras','jsextras','crypt','JSJaCConfig','JSJaCConstants','JSJaCCookie','JSJaCJSON','JSJaCJID','JSJaCBuilder','JSJaCPacket','JSJaCError','JSJaCKeys','JSJaCConnection','JSJaCHttpPollingConnection','JSJaCHttpBindingConnection','JSJaCConsoleLogger'];var scripts=document.getElementsByTagName("script");var path='./';for(var i=0;i<scripts.length;i++){if(scripts.item(i).src&&scripts.item(i).src.match(/JSJaC\.js$/)){path=scripts.item(i).src.replace(/JSJaC.js$/,'');break;}} 
    525523for(var i=0;i<includes.length;i++) 
    526524this.require(path+includes[i]+'.js');},bind:function(fn,obj,optArg){return function(arg){return fn.apply(obj,[arg,optArg]);};}};if(typeof JSJaCConnection=='undefined') 
  • HelpIM3/branches/chatgroups/htdocs/lib/jsjac/jsjac.uncompressed.js

    r1204 r1435  
    3939 * @fileoverview Collection of functions to make live easier 
    4040 * @author Stefan Strigler 
    41  * @version $Revision: 437 $ 
     41 * @version $Revision$ 
    4242 */ 
    4343 
     
    125125  return (A > B)? A : B; 
    126126}; 
    127 /* Copyright (c) 1998 - 2007, Paul Johnston & Contributors 
     127 
     128Number.min = function(A, B) { 
     129  return (A < B)? A : B; 
     130};/* Copyright (c) 1998 - 2007, Paul Johnston & Contributors 
    128131 * All rights reserved. 
    129132 * 
     
    163166 * methods. 
    164167 * @author Stefan Strigler steve@zeank.in-berlin.de 
    165  * @version $Revision: 482 $ 
     168 * @version $Revision$ 
    166169 */ 
    167170 
     
    926929 * http://webfx.eae.net/dhtml/xmlextras/xmlextras.html 
    927930 * @author Stefan Strigler steve@zeank.in-berlin.de 
    928  * @version $Revision: 499 $ 
     931 * @version $Revision$ 
    929932 */ 
    930933 
     
    14551458 * 
    14561459 * @author Stefan Strigler 
    1457  * @version $Revision: 504 $ 
     1460 * @version $Revision$ 
    14581461 */ 
    14591462 
     
    16771680 * dealing with JIDs 
    16781681 * @author Stefan Strigler 
    1679  * @version $Revision: 437 $ 
     1682 * @version $Revision$ 
    16801683 */ 
    16811684 
     
    19401943 * @fileoverview Contains all Jabber/XMPP packet related classes. 
    19411944 * @author Stefan Strigler steve@zeank.in-berlin.de 
    1942  * @version $Revision: 510 $ 
     1945 * @version $Revision$ 
    19431946 */ 
    19441947 
     
    21162119 */ 
    21172120JSJaCPacket.prototype.getXMLNS = function() { 
    2118   return this.getNode().namespaceURI; 
     2121  return this.getNode().namespaceURI || this.getNode().getAttribute('xmlns'); 
    21192122}; 
    21202123 
     
    21302133    return null; 
    21312134  } 
    2132   
     2135 
    21332136  name = name || '*'; 
    21342137  ns = ns || '*'; 
     
    21422145  if (ns != '*') { 
    21432146    for (var i=0; i<nodes.length; i++) { 
    2144       if (nodes.item(i).namespaceURI == ns) { 
     2147      if (nodes.item(i).namespaceURI == ns || nodes.item(i).getAttribute('xmlns') == ns) { 
    21452148        return nodes.item(i); 
    21462149      } 
     
    22342237}; 
    22352238 
    2236 /** 
    2237  * Replaces this node with given node 
    2238  * @private 
    2239  */ 
    2240 JSJaCPacket.prototype._replaceNode = function(aNode) { 
    2241   // copy attribs 
    2242   for (var i=0; i<aNode.attributes.length; i++) 
    2243     if (aNode.attributes.item(i).nodeName != 'xmlns') 
    2244       this.getNode().setAttribute(aNode.attributes.item(i).nodeName, 
    2245                                   aNode.attributes.item(i).nodeValue); 
    2246  
    2247   // copy children 
    2248   for (var i=0; i<aNode.childNodes.length; i++) 
    2249     if (this.getDoc().importNode) 
    2250       this.getNode().appendChild(this.getDoc().importNode(aNode. 
    2251                                                           childNodes.item(i), 
    2252                                                           true)); 
    2253     else 
    2254       this.getNode().appendChild(aNode.childNodes.item(i).cloneNode(true)); 
    2255 }; 
    2256   
     2239 
     2240if (document.ELEMENT_NODE == null) { 
     2241  document.ELEMENT_NODE = 1; 
     2242  document.ATTRIBUTE_NODE = 2; 
     2243  document.TEXT_NODE = 3; 
     2244  document.CDATA_SECTION_NODE = 4; 
     2245  document.ENTITY_REFERENCE_NODE = 5; 
     2246  document.ENTITY_NODE = 6; 
     2247  document.PROCESSING_INSTRUCTION_NODE = 7; 
     2248  document.COMMENT_NODE = 8; 
     2249  document.DOCUMENT_NODE = 9; 
     2250  document.DOCUMENT_TYPE_NODE = 10; 
     2251  document.DOCUMENT_FRAGMENT_NODE = 11; 
     2252  document.NOTATION_NODE = 12; 
     2253} 
     2254 
     2255/** 
     2256 * import node into this packets document 
     2257 * @private 
     2258 */ 
     2259JSJaCPacket.prototype._importNode = function(node, allChildren) { 
     2260  switch (node.nodeType) { 
     2261  case document.ELEMENT_NODE: 
     2262 
     2263  if (this.getDoc().createElementNS) { 
     2264    var newNode = this.getDoc().createElementNS(node.namespaceURI, node.nodeName); 
     2265  } else { 
     2266    var newNode = this.getDoc().createElement(node.nodeName); 
     2267  } 
     2268 
     2269  /* does the node have any attributes to add? */ 
     2270  if (node.attributes && node.attributes.length > 0) 
     2271    for (var i = 0, il = node.attributes.length;i < il; i++) { 
     2272      var attr = node.attributes.item(i); 
     2273      if (attr.nodeName == 'xmlns' && newNode.getAttribute('xmlns') != null ) continue; 
     2274      if (newNode.setAttributeNS && attr.namespaceURI) { 
     2275        newNode.setAttributeNS(attr.namespaceURI, 
     2276                               attr.nodeName, 
     2277                               attr.nodeValue); 
     2278      } else { 
     2279        newNode.setAttribute(attr.nodeName, 
     2280                             attr.nodeValue); 
     2281      } 
     2282    } 
     2283  /* are we going after children too, and does the node have any? */ 
     2284  if (allChildren && node.childNodes && node.childNodes.length > 0) { 
     2285    for (var i = 0, il = node.childNodes.length; i < il; i++) { 
     2286      newNode.appendChild(this._importNode(node.childNodes.item(i), allChildren)); 
     2287    } 
     2288  } 
     2289  return newNode; 
     2290  break; 
     2291  case document.TEXT_NODE: 
     2292  case document.CDATA_SECTION_NODE: 
     2293  case document.COMMENT_NODE: 
     2294  return this.getDoc().createTextNode(node.nodeValue); 
     2295  break; 
     2296  } 
     2297}; 
     2298 
    22572299/** 
    22582300 * Set node value of a child node 
     
    22772319  } 
    22782320  return aNode; 
    2279 }; 
    2280  
    2281 /** 
    2282  * Create an empty node with the given nodeName and the given xmlns 
    2283  * @private 
    2284  */ 
    2285 JSJaCPacket.prototype._setEmptyChildNode = function(nodeName, xmlns) { 
    2286   var child; 
    2287   try { 
    2288     child = this.getDoc().createElementNS(xmlns,nodeName); 
    2289   } catch (e) { 
    2290     // fallback 
    2291     child = this.getDoc().createElement(nodeName); 
    2292   } 
    2293   if (child && child.getAttribute('xmlns') != xmlns) // fix opera 8.5x 
    2294     child.setAttribute('xmlns',xmlns); 
    2295   this.getNode().appendChild(child); 
    2296   return child; 
    22972321}; 
    22982322 
     
    24772501 */ 
    24782502JSJaCIQ.prototype.setQuery = function(xmlns) { 
    2479   return this._setEmptyChildNode('query', xmlns); 
     2503  var query; 
     2504  try { 
     2505    query = this.getDoc().createElementNS(xmlns,'query'); 
     2506  } catch (e) { 
     2507    query = this.getDoc().createElement('query'); 
     2508        query.setAttribute('xmlns',xmlns); 
     2509  } 
     2510  this.getNode().appendChild(query); 
     2511  return query; 
    24802512}; 
    24812513 
     
    24942526 */ 
    24952527JSJaCIQ.prototype.getQueryXMLNS = function() { 
    2496   if (this.getQuery()) 
    2497     return this.getQuery().namespaceURI; 
    2498   else 
     2528  if (this.getQuery()) { 
     2529    return this.getQuery().namespaceURI || this.getQuery().getAttribute('xmlns'); 
     2530  } else { 
    24992531    return null; 
     2532  } 
    25002533}; 
    25012534 
     
    25742607}; 
    25752608/** 
    2576  * Sets a 'chat-state' attribute for this message, 
    2577  * see XEP-0085 
    2578  * @param {String} state to append to this message 
    2579  * @return this message if state is set, otherwise null 
    2580  * @type JSJaCMessage 
    2581  */ 
    2582 JSJaCMessage.prototype.setState = function (state) { 
    2583   var validState = false; 
    2584   for (var i=0; i<JSJACPACKET_CHAT_STATES.length; i++) { 
    2585     if (JSJACPACKET_CHAT_STATES[i] == state) 
    2586       validState = true; 
    2587     if (this.getChild(JSJACPACKET_CHAT_STATES[i])) 
    2588       return null; 
    2589   } 
    2590   if (!validState) 
    2591     return null; 
    2592   this._setEmptyChildNode(state, NS_CHAT_STATES); 
    2593   return this; 
    2594 }; 
    2595 /** 
    25962609 * Gets the 'thread' identifier for this message 
    25972610 * @return A thread identifier 
     
    26172630  return this.getChildVal('subject') 
    26182631}; 
    2619 /** 
    2620  * Gets the'chat-state' appended to the message, 
    2621  * see XEP-0085 
    2622  * @return chat state 
    2623  * @type String 
    2624  */ 
    2625 JSJaCMessage.prototype.getState = function () { 
    2626   var state; 
    2627   for (var i=0; i<JSJACPACKET_CHAT_STATES.length; i++) 
    2628     if (this.getChild(JSJACPACKET_CHAT_STATES[i])) 
    2629       return JSJACPACKET_CHAT_STATES[i]; 
    2630   return null; 
    2631 }; 
     2632 
    26322633 
    26332634/** 
     
    26432644 */ 
    26442645JSJaCPacket.wrapNode = function(node) { 
    2645   var aNode = null; 
    2646  
    2647   try { 
    2648     switch (node.nodeName.toLowerCase()) { 
    2649     case 'presence': 
    2650       aNode = new JSJaCPresence(); 
     2646  var oPacket = null; 
     2647 
     2648  switch (node.nodeName.toLowerCase()) { 
     2649  case 'presence': 
     2650      oPacket = new JSJaCPresence(); 
    26512651      break; 
    2652     case 'message': 
    2653       aNode = new JSJaCMessage(); 
     2652  case 'message': 
     2653      oPacket = new JSJaCMessage(); 
    26542654      break; 
    2655     case 'iq': 
    2656       aNode = new JSJaCIQ(); 
     2655  case 'iq': 
     2656      oPacket = new JSJaCIQ(); 
    26572657      break; 
    2658     } 
    2659  
    2660     aNode._replaceNode(node); 
    2661   } catch(e) { } 
    2662   return aNode; 
    2663 }; 
    2664  
     2658  } 
     2659 
     2660  if (oPacket) { 
     2661    oPacket.getDoc().replaceChild(oPacket._importNode(node, true), 
     2662                                  oPacket.getNode()); 
     2663  } 
     2664 
     2665  return oPacket; 
     2666}; 
     2667/** 
     2668 * Gets the'chat-state' appended to the message, 
     2669 * see XEP-0085 
     2670 * @return chat state 
     2671 * @type String 
     2672 */ 
     2673JSJaCMessage.prototype.getState = function () { 
     2674  var stateEl = this.getChild('*', NS_CHAT_STATES); 
     2675  if (stateEl) 
     2676    return stateEl.tagName; 
     2677  else 
     2678    return null; 
     2679}; 
     2680/** 
     2681 * Sets a 'chat-state' attribute for this message, 
     2682 * see XEP-0085 
     2683 * @param {String} state to append to this message 
     2684 * @return this message if state is set, otherwise null 
     2685 * @type JSJaCMessage 
     2686 */ 
     2687JSJaCMessage.prototype.setState = function (state) { 
     2688  if (this.getChild('*', NS_CHAT_STATES)) 
     2689    return null; 
     2690  var validState = false; 
     2691  for (var i=0; i<JSJACPACKET_CHAT_STATES.length; i++) { 
     2692    if (JSJACPACKET_CHAT_STATES[i] == state) 
     2693      validState = true; 
     2694  } 
     2695  if (!validState) 
     2696    return null; 
     2697  this.appendNode(state, {xmlns: NS_CHAT_STATES}); 
     2698  return this; 
     2699}; 
    26652700/** 
    26662701 * @fileoverview Contains all things in common for all subtypes of connections 
    26672702 * supported. 
    26682703 * @author Stefan Strigler steve@zeank.in-berlin.de 
    2669  * @version $Revision: 512 $ 
     2704 * @version $Revision$ 
    26702705 */ 
    26712706 
     
    28462881 
    28472882  var slot = this._getFreeSlot(); 
     2883 
    28482884  this._req[slot] = this._setupRequest(true); 
    2849   this._req[slot].r.onreadystatechange =  
    2850   JSJaC.bind(function() { 
    2851                if (this._req[slot].r.readyState == 4) { 
    2852                  this.oDbg.log("async recv (disconnect): "+this._req[slot].r.responseText,4); 
    2853                  this._connected = false; 
    2854                  clearInterval(this._interval); 
    2855                  clearInterval(this._inQto); 
    2856                  if (this._timeout) 
    2857                    clearTimeout(this._timeout); // remove timer 
    2858  
    2859                  try { 
    2860                    JSJaCCookie.read(this._cookie_prefix+'JSJaC_State').erase(); 
    2861                  } catch (e) {} 
    2862  
    2863                  this.oDbg.log("Disconnected: "+this._req[slot].r.responseText,2); 
    2864                  this.oDbg.log("Aborting remaining connections",4); 
    2865                  for (var i=0; i<this._hold+1; i++) 
    2866                    if (typeof(this._req[i]) != 'undefined' || typeof(this._req[i].r) != 'undefined' ) 
    2867                      this._req[i].r.abort(); 
    2868                  this._handleEvent('ondisconnect'); 
    2869                } 
    2870              }, this); 
     2885 
     2886  this._req[slot].r.onreadystatechange = JSJaC.bind(function() { 
     2887    try { 
     2888      if (this._req[slot].r.readyState == 4) { 
     2889        this.oDbg.log("async recv: "+this._req[slot].r.responseText,4); 
     2890        this._handleResponse(this._req[slot]); 
     2891      } 
     2892    } catch(e) { this.oDbg.log(e, 1); } 
     2893  }, this); 
    28712894 
    28722895  request = this._getRequestString(false, true); 
    28732896 
    2874   if (typeof(this._rid) != 'undefined') // remember request id if any 
    2875     this._req[slot].rid = this._rid; 
    2876   this.oDbg.log("Disconnecting: " + request,4); 
     2897  this.oDbg.log("Disconnecting: " + request, 4); 
    28772898  this._req[slot].r.send(request); 
    2878  
    28792899}; 
    28802900 
     
    30223042 * @param {Function} handler The handler to be called when event occurs. If your handler returns 'true' it cancels bubbling of the event. No other registered handlers for this event will be fired. 
    30233043 */ 
    3024 JSJaCConnection.prototype.registerIQGet = 
    3025   function(childName, childNS, handler) { 
     3044JSJaCConnection.prototype.registerIQGet = function(childName, childNS, handler) { 
    30263045  this.registerHandler('iq', childName, childNS, 'get', handler); 
    30273046}; 
     
    30373056 * @param {Function} handler The handler to be called when event occurs. If your handler returns 'true' it cancels bubbling of the event. No other registered handlers for this event will be fired. 
    30383057 */ 
    3039 JSJaCConnection.prototype.registerIQSet = 
    3040   function(childName, childNS, handler) { 
     3058JSJaCConnection.prototype.registerIQSet = function(childName, childNS, handler) { 
    30413059  this.registerHandler('iq', childName, childNS, 'set', handler); 
    30423060}; 
     
    31583176 
    31593177  handlers = handlers || {}; 
    3160   var error_handler = handlers.error_handler || function(aIq) { 
    3161     this.oDbg.log(aIq.xml(), 1); 
    3162   }; 
     3178    var error_handler = handlers.error_handler || JSJaC.bind(function(aIq) { 
     3179        this.oDbg.log(aIq.xml(), 1); 
     3180    }, this); 
    31633181  
    3164   var result_handler = handlers.result_handler ||  function(aIq) { 
    3165     this.oDbg.log(aIq.xml(), 2); 
    3166   }; 
    3167   // unsure, what's the use of this? 
    3168   var default_handler = handlers.default_handler || function(aIq) { 
    3169     this.oDbg.log(aIq.xml(), 2); 
    3170   }; 
     3182    var result_handler = handlers.result_handler ||  JSJaC.bind(function(aIq) { 
     3183        this.oDbg.log(aIq.xml(), 2); 
     3184    }, this); 
    31713185 
    31723186  var iqHandler = function(aIq, arg) { 
     
    31783192      result_handler(aIq, arg); 
    31793193      break; 
    3180       default: // may it be? 
    3181       default_handler(aIq, arg); 
    31823194    } 
    31833195  }; 
     
    35993611JSJaCConnection.prototype._doStreamBind = function() { 
    36003612  var iq = new JSJaCIQ(); 
    3601   iq.setIQ(this.domain,'set','bind_1'); 
     3613  iq.setIQ(null,'set','bind_1'); 
    36023614  iq.appendNode("bind", {xmlns: "urn:ietf:params:xml:ns:xmpp-bind"}, 
    36033615                [["resource", this.resource]]); 
     
    37003712      this.oDbg.log("handling "+pID,3); 
    37013713      try { 
    3702         if (this._regIDs[i].cb.call(this, aJSJaCPacket,this._regIDs[i].arg) === false) { 
     3714        if (this._regIDs[i].cb.call(this, aJSJaCPacket, this._regIDs[i].arg) === false) { 
    37033715          // don't unregister 
    37043716          return false; 
     
    37093721      } catch (e) { 
    37103722        // broken handler? 
    3711         this.oDbg.log(e.name+": "+ e.message); 
     3723        this.oDbg.log(e.name+": "+ e.message, 1); 
    37123724        this._unregisterPID(pID); 
    37133725        return true; 
     
    38403852  this._req[slot].r.onreadystatechange =  
    38413853  JSJaC.bind(function() { 
    3842                if (!this.connected()) 
    3843                  return; 
    38443854               if (this._req[slot].r.readyState == 4) { 
    38453855                 this._setStatus('processing'); 
    38463856                 this.oDbg.log("async recv: "+this._req[slot].r.responseText,4); 
    38473857                 this._handleResponse(this._req[slot]); 
     3858 
     3859                 if (!this.connected()) 
     3860                   return; 
     3861 
    38483862                 // schedule next tick 
    38493863                 if (this._pQueue.length) { 
     
    39713985 * @fileoverview All stuff related to HTTP Binding 
    39723986 * @author Stefan Strigler steve@zeank.in-berlin.de 
    3973  * @version $Revision: 513 $ 
     3987 * @version $Revision$ 
    39743988 */ 
    39753989 
     
    40264040 */ 
    40274041JSJaCHttpBindingConnection.prototype.inherit = function(oArg) { 
    4028   this.domain = oArg.domain || 'localhost'; 
    4029   this.username = oArg.username; 
    4030   this.resource = oArg.resource; 
     4042  if (oArg.jid) { 
     4043    var oJid = new JSJaCJID(oArg.jid); 
     4044    this.domain = oJid.getDomain(); 
     4045    this.username = oJid.getNode(); 
     4046    this.resource = oJid.getResource(); 
     4047  } else { 
     4048    this.domain = oArg.domain || 'localhost'; 
     4049    this.username = oArg.username; 
     4050    this.resource = oArg.resource; 
     4051  } 
    40314052  this._sid = oArg.sid; 
    40324053  this._rid = oArg.rid; 
     
    42664287 
    42674288  if (body.getAttribute('maxpause')) 
    4268     this._pause = Number.max(body.getAttribute('maxpause'), JSJACHBC_MAXPAUSE); 
     4289    this._pause = Number.min(body.getAttribute('maxpause'), JSJACHBC_MAXPAUSE); 
    42694290 
    42704291  // must be done after response attributes have been collected 
     
    43124333        return null; 
    43134334      } 
    4314       this.oDbg.log("repeating ("+this._errcnt+")",1); 
    43154335      
    4316       this._setStatus('proto_error_fallback'); 
     4336      if (this.connected()) { 
     4337        this.oDbg.log("repeating ("+this._errcnt+")",1); 
     4338        this._setStatus('proto_error_fallback'); 
    43174339      
    4318       // schedule next tick 
    4319       setTimeout(JSJaC.bind(this._resume, this), 
    4320                  this.getPollInterval()); 
     4340        // schedule next tick 
     4341        setTimeout(JSJaC.bind(this._resume, this), 
     4342                   this.getPollInterval()); 
     4343      } 
    43214344      
    43224345      return null; 
     
    43244347  } catch (e) { 
    43254348    this.oDbg.log("XMLHttpRequest error: status not available", 1); 
    4326         this._errcnt++; 
    4327         if (this._errcnt > JSJAC_ERR_COUNT) { 
    4328           // abort 
    4329           this._abort(); 
    4330         } else { 
    4331           this.oDbg.log("repeating ("+this._errcnt+")",1); 
     4349          this._errcnt++; 
     4350          if (this._errcnt > JSJAC_ERR_COUNT) { 
     4351            // abort 
     4352            this._abort(); 
     4353          } else { 
     4354      if (this.connected()) { 
     4355              this.oDbg.log("repeating ("+this._errcnt+")",1); 
    43324356      
    4333           this._setStatus('proto_error_fallback'); 
     4357              this._setStatus('proto_error_fallback'); 
    43344358      
    4335           // schedule next tick 
    4336           setTimeout(JSJaC.bind(this._resume, this), 
    4337                      this.getPollInterval());  
     4359              // schedule next tick 
     4360              setTimeout(JSJaC.bind(this._resume, this), 
     4361                   this.getPollInterval());  
     4362      } 
    43384363    } 
    43394364    return null; 
     
    43554380    this._setStatus('internal_server_error'); 
    43564381    this._handleEvent('onerror', 
    4357                                           JSJaCError('500','wait','internal-server-error')); 
     4382                      JSJaCError('500','wait','internal-server-error')); 
    43584383 
    43594384    return null; 
     
    43764401    clearInterval(this._interval); 
    43774402    clearInterval(this._inQto); 
     4403 
     4404    try { 
     4405      JSJaCCookie.read(this._cookie_prefix+'JSJaC_State').erase(); 
     4406    } catch (e) {} 
     4407 
     4408    this._connected = false; 
    43784409 
    43794410    var condition = body.getAttribute('condition'); 
     
    43844415      condition = 'session-terminate'; 
    43854416    this._handleEvent('onerror',JSJaCError('503','cancel',condition)); 
    4386     this._connected = false; 
     4417 
     4418    this.oDbg.log("Aborting remaining connections",4); 
     4419 
     4420    for (var i=0; i<this._hold+1; i++) { 
     4421      try { 
     4422        this._req[i].r.abort(); 
     4423      } catch(e) { this.oDbg.log(e, 1); } 
     4424    } 
     4425 
     4426    this.oDbg.log("parseResponse done with terminating", 3); 
     4427 
    43874428    this.oDbg.log("Disconnected.",1); 
    4388     try { 
    4389       JSJaCCookie.read(this._cookie_prefix+'JSJaC_State').erase(); 
    4390     } catch (e) {} 
    4391     this.oDbg.log("Aborting remaining connections",4); 
    4392     for (var i=0; i<this._hold+1; i++) 
    4393       if (typeof(this._req[i]) != 'undefined' || typeof(this._req[i].r) != 'undefined' ) 
    4394         this._req[i].r.abort(); 
    43954429    this._handleEvent('ondisconnect'); 
     4430 
    43964431    return null; 
    43974432  } 
     
    44974532 * @fileoverview All stuff related to HTTP Polling 
    44984533 * @author Stefan Strigler steve@zeank.in-berlin.de 
    4499  * @version $Revision: 511 $ 
     4534 * @version $Revision$ 
    45004535 */ 
    45014536 
     
    48314866 * and modified to break it. 
    48324867 * @author Stefan Strigler steve@zeank.in-berlin.de  
    4833  * @version $Revision: 491 $ 
     4868 * @version $Revision$ 
    48344869 */ 
    48354870 
    48364871var JSJaC = { 
    4837   Version: '$Rev: 491 $', 
     4872  Version: '$Rev$', 
    48384873  require: function(libraryName) { 
    48394874    // inserting via DOM fails in Safari 2.0, so brute force approach