/* Gibberish-AES 
* A lightweight Javascript Libray for OpenSSL compatible AES CBC encryption.
*
* Author: Mark Percival
* Email: mark@mpercival.com
* Copyright: Mark Percival - http://mpercival.com 2008
* Josh Davis - http://www.josh-davis.org/ecmaScrypt 2007
* Chris Veness - http://www.movable-type.co.uk/scripts/aes.html 2007
* Michel I. Gallant - http://www.jensign.com/
*
* License: MIT
* Usage: Gibberish.encrypt("secret", "password", 256)
* Outputs: AES Encrypted text encoded in Base64
*/
var GibberishAES=(function(){var m=14,s=8,f=false,L=function(M){try{return unescape(encodeURIComponent(M))}catch(N){throw"Error on UTF-8 encode"}},I=function(M){try{return decodeURIComponent(escape(M))}catch(N){throw ("Bad Key")}},z=function(O){var P=[],N,M;if(O.length<16){N=16-O.length;P=[N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N]}for(M=0;M<O.length;M++){P[M]=O[M]}return P},h=function(Q,O){var M="",P,N;if(O){P=Q[15];if(P>16){throw ("Decryption error: Maybe bad key")}if(P==16){return""}for(N=0;N<16-P;N++){M+=String.fromCharCode(Q[N])}}else{for(N=0;N<16;N++){M+=String.fromCharCode(Q[N])}}return M},o=function(O){var M="",N;for(N=0;N<O.length;N++){M+=(O[N]<16?"0":"")+O[N].toString(16)}return M},A=function(N){var M=[];N.replace(/(..)/g,function(O){M.push(parseInt(O,16))});return M},l=function(M){M=L(M);var O=[],N;for(N=0;N<M.length;N++){O[N]=M.charCodeAt(N)}return O},c=function(M){switch(M){case 128:m=10;s=4;break;case 192:m=12;s=6;break;case 256:m=14;s=8;break;default:throw ("Invalid Key Size Specified:"+M)}},q=function(N){var M=[],O;for(O=0;O<N;O++){M=M.concat(Math.floor(Math.random()*256))}return M},n=function(Q,S){var T=m>=12?3:2,R=[],O=[],M=[],U=[],N=Q.concat(S),P;M[0]=GibberishAES.Hash.MD5(N);U=M[0];for(P=1;P<T;P++){M[P]=GibberishAES.Hash.MD5(M[P-1].concat(N));U=U.concat(M[P])}R=U.slice(0,4*s);O=U.slice(4*s,4*s+16);return{key:R,iv:O}},b=function(Q,P,N){P=D(P);var S=Math.ceil(Q.length/16),R=[],O,M=[];for(O=0;O<S;O++){R[O]=z(Q.slice(O*16,O*16+16))}if(Q.length%16===0){R.push([16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16]);S++}for(O=0;O<R.length;O++){R[O]=(O===0)?y(R[O],N):y(R[O],M[O-1]);M[O]=d(R[O],P)}return M},v=function(Q,S,P){S=D(S);var T=Q.length/16,N=[],R,M=[],O="";for(R=0;R<T;R++){N.push(Q.slice(R*16,(R+1)*16))}for(R=N.length-1;R>=0;R--){M[R]=C(N[R],S);M[R]=(R===0)?y(M[R],P):y(M[R],N[R-1])}for(R=0;R<T-1;R++){O+=h(M[R])}O+=h(M[R],true);return I(O)},d=function(P,O){f=false;var N=G(P,O,0),M;for(M=1;M<(m+1);M++){N=H(N);N=a(N);if(M<m){N=K(N)}N=G(N,O,M)}return N},C=function(P,O){f=true;var N=G(P,O,m),M;for(M=m-1;M>-1;M--){N=a(N);N=H(N);N=G(N,O,M);if(M>0){N=K(N)}}return N},H=function(P){var O=f?x:J,M=[],N;for(N=0;N<16;N++){M[N]=O[P[N]]}return M},a=function(P){var M=[],O=f?[0,13,10,7,4,1,14,11,8,5,2,15,12,9,6,3]:[0,5,10,15,4,9,14,3,8,13,2,7,12,1,6,11],N;for(N=0;N<16;N++){M[N]=P[O[N]]}return M},K=function(N){var M=[],O;if(!f){for(O=0;O<4;O++){M[O*4]=w[N[O*4]]^e[N[1+O*4]]^N[2+O*4]^N[3+O*4];M[1+O*4]=N[O*4]^w[N[1+O*4]]^e[N[2+O*4]]^N[3+O*4];M[2+O*4]=N[O*4]^N[1+O*4]^w[N[2+O*4]]^e[N[3+O*4]];M[3+O*4]=e[N[O*4]]^N[1+O*4]^N[2+O*4]^w[N[3+O*4]]}}else{for(O=0;O<4;O++){M[O*4]=k[N[O*4]]^i[N[1+O*4]]^B[N[2+O*4]]^g[N[3+O*4]];M[1+O*4]=g[N[O*4]]^k[N[1+O*4]]^i[N[2+O*4]]^B[N[3+O*4]];M[2+O*4]=B[N[O*4]]^g[N[1+O*4]]^k[N[2+O*4]]^i[N[3+O*4]];M[3+O*4]=i[N[O*4]]^B[N[1+O*4]]^g[N[2+O*4]]^k[N[3+O*4]]}}return M},G=function(P,Q,N){var M=[],O;for(O=0;O<16;O++){M[O]=P[O]^Q[N][O]}return M},y=function(P,O){var M=[],N;for(N=0;N<16;N++){M[N]=P[N]^O[N]}return M},D=function(R){var M=[],N=[],Q,S,P,T=[],O;for(Q=0;Q<s;Q++){S=[R[4*Q],R[4*Q+1],R[4*Q+2],R[4*Q+3]];M[Q]=S}for(Q=s;Q<(4*(m+1));Q++){M[Q]=[];for(P=0;P<4;P++){N[P]=M[Q-1][P]}if(Q%s===0){N=u(t(N));N[0]^=E[Q/s-1]}else{if(s>6&&Q%s==4){N=u(N)}}for(P=0;P<4;P++){M[Q][P]=M[Q-s][P]^N[P]}}for(Q=0;Q<(m+1);Q++){T[Q]=[];for(O=0;O<4;O++){T[Q].push(M[Q*4+O][0],M[Q*4+O][1],M[Q*4+O][2],M[Q*4+O][3])}}return T},u=function(M){for(var N=0;N<4;N++){M[N]=J[M[N]]}return M},t=function(M){var O=M[0],N;for(N=0;N<4;N++){M[N]=M[N+1]}M[3]=O;return M},J=[99,124,119,123,242,107,111,197,48,1,103,43,254,215,171,118,202,130,201,125,250,89,71,240,173,212,162,175,156,164,114,192,183,253,147,38,54,63,247,204,52,165,229,241,113,216,49,21,4,199,35,195,24,150,5,154,7,18,128,226,235,39,178,117,9,131,44,26,27,110,90,160,82,59,214,179,41,227,47,132,83,209,0,237,32,252,177,91,106,203,190,57,74,76,88,207,208,239,170,251,67,77,51,133,69,249,2,127,80,60,159,168,81,163,64,143,146,157,56,245,188,182,218,33,16,255,243,210,205,12,19,236,95,151,68,23,196,167,126,61,100,93,25,115,96,129,79,220,34,42,144,136,70,238,184,20,222,94,11,219,224,50,58,10,73,6,36,92,194,211,172,98,145,149,228,121,231,200,55,109,141,213,78,169,108,86,244,234,101,122,174,8,186,120,37,46,28,166,180,198,232,221,116,31,75,189,139,138,112,62,181,102,72,3,246,14,97,53,87,185,134,193,29,158,225,248,152,17,105,217,142,148,155,30,135,233,206,85,40,223,140,161,137,13,191,230,66,104,65,153,45,15,176,84,187,22],x=[82,9,106,213,48,54,165,56,191,64,163,158,129,243,215,251,124,227,57,130,155,47,255,135,52,142,67,68,196,222,233,203,84,123,148,50,166,194,35,61,238,76,149,11,66,250,195,78,8,46,161,102,40,217,36,178,118,91,162,73,109,139,209,37,114,248,246,100,134,104,152,22,212,164,92,204,93,101,182,146,108,112,72,80,253,237,185,218,94,21,70,87,167,141,157,132,144,216,171,0,140,188,211,10,247,228,88,5,184,179,69,6,208,44,30,143,202,63,15,2,193,175,189,3,1,19,138,107,58,145,17,65,79,103,220,234,151,242,207,206,240,180,230,115,150,172,116,34,231,173,53,133,226,249,55,232,28,117,223,110,71,241,26,113,29,41,197,137,111,183,98,14,170,24,190,27,252,86,62,75,198,210,121,32,154,219,192,254,120,205,90,244,31,221,168,51,136,7,199,49,177,18,16,89,39,128,236,95,96,81,127,169,25,181,74,13,45,229,122,159,147,201,156,239,160,224,59,77,174,42,245,176,200,235,187,60,131,83,153,97,23,43,4,126,186,119,214,38,225,105,20,99,85,33,12,125],E=[1,2,4,8,16,32,64,128,27,54,108,216,171,77,154,47,94,188,99,198,151,53,106,212,179,125,250,239,197,145],w=[0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86,88,90,92,94,96,98,100,102,104,106,108,110,112,114,116,118,120,122,124,126,128,130,132,134,136,138,140,142,144,146,148,150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,182,184,186,188,190,192,194,196,198,200,202,204,206,208,210,212,214,216,218,220,222,224,226,228,230,232,234,236,238,240,242,244,246,248,250,252,254,27,25,31,29,19,17,23,21,11,9,15,13,3,1,7,5,59,57,63,61,51,49,55,53,43,41,47,45,35,33,39,37,91,89,95,93,83,81,87,85,75,73,79,77,67,65,71,69,123,121,127,125,115,113,119,117,107,105,111,109,99,97,103,101,155,153,159,157,147,145,151,149,139,137,143,141,131,129,135,133,187,185,191,189,179,177,183,181,171,169,175,173,163,161,167,165,219,217,223,221,211,209,215,213,203,201,207,205,195,193,199,197,251,249,255,253,243,241,247,245,235,233,239,237,227,225,231,229],e=[0,3,6,5,12,15,10,9,24,27,30,29,20,23,18,17,48,51,54,53,60,63,58,57,40,43,46,45,36,39,34,33,96,99,102,101,108,111,106,105,120,123,126,125,116,119,114,113,80,83,86,85,92,95,90,89,72,75,78,77,68,71,66,65,192,195,198,197,204,207,202,201,216,219,222,221,212,215,210,209,240,243,246,245,252,255,250,249,232,235,238,237,228,231,226,225,160,163,166,165,172,175,170,169,184,187,190,189,180,183,178,177,144,147,150,149,156,159,154,153,136,139,142,141,132,135,130,129,155,152,157,158,151,148,145,146,131,128,133,134,143,140,137,138,171,168,173,174,167,164,161,162,179,176,181,182,191,188,185,186,251,248,253,254,247,244,241,242,227,224,229,230,239,236,233,234,203,200,205,206,199,196,193,194,211,208,213,214,223,220,217,218,91,88,93,94,87,84,81,82,67,64,69,70,79,76,73,74,107,104,109,110,103,100,97,98,115,112,117,118,127,124,121,122,59,56,61,62,55,52,49,50,35,32,37,38,47,44,41,42,11,8,13,14,7,4,1,2,19,16,21,22,31,28,25,26],g=[0,9,18,27,36,45,54,63,72,65,90,83,108,101,126,119,144,153,130,139,180,189,166,175,216,209,202,195,252,245,238,231,59,50,41,32,31,22,13,4,115,122,97,104,87,94,69,76,171,162,185,176,143,134,157,148,227,234,241,248,199,206,213,220,118,127,100,109,82,91,64,73,62,55,44,37,26,19,8,1,230,239,244,253,194,203,208,217,174,167,188,181,138,131,152,145,77,68,95,86,105,96,123,114,5,12,23,30,33,40,51,58,221,212,207,198,249,240,235,226,149,156,135,142,177,184,163,170,236,229,254,247,200,193,218,211,164,173,182,191,128,137,146,155,124,117,110,103,88,81,74,67,52,61,38,47,16,25,2,11,215,222,197,204,243,250,225,232,159,150,141,132,187,178,169,160,71,78,85,92,99,106,113,120,15,6,29,20,43,34,57,48,154,147,136,129,190,183,172,165,210,219,192,201,246,255,228,237,10,3,24,17,46,39,60,53,66,75,80,89,102,111,116,125,161,168,179,186,133,140,151,158,233,224,251,242,205,196,223,214,49,56,35,42,21,28,7,14,121,112,107,98,93,84,79,70],i=[0,11,22,29,44,39,58,49,88,83,78,69,116,127,98,105,176,187,166,173,156,151,138,129,232,227,254,245,196,207,210,217,123,112,109,102,87,92,65,74,35,40,53,62,15,4,25,18,203,192,221,214,231,236,241,250,147,152,133,142,191,180,169,162,246,253,224,235,218,209,204,199,174,165,184,179,130,137,148,159,70,77,80,91,106,97,124,119,30,21,8,3,50,57,36,47,141,134,155,144,161,170,183,188,213,222,195,200,249,242,239,228,61,54,43,32,17,26,7,12,101,110,115,120,73,66,95,84,247,252,225,234,219,208,205,198,175,164,185,178,131,136,149,158,71,76,81,90,107,96,125,118,31,20,9,2,51,56,37,46,140,135,154,145,160,171,182,189,212,223,194,201,248,243,238,229,60,55,42,33,16,27,6,13,100,111,114,121,72,67,94,85,1,10,23,28,45,38,59,48,89,82,79,68,117,126,99,104,177,186,167,172,157,150,139,128,233,226,255,244,197,206,211,216,122,113,108,103,86,93,64,75,34,41,52,63,14,5,24,19,202,193,220,215,230,237,240,251,146,153,132,143,190,181,168,163],B=[0,13,26,23,52,57,46,35,104,101,114,127,92,81,70,75,208,221,202,199,228,233,254,243,184,181,162,175,140,129,150,155,187,182,161,172,143,130,149,152,211,222,201,196,231,234,253,240,107,102,113,124,95,82,69,72,3,14,25,20,55,58,45,32,109,96,119,122,89,84,67,78,5,8,31,18,49,60,43,38,189,176,167,170,137,132,147,158,213,216,207,194,225,236,251,246,214,219,204,193,226,239,248,245,190,179,164,169,138,135,144,157,6,11,28,17,50,63,40,37,110,99,116,121,90,87,64,77,218,215,192,205,238,227,244,249,178,191,168,165,134,139,156,145,10,7,16,29,62,51,36,41,98,111,120,117,86,91,76,65,97,108,123,118,85,88,79,66,9,4,19,30,61,48,39,42,177,188,171,166,133,136,159,146,217,212,195,206,237,224,247,250,183,186,173,160,131,142,153,148,223,210,197,200,235,230,241,252,103,106,125,112,83,94,73,68,15,2,21,24,59,54,33,44,12,1,22,27,56,53,34,47,100,105,126,115,80,93,74,71,220,209,198,203,232,229,242,255,180,185,174,163,128,141,154,151],k=[0,14,28,18,56,54,36,42,112,126,108,98,72,70,84,90,224,238,252,242,216,214,196,202,144,158,140,130,168,166,180,186,219,213,199,201,227,237,255,241,171,165,183,185,147,157,143,129,59,53,39,41,3,13,31,17,75,69,87,89,115,125,111,97,173,163,177,191,149,155,137,135,221,211,193,207,229,235,249,247,77,67,81,95,117,123,105,103,61,51,33,47,5,11,25,23,118,120,106,100,78,64,82,92,6,8,26,20,62,48,34,44,150,152,138,132,174,160,178,188,230,232,250,244,222,208,194,204,65,79,93,83,121,119,101,107,49,63,45,35,9,7,21,27,161,175,189,179,153,151,133,139,209,223,205,195,233,231,245,251,154,148,134,136,162,172,190,176,234,228,246,248,210,220,206,192,122,116,102,104,66,76,94,80,10,4,22,24,50,60,46,32,236,226,240,254,212,218,200,198,156,146,128,142,164,170,184,182,12,2,16,30,52,58,40,38,124,114,96,110,68,74,88,86,55,57,43,37,15,1,19,29,71,73,91,85,127,113,99,109,215,217,203,197,239,225,243,253,167,169,187,181,159,145,131,141],p=function(O,S){var R=q(8),T=n(l(S),R),Q=T.key,N=T.iv,M,P=[[83,97,108,116,101,100,95,95].concat(R)];O=l(O);M=b(O,Q,N);M=P.concat(M);return F.encode(M)},r=function(O,R){var N=F.decode(O),Q=N.slice(8,16),S=n(l(R),Q),P=S.key,M=S.iv;N=N.slice(16,N.length);O=v(N,P,M);return O},j=function(ac){function X(aB,aA){return(aB<<aA)|(aB>>>(32-aA))}function ah(aE,aB){var aG,aA,aD,aF,aC;aD=(aE&2147483648);aF=(aB&2147483648);aG=(aE&1073741824);aA=(aB&1073741824);aC=(aE&1073741823)+(aB&1073741823);if(aG&aA){return(aC^2147483648^aD^aF)}if(aG|aA){if(aC&1073741824){return(aC^3221225472^aD^aF)}else{return(aC^1073741824^aD^aF)}}else{return(aC^aD^aF)}}function au(aA,aC,aB){return(aA&aC)|((~aA)&aB)}function at(aA,aC,aB){return(aA&aB)|(aC&(~aB))}function ar(aA,aC,aB){return(aA^aC^aB)}function U(aA,aC,aB){return(aC^(aA|(~aB)))}function ae(aC,aB,aG,aF,aA,aD,aE){aC=ah(aC,ah(ah(au(aB,aG,aF),aA),aE));return ah(X(aC,aD),aB)}function T(aC,aB,aG,aF,aA,aD,aE){aC=ah(aC,ah(ah(at(aB,aG,aF),aA),aE));return ah(X(aC,aD),aB)}function ay(aC,aB,aG,aF,aA,aD,aE){aC=ah(aC,ah(ah(ar(aB,aG,aF),aA),aE));return ah(X(aC,aD),aB)}function ad(aC,aB,aG,aF,aA,aD,aE){aC=ah(aC,ah(ah(U(aB,aG,aF),aA),aE));return ah(X(aC,aD),aB)}function M(aG){var aH,aD=aG.length,aC=aD+8,aB=(aC-(aC%64))/64,aF=(aB+1)*16,aI=[],aA=0,aE=0;while(aE<aD){aH=(aE-(aE%4))/4;aA=(aE%4)*8;aI[aH]=(aI[aH]|(aG[aE]<<aA));aE++}aH=(aE-(aE%4))/4;aA=(aE%4)*8;aI[aH]=aI[aH]|(128<<aA);aI[aF-2]=aD<<3;aI[aF-1]=aD>>>29;return aI}function V(aC){var aD,aA,aB=[];for(aA=0;aA<=3;aA++){aD=(aC>>>(aA*8))&255;aB=aB.concat(aD)}return aB}var af=[],al,O,ag,W,N,az,ax,aw,av,ao=7,am=12,aj=17,ai=22,ab=5,aa=9,Z=14,Y=20,S=4,R=11,Q=16,P=23,aq=6,ap=10,an=15,ak=21;af=M(ac);az=1732584193;ax=4023233417;aw=2562383102;av=271733878;for(al=0;al<af.length;al+=16){O=az;ag=ax;W=aw;N=av;az=ae(az,ax,aw,av,af[al+0],ao,3614090360);av=ae(av,az,ax,aw,af[al+1],am,3905402710);aw=ae(aw,av,az,ax,af[al+2],aj,606105819);ax=ae(ax,aw,av,az,af[al+3],ai,3250441966);az=ae(az,ax,aw,av,af[al+4],ao,4118548399);av=ae(av,az,ax,aw,af[al+5],am,1200080426);aw=ae(aw,av,az,ax,af[al+6],aj,2821735955);ax=ae(ax,aw,av,az,af[al+7],ai,4249261313);az=ae(az,ax,aw,av,af[al+8],ao,1770035416);av=ae(av,az,ax,aw,af[al+9],am,2336552879);aw=ae(aw,av,az,ax,af[al+10],aj,4294925233);ax=ae(ax,aw,av,az,af[al+11],ai,2304563134);az=ae(az,ax,aw,av,af[al+12],ao,1804603682);av=ae(av,az,ax,aw,af[al+13],am,4254626195);aw=ae(aw,av,az,ax,af[al+14],aj,2792965006);ax=ae(ax,aw,av,az,af[al+15],ai,1236535329);az=T(az,ax,aw,av,af[al+1],ab,4129170786);av=T(av,az,ax,aw,af[al+6],aa,3225465664);aw=T(aw,av,az,ax,af[al+11],Z,643717713);ax=T(ax,aw,av,az,af[al+0],Y,3921069994);az=T(az,ax,aw,av,af[al+5],ab,3593408605);av=T(av,az,ax,aw,af[al+10],aa,38016083);aw=T(aw,av,az,ax,af[al+15],Z,3634488961);ax=T(ax,aw,av,az,af[al+4],Y,3889429448);az=T(az,ax,aw,av,af[al+9],ab,568446438);av=T(av,az,ax,aw,af[al+14],aa,3275163606);aw=T(aw,av,az,ax,af[al+3],Z,4107603335);ax=T(ax,aw,av,az,af[al+8],Y,1163531501);az=T(az,ax,aw,av,af[al+13],ab,2850285829);av=T(av,az,ax,aw,af[al+2],aa,4243563512);aw=T(aw,av,az,ax,af[al+7],Z,1735328473);ax=T(ax,aw,av,az,af[al+12],Y,2368359562);az=ay(az,ax,aw,av,af[al+5],S,4294588738);av=ay(av,az,ax,aw,af[al+8],R,2272392833);aw=ay(aw,av,az,ax,af[al+11],Q,1839030562);ax=ay(ax,aw,av,az,af[al+14],P,4259657740);az=ay(az,ax,aw,av,af[al+1],S,2763975236);av=ay(av,az,ax,aw,af[al+4],R,1272893353);aw=ay(aw,av,az,ax,af[al+7],Q,4139469664);ax=ay(ax,aw,av,az,af[al+10],P,3200236656);az=ay(az,ax,aw,av,af[al+13],S,681279174);av=ay(av,az,ax,aw,af[al+0],R,3936430074);aw=ay(aw,av,az,ax,af[al+3],Q,3572445317);ax=ay(ax,aw,av,az,af[al+6],P,76029189);az=ay(az,ax,aw,av,af[al+9],S,3654602809);av=ay(av,az,ax,aw,af[al+12],R,3873151461);aw=ay(aw,av,az,ax,af[al+15],Q,530742520);ax=ay(ax,aw,av,az,af[al+2],P,3299628645);az=ad(az,ax,aw,av,af[al+0],aq,4096336452);av=ad(av,az,ax,aw,af[al+7],ap,1126891415);aw=ad(aw,av,az,ax,af[al+14],an,2878612391);ax=ad(ax,aw,av,az,af[al+5],ak,4237533241);az=ad(az,ax,aw,av,af[al+12],aq,1700485571);av=ad(av,az,ax,aw,af[al+3],ap,2399980690);aw=ad(aw,av,az,ax,af[al+10],an,4293915773);ax=ad(ax,aw,av,az,af[al+1],ak,2240044497);az=ad(az,ax,aw,av,af[al+8],aq,1873313359);av=ad(av,az,ax,aw,af[al+15],ap,4264355552);aw=ad(aw,av,az,ax,af[al+6],an,2734768916);ax=ad(ax,aw,av,az,af[al+13],ak,1309151649);az=ad(az,ax,aw,av,af[al+4],aq,4149444226);av=ad(av,az,ax,aw,af[al+11],ap,3174756917);aw=ad(aw,av,az,ax,af[al+2],an,718787259);ax=ad(ax,aw,av,az,af[al+9],ak,3951481745);az=ah(az,O);ax=ah(ax,ag);aw=ah(aw,W);av=ah(av,N)}return V(az).concat(V(ax),V(aw),V(av))},F=(function(){var M="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",O=M.split(""),N=function(Q,U){var V=[],T="",S,R;totalChunks=Math.floor(Q.length*16/3);for(S=0;S<Q.length*16;S++){V.push(Q[Math.floor(S/16)][S%16])}for(S=0;S<V.length;S=S+3){T+=O[V[S]>>2];T+=O[((V[S]&3)<<4)|(V[S+1]>>4)];if(!(V[S+1]===undefined)){T+=O[((V[S+1]&15)<<2)|(V[S+2]>>6)]}else{T+="="}if(!(V[S+2]===undefined)){T+=O[V[S+2]&63]}else{T+="="}}R=T.slice(0,64)+"\n";for(S=1;S<(Math.ceil(T.length/64));S++){R+=T.slice(S*64,S*64+64)+(Math.ceil(T.length/64)==S+1?"":"\n")}return R},P=function(R){R=R.replace(/\n/g,"");var T=[],U=[],Q=[],S;for(S=0;S<R.length;S=S+4){U[0]=M.indexOf(R.charAt(S));U[1]=M.indexOf(R.charAt(S+1));U[2]=M.indexOf(R.charAt(S+2));U[3]=M.indexOf(R.charAt(S+3));Q[0]=(U[0]<<2)|(U[1]>>4);Q[1]=((U[1]&15)<<4)|(U[2]>>2);Q[2]=((U[2]&3)<<6)|U[3];T.push(Q[0],Q[1],Q[2])}T=T.slice(0,T.length-(T.length%16));return T};if(typeof Array.indexOf==="function"){M=O}return{encode:N,decode:P}})();return{size:c,h2a:A,expandKey:D,encryptBlock:d,decryptBlock:C,Decrypt:f,s2a:l,rawEncrypt:b,rawDecrypt:v,dec:r,openSSLKey:n,a2h:o,enc:p,Hash:{MD5:j},Base64:F}})();
// jsr_class.js
//
// JSONscriptRequest -- a simple class for making HTTP requests
// using dynamically generated script tags and JSON
//
// Author: Jason Levitt
// Date: December 7th, 2005
//
// A SECURITY WARNING FROM DOUGLAS CROCKFORD:
// "The dynamic <script> tag hack suffers from a problem. It allows a page 
// to access data from any server in the web, which is really useful. 
// Unfortunately, the data is returned in the form of a script. That script 
// can deliver the data, but it runs with the same authority as scripts on 
// the base page, so it is able to steal cookies or misuse the authorization 
// of the user with the server. A rogue script can do destructive things to 
// the relationship between the user and the base server."
//
// So, be extremely cautious in your use of this script.
//
//
// Sample Usage:
//
// <script type="text/javascript" src="jsr_class.js"></script>
// 
// function callbackfunc(jsonData) {
//      alert('Latitude = ' + jsonData.ResultSet.Result[0].Latitude + 
//            '  Longitude = ' + jsonData.ResultSet.Result[0].Longitude);
//      aObj.removeScriptTag();
// }
//
// request = 'http://api.local.yahoo.com/MapsService/V1/geocode?appid=YahooDemo&
//            output=json&callback=callbackfunc&location=78704';
// aObj = new JSONscriptRequest(request);
// aObj.buildScriptTag();
// aObj.addScriptTag();
//
//
// Constructor -- pass a REST request URL to the constructor
//
function JSONscriptRequest(fullUrl) {
    // REST request path
    this.fullUrl = fullUrl; 
    // Keep IE from caching requests
    this.noCacheIE = '&noCacheIE=' + (new Date()).getTime();
    // Get the DOM location to put the script tag
    this.headLoc = document.getElementsByTagName("head").item(0);
    // Generate a unique script tag id
    this.scriptId = 'JscriptId' + JSONscriptRequest.scriptCounter++;
}

