\n\n▄████▄ ██▀███ ▓██ ██▓ ██▓███ ▄▄▄█████▓ ▄▄▄ ██▓ ██ ▄█▀ \n▒██▀ ▀█ ▓██ ▒ ██▒▒██ ██▒▓██░ ██▒▓ ██▒ ▓▒▒████▄ ▓██▒ ██▄█▒ \n▒▓█ ▄ ▓██ ░▄█ ▒ ▒██ ██░▓██░ ██▓▒▒ ▓██░ ▒░▒██ ▀█▄ ▒██░ ▓███▄░ \n▒▓▓▄ ▄██▒▒██▀▀█▄ ░ ▐██▓░▒██▄█▓▒ ▒░ ▓██▓ ░ ░██▄▄▄▄██ ▒██░ ▓██ █▄ \n▒ ▓███▀ ░░██▓ ▒██▒ ░ ██▒▓░▒██▒ ░ ░ ▒██▒ ░ ▓█ ▓██▒░██████▒▒██▒ █▄ \n░ ░▒ ▒ ░░ ▒▓ ░▒▓░ ██▒▒▒ ▒▓▒░ ░ ░ ▒ ░░ ▒▒ ▓▒█░░ ▒░▓ ░▒ ▒▒ ▓▒ \n ░ ▒ ░▒ ░ ▒░▓██ ░▒░ ░▒ ░ ░ ▒ ▒▒ ░░ ░ ▒ ░░ ░▒ ▒░ \n░ ░░ ░ ▒ ▒ ░░ ░░ ░ ░ ▒ ░ ░ ░ ░░ ░ \n░ ░ ░ ░ ░ ░ ░ ░ ░░ ░ \n░ ░ ░ \n https://github.com/hexagon/cryptalk \n \n Tip of the day: /help \n----------------------------------------------------------------------",nick:{maxLen:20,minLen:2},key:{maxLen:1024,minLen:8},room:{minLen:1,maxLen:64},notifications:{maxOnePerMs:3e3}}),define("templates",{help:" \nCryptalk, encrypted instant chat. \n \n----------------------------------------------------------------------\t\n \nClient: \t\t\t\n\t/key\t\tStrongPassphrase\tSets encryption key \n\t/nick\t\tNickName\t\tSets an optional nick \n\t/mute \t\t\t\t\tAudio on\t\t\t\t\t\t\t\t\t\n\t/unmute \t\t\t\tAudio off\t\t\t\t\t\t\t\t\t\n\t/clear\t\t\t\t\tClear on-screen buffer \n\t/help\t\t\t\t\tThis \n\t/title\t\t\t\t\tSet your local page title\t\t\t\t\t\n\t/torch\t\tAfterSeconds\t\tConsole messages are torched \t\t\n\t\t\t\t\t\tafter this amount of seconds \t\t\t\t\t\n\t\t\t\t\t\t(default 600).\t\t\t\t\t\t\t\t\t\n \nRoom: \t\t\t\t\n\t/join\t\tRoomId\t\t\tJoin a room\t \n\t/leave\t\t\t\t\tLeave the room \n\t/count\t\t\t\t\tCount participants \n \nHost: \t\t \t\n\t/hosts\t\t\t\t\tList available hosts \t\t\n\t/connect\tHostIndex\t\tConnect to selected host \t\n\t/disconnect\t\t\t\tDisconnect from host \t\t\t \n \nYou can select any of the five last commands/messages with up/down key.\n \nDue to security reasons, /key command is not saved, and command \nhistory is automatically cleared after one minute of inactivity. \n \nIt is highly recommended to use incognito mode while chatting, \nto prevent browsers from keeping history or cache. \n \n----------------------------------------------------------------------\t\n
",default_nick:"Anonymous",post:{motd:'{text}',info:'[{timestamp}] INF> {text}',server:'[{timestamp}] SRV> {text}',error:'[{timestamp}] ERR> {text}',message:'[{timestamp}] MSG> {nick}> {text}'},messages:{key_to_short:"Hmm, that's a weak key, try again...",key_to_long:"Man that's a long key. Make it a tad short, 'kay?",key_ok:"Key set, you can now start communicating.",key_no_host:"You have to connect to a host before setting the key.",join_no_host:"You have to connect to a host before joining a room.",nick_to_short:"Nickname is too short, it has to be at least {nick_minLen} characters long. Try again.",nick_to_long:"Nickname is too long, it can be at most {nick_maxLen} characters long. Try again.",nick_set:"From now on, you're referred to as '{nick}'.",msg_no_room:"You have to join a room before sending messages. See /help.",not_in_room:"You have to be in a room to count participants...",msg_no_key:"You have to set an encryption key before sending a message. See /help.",leave_from_nowhere:"How are you supposed to leave, while being nowhere?",torch_is_now:"Messages are now torched after {ttl} seconds.",torch_not_set:"Invalid torch delay entered, nothing changed. See /help.",title_set:"The title of this window is now '{title}'.",muted:"Notifications and sounds are now muted.",unmuted:"Notifications and sounds are now on.",unrecognized_command:'Unrecognized command: "{commandName}"',room_name_too_long:"Isn't that a bit long?",room_name_too_short:"Nah, too short.",joined_room:"Joined room {roomName}.",left_room:"Left room {roomName}.",already_in_room:"You are already in a room ({room}), stoopid.",unable_to_decrypt:"Unabled to decrypt received message, keys does not match.",socket_error:"A network error has occurred. A restart may be required to bring back full functionality.
Examine the logs for more details.",connecting:"Connecting to host {host}...",connected:"A connection to the server has been established. Happy chatting!",disconnected:"Disconnected from host {host}.",already_connected:"You have to disconnect from {host} before joining another.",reconnect_no_host:"There is no host to reconnect with.",host_available:'{index}\t[AVAILABLE]\t{name}\n',host_unavailable:'{index}\t[UNAVAILABLE]\t{name}\n'},server:{person_joined:"A person joined this room.",person_left:"A person left this room.",person_count:"There is {payload} person(s) in this room, including you.",command_failed:"Server command failed, you're probably trying to du something bogus.",bogus:"Received a bogus message from server."},client:{title:"Cryptalk - Offline"}}),define("hosts",{autoconnect:0,hosts:[{name:"default",host:"",path:"/js/lib/settings.js"}]}),define("window",["castrato"],function(t){var e={},n=function(){t.emit("window:focused")},o=function(){t.emit("window:blurred")};return e.setTitle=function(t){document.title=t},e.getTitle=function(){return document.title},window.addEventListener?(window.addEventListener("focus",n,!0),window.addEventListener("blur",o,!0)):(window.observe("focusin",n),window.observe("focusout",o)),t.on("window:title",e.setTitle),e}),define("host",["$","castrato","settings","templates","hosts","window"],function(t,e,n,o,i,r){var s,c,a={},u=function(t){s&&s.emit(t.data,t.payload)},c=function(){e.emit("info",JSON.stringify(c||{}))},f=function(n,r){var s,c=0,a=i.hosts.length,u="\n",f=function(n,i,s){return function(c){n.settings=s?c:0,u+=t.template(o.messages[s?"host_available":"host_unavailable"],{name:n.name,path:n.path,index:i}),0===--a&&(e.emit("console:info",u),r())}};for(n=n&&"force"===n.toLowerCase();s=i.hosts[c];)n||void 0===s.settings?require([s.path],f(s,c,1),f(s,c,0)):s.settings?f(s,c,1)():f(s,c,0)(),c++},d=function(r,u){e.emit("console:lockInput");var f,r=void 0==r?i.autoconnect:r;if(c&&c.connected)return e.emit("console:error",t.template(o.messages.already_connected,{host:c.name||"localhost"})),void e.emit("console:unlockInput");if(t.isDigits(r)){if(!(c=i.hosts[+r]))return e.emit("console:error","Undefined host index: "+r),void e.emit("console:unlockInput");c.settings?n=c.settings:f=c.path}else r?f=r.settings:n=r.settings;return f?require([f],function(t){return c.settings=t,d(r,u)},function(){e.emit("console:error","Could not fetch host settings: "+f),e.emit("console:unlockInput")}):(e.emit("console:info",t.template(o.messages.connecting,{host:c.name||"localhost"})),e.emit("console:motd",c.settings.motd),s=t.io(c.host,{forceNew:!0,"force new connection":!0}),void s.on("room:joined",function(n){e.emit("console:info",t.template(o.messages.joined_room,{roomName:t.escapeHtml(a.room)})),s.emit("room:count")}).on("room:left",function(){e.emit("console:info",t.template(o.messages.left_room,{roomName:t.escapeHtml(a.room)})),e.emit("room:changed",!1)}).on("message:send",function(n){var i=t.AES.decrypt(n.msg,t.SHA1(a.room)+a.key),r=t.escapeHtml(i),s=n.nick?t.escapeHtml(t.AES.decrypt(n.nick,t.SHA1(a.room)+a.key)):o.default_nick;i?e.emit("console:message",{message:r,nick:s}):e.emit("console:error",o.messages.unable_to_decrypt)}).on("message:server",function(n){if(n.msg){var i=t.escapeHtml(n.msg);if(o.server[i])if(void 0!==n.payload){var r=t.escapeHtml(n.payload);e.emit("console:server",t.template(o.server[i],{payload:r}))}else e.emit("console:server",o.server[i]);else e.emit("console:error",o.server.bogus)}else e.emit("console:error",o.server.bogus)}).on("connect",function(){e.emit("console:info",t.template(o.messages.connected,{host:c.name||"localhost"})),e.emit("window:title",c.settings.title),e.emit("console:unlockInput"),u(),c.connected=1}).on("disconnect",function(){room=0,key=0,c.connected=0,e.emit("console:info",t.template(o.messages.disconnected,{host:c.name||"localhost"})),e.emit("room:changed",void 0),e.emit("window:title",o.client.title)}).on("connect_error",function(){room=0,key=0,c.connected=0,e.emit("console:error",o.messages.socket_error),e.emit("console:unlockInput")}))},l=function(){s.disconnect()},m=function(t){a=Object.assign({},a,t)};e.on("command:host",c),e.on("command:hosts",f),e.on("command:connect",d),e.on("command:disconnect",l),e.on("command:reconnect",l),e.on("socket:emit",u),e.on("host:param",m)}),define("client",["$","castrato","settings","templates"],function(t,e,n,o){var i,r,s=function(t){return t.length>n.key.maxLen?e.emit("console:error",o.messages.key_to_long):t.lengthn.nick.maxLen?e("console:error",t.template(o.messages.nick_to_long,{nick_maxLen:n.nick.maxLen})):r.length=n.room.maxLen?e.emit("console:error",t.template(o.messages.room_name_too_long)):r.lengthn.notifications.maxOnePerMs)if(void 0===i&&(i=!1),u&&"granted"===Notification.permission){var r=new Notification(t,{body:e,icon:o});r.onshow=function(){setTimeout(function(){r.close()},3e3)},c=f()}else i&&g("Attention",1e3)};u=void 0!==window.Notification,t.on("notification:send",function(t){y(t.title,t.body,t.icon,!0)}),t.on("notification:on",function(){d()}),t.on("notification:off",function(){l()}),h(),l(),c=f(),m()}),define("queue",[],function(){var t={},e=[],n=function(){return performance.now()||Date.now()};return t.add_function_delayed=function(t,o,i){e.push({func:o,pushed:n(),delay:t,data:i})},t.get=function(){return e},t.run=function(){for(var o,i,r=0;o=e[r++];)n()-o.pushed>o.delay&&(o.func(),e.splice(r-1,1));if(e.length){for(i=n();n()-i<1;);t.run()}},t}),define("audio",["queue","castrato","templates"],function(t,e,n){var o=!1,i=!0,r=!1,s=function(e,n){if(n=void 0===n?0:n,o&&i&&n0&&i<3600?(e.emit("console:info",t.template(o.messages.torch_is_now,{ttl:i})),n.ttl=1e3*i):e.emit("console:error",t.template(o.messages.torch_not_set))},param:function(t){s=Object.assign({},s,t)},showNotification:function(t,n,o){var r="message"!==t?"Cryptalk":n,s="message"===t?"gfx/icon_128x128.png":"error"==t?"gfx/icon_128x128_error.png":"gfx/icon_128x128_info.png";e.emit("notification:send",{title:r.substring(0,20),body:o.substring(0,80),icon:s}),"message"===t&&e.emit("audio:play",i.message)},motd:function(t){c.post("motd",t)},info:function(t){c.post("info",t)},error:function(t){c.post("error",t)},server:function(t){c.post("server",t)},message:function(t){c.post("message",t.message,t.nick)},clearInput:function(){r.input[0].value=""},clear:function(){r.chat[0].innerHTML=""},lockInput:function(){r.input[0].setAttribute("disabled","disabled"),r.inputWrapper[0].className="loading"},unlockInput:function(){r.input[0].removeAttribute("disabled"),r.inputWrapper[0].className="",r.input.focus()},_require:function(t,e){c.lockInput(),c.post("info","Requiring "+t+"..."),require([t],function(){c.post("info","Successfully required "+t+"."),c.unlockInput(),e()},function(n){c.post("error",'An error occurred while trying to load "'+t+'":\n'+n),c.unlockInput(),e()})}},a=function(n){var i,a,u,f;if(!n.ctrlKey&&!n.altKey&&r.input[0]!==t.activeElement())return r.input.focus();if(13===n.keyCode&&(i=r.input[0].value))if("/"===(i[0]||i.slice(0,1)))a=t.ssplit(i.slice(1)," "),f=a[0],u=a[1],e.emit("command:"+f,u,function(e,n){return n?void c.clearInput():c.post("error",t.template(o.messages.unrecognized_command,{commandName:f}))});else{if(!s.room||!s.key)return s.room?c.post("error",o.messages.msg_no_key):c.post("error",o.messages.msg_no_room);e.emit("socket:emit",{data:"message:send",payload:{room:t.SHA1(s.room),msg:t.AES.encrypt(i,t.SHA1(s.room)+s.key).toString(),nick:!!s.nick&&t.AES.encrypt(s.nick,t.SHA1(s.room)+s.key).toString()}}),c.clearInput()}};t(document).on("keydown",a),r.input.focus();for(var u in c)"_require"!==u&&"post"!==u&&e.on("console:"+u,c[u]);e.on("console:require",c._require),e.on("console:post",function(t){c.post(t.type,t.data,t.nick)})}),define("cryptalk",["castrato","host","client","console"],function(t,e,n){t.on("window:focused",function(){t.emit("audio:off"),t.emit("notification:off")}).on("window:blurred",function(){t.emit("audio:on"),t.emit("notification:on")}).on("command:mute",function(){t.emit("audio:mute")}).on("command:unmute",function(){t.emit("audio:unmute")}).on("room:changed",function(e){t.emit("console:param",{room:e}).emit("host:param",{room:e})}).on("nick:changed",function(e){t.emit("console:param",{nick:e})}).on("key:changed",function(e){t.emit("console:param",{key:e}).emit("host:param",{key:e})}).emit("command:connect",void 0,function(){(hash=window.location.hash)&&(parts=hash.slice(1).split(":"),parts[0]&&t.emit("command:join",parts[0]),parts[1]&&t.emit("command:key",parts[1]))})}),require.config({baseUrl:"js/lib/",paths:{websocket:"/socket.io/socket.io"},packages:[{name:"crypto-js",location:"../vendor/crypto-js-3.1.9",main:"index"}]}),require(["cryptalk"]),define("main",function(){});
\ No newline at end of file
diff --git a/public/js/lib/$.js b/public/js/lib/$.js
index 0a46c30..6442782 100644
--- a/public/js/lib/$.js
+++ b/public/js/lib/$.js
@@ -1,9 +1,8 @@
define(['$.utils', '$.proto'], function (utils, proto) {
// Create a custom edition of Array, extended with $.proto
- var ElementArray = function () {};
+ function ElementArray () {};
ElementArray.prototype = new Array;
- ElementArray.constructor = Array;
for(var key in proto) ElementArray.prototype[key] = proto[key];
// Create to actual dollar function