text: // Version: 3.4.4
  (function(){
  var m=null,p=!1;function s(){return function(){}}
  window.JSON&&window.JSON.stringify||function(){function a(){try{return this.valueOf()}catch(a){return m}}function c(a){d.lastIndex=0;return d.test(a)?'"'+a.replace(d,function(a){var b=v[a];return"string"===typeof b?b:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+a+'"'}function b(d,E){var h,k,j,l,i,r=e,g=E[d];g&&"object"===typeof g&&(g=a.call(g));"function"===typeof f&&(g=f.call(E,d,g));switch(typeof g){case "string":return c(g);case "number":return isFinite(g)?String(g):"null";case "boolean":case "null":return String(g);
  case "object":if(!g)return"null";e+=o;i=[];if("[object Array]"===Object.prototype.toString.apply(g)){l=g.length;for(h=0;h<l;h+=1)i[h]=b(h,g)||"null";j=0===i.length?"[]":e?"[\n"+e+i.join(",\n"+e)+"\n"+r+"]":"["+i.join(",")+"]";e=r;return j}if(f&&"object"===typeof f){l=f.length;for(h=0;h<l;h+=1)k=f[h],"string"===typeof k&&(j=b(k,g))&&i.push(c(k)+(e?": ":":")+j)}else for(k in g)Object.hasOwnProperty.call(g,k)&&(j=b(k,g))&&i.push(c(k)+(e?": ":":")+j);j=0===i.length?"{}":e?"{\n"+e+i.join(",\n"+e)+"\n"+
  r+"}":"{"+i.join(",")+"}";e=r;return j}}window.JSON||(window.JSON={});var d=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,e,o,v={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},f;"function"!==typeof JSON.stringify&&(JSON.stringify=function(a,c,d){var k;o=e="";if("number"===typeof d)for(k=0;k<d;k+=1)o+=" ";else"string"===typeof d&&(o=d);if((f=c)&&"function"!==typeof c&&("object"!==typeof c||"number"!==
  typeof c.length))throw Error("JSON.stringify");return b("",{"":a})});"function"!==typeof JSON.parse&&(JSON.parse=function(a){return eval("("+a+")")})}();var aa=1,t=p,ba=[],w="-pnpres",A=1E3,da="/",ea="&",fa=/{([\w\-]+)}/g;function B(){return"x"+ ++aa+""+ +new Date}function D(){return+new Date}var F,I=Math.floor(20*Math.random());F=function(a,c){return 0<a.indexOf("pubsub.")&&a.replace("pubsub","ps"+(c?ga().split("-")[0]:20>++I?I:I=1))||a};
  function ha(a,c){var b=a.join(da);if(c){var d=[],b=b+"?",e;for(e in c)d.push(e+"="+J(c[e]));b+=d.join(ea)}return b}function ia(a,c){function b(){e+c>D()?(clearTimeout(d),d=setTimeout(b,c)):(e=D(),a())}var d,e=0;return b}function ja(a,c){var b=[];N(a||[],function(a){c(a)&&b.push(a)});return b}function ka(a,c){return a.replace(fa,function(a,d){return c[d]||a})}
  function ga(a){var c="xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(a){var c=16*Math.random()|0;return("x"==a?c:c&3|8).toString(16)});a&&a(c);return c}function N(a,c){if(a&&c)if("undefined"!=typeof a[0])for(var b=0,d=a.length;b<d;)c.call(a[b],a[b],b++);else for(b in a)a.hasOwnProperty&&a.hasOwnProperty(b)&&c.call(a[b],b,a[b])}function O(a,c){var b=[];N(a||[],function(a,e){b.push(c(a,e))});return b}
  function J(a){return O(encodeURIComponent(a).split(""),function(a){return 0>"-_.!~*'()".indexOf(a)?a:"%"+a.charCodeAt(0).toString(16).toUpperCase()}).join("")}function la(a){var c=[];N(a,function(a,d){d.g&&c.push(a)});return c.sort()}function P(){setTimeout(function(){t||(t=1,N(ba,function(a){a()}))},A)}
  if(!window.PUBNUB){var R=function(a){return document.getElementById(a)},na=function(a){console.error(a)},oa=function(a,c){var b=[];N(a.split(/\s+/),function(a){N((c||document).getElementsByTagName(a),function(a){b.push(a)})});return b},S=function(a,c,b){N(a.split(","),function(a){function e(a){a||(a=window.event);b(a)||(a.cancelBubble=!0,a.returnValue=p,a.preventDefault&&a.preventDefault(),a.stopPropagation&&a.stopPropagation())}c.addEventListener?c.addEventListener(a,e,p):c.attachEvent?c.attachEvent("on"+
  a,e):c["on"+a]=e})},pa=function(){return oa("head")[0]},T=function(a,c,b){if(b)a.setAttribute(c,b);else return a&&a.getAttribute&&a.getAttribute(c)},sa=function(a,c){for(var b in c)if(c.hasOwnProperty(b))try{a.style[b]=c[b]+(0<"|width|height|top|left|".indexOf(b)&&"number"==typeof c[b]?"px":"")}catch(d){}},ta=function(a){return document.createElement(a)},ua=function(){return U||W()?0:B()},wa=function(a){function c(a,b){L||(L=1,a||M(b),g.onerror=m,clearTimeout(V),setTimeout(function(){a&&u();var b=
  R(q),c=b&&b.parentNode;c&&c.removeChild(b)},A))}if(U||W()){a:{var b,d,e=function(){if(!v){v=1;clearTimeout(Q);try{d=JSON.parse(b.responseText)}catch(a){return l(1)}k(d)}},o=0,v=0,f=a.timeout||1E4,Q=setTimeout(function(){l(1)},f),E=a.b||s(),h=a.data||{},k=a.c||s(),j="undefined"===typeof a.h,l=function(a){o||(o=1,clearTimeout(Q),b&&(b.onerror=b.onload=m,b.abort&&b.abort(),b=m),a&&E())};try{b=W()||window.XDomainRequest&&new XDomainRequest||new XMLHttpRequest;b.onerror=b.onabort=function(){l(1)};b.onload=
  b.onloadend=e;j&&(b.timeout=f);h.pnsdk=va;var i=ha(a.url,h);b.open("GET",i,j);b.send()}catch(r){l(0);U=0;a=wa(a);break a}a=l}return a}var g=ta("script"),e=a.a,q=B(),L=0,V=setTimeout(function(){c(1)},a.timeout||1E4),u=a.b||s(),f=a.data||{},M=a.c||s();window[e]=function(a){c(0,a)};a.h||(g[xa]=xa);g.onerror=function(){c(1)};f.pnsdk=va;g.src=ha(a.url,f);T(g,"id",q);pa().appendChild(g);return c},ya=function(){return!("onLine"in navigator)?1:navigator.onLine},W=function(){if(!za||!za.get)return 0;var a=
  {id:W.id++,send:s(),abort:function(){a.id={}},open:function(c,b){W[a.id]=a;za.get(a.id,b)}};return a},xa="async",va="PubNub-JS-Web/3.4.4",U=-1==navigator.userAgent.indexOf("MSIE 6");window.console||(window.console=window.console||{});console.log||(console.log=console.error=(window.opera||{}).postError||s());var Aa,X=window.localStorage;Aa={get:function(a){try{return X?X.getItem(a):-1==document.cookie.indexOf(a)?m:((document.cookie||"").match(RegExp(a+"=([^;]+)"))||[])[1]||m}catch(c){}},set:function(a,
  c){try{if(X)return X.setItem(a,c)&&0;document.cookie=a+"="+c+"; expires=Thu, 1 Aug 2030 20:00:00 UTC; path=/"}catch(b){}}};var Y={list:{},unbind:function(a){Y.list[a]=[]},bind:function(a,c){(Y.list[a]=Y.list[a]||[]).push(c)},fire:function(a,c){N(Y.list[a]||[],function(a){a(c)})}},Z=R("pubnub")||0,Ba=function(a){function c(){}function b(){z.time(function(a){a||u&&u(1);setTimeout(b,h)})}function d(){ca()||u&&u(1);setTimeout(d,A)}function e(a){N(la(x),function(b){(b=x[b])&&a(b)})}function o(a){a&&(q.i=
  0);!q.i&&q.length&&(q.i=1,y(q.shift()))}a.jsonp&&(U=0);var v=a.subscribe_key||"";a.uuid||Aa.get(v+"uuid");a.xdr=wa;a.db=Aa;a.error=na;a._is_online=ya;a.jsonp_cb=ua;var f,Q=+a.windowing||10,E=(+a.timeout||310)*A,h=(+a.keepalive||60)*A,k=a.publish_key||"",j=a.subscribe_key||"",l=a.ssl?"s":"",i="http"+l+"://"+(a.origin||"pubsub.pubnub.com"),r=F(i),g=F(i),q=[],L=0,V=0,u=0,M=0,ma=0,K=0,x={},y=a.xdr,n=a.error||s(),ca=a._is_online||function(){return 1},C=a.jsonp_cb||function(){return 0},G=a.db||{get:s(),
  set:s()},H=a.uuid||G&&G.get(j+"uuid")||"",z={LEAVE:function(a,b){var c={uuid:H},d=F(i),e=C();0<a.indexOf(w)||("0"!=e&&(c.callback=e),y({h:b||l,timeout:2E3,a:e,data:c,url:[d,"v2","presence","sub_key",j,"channel",J(a),"leave"]}))},history:function(a,b){var b=a.callback||b,c=a.count||a.limit||100,d=a.reverse||"false",e=a.error||s(),f=a.channel,g=a.start,k=a.end,i={},h=C();if(!f)return n("Missing Channel");if(!b)return n("Missing Callback");if(!j)return n("Missing Subscribe Key");i.stringtoken="true";
  i.count=c;i.reverse=d;h&&(i.callback=h);g&&(i.start=g);k&&(i.end=k);y({a:h,data:i,c:function(a){b(a)},b:e,url:[r,"v2","history","sub-key",j,"channel",J(f)]})},replay:function(a){var b=b||a.callback||s(),c=a.source,d=a.destination,e=a.stop,f=a.start,g=a.end,i=a.reverse,a=a.limit,h=C(),l={};if(!c)return n("Missing Source Channel");if(!d)return n("Missing Destination Channel");if(!k)return n("Missing Publish Key");if(!j)return n("Missing Subscribe Key");"0"!=h&&(l.callback=h);e&&(l.stop="all");i&&(l.reverse=
  "true");f&&(l.start=f);g&&(l.end=g);a&&(l.count=a);y({a:h,c:function(a){b(a)},b:function(){b([0,"Disconnected"])},url:[r,"v1","replay",k,j,c,d],data:l})},time:function(a){var b=C();y({a:b,timeout:5*A,url:[r,"time",b],c:function(b){a(b[0])},b:function(){a(0)}})},publish:function(a,b){var b=b||a.callback||s(),c=a.message,d=a.channel,e=C();if(!c)return n("Missing Message");if(!d)return n("Missing Channel");if(!k)return n("Missing Publish Key");if(!j)return n("Missing Subscribe Key");c=JSON.stringify(c);
  d=[r,"publish",k,j,0,J(d),e,J(c)];q.push({a:e,timeout:5*A,url:d,data:{uuid:H},c:function(a){b(a);o(1)},b:function(){b([0,"Failed",c]);o(1)}});o()},unsubscribe:function(a){a=a.channel;K=0;M=1;a=O((a.join?a.join(","):""+a).split(","),function(a){return a+","+a+w}).join(",");N(a.split(","),function(a){t&&z.LEAVE(a,0);x[a]=0});t&&c()},subscribe:function(a,b){function d(a){a?setTimeout(f,A):(r=F(i,1),g=F(i,1),setTimeout(function(){z.time(d)},A));e(function(b){if(a&&b.d){b.d=0;return b.m(b.name)}if(!a&&
  !b.d){b.d=1;b.l(b.name)}})}function f(){var a=C(),b=la(x).join(",");b&&(u=y({timeout:ca,a:a,b:function(){z.time(d)},data:{uuid:H},url:[g,"subscribe",j,J(b),a,K],c:function(a){if(!a)return setTimeout(f,ra);e(function(a){a.f||(a.f=1,a.k(a.name))});K=!K&&M&&G.get(j)||a[1];qa&&(Timetoken=1E4,qa=0);G.set(j,a[1]);var b,c=(2<a.length?a[2]:"").split(",");b=function(){var a=c.shift()||"";return[(x[a]||{}).a||L,(a||V).split(w)[0]]};N(a[0],function(c){var d=b();if(x[d[1]].g)d[0](c,a,d[1])});setTimeout(f,ra)}}))}
  var h=a.channel,b=(b=b||a.callback)||a.message,k=a.connect||s(),l=a.reconnect||s(),o=a.disconnect||s(),q=a.presence||0,v=a.noheresync||0,qa=a.backfill||0,ca=a.timeout||E,ra=a.windowing||Q;a.restore&&(M=1);K=0;if(!h)return n("Missing Channel");if(!b)return n("Missing Callback");if(!j)return n("Missing Subscribe Key");N((h.join?h.join(","):""+h).split(","),function(a){var c=x[a]||{};x[V=a]={name:a,f:c.f,d:c.d,g:1,a:L=b,k:k,l:o,m:l};q&&(z.subscribe({channel:a+w,callback:q}),!c.g&&!v&&z.here_now({channel:a,
  callback:function(b){N("uuids"in b?b.uuids:[],function(c){q({action:"join",uuid:c,timestamp:D(),occupancy:b.occupancy||1},b,a)})}}))});c=function(){u&&u(1);clearTimeout(ma);ma=setTimeout(f,100)};if(!t)return ba.push(c);c()},here_now:function(a,b){var b=a.callback||b,c=a.error||s(),d=a.channel,e=C(),f=m;if(!d)return n("Missing Channel");if(!b)return n("Missing Callback");if(!j)return n("Missing Subscribe Key");"0"!=e&&(f={},f.callback=e);y({a:e,data:f,c:function(a){b(a)},b:c,url:[r,"v2","presence",
  "sub_key",j,"channel",J(d)]})},xdr:y,ready:P,db:G,uuid:ga,map:O,each:N,"each-channel":e,grep:ja,supplant:ka,now:D,unique:B,updater:ia};H||(H=z.uuid());G.set(j+"uuid",H);setTimeout(d,A);setTimeout(b,h);f=z;f.css=sa;f.$=R;f.create=ta;f.bind=S;f.head=pa;f.search=oa;f.attr=T;f.events=Y;f.init=Ba;S("beforeunload",window,function(){f["each-channel"](function(a){f.LEAVE(a.name,1)});return!0});if(a.notest)return f;S("offline",window,f._reset_offline);S("offline",document,f._reset_offline);return f};S("load",
  window,function(){setTimeout(P,0)});var $=Z||{};PUBNUB=Ba({notest:1,publish_key:T($,"pub-key"),subscribe_key:T($,"sub-key"),ssl:!document.location.href.indexOf("https")||"on"==T($,"ssl"),origin:T($,"origin"),uuid:T($,"uuid")});window.jQuery&&(window.jQuery.PUBNUB=PUBNUB);"undefined"!==typeof module&&(module.exports=PUBNUB)&&P();var za=R("pubnubs")||0;if(Z){sa(Z,{position:"absolute",top:-A});if("opera"in window||T(Z,"flash"))Z.innerHTML="<object id=pubnubs data=https://pubnub.a.ssl.fastly.net/pubnub.swf><param name=movie value=https://pubnub.a.ssl.fastly.net/pubnub.swf><param name=allowscriptaccess value=always></object>";
  PUBNUB.rdx=function(a,c){if(!c)return W[a].onerror();W[a].responseText=unescape(c);W[a].onload()};W.id=A}}
  var Ca=PUBNUB.ws=function(a,c){if(!(this instanceof Ca))return new Ca(a,c);var b=this,a=b.url=a||"";b.protocol=c||"Sec-WebSocket-Protocol";var d=a.split("/"),d={ssl:"wss:"===d[0],origin:d[2],publish_key:d[3],subscribe_key:d[4],channel:d[5]};b.CONNECTING=0;b.OPEN=1;b.CLOSING=2;b.CLOSED=3;b.CLOSE_NORMAL=1E3;b.CLOSE_GOING_AWAY=1001;b.CLOSE_PROTOCOL_ERROR=1002;b.CLOSE_UNSUPPORTED=1003;b.CLOSE_TOO_LARGE=1004;b.CLOSE_NO_STATUS=1005;b.CLOSE_ABNORMAL=1006;b.onclose=b.onerror=b.onmessage=b.onopen=b.onsend=
  s();b.binaryType="";b.extensions="";b.bufferedAmount=0;b.trasnmitting=p;b.buffer=[];b.readyState=b.CONNECTING;if(!a)return b.readyState=b.CLOSED,b.onclose({code:b.CLOSE_ABNORMAL,reason:"Missing URL",wasClean:!0}),b;b.e=PUBNUB.init(d);b.e.j=d;b.j=d;b.e.subscribe({restore:p,channel:d.channel,disconnect:b.onerror,reconnect:b.onopen,error:function(){b.onclose({code:b.CLOSE_ABNORMAL,reason:"Missing URL",wasClean:p})},callback:function(a){b.onmessage({data:a})},connect:function(){b.readyState=b.OPEN;b.onopen()}})};
  Ca.prototype.send=function(a){var c=this;c.e.publish({channel:c.e.j.channel,message:a,callback:function(a){c.onsend({data:a})}})};
  })();
  PUBNUB['crypto'] = (function(){
      var Nr = 14,
      /* Default to 256 Bit Encryption */
      Nk = 8,
      Decrypt = false,
  
      enc_utf8 = function(s)
      {
          try {
              return unescape(encodeURIComponent(s));
          }
          catch(e) {
              throw 'Error on UTF-8 encode';
          }
      },
  
      dec_utf8 = function(s)
      {
          try {
              return decodeURIComponent(escape(s));
          }
          catch(e) {
              throw ('Bad Key');
          }
      },
  
      padBlock = function(byteArr)
      {
          var array = [], cpad, i;
          if (byteArr.length < 16) {
              cpad = 16 - byteArr.length;
              array = [cpad, cpad, cpad, cpad, cpad, cpad, cpad, cpad, cpad, cpad, cpad, cpad, cpad, cpad, cpad, cpad];
          }
          for (i = 0; i < byteArr.length; i++)
          {
              array[i] = byteArr[i];
          }
          return array;
      },
  
      block2s = function(block, lastBlock)
      {
          var string = '', padding, i;
          if (lastBlock) {
              padding = block[15];
              if (padding > 16) {
                  throw ('Decryption error: Maybe bad key');
              }
              if (padding == 16) {
                  return '';
              }
              for (i = 0; i < 16 - padding; i++) {
                  string += String.fromCharCode(block[i]);
              }
          } else {
              for (i = 0; i < 16; i++) {
                  string += String.fromCharCode(block[i]);
              }
          }
          return string;
      },
  
      a2h = function(numArr)
      {
          var string = '', i;
          for (i = 0; i < numArr.length; i++) {
              string += (numArr[i] < 16 ? '0': '') + numArr[i].toString(16);
          }
          return string;
      },
  
      h2a = function(s)
      {
          var ret = [];
          s.replace(/(..)/g,
          function(s) {
              ret.push(parseInt(s, 16));
          });
          return ret;
      },
  
      s2a = function(string, binary) {
          var array = [], i;
  
          if (! binary) {
              string = enc_utf8(string);
          }
  
          for (i = 0; i < string.length; i++)
          {
              array[i] = string.charCodeAt(i);
          }
  
          return array;
      },
  
      size = function(newsize)
      {
          switch (newsize)
          {
          case 128:
              Nr = 10;
              Nk = 4;
              break;
          case 192:
              Nr = 12;
              Nk = 6;
              break;
          case 256:
              Nr = 14;
              Nk = 8;
              break;
          default:
              throw ('Invalid Key Size Specified:' + newsize);
          }
      },
  
      randArr = function(num) {
          var result = [], i;
          for (i = 0; i < num; i++) {
              result = result.concat(Math.floor(Math.random() * 256));
          }
          return result;
      },
  
      openSSLKey = function(passwordArr, saltArr) {
          // Number of rounds depends on the size of the AES in use
          // 3 rounds for 256
          //        2 rounds for the key, 1 for the IV
          // 2 rounds for 128
          //        1 round for the key, 1 round for the IV
          // 3 rounds for 192 since it's not evenly divided by 128 bits
          var rounds = Nr >= 12 ? 3: 2,
          key = [],
          iv = [],
          md5_hash = [],
          result = [],
          data00 = passwordArr.concat(saltArr),
          i;
          md5_hash[0] = GibberishAES.Hash.MD5(data00);
          result = md5_hash[0];
          for (i = 1; i < rounds; i++) {
              md5_hash[i] = GibberishAES.Hash.MD5(md5_hash[i - 1].concat(data00));
              result = result.concat(md5_hash[i]);
          }
          key = result.slice(0, 4 * Nk);
          iv = result.slice(4 * Nk, 4 * Nk + 16);
          return {
              key: key,
              iv: iv
          };
      },
  
      rawEncrypt = function(plaintext, key, iv) {
          // plaintext, key and iv as byte arrays
          key = expandKey(key);
          var numBlocks = Math.ceil(plaintext.length / 16),
          blocks = [],
          i,
          cipherBlocks = [];
          for (i = 0; i < numBlocks; i++) {
              blocks[i] = padBlock(plaintext.slice(i * 16, i * 16 + 16));
          }
          if (plaintext.length % 16 === 0) {
              blocks.push([16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16]);
              // CBC OpenSSL padding scheme
              numBlocks++;
          }
          for (i = 0; i < blocks.length; i++) {
              blocks[i] = (i === 0) ? xorBlocks(blocks[i], iv) : xorBlocks(blocks[i], cipherBlocks[i - 1]);
              cipherBlocks[i] = encryptBlock(blocks[i], key);
          }
          return cipherBlocks;
      },
  
      rawDecrypt = function(cryptArr, key, iv, binary) {
          //  cryptArr, key and iv as byte arrays
          key = expandKey(key);
          var numBlocks = cryptArr.length / 16,
          cipherBlocks = [],
          i,
          plainBlocks = [],
          string = '';
          for (i = 0; i < numBlocks; i++) {
              cipherBlocks.push(cryptArr.slice(i * 16, (i + 1) * 16));
          }
          for (i = cipherBlocks.length - 1; i >= 0; i--) {
              plainBlocks[i] = decryptBlock(cipherBlocks[i], key);
              plainBlocks[i] = (i === 0) ? xorBlocks(plainBlocks[i], iv) : xorBlocks(plainBlocks[i], cipherBlocks[i - 1]);
          }
          for (i = 0; i < numBlocks - 1; i++) {
              string += block2s(plainBlocks[i]);
          }
          string += block2s(plainBlocks[i], true);
          return binary ? string : dec_utf8(string);
      },
  
      encryptBlock = function(block, words) {
          Decrypt = false;
          var state = addRoundKey(block, words, 0),
          round;
          for (round = 1; round < (Nr + 1); round++) {
              state = subBytes(state);
              state = shiftRows(state);
              if (round < Nr) {
                  state = mixColumns(state);
              }
              //last round? don't mixColumns
              state = addRoundKey(state, words, round);
          }
  
          return state;
      },
  
      decryptBlock = function(block, words) {
          Decrypt = true;
          var state = addRoundKey(block, words, Nr),
          round;
          for (round = Nr - 1; round > -1; round--) {
              state = shiftRows(state);
              state = subBytes(state);
              state = addRoundKey(state, words, round);
              if (round > 0) {
                  state = mixColumns(state);
              }
              //last round? don't mixColumns
          }
  
          return state;
      },
  
      subBytes = function(state) {
          var S = Decrypt ? SBoxInv: SBox,
          temp = [],
          i;
          for (i = 0; i < 16; i++) {
              temp[i] = S[state[i]];
          }
          return temp;
      },
  
      shiftRows = function(state) {
          var temp = [],
          shiftBy = Decrypt ? [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],
          i;
          for (i = 0; i < 16; i++) {
              temp[i] = state[shiftBy[i]];
          }
          return temp;
      },
  
      mixColumns = function(state) {
          var t = [],
          c;
          if (!Decrypt) {
              for (c = 0; c < 4; c++) {
                  t[c * 4] = G2X[state[c * 4]] ^ G3X[state[1 + c * 4]] ^ state[2 + c * 4] ^ state[3 + c * 4];
                  t[1 + c * 4] = state[c * 4] ^ G2X[state[1 + c * 4]] ^ G3X[state[2 + c * 4]] ^ state[3 + c * 4];
                  t[2 + c * 4] = state[c * 4] ^ state[1 + c * 4] ^ G2X[state[2 + c * 4]] ^ G3X[state[3 + c * 4]];
                  t[3 + c * 4] = G3X[state[c * 4]] ^ state[1 + c * 4] ^ state[2 + c * 4] ^ G2X[state[3 + c * 4]];
              }
          }else {
              for (c = 0; c < 4; c++) {
                  t[c*4] = GEX[state[c*4]] ^ GBX[state[1+c*4]] ^ GDX[state[2+c*4]] ^ G9X[state[3+c*4]];
                  t[1+c*4] = G9X[state[c*4]] ^ GEX[state[1+c*4]] ^ GBX[state[2+c*4]] ^ GDX[state[3+c*4]];
                  t[2+c*4] = GDX[state[c*4]] ^ G9X[state[1+c*4]] ^ GEX[state[2+c*4]] ^ GBX[state[3+c*4]];
                  t[3+c*4] = GBX[state[c*4]] ^ GDX[state[1+c*4]] ^ G9X[state[2+c*4]] ^ GEX[state[3+c*4]];
              }
          }
  
          return t;
      },
  
      addRoundKey = function(state, words, round) {
          var temp = [],
          i;
          for (i = 0; i < 16; i++) {
              temp[i] = state[i] ^ words[round][i];
          }
          return temp;
      },
  
      xorBlocks = function(block1, block2) {
          var temp = [],
          i;
          for (i = 0; i < 16; i++) {
              temp[i] = block1[i] ^ block2[i];
          }
          return temp;
      },
  
      expandKey = function(key) {
          // Expects a 1d number array
          var w = [],
          temp = [],
          i,
          r,
          t,
          flat = [],
          j;
  
          for (i = 0; i < Nk; i++) {
              r = [key[4 * i], key[4 * i + 1], key[4 * i + 2], key[4 * i + 3]];
              w[i] = r;
          }
  
          for (i = Nk; i < (4 * (Nr + 1)); i++) {
              w[i] = [];
              for (t = 0; t < 4; t++) {
                  temp[t] = w[i - 1][t];
              }
              if (i % Nk === 0) {
                  temp = subWord(rotWord(temp));
                  temp[0] ^= Rcon[i / Nk - 1];
              } else if (Nk > 6 && i % Nk == 4) {
                  temp = subWord(temp);
              }
              for (t = 0; t < 4; t++) {
                  w[i][t] = w[i - Nk][t] ^ temp[t];
              }
          }
          for (i = 0; i < (Nr + 1); i++) {
              flat[i] = [];
              for (j = 0; j < 4; j++) {
                  flat[i].push(w[i * 4 + j][0], w[i * 4 + j][1], w[i * 4 + j][2], w[i * 4 + j][3]);
              }
          }
          return flat;
      },
  
      subWord = function(w) {
          // apply SBox to 4-byte word w
          for (var i = 0; i < 4; i++) {
              w[i] = SBox[w[i]];
          }
          return w;
      },
  
      rotWord = function(w) {
          // rotate 4-byte word w left by one byte
          var tmp = w[0],
          i;
          for (i = 0; i < 4; i++) {
              w[i] = w[i + 1];
          }
          w[3] = tmp;
          return w;
      },
  
  // jlcooke: 2012-07-12: added strhex + invertArr to compress G2X/G3X/G9X/GBX/GEX/SBox/SBoxInv/Rcon saving over 7KB, and added encString, decString
      strhex = function(str,size) {
          var ret = [];
          for (i=0; i<str.length; i+=size)
              ret[i/size] = parseInt(str.substr(i,size), 16);
          return ret;
      },
      invertArr = function(arr) {
          var ret = [];
          for (i=0; i<arr.length; i++)
              ret[arr[i]] = i;
          return ret;
      },
      Gxx = function(a, b) {
          var i, ret;
  
          ret = 0;
          for (i=0; i<8; i++) {
              ret = ((b&1)==1) ? ret^a : ret;
              /* xmult */
              a = (a>0x7f) ? 0x11b^(a<<1) : (a<<1);
              b >>>= 1;
          }
  
          return ret;
      },
      Gx = function(x) {
          var r = [];
          for (var i=0; i<256; i++)
              r[i] = Gxx(x, i);
          return r;
      },
  
      // S-box
  /*
      SBox = [
      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], //*/ SBox = strhex('637c777bf26b6fc53001672bfed7ab76ca82c97dfa5947f0add4a2af9ca472c0b7fd9326363ff7cc34a5e5f171d8311504c723c31896059a071280e2eb27b27509832c1a1b6e5aa0523bd6b329e32f8453d100ed20fcb15b6acbbe394a4c58cfd0efaafb434d338545f9027f503c9fa851a3408f929d38f5bcb6da2110fff3d2cd0c13ec5f974417c4a77e3d645d197360814fdc222a908846eeb814de5e0bdbe0323a0a4906245cc2d3ac629195e479e7c8376d8dd54ea96c56f4ea657aae08ba78252e1ca6b4c6e8dd741f4bbd8b8a703eb5664803f60e613557b986c11d9ee1f8981169d98e949b1e87e9ce5528df8ca1890dbfe6426841992d0fb054bb16',2),
  
      // Precomputed lookup table for the inverse SBox
  /*    SBoxInv = [
      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], //*/ SBoxInv = invertArr(SBox),
  
      // Rijndael Rcon
  /*
      Rcon = [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],
  //*/ Rcon = strhex('01020408102040801b366cd8ab4d9a2f5ebc63c697356ad4b37dfaefc591',2),
  
  /*
      G2X = [
      0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16,
      0x18, 0x1a, 0x1c, 0x1e, 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e,
      0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, 0x40, 0x42, 0x44, 0x46,
      0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
      0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76,
      0x78, 0x7a, 0x7c, 0x7e, 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e,
      0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e, 0xa0, 0xa2, 0xa4, 0xa6,
      0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
      0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6,
      0xd8, 0xda, 0xdc, 0xde, 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee,
      0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe, 0x1b, 0x19, 0x1f, 0x1d,
      0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05,
      0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d,
      0x23, 0x21, 0x27, 0x25, 0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55,
      0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45, 0x7b, 0x79, 0x7f, 0x7d,
      0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65,
      0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d,
      0x83, 0x81, 0x87, 0x85, 0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5,
      0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5, 0xdb, 0xd9, 0xdf, 0xdd,
      0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5,
      0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed,
      0xe3, 0xe1, 0xe7, 0xe5
      ], //*/ G2X = Gx(2),
  
  /*    G3X = [
      0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d,
      0x14, 0x17, 0x12, 0x11, 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39,
      0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21, 0x60, 0x63, 0x66, 0x65,
      0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71,
      0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d,
      0x44, 0x47, 0x42, 0x41, 0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9,
      0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1, 0xf0, 0xf3, 0xf6, 0xf5,
      0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1,
      0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd,
      0xb4, 0xb7, 0xb2, 0xb1, 0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99,
      0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81, 0x9b, 0x98, 0x9d, 0x9e,
      0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a,
      0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6,
      0xbf, 0xbc, 0xb9, 0xba, 0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2,
      0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea, 0xcb, 0xc8, 0xcd, 0xce,
      0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda,
      0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46,
      0x4f, 0x4c, 0x49, 0x4a, 0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62,
      0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a, 0x3b, 0x38, 0x3d, 0x3e,
      0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a,
      0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16,
      0x1f, 0x1c, 0x19, 0x1a
      ], //*/ G3X = Gx(3),
  
  /*
      G9X = [
      0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53,
      0x6c, 0x65, 0x7e, 0x77, 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf,
      0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7, 0x3b, 0x32, 0x29, 0x20,
      0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
      0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8,
      0xc7, 0xce, 0xd5, 0xdc, 0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49,
      0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01, 0xe6, 0xef, 0xf4, 0xfd,
      0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91,
      0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e,
      0x21, 0x28, 0x33, 0x3a, 0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2,
      0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa, 0xec, 0xe5, 0xfe, 0xf7,
      0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b,
      0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f,
      0x10, 0x19, 0x02, 0x0b, 0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8,
      0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0, 0x47, 0x4e, 0x55, 0x5c,
      0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30,
      0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9,
      0xf6, 0xff, 0xe4, 0xed, 0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35,
      0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d, 0xa1, 0xa8, 0xb3, 0xba,
      0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6,
      0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62,
      0x5d, 0x54, 0x4f, 0x46
      ], //*/ G9X = Gx(9),
  
  /*    GBX = [
      0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45,
      0x74, 0x7f, 0x62, 0x69, 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81,
      0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9, 0x7b, 0x70, 0x6d, 0x66,
      0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12,
      0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e,
      0xbf, 0xb4, 0xa9, 0xa2, 0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7,
      0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f, 0x46, 0x4d, 0x50, 0x5b,
      0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f,
      0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8,
      0xf9, 0xf2, 0xef, 0xe4, 0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c,
      0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54, 0xf7, 0xfc, 0xe1, 0xea,
      0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e,
      0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02,
      0x33, 0x38, 0x25, 0x2e, 0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd,
      0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5, 0x3c, 0x37, 0x2a, 0x21,
      0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55,
      0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44,
      0x75, 0x7e, 0x63, 0x68, 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80,
      0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8, 0x7a, 0x71, 0x6c, 0x67,
      0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13,
      0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f,
      0xbe, 0xb5, 0xa8, 0xa3
      ], //*/ GBX = Gx(0xb),
  
  /*
      GDX = [
      0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f,
      0x5c, 0x51, 0x46, 0x4b, 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3,
      0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b, 0xbb, 0xb6, 0xa1, 0xac,
      0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0,
      0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14,
      0x37, 0x3a, 0x2d, 0x20, 0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e,
      0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26, 0xbd, 0xb0, 0xa7, 0xaa,
      0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6,
      0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9,
      0x8a, 0x87, 0x90, 0x9d, 0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25,
      0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d, 0xda, 0xd7, 0xc0, 0xcd,
      0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91,
      0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75,
      0x56, 0x5b, 0x4c, 0x41, 0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42,
      0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a, 0xb1, 0xbc, 0xab, 0xa6,
      0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa,
      0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8,
      0xeb, 0xe6, 0xf1, 0xfc, 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44,
      0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c, 0x0c, 0x01, 0x16, 0x1b,
      0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47,
      0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3,
      0x80, 0x8d, 0x9a, 0x97
      ], //*/ GDX = Gx(0xd),
  
  /*
      GEX = [
      0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62,
      0x48, 0x46, 0x54, 0x5a, 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca,
      0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba, 0xdb, 0xd5, 0xc7, 0xc9,
      0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81,
      0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59,
      0x73, 0x7d, 0x6f, 0x61, 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87,
      0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7, 0x4d, 0x43, 0x51, 0x5f,
      0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17,
      0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14,
      0x3e, 0x30, 0x22, 0x2c, 0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc,
      0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc, 0x41, 0x4f, 0x5d, 0x53,
      0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b,
      0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3,
      0xe9, 0xe7, 0xf5, 0xfb, 0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0,
      0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0, 0x7a, 0x74, 0x66, 0x68,
      0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20,
      0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e,
      0xa4, 0xaa, 0xb8, 0xb6, 0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26,
      0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56, 0x37, 0x39, 0x2b, 0x25,
      0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d,
      0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5,
      0x9f, 0x91, 0x83, 0x8d
      ], //*/ GEX = Gx(0xe),
  
      enc = function(string, pass, binary) {
          // string, password in plaintext
          var salt = randArr(8),
          pbe = openSSLKey(s2a(pass, binary), salt),
          key = pbe.key,
          iv = pbe.iv,
          cipherBlocks,
          saltBlock = [[83, 97, 108, 116, 101, 100, 95, 95].concat(salt)];
          string = s2a(string, binary);
          cipherBlocks = rawEncrypt(string, key, iv);
          // Spells out 'Salted__'
          cipherBlocks = saltBlock.concat(cipherBlocks);
          return Base64.encode(cipherBlocks);
      },
  
      dec = function(string, pass, binary) {
          // string, password in plaintext
          var cryptArr = Base64.decode(string),
          salt = cryptArr.slice(8, 16),
          pbe = openSSLKey(s2a(pass, binary), salt),
          key = pbe.key,
          iv = pbe.iv;
          cryptArr = cryptArr.slice(16, cryptArr.length);
          // Take off the Salted__ffeeddcc
          string = rawDecrypt(cryptArr, key, iv, binary);
          return string;
      },
  
      MD5 = function(numArr) {
  
          function rotateLeft(lValue, iShiftBits) {
              return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
          }
  
          function addUnsigned(lX, lY) {
              var lX4,
              lY4,
              lX8,
              lY8,
              lResult;
              lX8 = (lX & 0x80000000);
              lY8 = (lY & 0x80000000);
              lX4 = (lX & 0x40000000);
              lY4 = (lY & 0x40000000);
              lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
              if (lX4 & lY4) {
                  return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
              }
              if (lX4 | lY4) {
                  if (lResult & 0x40000000) {
                      return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
                  } else {
                      return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
                  }
              } else {
                  return (lResult ^ lX8 ^ lY8);
              }
          }
  
          function f(x, y, z) {
              return (x & y) | ((~x) & z);
          }
          function g(x, y, z) {
              return (x & z) | (y & (~z));
          }
          function h(x, y, z) {
              return (x ^ y ^ z);
          }
          function funcI(x, y, z) {
              return (y ^ (x | (~z)));
          }
  
          function ff(a, b, c, d, x, s, ac) {
              a = addUnsigned(a, addUnsigned(addUnsigned(f(b, c, d), x), ac));
              return addUnsigned(rotateLeft(a, s), b);
          }
  
          function gg(a, b, c, d, x, s, ac) {
              a = addUnsigned(a, addUnsigned(addUnsigned(g(b, c, d), x), ac));
              return addUnsigned(rotateLeft(a, s), b);
          }
  
          function hh(a, b, c, d, x, s, ac) {
              a = addUnsigned(a, addUnsigned(addUnsigned(h(b, c, d), x), ac));
              return addUnsigned(rotateLeft(a, s), b);
          }
  
          function ii(a, b, c, d, x, s, ac) {
              a = addUnsigned(a, addUnsigned(addUnsigned(funcI(b, c, d), x), ac));
              return addUnsigned(rotateLeft(a, s), b);
          }
  
          function convertToWordArray(numArr) {
              var lWordCount,
              lMessageLength = numArr.length,
              lNumberOfWords_temp1 = lMessageLength + 8,
              lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64,
              lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16,
              lWordArray = [],
              lBytePosition = 0,
              lByteCount = 0;
              while (lByteCount < lMessageLength) {
                  lWordCount = (lByteCount - (lByteCount % 4)) / 4;
                  lBytePosition = (lByteCount % 4) * 8;
                  lWordArray[lWordCount] = (lWordArray[lWordCount] | (numArr[lByteCount] << lBytePosition));
                  lByteCount++;
              }
              lWordCount = (lByteCount - (lByteCount % 4)) / 4;
              lBytePosition = (lByteCount % 4) * 8;
              lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
              lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
              lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
              return lWordArray;
          }
  
          function wordToHex(lValue) {
              var lByte,
              lCount,
              wordToHexArr = [];
              for (lCount = 0; lCount <= 3; lCount++) {
                  lByte = (lValue >>> (lCount * 8)) & 255;
                  wordToHexArr = wordToHexArr.concat(lByte);
               }
              return wordToHexArr;
          }
  
          /*function utf8Encode(string) {
              string = string.replace(/\r\n/g, "\n");
              var utftext = "",
              n,
              c;
  
              for (n = 0; n < string.length; n++) {
  
                  c = string.charCodeAt(n);
  
                  if (c < 128) {
                      utftext += String.fromCharCode(c);
                  }
                  else if ((c > 127) && (c < 2048)) {
                      utftext += String.fromCharCode((c >> 6) | 192);
                      utftext += String.fromCharCode((c & 63) | 128);
                  }
                  else {
                      utftext += String.fromCharCode((c >> 12) | 224);
                      utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                      utftext += String.fromCharCode((c & 63) | 128);
                  }
  
              }
  
              return utftext;
          }*/
  
          var x = [],
          k,
          AA,
          BB,
          CC,
          DD,
          a,
          b,
          c,
          d,
          rnd = strhex('67452301efcdab8998badcfe10325476d76aa478e8c7b756242070dbc1bdceeef57c0faf4787c62aa8304613fd469501698098d88b44f7afffff5bb1895cd7be6b901122fd987193a679438e49b40821f61e2562c040b340265e5a51e9b6c7aad62f105d02441453d8a1e681e7d3fbc821e1cde6c33707d6f4d50d87455a14eda9e3e905fcefa3f8676f02d98d2a4c8afffa39428771f6816d9d6122fde5380ca4beea444bdecfa9f6bb4b60bebfbc70289b7ec6eaa127fad4ef308504881d05d9d4d039e6db99e51fa27cf8c4ac5665f4292244432aff97ab9423a7fc93a039655b59c38f0ccc92ffeff47d85845dd16fa87e4ffe2ce6e0a30143144e0811a1f7537e82bd3af2352ad7d2bbeb86d391',8);
  
          x = convertToWordArray(numArr);
  
          a = rnd[0];
          b = rnd[1];
          c = rnd[2];
          d = rnd[3]
  
          for (k = 0; k < x.length; k += 16) {
              AA = a;
              BB = b;
              CC = c;
              DD = d;
              a = ff(a, b, c, d, x[k + 0], 7, rnd[4]);
              d = ff(d, a, b, c, x[k + 1], 12, rnd[5]);
              c = ff(c, d, a, b, x[k + 2], 17, rnd[6]);
              b = ff(b, c, d, a, x[k + 3], 22, rnd[7]);
              a = ff(a, b, c, d, x[k + 4], 7, rnd[8]);
              d = ff(d, a, b, c, x[k + 5], 12, rnd[9]);
              c = ff(c, d, a, b, x[k + 6], 17, rnd[10]);
              b = ff(b, c, d, a, x[k + 7], 22, rnd[11]);
              a = ff(a, b, c, d, x[k + 8], 7, rnd[12]);
              d = ff(d, a, b, c, x[k + 9], 12, rnd[13]);
              c = ff(c, d, a, b, x[k + 10], 17, rnd[14]);
              b = ff(b, c, d, a, x[k + 11], 22, rnd[15]);
              a = ff(a, b, c, d, x[k + 12], 7, rnd[16]);
              d = ff(d, a, b, c, x[k + 13], 12, rnd[17]);
              c = ff(c, d, a, b, x[k + 14], 17, rnd[18]);
              b = ff(b, c, d, a, x[k + 15], 22, rnd[19]);
              a = gg(a, b, c, d, x[k + 1], 5, rnd[20]);
              d = gg(d, a, b, c, x[k + 6], 9, rnd[21]);
              c = gg(c, d, a, b, x[k + 11], 14, rnd[22]);
              b = gg(b, c, d, a, x[k + 0], 20, rnd[23]);
              a = gg(a, b, c, d, x[k + 5], 5, rnd[24]);
              d = gg(d, a, b, c, x[k + 10], 9, rnd[25]);
              c = gg(c, d, a, b, x[k + 15], 14, rnd[26]);
              b = gg(b, c, d, a, x[k + 4], 20, rnd[27]);
              a = gg(a, b, c, d, x[k + 9], 5, rnd[28]);
              d = gg(d, a, b, c, x[k + 14], 9, rnd[29]);
              c = gg(c, d, a, b, x[k + 3], 14, rnd[30]);
              b = gg(b, c, d, a, x[k + 8], 20, rnd[31]);
              a = gg(a, b, c, d, x[k + 13], 5, rnd[32]);
              d = gg(d, a, b, c, x[k + 2], 9, rnd[33]);
              c = gg(c, d, a, b, x[k + 7], 14, rnd[34]);
              b = gg(b, c, d, a, x[k + 12], 20, rnd[35]);
              a = hh(a, b, c, d, x[k + 5], 4, rnd[36]);
              d = hh(d, a, b, c, x[k + 8], 11, rnd[37]);
              c = hh(c, d, a, b, x[k + 11], 16, rnd[38]);
              b = hh(b, c, d, a, x[k + 14], 23, rnd[39]);
              a = hh(a, b, c, d, x[k + 1], 4, rnd[40]);
              d = hh(d, a, b, c, x[k + 4], 11, rnd[41]);
              c = hh(c, d, a, b, x[k + 7], 16, rnd[42]);
              b = hh(b, c, d, a, x[k + 10], 23, rnd[43]);
              a = hh(a, b, c, d, x[k + 13], 4, rnd[44]);
              d = hh(d, a, b, c, x[k + 0], 11, rnd[45]);
              c = hh(c, d, a, b, x[k + 3], 16, rnd[46]);
              b = hh(b, c, d, a, x[k + 6], 23, rnd[47]);
              a = hh(a, b, c, d, x[k + 9], 4, rnd[48]);
              d = hh(d, a, b, c, x[k + 12], 11, rnd[49]);
              c = hh(c, d, a, b, x[k + 15], 16, rnd[50]);
              b = hh(b, c, d, a, x[k + 2], 23, rnd[51]);
              a = ii(a, b, c, d, x[k + 0], 6, rnd[52]);
              d = ii(d, a, b, c, x[k + 7], 10, rnd[53]);
              c = ii(c, d, a, b, x[k + 14], 15, rnd[54]);
              b = ii(b, c, d, a, x[k + 5], 21, rnd[55]);
              a = ii(a, b, c, d, x[k + 12], 6, rnd[56]);
              d = ii(d, a, b, c, x[k + 3], 10, rnd[57]);
              c = ii(c, d, a, b, x[k + 10], 15, rnd[58]);
              b = ii(b, c, d, a, x[k + 1], 21, rnd[59]);
              a = ii(a, b, c, d, x[k + 8], 6, rnd[60]);
              d = ii(d, a, b, c, x[k + 15], 10, rnd[61]);
              c = ii(c, d, a, b, x[k + 6], 15, rnd[62]);
              b = ii(b, c, d, a, x[k + 13], 21, rnd[63]);
              a = ii(a, b, c, d, x[k + 4], 6, rnd[64]);
              d = ii(d, a, b, c, x[k + 11], 10, rnd[65]);
              c = ii(c, d, a, b, x[k + 2], 15, rnd[66]);
              b = ii(b, c, d, a, x[k + 9], 21, rnd[67]);
              a = addUnsigned(a, AA);
              b = addUnsigned(b, BB);
              c = addUnsigned(c, CC);
              d = addUnsigned(d, DD);
          }
  
          return wordToHex(a).concat(wordToHex(b), wordToHex(c), wordToHex(d));
      },
  
      encString = function(plaintext, key, iv) {
          plaintext = s2a(plaintext);
  
          key = s2a(key);
          for (var i=key.length; i<32; i++)
              key[i] = 0;
  
          if (iv == null) {
              iv = genIV();
          } else {
              iv = s2a(iv);
              for (var i=iv.length; i<16; i++)
                  iv[i] = 0;
          }
  
          var ct = rawEncrypt(plaintext, key, iv);
          var ret = [iv];
          for (var i=0; i<ct.length; i++)
              ret[ret.length] = ct[i];
          return Base64.encode(ret);
      },
  
      decString = function(ciphertext, key) {
          var tmp = Base64.decode(ciphertext);
          var iv = tmp.slice(0, 16);
          var ct = tmp.slice(16, tmp.length);
  
          key = s2a(key);
          for (var i=key.length; i<32; i++)
              key[i] = 0;
  
          var pt = rawDecrypt(ct, key, iv, false);
          return pt;
      },
  
      Base64 = (function(){
          // Takes a Nx16x1 byte array and converts it to Base64
          var _chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
          chars = _chars.split(''),
  
          encode = function(b, withBreaks) {
              var flatArr = [],
              b64 = '',
              i,
              broken_b64;
              totalChunks = Math.floor(b.length * 16 / 3);
              for (i = 0; i < b.length * 16; i++) {
                  flatArr.push(b[Math.floor(i / 16)][i % 16]);
              }
              for (i = 0; i < flatArr.length; i = i + 3) {
                  b64 += chars[flatArr[i] >> 2];
                  b64 += chars[((flatArr[i] & 3) << 4) | (flatArr[i + 1] >> 4)];
                  if (! (flatArr[i + 1] === undefined)) {
                      b64 += chars[((flatArr[i + 1] & 15) << 2) | (flatArr[i + 2] >> 6)];
                  } else {
                      b64 += '=';
                  }
                  if (! (flatArr[i + 2] === undefined)) {
                      b64 += chars[flatArr[i + 2] & 63];
                  } else {
                      b64 += '=';
                  }
              }
              // OpenSSL is super particular about line breaks
              broken_b64 = b64.slice(0, 64); // + '\n';
              for (i = 1; i < (Math.ceil(b64.length / 64)); i++) {
                  broken_b64 += b64.slice(i * 64, i * 64 + 64) + (Math.ceil(b64.length / 64) == i + 1 ? '': '\n');
              }
              return broken_b64;
          },
  
          decode = function(string) {
              string = string.replace(/\n/g, '');
              var flatArr = [],
              c = [],
              b = [],
              i;
              for (i = 0; i < string.length; i = i + 4) {
                  c[0] = _chars.indexOf(string.charAt(i));
                  c[1] = _chars.indexOf(string.charAt(i + 1));
                  c[2] = _chars.indexOf(string.charAt(i + 2));
                  c[3] = _chars.indexOf(string.charAt(i + 3));
  
                  b[0] = (c[0] << 2) | (c[1] >> 4);
                  b[1] = ((c[1] & 15) << 4) | (c[2] >> 2);
                  b[2] = ((c[2] & 3) << 6) | c[3];
                  flatArr.push(b[0], b[1], b[2]);
              }
              flatArr = flatArr.slice(0, flatArr.length - (flatArr.length % 16));
              return flatArr;
          };
  
          //internet explorer
          if(typeof Array.indexOf === "function") {
              _chars = chars;
          }
  
          /*
          //other way to solve internet explorer problem
          if(!Array.indexOf){
              Array.prototype.indexOf = function(obj){
                  for(var i=0; i<this.length; i++){
                      if(this[i]===obj){
                          return i;
                      }
                  }
                  return -1;
              }
          }
          */
  
  
          return {
              "encode": encode,
              "decode": decode
          };
      })();
  
      return {
          "size": size,
          "h2a":h2a,
          "expandKey":expandKey,
          "encryptBlock":encryptBlock,
          "decryptBlock":decryptBlock,
          "Decrypt":Decrypt,
          "s2a":s2a,
          "rawEncrypt":rawEncrypt,
          "rawDecrypt":rawDecrypt,
          "dec":dec,
          "openSSLKey":openSSLKey,
          "a2h":a2h,
          "enc":enc,
          "Hash":{"MD5":MD5},
          "Base64":Base64
      };
  
  })();
  PUBNUB['secure'] = (function(){
      var crypto = PUBNUB['crypto'];
      crypto.size(256);
  
      var cipher_key = "";
      var iv = crypto.s2a("0123456789012345");
  
      function encrypt(data) {
          var hex_message = crypto.s2a(JSON.stringify(data));
          var encryptedHexArray = crypto.rawEncrypt(hex_message, cipher_key, iv);
          var base_64_encrypted = crypto.Base64.encode(encryptedHexArray);
          return base_64_encrypted || data.data.message;
      }
  
      function decrypt(data, options) {
          options = options ? options : {};
  
          try {
              var binary_enc = crypto.Base64.decode(data);
              var json_plain = crypto.rawDecrypt(binary_enc, cipher_key, iv, false);
              var plaintext = JSON.parse(json_plain);
  
              return plaintext;
          }
          catch (e) {
              return options.parse_error || null;
          }
      }
  
      return function (setup) {
          cipher_key = crypto.s2a(SHA256(setup.cipher_key).slice(0,32));
          var pubnub = PUBNUB.init(setup);
          return {
              raw_encrypt : encrypt,
              raw_decrypt : decrypt,
              time        : PUBNUB.time,
              publish     : function (args) {
                  args.message = encrypt(args.message);
                  return pubnub.publish(args);
              },
              subscribe   : function (args) {
                  var callback = args.callback || args.message;
                  args.callback = function (message, envelope, channel) {
                      var decrypted = decrypt(message);
                      decrypted && callback(decrypted, envelope, channel);
                  }
                  return pubnub.subscribe(args);
              },
              history     : function (args) {
                  var encrypted_messages = "";
                  var old_callback = args.callback;
  
                  function new_callback(response) {
                      encrypted_messages     = response[0];
                      var decrypted_messages = [];
  
                      for (a = 0; a < encrypted_messages.length; a++) {
                          var new_message = decrypt( encrypted_messages[a], {
                              "parse_error":"DECRYPT_ERROR"
                          } );
                          decrypted_messages.push((new_message));
                      }
  
                      old_callback([
                          decrypted_messages,
                          response[1],
                          response[2]
                      ]);
                  }
  
                  args.callback = new_callback;
                  pubnub.history(args);
                  return true;
              }
          };
      };
  })();
  
  function SHA256(s) {
  
      var chrsz = 8;
      var hexcase = 0;
  
      function safe_add(x, y) {
          var lsw = (x & 0xFFFF) + (y & 0xFFFF);
          var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
          return (msw << 16) | (lsw & 0xFFFF);
      }
  
      function S(X, n) {
          return ( X >>> n ) | (X << (32 - n));
      }
  
      function R(X, n) {
          return ( X >>> n );
      }
  
      function Ch(x, y, z) {
          return ((x & y) ^ ((~x) & z));
      }
  
      function Maj(x, y, z) {
          return ((x & y) ^ (x & z) ^ (y & z));
      }
  
      function Sigma0256(x) {
          return (S(x, 2) ^ S(x, 13) ^ S(x, 22));
      }
  
      function Sigma1256(x) {
          return (S(x, 6) ^ S(x, 11) ^ S(x, 25));
      }
  
      function Gamma0256(x) {
          return (S(x, 7) ^ S(x, 18) ^ R(x, 3));
      }
  
      function Gamma1256(x) {
          return (S(x, 17) ^ S(x, 19) ^ R(x, 10));
      }
  
      function core_sha256(m, l) {
          var K = new Array(0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 0xE49B69C1, 0xEFBE4786, 0xFC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x6CA6351, 0x14292967, 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2);
          var HASH = new Array(0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19);
          var W = new Array(64);
          var a, b, c, d, e, f, g, h, i, j;
          var T1, T2;
  
          m[l >> 5] |= 0x80 << (24 - l % 32);
          m[((l + 64 >> 9) << 4) + 15] = l;
  
          for (var i = 0; i < m.length; i += 16) {
              a = HASH[0];
              b = HASH[1];
              c = HASH[2];
              d = HASH[3];
              e = HASH[4];
              f = HASH[5];
              g = HASH[6];
              h = HASH[7];
  
              for (var j = 0; j < 64; j++) {
                  if (j < 16) W[j] = m[j + i];
                  else W[j] = safe_add(safe_add(safe_add(Gamma1256(W[j - 2]), W[j - 7]), Gamma0256(W[j - 15])), W[j - 16]);
  
                  T1 = safe_add(safe_add(safe_add(safe_add(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]);
                  T2 = safe_add(Sigma0256(a), Maj(a, b, c));
  
                  h = g;
                  g = f;
                  f = e;
                  e = safe_add(d, T1);
                  d = c;
                  c = b;
                  b = a;
                  a = safe_add(T1, T2);
              }
  
              HASH[0] = safe_add(a, HASH[0]);
              HASH[1] = safe_add(b, HASH[1]);
              HASH[2] = safe_add(c, HASH[2]);
              HASH[3] = safe_add(d, HASH[3]);
              HASH[4] = safe_add(e, HASH[4]);
              HASH[5] = safe_add(f, HASH[5]);
              HASH[6] = safe_add(g, HASH[6]);
              HASH[7] = safe_add(h, HASH[7]);
          }
          return HASH;
      }
  
      function str2binb(str) {
          var bin = Array();
          var mask = (1 << chrsz) - 1;
          for (var i = 0; i < str.length * chrsz; i += chrsz) {
              bin[i >> 5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - i % 32);
          }
          return bin;
      }
  
      function Utf8Encode(string) {
          string = string.replace(/\r\n/g, "\n");
          var utftext = "";
  
          for (var n = 0; n < string.length; n++) {
  
              var c = string.charCodeAt(n);
  
              if (c < 128) {
                  utftext += String.fromCharCode(c);
              }
              else if ((c > 127) && (c < 2048)) {
                  utftext += String.fromCharCode((c >> 6) | 192);
                  utftext += String.fromCharCode((c & 63) | 128);
              }
              else {
                  utftext += String.fromCharCode((c >> 12) | 224);
                  utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                  utftext += String.fromCharCode((c & 63) | 128);
              }
  
          }
  
          return utftext;
      }
  
      function binb2hex(binarray) {
          var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
          var str = "";
          for (var i = 0; i < binarray.length * 4; i++) {
              str += hex_tab.charAt((binarray[i >> 2] >> ((3 - i % 4) * 8 + 4)) & 0xF) +
                  hex_tab.charAt((binarray[i >> 2] >> ((3 - i % 4) * 8  )) & 0xF);
          }
          return str;
      }
  
      s = Utf8Encode(s);
      return binb2hex(core_sha256(str2binb(s), s.length * chrsz));
  }
  (function(){function n(c){b.each(d,function(a){if(a in g&&c in g[a]){var e=g[a][c];e.connected&&(e.connected=!1,e.socket.user_count--,b.events.fire(a+"leave",e))}})}function l(c,a,e,h,d){var k=j(a);b.publish({channel:k.channel,message:{name:c,ns:a,data:e,uuid:m,geo:k.location||[0,0]},callback:function(b){if(b[0])return(d||function(){})(b);var i=2*(h||500);setTimeout(function(){l(c,a,e,i,d)},5500<i?5500:i)}})}function o(c){c=c||function(){};navigator&&navigator.geolocation&&navigator.geolocation.getCurrentPosition(function(b){socket.location=
  [b.coords.latitude,b.coords.longitude];c(socket.location)})||c([0,0])}function j(c){var a=d[c]||(d[c]={namespace:c,connected:!1,users:g[c]={},user_count:1,get_user_list:function(){return d[c].users},get_user_count:function(){return d[c].user_count},emit:function(b,a,d){l(b,c,a,0,d)},send:function(b,a){l("message",c,b,0,a)},on:function(a,d){"string"===typeof a?b.events.bind(c+a,d):"object"===typeof a&&b.each(a,function(a){b.events.bind(c+a,d)})},disconnect:function(){b.unsubscribe({channel:a.channel})},
  history:function(a,d){var g=j(c);a.channel=g.channel;b.history(a,function(a){var b=[];PUBNUB.each(a[0]||[],function(a){"message"==a.name&&a.ns==c&&b.push(a)});a[0]=b;d(a)})},here_now:function(a){var d=j(c);b.here_now({channel:d.channel},a)}});return a}var b=PUBNUB,p=0,m=PUBNUB.db.get("uuid")||b.uuid(function(b){PUBNUB.db.set("uuid",m=b)}),d={},g={},q=window.io={connected:{},connect:function(c,a){function e(){var a=b.map(d,function(a){return a});l("ping",i,{nss:a,cuser:r})}var h=(c+"////").split("/"),
  a=a||{},r=a.user||{},k="presence"in a?a.presence:!0,s=h[2],i=(h[3]||"standard")+"-"+a.channel,h=a.channel,f=j(i);f.channel=h;f.password="GibberishAES"in window&&a.password;if(h in q.connected)return f;a.geo&&setInterval(o,15E3)&&o();a.uuid=m;a.origin=s;b=q.connected[h]=p?b:PUBNUB[f.password?"secure":"init"](a);p=1;f.disconnected=0;b.subscribe({channel:f.channel,disconnect:function(){f.disconnected||(f.disconnected=1,b.each(d,function(a){b.events.fire(a+"disconnect",{})}))},reconnect:function(){b.disconnected=
  0},connect:function(){f.disconnected=0;b.each(d,function(a){var c=j(a);c.connected||(c.connected=!0,b.events.fire(a+"connect",{}))});e()},presence:k&&function(a){"leave"===a.action&&n(a.uuid);"timeout"===a.action&&n(a.uuid);"join"===a.action&&e()},callback:function(a){f.disconnected&&b.each(d,function(a){b.events.fire(a+"reconnect",{})});f.disconnected=0;var c=a.data;a.ns in d&&c&&b.events.fire(a.ns+a.name,c);a.uuid&&a.uuid!==m&&"ping"===a.name&&b.each(c.nss,function(d){g[d]=g[d]||{};var e=g[d][a.uuid]=
  g[d][a.uuid]||{geo:a.geo||[0,0],uuid:a.uuid,last:+new Date,socket:f,namespace:d,connected:!1,slot:f.user_count++};e.last=+new Date;e.data=c.cuser;e.connected||(b.events.fire(d+"join",e),e.connected=!0)})}});k&&(setInterval(e,3E4),e());return f}}})();
  