// Static script ID counter
JSONscriptRequest.scriptCounter = 1;

// buildScriptTag method
//
JSONscriptRequest.prototype.buildScriptTag = function () {

    // Create the script tag
    this.scriptObj = document.createElement("script");
    
    // Add script object attributes
    this.scriptObj.setAttribute("type", "text/javascript");
    this.scriptObj.setAttribute("charset", "utf-8");
    this.scriptObj.setAttribute("src", this.fullUrl + this.noCacheIE);
    this.scriptObj.setAttribute("id", this.scriptId);
}
 
// removeScriptTag method
// 
JSONscriptRequest.prototype.removeScriptTag = function () {
    // Destroy the script tag
    this.headLoc.removeChild(this.scriptObj);  
}

// addScriptTag method
//
JSONscriptRequest.prototype.addScriptTag = function () {
    // Create the script tag
    this.headLoc.appendChild(this.scriptObj);
}

Object.prototype.Inherits = function( parent )
	{
		
		if( arguments.length > 1 )
		{
			parent.apply( this, Array.prototype.slice.call( arguments, 1 ) );
		}
		else
		{
			parent.call( this );
		}
	}

	Function.prototype.Inherits = function( parent )
	{
		this.prototype = new parent();
		this.prototype.constructor = this;
	}

	createNamespace = function(namespace)
	{
		namespaces = namespace.split('.');
		var current_namespace = '';
		for(var i = 0; i < namespaces.length; i++)
		{
			if(i > 0)
			{
				current_namespace += '.';
			}
			current_namespace += namespaces[i];
			var exists = false;
			eval('exists = typeof(' + current_namespace + ') != "undefined";');
			if(!exists)
			{
				eval(current_namespace + ' = {};');
			}
		}
	}
	
	createNamespace('X2O');
	
	//event types
	X2O.X2OEvent = function(){ return{}	}();
	X2O.X2OEvent.LOAD_COMPLETE = 0;
	X2O.X2OEvent.INSERT_COMPLETE = 1;
	X2O.X2OEvent.UPDATE_COMPLETE = 2;
	X2O.X2OEvent.DELETE_COMPLETE = 3;
	X2O.X2OEvent.FAULT_EVENT = 4;
	
	//event dispatcher module
	X2O.X2OEventDispatcher = function(){
		var LOAD_COMPLETE_HANDLER = null;
		var INSERT_COMPLETE_HANDLER = null;
		var UPDATE_COMPLETE_HANDLER = null;
		var DELETE_COMPLETE_HANDLER = null;
		var FAULT_HANDLER = null;
		
		this.addEventListener = function(event_type, handler)
		{
			if(typeof(handler) == 'function')
			{
				switch(event_type)
				{
					case X2O.X2OEvent.LOAD_COMPLETE:
						LOAD_COMPLETE_HANDLER = handler;
						break;
					case X2O.X2OEvent.INSERT_COMPLETE:
						INSERT_COMPLETE_HANDLER = handler;
						break;
					case X2O.X2OEvent.UPDATE_COMPLETE:
						UPDATE_COMPLETE_HANDLER = handler;
						break;
					case X2O.X2OEvent.DELETE_COMPLETE:
						DELETE_COMPLETE_HANDLER = handler;
						break;
					case X2O.X2OEvent.FAULT_EVENT:
						FAULT_HANDLER = handler;
						break;
				}
			}
			else throw('The event listener must be a function.');
		}
		
		this.callLoadCompleteHandler = function()
		{
			if(LOAD_COMPLETE_HANDLER)
			{
				LOAD_COMPLETE_HANDLER.call(this,this);
			}
			else throw("The load complete handler has not been set. Please use addEventListener to add an event listener for the event type LOAD_COMPLETE.");
		}
		
		this.callInsertCompleteHandler = function(id)
		{
			if(INSERT_COMPLETE_HANDLER)
			{
				if(typeof(id) != 'undefined' && id != null)
				{
					this.setID(id);
				}
				INSERT_COMPLETE_HANDLER.call(this,this);
			}
			else throw("The insert complete handler has not been set. Please use addEventListener to add an event listener for the event type INSERT_COMPLETE.");
		}
		
		this.callUpdateCompleteHandler = function(message)
		{
			if(UPDATE_COMPLETE_HANDLER)
			{
				UPDATE_COMPLETE_HANDLER.call(this,this, message);
			}
			else throw("The update complete handler has not been set. Please use addEventListener to add an event listener for the event type UPDATE_COMPLETE.");
		}
		
		this.callDeleteCompleteHandler = function(message)
		{
			if(DELETE_COMPLETE_HANDLER)
			{
				DELETE_COMPLETE_HANDLER.call(this,this, message);
			}
			else throw("The delete complete handler has not been set. Please use addEventListener to add an event listener for the event type DELETE_COMPLETE.");
		}
		
		this.callFaultHandler = function(faultDetail)
		{
			if(FAULT_HANDLER)
			{
				FAULT_HANDLER.call(this,this,faultDetail);
			}
			else throw("The fault handler has not been set. Please use addEventListener to add an event listener for the event type FAULT_EVENT.");
		}
	}
	X2O.X2OEventDispatcher.UniqueDispatcherID = 0;
	//end X2OEventDispatcher
	
	X2O.X2OInstances = function()
	{
		return {
			Instances: []
		}
	}();

	
	X2O.X2OBaseItem = function(){};
	X2O.X2OBaseItem.Inherits(X2O.X2OEventDispatcher);
	X2O.X2OBaseItem = function(item_type, serviceName, related_types)
	{
		this.Inherits(X2O.X2OEventDispatcher);
		if(typeof(item_type) == 'undefined')
			item_type = 'X2O.X2OBaseItem';
		
		if(typeof(serviceName) == 'undefined')
			serviceName = '';
		
		var my_id = 0;
		if(serviceName != '')
		{
			my_id = X2O.X2OEventDispatcher.UniqueDispatcherID++;
			X2O.X2OInstances.Instances[my_id] = this;
		}
		
		//private vars
		var _related_types = null;
		if(	typeof(related_types) != 'undefined' 
			&&
			related_types != null)
		{
			_related_types = related_types;
		}
		
		this.GetRelatedType = function(property_name)
		{
			if(typeof(_related_types) != 'undefined' &&
				_related_types != null &&
			   typeof(_related_types[property_name]) != 'undefined'
			   &&
			   _related_types[property_name] != null)
			   {
				   return _related_types[property_name];
			   }
			   else throw('This item does not have a related property named ' + property_name);
		}
		
		//public vars
		this.type = item_type;
		this.serviceName = serviceName;
		this.jsonRequester = null;	
		
		this.getUID = function() { return my_id;}
		this.deserialize = function(obj) 
		{
			for (var j in obj) 
			{
				var prop = obj[j];
				switch(typeof(prop))
				{
					case 'string':
						eval('this.set' + j + '(\"' + prop.replace(/&lt;br&gt;/gm, '<br />').replace(/\n/gm, '').replace(/\r/gm, '') + '\")');
					break;
					case 'object':
						if((prop instanceof Array && prop.length > 0) || 
						(!(prop instanceof Array) && prop != null))
						{
							var class_name = this.GetRelatedType(j);
							eval('this.' + j + ' = new ' + class_name +'();');
							this[j].deserialize(prop);
						}
						else
						{
							if(typeof(this['set' + j]) == 'function')
							{
								eval('this.set' + j + '(null)');
							}
							else this[j] = null;
							
						}
						break;
					case 'number':
						eval('this.set' + j + '(' + prop + ')');
					case 'function':
					default:
						break;
					break;
				}
			}
		}
		
		this.serialize = function()
		{
			var ret = "{";
			for(var prop in this)
			{
				if(prop == 'type' || prop == 'serviceName' || prop == 'jsonRequester')
					continue;
				
				if(typeof(prop) != 'function' &&
				typeof(this[prop]) != 'function')
				{
					if(typeof(this[prop]) == 'string')
					{
							ret += prop + ':"' + this[prop] + '",\n';
						
					}
					else if(!(this[prop] instanceof X2O.X2OBaseItem) &&
					   !(this[prop] instanceof X2O.X2OBaseCollection))
					   {
						   ret += prop + ': ' + this[prop] + ',\n';
					   }
					   else {
							if(typeof(this[prop]) != 'undefined')
							{
								ret += prop + ': ' + this[prop].serialize() + ',\n';
							}
							else
							{
								ret += prop + ': null,\n';
							}
					   }
				}
			}
				if(ret.length > 1)
				{
					ret = ret.substring(0,ret.length - 2);
				}
				
			 ret += "}";
			 return ret;
		}
		
		this.toString = function()
		{
			var ret = "";
			for(var prop in this)
			{
				if(prop == 'type' || prop == 'serviceName' || prop == 'jsonRequester' || prop == 'getUID')
					continue;
				
				
				if(typeof(this[prop]) == 'function')
				{
					if(prop.match('^get') == 'get')
					{
						ret += prop.substring(3) + ': ' + eval('this.' + prop + '()') + '\n';
					}
					else continue;
				}
			   else if(!(this[prop] instanceof X2O.X2OBaseItem) &&
				   !(this[prop] instanceof X2O.X2OBaseCollection))
			   {
				   ret += prop + ': ' + this[prop] + '\n';
			   }
			   else
			   {
					if(typeof(this[prop]) != 'undefined')
					{
						ret += prop + ': ' + this[prop].toString() + '\n';
					}
					else
					{
						ret += prop + ': null\n';
					}
			   }
			}
			 return ret;
		}
	}
	
	//end X2oBaseItem	
	
	X2O.X2OBaseCollection = function(){};
	
	X2O.X2OBaseCollection.Inherits(X2O.X2OEventDispatcher);
	X2O.X2OBaseCollection = function(type,itemtype,serviceName)
	{
		this.Inherits(X2O.X2OEventDispatcher);
		
		var _items = [];
		
		if(typeof(type) == 'undefined')
			type = 'X2O.X2OBaseCollection';
		
		if(typeof(itemtype) == 'undefined')
			itemtype = '';
		if(typeof(serviceName) == 'undefined')
			serviceName = '';
		
		var my_id = 0;
		if(itemtype != '' && serviceName != '')
		{
			my_id = X2O.X2OEventDispatcher.UniqueDispatcherID++;
			X2O.X2OInstances.Instances[my_id] = this;
		}
		//public vars
		this.itemtype = itemtype;
		this.type = type;
		this.serviceName = serviceName;
		this.jsonRequester = null;	
		this.addItem = function(item)
		{
			if(typeof(item.getUID) == 'function')
			{
				_items.push(item);
			}
			else
			{
				throw('Item to add to this collection must be derived from X2O.X2OBaseItem.');
			}
		}
		
		this.clear = function()
		{
			_items = [];
		}
		
		this.getVOs = function () { return _items;}
		
		this.getCount = function() { return _items.length; }
		
		this.getItemAt = function(i)
		{
			if(_items.length > i && i >= 0)
			{
				return _items[i];
			}
			else throw('This collection does not contain any items at the given index ' + i);
		}
		
		this.setItemAt = function(VO, i)
		{
			if(typeof(VO.getUID) == 'function')
			{
				if(_items.length > i)
				{
					_items.splice(i,0,VO);
				}
				else throw('Cannot add this VO at the index ' + i + ' because this collection does not contain that many elements. Use addItem to add it to the end of the collection.');
			}
			else throw('Item to add to this collection must be derived from X2O.X2OBaseItem.');
		}
		
		this.getItemIndex = function(VO)
		{
			if(typeof(VO.getUID) == 'function')
			{
				for(var i in _items)
				{
					if(_items[i].getID() == id)
					{
						return i;
					}
				}
			}
			else throw('Item to get index of in this collection cannot be found.');
		}
		
		this.removeItemAt = function(i)
		{
			if(_items.length > i && i >= 0)
			{
				_items.splice(i,1);
				return;
			}
			else throw('This collection does not contain any items at the given index ' + i);
		}
		
		this.removeVOByID =function(id)
		{
			for(var i in _items)
			{
				if(_items[i].getID() == id)
				{
					_items.splice(i,1);
					return;
				}
			}
			throw('Cannot find VO with given ID in this collection.')
		}
		
		this.removeVO = function(itemVO)
		{
			if(typeof(item.getUID) != 'function')
			{
				throw('Item to add to this collection must be derived from X2O.X2OBaseItem.')
			}
			
			for(var i in _items)
			{
				if(_items[i].getID() == itemVO.getID())
				{
					_items.splice(i,1);
					return;
				}
			}
		}
		
				
		this.getUID = function() { return my_id;}
		this.deserialize = function(objs) { 
		
			if(typeof(objs) == 'undefined' || objs == null || objs.length == 0)
			{
				return;
			}
			if(objs.length > 0)
			{
				for(var i = 0; i < objs.length; i++)
				{
				
					//eval('var current_item = new ' + this.itemtype + '("' + this.itemtype + '", "' + this.itemtype + '");');
					eval('var current_item = new ' + this.itemtype + '();');
					current_item.deserialize(objs[i]);
					this.addItem(current_item);
				}
			}
			else throw('Deserialize must be called on a collection.');
		}
		
		this.serialize = function()
		{
			var ret = '[';
			for(var i = 0; i < _items.length; i++)
			{
				ret += _items[i].serialize() + ',';
			}
			if(ret.length > 1)
			{
				ret = ret.substring(0,ret.length - 1);
			}
			return ret + ']';
		}
		
		this.toString = function()
		{
			var ret = '\n\n';
			for(var i = 0; i < _items.length; i++)
			{
				ret += _items[i].toString() + '\n';
			}
			
			return ret;
		}
		
	}
	
	X2O.X2OManager = function(){};
	X2O.X2OManager.Inherits(X2O.X2OBaseItem);
	X2O.X2OManager = function() {
		this.Inherits(X2O.X2OBaseItem, 'X2O.X2OManager','login');
		
		var liveHostURL = '/';
		var liveAssetsURL = "/";
		
		function setHostURL(url)
		{
			if(X2O.DataHelper.isObjectData(url))
			{
				X2O.X2OManager.hostURL = url;
			}
		}
		function setAssetsHostURL(url)
		{
			if(X2O.DataHelper.isObjectData(url))
			{
				X2O.X2OManager.assetsURL = url;
			}
		}
		
		this.login = function(server_type)
		{
			if(typeof(server_type) == 'undefined')
			{
				server_type = X2O.X2OManager.DEV_LOGIN;
			}
			
			try
			{
				if(server_type == X2O.X2OManager.LIVE_LOGIN)
				{
					if(liveHostURL == '' || liveAssetsURL == '')
					{
							throw('You do not have promotion enabled on this X2O account.');
					}
					
					setHostURL(liveHostURL);
					setAssetsHostURL(liveAssetsURL);
				}
				else
				{
					setHostURL(X2O.X2OManager.hostURL);
					setAssetsHostURL(X2O.X2OManager.assetsURL);
				}
				
				var service_uri = X2O.X2OManager.hostURL + this.serviceName + '.x2o?jsid=' + this.getUID();
				this.jsonRequester = new JSONscriptRequest(service_uri);
				this.jsonRequester.buildScriptTag();
				this.jsonRequester.addScriptTag(); //make the call
				
			}
			catch(error)
			{
				this.callFaultHandler('There was a problem logging in. Details are: ' + error);
			}
		}
	}
	
	/*static properties*/
	X2O.X2OManager.LIVE_LOGIN = 1;
	X2O.X2OManager.DEV_LOGIN = 0;
		
	X2O.X2OManager.token = '';
	
	X2O.X2OManager.hostURL = "http://x2o-SampleRecipeApplication-WeAreMammoth.x2oframework.net/";
	X2O.X2OManager.assetsURL = "http://assets-SampleRecipeApplication-WeAreMammoth.x2oframework.net/";
	
	
	/*public static class X2ORequest*/
	X2O.X2ORequest = function() 
	{
		return {
	
			/*public methods*/
			getToken :function(response)
			{
				return response.token;
			},
			
			getEncryptedRequestToken : function()
			{
				if(typeof(X2O.X2OManager.token) == 'undefined' ||
				X2O.X2OManager.token == null || X2O.X2OManager.token == '')
				{
					throw("You must log in to X2O by instantiating a X2O.X2OManager object and calling its login() method.");
				}
				var token = X2O.X2OManager.token + "|" + X2O.X2ORequest.usableID + "_" + (new Date()).getTime();
				var send_stuff = this.encrypt(token);
				
				X2O.X2ORequest.usableID++;
				return send_stuff;
			},
			
			decrypt : function(input)
			{
				
	
				var iv = "3B172DAFFB4FE0E6B9007E30F1F88370";
				var key = "929EACD5C293DF7D88D1B211D8FFB269";
					
				GibberishAES.size(128);
				try
				{
					var ivarr = GibberishAES.h2a(iv);
					var keyarr = GibberishAES.h2a(key);
					var secret = GibberishAES.Base64.decode(input);
					var resp = GibberishAES.rawDecrypt(secret, keyarr, ivarr);
					return resp;
				}
				catch(error)
				{
					throw('Could not decrypt properly. Details are: ' + error);
				}
			},
			
			encrypt : function(objInput)
			{
				try
				{
					var iv = "3B172DAFFB4FE0E6B9007E30F1F88370";
					var key = "929EACD5C293DF7D88D1B211D8FFB269";
					GibberishAES.size(128);
					var ivarr = GibberishAES.h2a(iv);
					var keyarr = GibberishAES.h2a(key);
					var plaintext = GibberishAES.s2a(objInput);
					var enc = GibberishAES.rawEncrypt(plaintext, keyarr, ivarr);
					var encoded_encrypted = GibberishAES.Base64.encode(enc);
					return encoded_encrypted;
				}
				catch(err)
				{
					throw ('Could not encrypt properly. Details are: ' + err);
				}
				
				return objInput;
			},
			
			decryptResponse : function(input_string)
			{
				var final_response_object = null;
				try
				{
					final_response_object = eval('(' + this.decrypt(input_string) + ')');
				}
				catch(error)
				{
					throw("Could not decrypt the response. Make sure you are using the correct version of the generated javascript library.");
				}
				return final_response_object;
			}
		}
	}(); //call to make it static
	
	/*static properties*/
	X2O.X2ORequest.usableID = 0;
	//end X2ORequest
	
	//static datahelper util class
	X2O.DataHelper = function() {
		return {
			isObjectData : function(obj)
			{
				if (obj && obj != null && obj.toString && obj.toString() !="")
					return true;
				else
					return false;
			},
				
			writeObjectData : function(obj)
			{
				if (this.isObjectData(obj))
					return obj.toString();
				else
					return "";
			},
				
			isValidID : function(obj)
			{
				if (this.isObjectData(obj) && obj > 0)
					return true;
				else
					return false;
			},
					
			convertStringDateToDate : function(dateString)
			{
				//mm-dd-yyyy hh:mm:ss (AM|PM)
				if (!this.isObjectData(dateString))
					return null;
					
				var dateArray = dateString.split(" ");

				var calendarString = dateArray[0];
				var clockString = dateArray[1];
				var add_twelve_hours = false;
				if(dateArray[2] == 'PM')
				{
					add_twelve_hours = true;
				}
				
				var calendarArray = calendarString.split("/");
				var month= calendarArray[0];
				var day = calendarArray[1];
				var year = calendarArray[2];
				
				var clockArray = clockString.split(":");
				var hours = add_twelve_hours ? (parseInt(clockArray[0]) + 12).toString() : clockArray[0];
				if(!add_twelve_hours && hours == '12')
				{
					hours = '00'; //hack for midnight
				}
				var minutes = clockArray[1];
				var seconds = clockArray[2];
				
				var mstotal = Date.UTC(year, month-1, day, hours, minutes, seconds);
				var d = new Date();
				d.setTime(mstotal);
				if(d instanceof Date)
					return d;
				else throw('Could not parse date value.');
			},
			
			convertDateToStringDate : function(date)
			{
				if (!this.isObjectData(date))
					return "";
					
				var monthString = (date.getUTCMonth()+1>=10) ? String(date.getUTCMonth()+1) : "0" + String(date.getUTCMonth()+1);
				var dateString = (date.getUTCDate()>=10) ? String(date.getUTCDate()) : "0" + String(date.getUTCDate());
				var hoursString = (date.getUTCHours()>=10) ? String(date.getUTCHours()) : "0" + String(date.getUTCHours());
				var minutesString = (date.getUTCMinutes()>=10) ? String(date.getUTCMinutes()) : "0" + String(date.getUTCMinutes());
				var secondsString = (date.getUTCSeconds()>=10) ? String(date.getUTCSeconds()) : "0" + String(date.getUTCSeconds());
				
				return String(date.getFullYear() + "-" + monthString + "-" + dateString + "T" + hoursString + ":" + minutesString + ":" + secondsString);
			}
		}
	}(); //call it to make it static
	//end DataHelper
	
	X2O.JsonHelper = function()
	{
		return {
			urlUncache : function(url)
			{
				//return url;
				if (url.indexOf("?") > -1)
				{
					return url + "&rand=" + (Math.random());
				}
				else
				{
					return url + "?rand=" + (Math.random());
				}
			}
		}
	}(); //call it to make it static
		
		/*MORE BASE STUFF HERE*/
	X2O.X2OError = function()
	{
		var _IsError = function(response)
		{
			if(typeof(response) != 'object')
			{
				X2O.X2OManager.token = "";
				return true;
			}
			if(typeof(response.success) != 'undefined' && typeof(response.success) == 'boolean')
			{
				X2O.X2OManager.token = X2O.X2ORequest.getToken(response);
				return response.success == false;
			}
			else
			{
				X2O.X2OManager.token =  X2O.X2ORequest.getToken(response);
				return false;
			}
		};
		return {
			CheckResponse: function(response) 
			{ 
				if(_IsError(response))
				{
					throw (response.message);
				}
			},
			GetSuccessMessage: function(response) 
			{
				if(!_IsError(response))
				{
					if(typeof(response.message) != 'undefined' && response.message != "")
					{
						return response.message;
					}
					else return null;
				}
				else return "";
			}
		}
	}();
	
	X2O.X2OResponseHandler = function()
	{
		return {
			HandleCompleteResponse: function(event_type, response, jsid) 
			{ 
				if(X2O.X2OInstances.Instances[jsid])
				{ 
					try{
						var response_object = X2O.X2ORequest.decryptResponse(response);
						X2O.X2OError.CheckResponse(response_object);
						var success_message = X2O.X2OError.GetSuccessMessage(response_object);
						if(success_message == null)
						{
							X2O.X2OInstances.Instances[jsid].deserialize(response_object.object);
						}
						
						switch(event_type)
						{
							case X2O.X2OEvent.LOAD_COMPLETE:
								X2O.X2OInstances.Instances[jsid].callLoadCompleteHandler();
							break;
							case X2O.X2OEvent.INSERT_COMPLETE:
								if(success_message != null)
								{
									var id = parseInt(success_message);
									if(isNaN(id))
									{
										throw('ID not returned properly from insert service call. Expected integer, got ' + id + ' instead.');
									}
									X2O.X2OInstances.Instances[jsid].callInsertCompleteHandler(id);
								}
								else
								{
									X2O.X2OInstances.Instances[jsid].callInsertCompleteHandler(success_message);
								}
							break;
							case X2O.X2OEvent.UPDATE_COMPLETE:
								X2O.X2OInstances.Instances[jsid].callUpdateCompleteHandler(success_message);
							break;
							case X2O.X2OEvent.DELETE_COMPLETE:
								X2O.X2OInstances.Instances[jsid].callDeleteCompleteHandler(success_message);
							break;
							default:
								throw('No event handler can be called.');
							break;
						}
					}
					catch(error)
					{
						X2O.X2OInstances.Instances[jsid].callFaultHandler(error);
					}
				}
				else throw('Cannot call complete handler. The object with returned jsid cannot be found.');
			},
			HandleFaultResponse: function(response, jsid) 
			{
				if(X2O.X2OInstances.Instances[jsid])
				{
					try
					{
						var response_object = X2O.X2ORequest.decryptResponse(response);
						X2O.X2OError.CheckResponse(response_object);
						X2O.X2OInstances.Instances[jsid].callFaultHandler();
					}
					catch(error)
					{
						X2O.X2OInstances.Instances[jsid].callFaultHandler(error);
					}
				}
				else throw('Cannot call fault handler. The object with returned jsid cannot be found.');
			}
		}
	}();