Initial commit
This commit is contained in:
		
							parent
							
								
									888d9ebc1f
								
							
						
					
					
						commit
						138eff9c96
					
				
					 11 changed files with 603 additions and 0 deletions
				
			
		
							
								
								
									
										80
									
								
								public/css/default.css
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								public/css/default.css
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,80 @@
 | 
			
		|||
/*------------------------------------*\
 | 
			
		||||
	GENERIC
 | 
			
		||||
\*------------------------------------*/
 | 
			
		||||
html {
 | 
			
		||||
	-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
 | 
			
		||||
	-moz-box-sizing: border-box;    /* Firefox, other Gecko */
 | 
			
		||||
	box-sizing: border-box;         /* Opera/IE 8+ */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
*, *:before, *:after {
 | 
			
		||||
	box-sizing: inherit;
 | 
			
		||||
 | 
			
		||||
	font-family: monospace, 'Courier New';
 | 
			
		||||
	font-size: 12px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
body, html {
 | 
			
		||||
	min-height: 100%;
 | 
			
		||||
	background-color: #000000;
 | 
			
		||||
	overflow: hidden;
 | 
			
		||||
	padding: 0px;
 | 
			
		||||
	margin:0px;
 | 
			
		||||
	color: #00DD00;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*------------------------------------*\
 | 
			
		||||
	CHAT
 | 
			
		||||
\*------------------------------------*/
 | 
			
		||||
#chat {
 | 
			
		||||
	left: 0;
 | 
			
		||||
	right: 0;
 | 
			
		||||
	bottom: 40px;
 | 
			
		||||
	position: absolute;
 | 
			
		||||
	list-style-type: none;
 | 
			
		||||
	padding:0;
 | 
			
		||||
	margin:0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Messages */
 | 
			
		||||
#chat li {
 | 
			
		||||
	white-space: pre;
 | 
			
		||||
	padding: 2px 10px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Message types */
 | 
			
		||||
/* the `i` element hold the actual message */
 | 
			
		||||
#chat i {
 | 
			
		||||
	font-style: normal;
 | 
			
		||||
}
 | 
			
		||||
#chat i.info	{ color: #7777ff; }
 | 
			
		||||
#chat i.server	{ color: #999999; }
 | 
			
		||||
#chat i.error	{ color: #ff7777; }
 | 
			
		||||
#chat i.message	{ color: #eeeeee; }
 | 
			
		||||
 | 
			
		||||
/*------------------------------------*\
 | 
			
		||||
	INPUT
 | 
			
		||||
\*------------------------------------*/
 | 
			
		||||
#input_wrapper {
 | 
			
		||||
	right:0;
 | 
			
		||||
	bottom:0;
 | 
			
		||||
	left:0;
 | 
			
		||||
	position: absolute;
 | 
			
		||||
 | 
			
		||||
	height:40px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#input {
 | 
			
		||||
	top: 0;
 | 
			
		||||
	bottom: 0;
 | 
			
		||||
	width: 100%;
 | 
			
		||||
	position: absolute;
 | 
			
		||||
 | 
			
		||||
	border: 0;
 | 
			
		||||
	outline: 0;
 | 
			
		||||
 | 
			
		||||
	padding: 5px 5px 5px 15px;
 | 
			
		||||
 | 
			
		||||
	color: #00dd00;
 | 
			
		||||
	background-color:#141414;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										27
									
								
								public/index.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								public/index.html
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
<!doctype html>
 | 
			
		||||
<head>
 | 
			
		||||
	<meta charset="utf-8">
 | 
			
		||||
	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
 | 
			
		||||
	<title>Cryptalk</title>
 | 
			
		||||
 | 
			
		||||
	<link rel="stylesheet" type="text/css" href="css/default.css">
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
 | 
			
		||||
	<!-- Messages -->
 | 
			
		||||
	<!-- Each message is contained within an li element -->
 | 
			
		||||
	<ul id="chat">
 | 
			
		||||
		<li>SRV> Booting ...</li>
 | 
			
		||||
	</ul>
 | 
			
		||||
 | 
			
		||||
	<!-- Message input -->
 | 
			
		||||
	<div id="input_wrapper">
 | 
			
		||||
		<input type="text" id="input" />
 | 
			
		||||
	</div>
 | 
			
		||||
	
 | 
			
		||||
	<!-- Only include the script needed for loading the app -->
 | 
			
		||||
	<script src="js/vendor/fandango.v20140918.min.js"></script>
 | 
			
		||||
	<script src="js/bootstrap.js"></script>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										30
									
								
								public/js/bootstrap.js
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								public/js/bootstrap.js
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
// This Javascript file is the only file besides fandango.js that will be fetched through DOM.
 | 
			
		||||
 | 
			
		||||
// Setup fandango
 | 
			
		||||
fandango.defaults({
 | 
			
		||||
	baseUrl: 'js/cryptalk_modules/',
 | 
			
		||||
	paths: {
 | 
			
		||||
		websocket: 'https://cdnjs.cloudflare.com/ajax/libs/socket.io/0.9.16/socket.io.min.js',
 | 
			
		||||
		aes: 'https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js',
 | 
			
		||||
		domReady: 'https://cdnjs.cloudflare.com/ajax/libs/require-domReady/2.0.1/domReady.min.js'
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	// CryptoJs AES does not support AMD modules. We'll have to create a shim.
 | 
			
		||||
	shim: {
 | 
			
		||||
		aes: {
 | 
			
		||||
			exports: function () { // String (the global variable name) or a function; returning the desired variable.
 | 
			
		||||
				return CryptoJS.AES;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// Fetch our modules asynchronously, when the DOM is finished loading.
 | 
			
		||||
//define('bootstrap_module', ['domReady'], function (domReady) {
 | 
			
		||||
//	domReady(function () {
 | 
			
		||||
//		require(['cryptalk']);
 | 
			
		||||
//	});
 | 
			
		||||
//});
 | 
			
		||||
 | 
			
		||||
// No need to wait for DOM - the Javascript is at the bottom
 | 
			
		||||
require(['cryptalk']);
 | 
			
		||||
							
								
								
									
										129
									
								
								public/js/cryptalk_modules/$.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								public/js/cryptalk_modules/$.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,129 @@
 | 
			
		|||
define('$', ['fandango', 'websocket', 'aes'], function (fandango, websocket, aes) {
 | 
			
		||||
	var exports = {
 | 
			
		||||
			selector: 0,
 | 
			
		||||
			utilities: {},
 | 
			
		||||
			prototype: {}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// Shortcuts
 | 
			
		||||
		utils = exports.utilities,
 | 
			
		||||
		proto = exports.prototype,
 | 
			
		||||
 | 
			
		||||
		each = fandango.each;
 | 
			
		||||
 | 
			
		||||
	// The DOM selector engine
 | 
			
		||||
	exports.selector = function (selector) {
 | 
			
		||||
		var match,
 | 
			
		||||
			matches = [];
 | 
			
		||||
 | 
			
		||||
		if (selector === document) {
 | 
			
		||||
			matches.push(document);
 | 
			
		||||
		} else {
 | 
			
		||||
			selector = selector.slice(1);
 | 
			
		||||
 | 
			
		||||
			if (match = document.getElementById(selector)) {
 | 
			
		||||
				matches.push(match);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Must ALWAYS return a native array: []
 | 
			
		||||
		return matches;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	// Namespace AES
 | 
			
		||||
	utils.AES = {
 | 
			
		||||
		decrypt: aes.decrypt,
 | 
			
		||||
		encrypt: aes.encrypt
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	// Namespace encode
 | 
			
		||||
	utils.AES = {
 | 
			
		||||
		decrypt: function (string, fgh) {
 | 
			
		||||
			return aes.decrypt(string, fgh).toString(CryptoJS.enc.Utf8);
 | 
			
		||||
		},
 | 
			
		||||
		encrypt: function (string, fgh) {
 | 
			
		||||
			return aes.encrypt(string, fgh).toString();
 | 
			
		||||
		},
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	// Namespace websocket
 | 
			
		||||
	utils.Websocket = {
 | 
			
		||||
		connect: websocket.connect,
 | 
			
		||||
		on: websocket.on
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	utils.ssplit = function (string, seperator) {
 | 
			
		||||
		var components = string.split(seperator);
 | 
			
		||||
		return [components.shift(), components.join(seperator)];
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	utils.activeElement = function () {
 | 
			
		||||
		try { return document.activeElement; } catch (e) {}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * A very simple implementation of sprintf()
 | 
			
		||||
	 * @param  {} str [description]
 | 
			
		||||
	 * @param  {[type]} map [description]
 | 
			
		||||
	 * @return {[type]}     [description]
 | 
			
		||||
	 */
 | 
			
		||||
	utils.template = function (str, map) {
 | 
			
		||||
		return str && str.replace(/{(\w+)}/gi, function(outer, inner) {
 | 
			
		||||
			return map.hasOwnProperty(inner) ? map[inner] : outer /* '' */;
 | 
			
		||||
		});
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	// Originating from mustasche.js
 | 
			
		||||
	// https://github.com/janl/mustache.js/blob/master/mustache.js#L43
 | 
			
		||||
	utils.escapeHtml = (function () {
 | 
			
		||||
		var pattern = /[&<>"'\/]/g,
 | 
			
		||||
			entities = {
 | 
			
		||||
				'&': '&',
 | 
			
		||||
				'<': '<',
 | 
			
		||||
				'>': '>',
 | 
			
		||||
				'"': '"',
 | 
			
		||||
				"'": ''',
 | 
			
		||||
				'/': '/'
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
		return function (string) {
 | 
			
		||||
			return String(string).replace(pattern, function (s) {
 | 
			
		||||
				return entities[s];
 | 
			
		||||
			});
 | 
			
		||||
		};
 | 
			
		||||
	}());
 | 
			
		||||
 | 
			
		||||
	// Extremely naive implementations of .html() and .append()
 | 
			
		||||
	proto.html = function (string) {
 | 
			
		||||
		each(this, function (element) {
 | 
			
		||||
			element.innerHTML = string;
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		return this;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	proto.append = function (string) {
 | 
			
		||||
		each(this, function (element) {
 | 
			
		||||
			element.innerHTML += string;
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		return this;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	// Extremely naive implementations of .on()
 | 
			
		||||
	proto.on = function (eventName, callback) {
 | 
			
		||||
		each(this, function (element) {
 | 
			
		||||
			element.addEventListener(eventName, callback);
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		return this;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	proto.focus = function () {
 | 
			
		||||
		this[0].focus();
 | 
			
		||||
 | 
			
		||||
		return this;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	return exports;
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										187
									
								
								public/js/cryptalk_modules/cryptalk.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								public/js/cryptalk_modules/cryptalk.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,187 @@
 | 
			
		|||
// Main cryptalk module. Will be called by bootstrap.js when the DOM is ready to interact with.
 | 
			
		||||
define('cryptalk', {
 | 
			
		||||
	data: {
 | 
			
		||||
		// If no host is given it will default to localhost.
 | 
			
		||||
		host: 'http://www.huset.nu:8080'
 | 
			
		||||
	},
 | 
			
		||||
	compiles: ['$'],
 | 
			
		||||
	requires: ['templates']
 | 
			
		||||
}, function ($, requires, data) {
 | 
			
		||||
	var socket,
 | 
			
		||||
		key,
 | 
			
		||||
		room,
 | 
			
		||||
		hash,
 | 
			
		||||
 | 
			
		||||
		// Collection of DOM components
 | 
			
		||||
		components = {
 | 
			
		||||
			chat: 	$('#chat'),
 | 
			
		||||
			input: 	$('#input')
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// Shortcut
 | 
			
		||||
		templates = requires.templates,
 | 
			
		||||
 | 
			
		||||
		// Adds a new message to the DOM
 | 
			
		||||
		post = function (type, text, clearChat, clearBuffer) {
 | 
			
		||||
			var tpl = templates.post[type],
 | 
			
		||||
				post = $.template(tpl, text && {
 | 
			
		||||
					text: text
 | 
			
		||||
				});
 | 
			
		||||
 | 
			
		||||
			// Always clear the input after a post
 | 
			
		||||
			if (clearBuffer) {
 | 
			
		||||
				components.input[0].value = '';
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Append the post to the chat DOM element
 | 
			
		||||
			components.chat[clearChat ? 'html' : 'append'](post);
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// Chat related commands
 | 
			
		||||
		commands = {
 | 
			
		||||
			help: function () {
 | 
			
		||||
				post('info', templates.help);
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			clear: function () {
 | 
			
		||||
				components.chat.html('');
 | 
			
		||||
				components.input[0].value = '';
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			leave: function () {
 | 
			
		||||
				socket.emit('room:leave', room);
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			key: function (payload) {
 | 
			
		||||
				// Make sure the key meets the length requirements
 | 
			
		||||
				if (payload.length < 8) {
 | 
			
		||||
					return post('info', templates.messages.key_weak);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// Set key
 | 
			
		||||
				key = payload;
 | 
			
		||||
 | 
			
		||||
				// Inform that the key has been set
 | 
			
		||||
				post('info', (room ? templates.messages.key_ok_ready : templates.messages.key_ok_but_no_room));
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			join: function (payload) {
 | 
			
		||||
				return (
 | 
			
		||||
					room
 | 
			
		||||
						? post('info', $.template(templates.messages.already_in_room, { roomName: room}))
 | 
			
		||||
						: socket.emit('room:join', payload)
 | 
			
		||||
				);
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			create: function (payload) {
 | 
			
		||||
				socket.emit('room:create');
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// Handler for the document`s keyDown-event.
 | 
			
		||||
		onKeyDown = function (e) {
 | 
			
		||||
			var buffer,
 | 
			
		||||
				parts,
 | 
			
		||||
				payload,
 | 
			
		||||
				command;
 | 
			
		||||
 | 
			
		||||
			// The Document object is bound to this element.
 | 
			
		||||
			// If the active element is not the input, focus on it and exit the function.
 | 
			
		||||
			if (components.input[0] !== $.activeElement()) {
 | 
			
		||||
				return components.input.focus();
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Return immediatly if the buffer is empty or if the hit key was not <enter>
 | 
			
		||||
			if (e.keyCode !== 13 || !(buffer = components.input[0].value)) {
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Handle command
 | 
			
		||||
			if (buffer[0] === '/') {
 | 
			
		||||
				parts = $.ssplit(buffer.slice(1), ' ');
 | 
			
		||||
				command = parts[0];
 | 
			
		||||
				payload = parts[1];
 | 
			
		||||
 | 
			
		||||
				// Check that there is an handler for this command
 | 
			
		||||
				if (!commands[command]) {
 | 
			
		||||
					return post('error', $.template(templates.messages.unrecognized_command, { commandName: command }));
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// Execute command handler
 | 
			
		||||
				commands[command](payload);
 | 
			
		||||
			} else /* Handle ordinary message */ {
 | 
			
		||||
				// Make sure that the users has joined a room
 | 
			
		||||
				if (!room) {
 | 
			
		||||
					return post('error', templates.messages.msg_no_room);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// And that a valid key is set
 | 
			
		||||
				if (!key) {
 | 
			
		||||
					return post('error', templates.messages.msg_no_key);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// Before sending the message.
 | 
			
		||||
				// Encrypt message using room UUID as salt and key as pepper.
 | 
			
		||||
				socket.emit('message:send', {
 | 
			
		||||
					room: room,
 | 
			
		||||
					msg: $.AES.encrypt(buffer, room + key)
 | 
			
		||||
				});
 | 
			
		||||
 | 
			
		||||
				// Adn the the buffer
 | 
			
		||||
				components.input[0].value = '';
 | 
			
		||||
			}
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
	// Connect to server
 | 
			
		||||
	socket = $.Websocket.connect(data.host);
 | 
			
		||||
 | 
			
		||||
	// Bind socket events
 | 
			
		||||
	socket
 | 
			
		||||
		.on('connect', function () {
 | 
			
		||||
			$(document).on('keydown', onKeyDown);
 | 
			
		||||
			components.input.focus();
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
		.on('room:created', function (data) {
 | 
			
		||||
			socket.emit('room:join', data);
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
		.on('room:joined', function (data) {
 | 
			
		||||
			room = data;
 | 
			
		||||
			post('info', $.template(templates.messages.joined_room, { roomName: room }));
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
		.on('room:left', function () {
 | 
			
		||||
			post('info', $.template(templates.messages.left_room, { roomName: room }));
 | 
			
		||||
			room = false;
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
		.on('message:send', function (data) {
 | 
			
		||||
			var decrypted = $.AES.decrypt(data, room + key),
 | 
			
		||||
				sanitized = $.escapeHtml(decrypted);
 | 
			
		||||
 | 
			
		||||
			if (!decrypted) {
 | 
			
		||||
				post('info', templates.messages.unable_to_decrypt);
 | 
			
		||||
			} else {
 | 
			
		||||
				// Post the message, but do not clear either the chat nor the buffer.
 | 
			
		||||
				post('message', sanitized, false, false);
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
		.on('message:server', function (data) {
 | 
			
		||||
			post('server', data);
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
	// Post the help/welcome message
 | 
			
		||||
	post('info', templates.help, true);
 | 
			
		||||
 | 
			
		||||
	// It's possible to provide room and key using the hashtag.
 | 
			
		||||
	// The room and key is then seperated by semicolon (room:key).
 | 
			
		||||
	// If there is no semicolon present, the complete hash will be treated as the room name and the key has to be set manually.
 | 
			
		||||
	if (hash = window.location.hash) {
 | 
			
		||||
		parts = hash.slice(1).split(':');
 | 
			
		||||
 | 
			
		||||
		parts[0] && commands.join(parts[0]);
 | 
			
		||||
		parts[1] && commands.key(parts[1]);
 | 
			
		||||
	}
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										50
									
								
								public/js/cryptalk_modules/templates.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								public/js/cryptalk_modules/templates.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,50 @@
 | 
			
		|||
// The templating function only supports variables.
 | 
			
		||||
// Define a variable as so: {variable_name}
 | 
			
		||||
define({
 | 
			
		||||
	help: '' +
 | 
			
		||||
		'<li>																				\n' +
 | 
			
		||||
		'Cryptalk, encrypted instant chat.													\n' +
 | 
			
		||||
		' 																					\n' +
 | 
			
		||||
		'----------------------------------------------------------------------------------	\n' +
 | 
			
		||||
		' 																					\n' +
 | 
			
		||||
		'Available commands: 																\n' +
 | 
			
		||||
		' 	/create 					Creates a room 										\n' +
 | 
			
		||||
		'	/join		RoomId				Joins a room									\n' +
 | 
			
		||||
		'	/leave		RoomId				Leaves a room									\n' +
 | 
			
		||||
		'	/key		OurStrongPassphrase		Sets the password used for 					\n' +
 | 
			
		||||
		'	 						encryption/decryption 									\n' +
 | 
			
		||||
		'	/clear						Clears on-screen buffer 							\n' +
 | 
			
		||||
		'	/help						This 												\n' +
 | 
			
		||||
		'	 																				\n' +
 | 
			
		||||
		'	Besides that, it\'s just to talk! 												\n' +
 | 
			
		||||
		'	 																				\n' +
 | 
			
		||||
		'Code available for review at https://www.github.com/hexagon/cryptalk 				\n' +
 | 
			
		||||
		'																					\n' +
 | 
			
		||||
		'---------------------------------------------------------------------------------	\n' +
 | 
			
		||||
		'</li>																				',
 | 
			
		||||
 | 
			
		||||
	post: {
 | 
			
		||||
		info: 		'<li>INF> <i class="info">{text}</i></li>',
 | 
			
		||||
		server: 	'<li>SRV> <i class="server">{text}</i></li>',
 | 
			
		||||
		error: 		'<li>ERR> <i class="error">{text}</i></li>',
 | 
			
		||||
		message: 	'<li>MSG> <i class="message">{text}</i></li>'
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	messages: {
 | 
			
		||||
		key_weak: 				'Hmm, that\'s a weak key, try again...',
 | 
			
		||||
		key_ok_ready: 			'Key set, you can now start communicating.',
 | 
			
		||||
		key_ok_but_no_room: 	'Key set, you can now join a room and start communicating.',
 | 
			
		||||
		msg_no_room: 			'You have to join a room before sending messages. See /help.',
 | 
			
		||||
		msg_no_key: 			'You have to set an encryption key before sending a message. See /help.',
 | 
			
		||||
 | 
			
		||||
		// Available variables: 'commandName'
 | 
			
		||||
		unrecognized_command: 	'Unrecognized command: "{commandName}"',
 | 
			
		||||
 | 
			
		||||
		// Available variables: 'roomName'
 | 
			
		||||
		joined_room: 			'Joined room {roomName}',
 | 
			
		||||
		left_room: 				'Left room {roomName}',
 | 
			
		||||
		already_in_room: 		'You are already in room {roomName}, stoopid.',
 | 
			
		||||
 | 
			
		||||
		unable_to_decrypt: 		'Unabled to decrypt received message, keys does not match.'
 | 
			
		||||
	}
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										10
									
								
								public/js/vendor/aes.v3.1.2.min.js
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								public/js/vendor/aes.v3.1.2.min.js
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
/*
 | 
			
		||||
CryptoJS v3.1.2
 | 
			
		||||
code.google.com/p/crypto-js
 | 
			
		||||
(c) 2009-2013 by Jeff Mott. All rights reserved.
 | 
			
		||||
code.google.com/p/crypto-js/wiki/License
 | 
			
		||||
*/
 | 
			
		||||
(function(){for(var q=CryptoJS,x=q.lib.BlockCipher,r=q.algo,j=[],y=[],z=[],A=[],B=[],C=[],s=[],u=[],v=[],w=[],g=[],k=0;256>k;k++)g[k]=128>k?k<<1:k<<1^283;for(var n=0,l=0,k=0;256>k;k++){var f=l^l<<1^l<<2^l<<3^l<<4,f=f>>>8^f&255^99;j[n]=f;y[f]=n;var t=g[n],D=g[t],E=g[D],b=257*g[f]^16843008*f;z[n]=b<<24|b>>>8;A[n]=b<<16|b>>>16;B[n]=b<<8|b>>>24;C[n]=b;b=16843009*E^65537*D^257*t^16843008*n;s[f]=b<<24|b>>>8;u[f]=b<<16|b>>>16;v[f]=b<<8|b>>>24;w[f]=b;n?(n=t^g[g[g[E^t]]],l^=g[g[l]]):n=l=1}var F=[0,1,2,4,8,
 | 
			
		||||
16,32,64,128,27,54],r=r.AES=x.extend({_doReset:function(){for(var c=this._key,e=c.words,a=c.sigBytes/4,c=4*((this._nRounds=a+6)+1),b=this._keySchedule=[],h=0;h<c;h++)if(h<a)b[h]=e[h];else{var d=b[h-1];h%a?6<a&&4==h%a&&(d=j[d>>>24]<<24|j[d>>>16&255]<<16|j[d>>>8&255]<<8|j[d&255]):(d=d<<8|d>>>24,d=j[d>>>24]<<24|j[d>>>16&255]<<16|j[d>>>8&255]<<8|j[d&255],d^=F[h/a|0]<<24);b[h]=b[h-a]^d}e=this._invKeySchedule=[];for(a=0;a<c;a++)h=c-a,d=a%4?b[h]:b[h-4],e[a]=4>a||4>=h?d:s[j[d>>>24]]^u[j[d>>>16&255]]^v[j[d>>>
 | 
			
		||||
8&255]]^w[j[d&255]]},encryptBlock:function(c,e){this._doCryptBlock(c,e,this._keySchedule,z,A,B,C,j)},decryptBlock:function(c,e){var a=c[e+1];c[e+1]=c[e+3];c[e+3]=a;this._doCryptBlock(c,e,this._invKeySchedule,s,u,v,w,y);a=c[e+1];c[e+1]=c[e+3];c[e+3]=a},_doCryptBlock:function(c,e,a,b,h,d,j,m){for(var n=this._nRounds,f=c[e]^a[0],g=c[e+1]^a[1],k=c[e+2]^a[2],p=c[e+3]^a[3],l=4,t=1;t<n;t++)var q=b[f>>>24]^h[g>>>16&255]^d[k>>>8&255]^j[p&255]^a[l++],r=b[g>>>24]^h[k>>>16&255]^d[p>>>8&255]^j[f&255]^a[l++],s=
 | 
			
		||||
b[k>>>24]^h[p>>>16&255]^d[f>>>8&255]^j[g&255]^a[l++],p=b[p>>>24]^h[f>>>16&255]^d[g>>>8&255]^j[k&255]^a[l++],f=q,g=r,k=s;q=(m[f>>>24]<<24|m[g>>>16&255]<<16|m[k>>>8&255]<<8|m[p&255])^a[l++];r=(m[g>>>24]<<24|m[k>>>16&255]<<16|m[p>>>8&255]<<8|m[f&255])^a[l++];s=(m[k>>>24]<<24|m[p>>>16&255]<<16|m[f>>>8&255]<<8|m[g&255])^a[l++];p=(m[p>>>24]<<24|m[f>>>16&255]<<16|m[g>>>8&255]<<8|m[k&255])^a[l++];c[e]=q;c[e+1]=r;c[e+2]=s;c[e+3]=p},keySize:8});q.AES=x._createHelper(r)})();
 | 
			
		||||
							
								
								
									
										26
									
								
								public/js/vendor/domReady.v2.0.1.min.js
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								public/js/vendor/domReady.v2.0.1.min.js
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,26 @@
 | 
			
		|||
/*
 | 
			
		||||
 | 
			
		||||
MIT License
 | 
			
		||||
-----------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2010-2011, The Dojo Foundation
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
in the Software without restriction, including without limitation the rights
 | 
			
		||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in
 | 
			
		||||
all copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
THE SOFTWARE.
 | 
			
		||||
*/
 | 
			
		||||
define(function(){"use strict";function e(e){var t;for(t=0;e.length>t;t+=1)e[t](h)}function t(){var t=c;l&&t.length&&(c=[],e(t))}function i(){l||(l=!0,o&&clearInterval(o),t())}function n(e){return l?e(h):c.push(e),n}var r,s,o,a="undefined"!=typeof window&&window.document,l=!a,h=a?document:null,c=[];if(a){if(document.addEventListener)document.addEventListener("DOMContentLoaded",i,!1),window.addEventListener("load",i,!1);else if(window.attachEvent){window.attachEvent("onload",i),s=document.createElement("div");try{r=null===window.frameElement}catch(u){}s.doScroll&&r&&window.external&&(o=setInterval(function(){try{s.doScroll(),i()}catch(e){}},30))}"complete"===document.readyState&&i()}return n.version="2.0.1",n.load=function(e,t,i,r){r.isBuild?i(null):n(i)},n});
 | 
			
		||||
							
								
								
									
										23
									
								
								public/js/vendor/fandango.v20140918.min.js
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								public/js/vendor/fandango.v20140918.min.js
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
(function(l){var y={"http://":1,"https://":1,"file://":1},u={deepCopy:!0,baseUrl:"",namespace:"default",timeout:1E3,paths:{}},g={};(function(){this.is=function(){var f=Object.prototype.hasOwnProperty,b=Object.prototype.toString,d={array:Array.isArray||function(a){return"[object Array]"==b.call(a)},arraylike:function(a){if(!a||!a.length&&0!==a.length||d.window(a))return!1;var c=a.length;return 1===a.nodeType||d.array(a)||!d["function"](a)&&(0===c||"number"===typeof c&&0<c&&!g.is(a,"primitive")&&c-
 | 
			
		||||
1 in a)},"boolean":function(a){return!0===a||!1===a},element:function(a){return!(!a||1!==a.nodeType)},finite:function(a){return isFinite(a)&&!isNaN(parseFloat(a))},integer:Number.isInteger||function(a){return"number"===typeof a&&d.finite(a)&&-9007199254740992<a&&9007199254740992>a&&Math.floor(a)===a},iterable:function(a){try{1 in obj}catch(c){return!1}return!0},nan:function(a){return d.number(a)&&a!=+a},number:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},object:function(a){return a===Object(a)},
 | 
			
		||||
primitive:function(a){return!0===a||!1===a||null==a||!!{string:1,number:1}[typeof a]},string:function(a){return"string"==typeof a||a instanceof String},undefined:function(a){return void 0===a},untyped:function(a){if(!a||a.nodeType||"[object Object]"!==b.call(a)||d.window(a))return!1;try{if(a.constructor&&!f.call(a,"constructor")&&!f.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}for(var e in a);return void 0===e||f.call(a,e)},window:function(a){return null!=a&&a==a.window},
 | 
			
		||||
empty:function(a){if(a){if(g.is(a,"array"))return 0===a.length;for(var c in a)if(f.call(a,c))return!1}return!0}},e=0,c=["Arguments","Date","Function","RegExp"];for(;4>e;e++)d[c[e].toLowerCase()]=function(a){a="[object "+a+"]";return function(c){return b.call(c)==a}}(c[e]);d.args=d.arguments;d.bool=d["boolean"];d.plain=d.untyped;return function(a,c){if(d["function"](c))return a===c(a);if(!d.string(c))return a===c;if((c=c.toLowerCase())&&d[c])return d[c](a);throw'Unknown type "'+c+'"';}}();this.each=
 | 
			
		||||
function(){var f=Array.prototype.some;return function(b,d,e){var c,a;if(void 0===b)return obj;e=e||g;if(f&&b.some===f)return b.some(d,e),b;if(g.is(b,"array")||g.is(b,"arraylike")){c=0;for(a=b.length;c<a&&(void 0===b[c]||!d.call(e,b[c],c,b));c++);return b}for(c in b)if(b.hasOwnProperty(c)&&d.call(e,b[c],c,b))break;return b}}();this.merge=function(f){var b,d,e,c,a;b=arguments.length;var C=!1;f=arguments[0];var w=1,z,l,A=0;if(!0===f||!1===f)C=f,f=arguments[w],w++;g.is(arguments[b-1],"function")&&(a=
 | 
			
		||||
arguments[b-1],b--);if(void 0===f)f={};else if(g.is(f,"primitive"))throw new TypeError("Cannot merge primitive data types: merge("+Array.prototype.join.call(arguments,", ")+")");l=g.is(f,"array");if(w<b)for(;c=arguments[w++];){l=l&&g.is(c,"array");for(e in c)d=f[e],b=c[e],void 0===b||b===f?l&&A--:(C&&b&&((z=g.is(b,"array"))||g.is(b,"untyped"))&&(b=g.merge(C,d&&(z?g.is(d,"array")?d:[]:g.is(d,"untyped")?d:{}),b,a)),a&&a(e,f,c)||(A&&(e=+e+A),f[e]=b));A=0}return f};this.subordinate=function(){function f(a){if(!a||
 | 
			
		||||
a.source===window&&a.data===e){var b=c.shift();a=b[0];var b=b[1],d=b.length;d?1===d?a(b[0]):2===d?a(b[0],b[1]):3===d?a(b[0],b[1],b[2]):4===d?a(b[0],b[1],b[2],b[3]):a.apply(void 0,b):a()}}var b=Array.prototype.slice,d=window.postMessage,e="__fandango@"+Math.random().toString(36),c=[],a=function(){return d?function(){d(e,"*")}:function(){setTimeout(f)}}();d&&window.addEventListener("message",f,!1);return function(e){a(c.push([arguments[arguments.length-1],b.call(arguments).slice(0,-1)])-1)}}();this.noop=
 | 
			
		||||
function(){};this.coalesce=function(){for(var f=0,b=arguments.length;f<b;f++)if(void 0!==arguments[f])return arguments[f]};this.hasOwn=function(f){var b=1,d=arguments.length,e,c=!0,a=!0;if(1===d)return!0;if(2===d)return f.hasOwnProperty(arguments[1]);for(;b<d;b++)if(e=arguments[b],!0===e||!1===e)a=e;else if(!f.hasOwnProperty(e)){if(a)return!1;c=!1}else if(!a)return!0;return c};this.freezeObject=Object.freeze||function(f){return object}}).call(g);var D=function(){var f={};headElement=document.getElementsByTagName("head")[0];
 | 
			
		||||
nativeSlice=[].slice;isOpera="undefined"!==typeof opera&&"[object Opera]"===opera.toString();createScriptNode=function(b){var d=document.createElement("script");d.setAttribute("id","script::"+b);d.type="text/javascript";d.charset="utf-8";d.async=!0;return d};useAttachEvent=!(!((useAttachEvent=createScriptNode())&&useAttachEvent.attachEvent&&useAttachEvent.attachEvent.toString&&0<useAttachEvent.attachEvent.toString().indexOf("[native code"))||isOpera);onError=function(b,d,e){return function(c){f[d]=
 | 
			
		||||
0;b.error=c||!0;for(e.parentElement.removeChild(e);func=b.onRejected.shift();)func(c,d)}};onProgress=function(b,d,e,c){return function(){var a,g;if(f[d]){f[d]=2;for(g=0;a=b.onProgress[g++];)a(d,e);c?e.onreadystatechange=null:(e.removeEventListener("load",b.loadListener),e.removeEventListener("error",b.errorListener));if(b.loaded.push(d)===b.load.length)for(g=0;a=b.onResolved[g++];)a(b.load)}}};isLoaded=function(b,d){for(var e=0,c;c=d[e++];)if(f[c])return!0;return!1};load=function(b){var d=0,e,c;if(0<
 | 
			
		||||
b.onResolved.length&&0>=b.load.length){for(;d=b.onResolved.shift();)d([]);return b.shared}for(;!b.error&&(e=b.load[d++]);)e=b.prefix+e+b.suffix,f[e]?onProgress(b,e,document.getElementById("script::"+e))():(f[e]=1,c=createScriptNode(e),useAttachEvent?c.attachEvent("onreadystatechange",onProgress(b,e,c,!0)):(b.loadListener=onProgress(b,e,c),b.errorListener=onError(b,e,c),c.addEventListener("load",b.loadListener,!1),c.addEventListener("error",b.errorListener,!1)),c.src=e,headElement.appendChild(c))};
 | 
			
		||||
unload=function(b){for(var d=0,e,c;e=b[d++];)(c=document.getElementById("script::"+e))&&c.parentElement.removeChild(c),f[e]=0};return function(b,d){var e,c={load:b,loaded:[],prefix:"",suffix:"",onResolved:[],onRejected:[],onProgress:[],onAlways:[],error:null,shared:e};void 0!==d&&!0!==d||load(c);e={prefix:function(a){c.prefix=a;return e},suffix:function(a){c.suffix=a;return e},now:function(){load(c);return e},and:function(a){c.load=c.load.concat(a);return e},unload:function(a){unload(a);return e},
 | 
			
		||||
isLoaded:function(a){return isLoaded(c,a)},done:function(){c.onResolved=c.onResolved.concat(nativeSlice.call(arguments));return e},fail:function(){c.onRejected=c.onRejected.concat(nativeSlice.call(arguments));return e},progress:function(){c.onProgress=c.onProgress.concat(nativeSlice.call(arguments));return e},always:function(){c.onAlways=c.onAlways.concat(nativeSlice.call(arguments));return e}};e["try"]=e.done;e["catch"]=e.fail;e["finally"]=e.always;e.add=e.and;return e}}(),E=function(){function f(a){var c=
 | 
			
		||||
function(){return[]},b={},e={},d,f;for(f=0;d=a[f++];)d.selector&&(c=d.selector),d.prototype&&("function"===typeof d.prototype?d.prototype.call(e):g.merge(e,d.prototype)),d.utilities&&("function"===typeof d.utilities?d.utilities.call(b):g.merge(b,d.utilities));var k=function(a,b,e){var d=0;a=c(a,b);this.context=b||document;this.identify=e;for(this.length=a.length;d<this.length;d++)this[d]=a[d];return this};k.prototype=e;k.prototype.length=0;k.prototype.selector="";k.prototype.splice=Array.prototype.slice;
 | 
			
		||||
return function(a){return g.merge(function(c,b){return new k(c,b,a)},b)}}function b(b){var e,d,h=c[b],q=g.is(h.factory,"function"),m=q?h.factory.length:0,k=h.amdStyle,r=h.compiles&&[],n=h.requires&&(k?[]:{}),l=h.inherits&&{},p,t,s;void 0===(e=h.deepCopy)&&(e=u.deepCopy);h=c[b]=g.merge(e,{},u,h);if(m&&h.requires)for(t=0;s=h.requires[t++];)k?n.push(c[s].exports):g.is(c[s].exports,"function")?n[s]=c[s].exports:g.merge(e,n[s]={},c[s].exports);if(m&&h.compiles)for(t=0;s=h.compiles[t++];)r.push(c[s].exports);
 | 
			
		||||
if(h.inherits)for(t=0;s=h.inherits[t++];)g.merge(e,l,c[s].exports);r&&(d=f(r));for(s in h.instances)p=h.instances[s],p.context=void 0===p.context?h.context:p.context,p.deepCopy=void 0===p.deepCopy?h.deepCopy:p.deepCopy,p.namespace=void 0===p.namespace?h.namespace:p.namespace,r=[],k?r=n:(d&&(e=function(){var a={namespace:p.namespace,module:b,instance:s};a.UID=[a.namespace,a.module,a.instance].join("/");return function(){return a}}(),d=d(e),d.identify=e,r.push(d)),n&&r.push(n),m>r.length&&r.push(p.data?
 | 
			
		||||
g.merge(p.deepCopy,{},p.data,h.data):h.data),m>r.length&&r.push(g.merge(p.deepCopy,{},p,h))),p.exports=q?h.factory.apply(p.context,r)||{}:h.factory,void 0===h.exports&&(h.exports=l?p.exports?g.merge(!0,{},l,p.exports):l:p.exports);h.state=3;if(a[b])for(;a[b].length;)a[b].pop()(b)}function d(d,f){var l,h=f.length,q,m,k=[],r={},n,x=[],p,t=void 0!==c[d].timeout?c[d].timeout:u.timeout,s=function(a){1===c[d].state&&(k.push(a),--h||(t&&clearTimeout(p),b(d)))};for(l=0;n=f[l++];)if(q=c[n],!q||1===q.state)(a[n]=
 | 
			
		||||
a[n]||[]).push(s),q||((m=u.paths[n])?g.is(m,"array")&&(m=m[0]):m=n,m=v(m),r[m]=n,x.push(m));else if(3===q.state)k.push(n);else if(2===q.state)throw Error('Could not instantiate "'+d+'"; dependency "'+n+'" has been rejected.');if(!((h=f.length)-k.length))return b(d);0<x.length&&D(x).fail(function(a,b){c[d].state=2;t&&clearTimeout(p);throw Error('Could not instantiate "'+d+'"; an error occured while trying to load "'+b+'".');}).progress(function(a){(a=r[a])&&!c[a]&&e(w,a)});t&&(p=setTimeout(function(){var a,
 | 
			
		||||
b,e=0,g=0;for(c[d].state=2;a=f[e++];)for(g=0;b=k[g++];)a===b&&(k.splice(--g,1),f.splice(--e,1));throw Error("Load timeout of "+t+'ms exceeded for module "'+d+'". Missing "'+f.join('", "')+'".');},t))}function e(){var a=0,f,B,h,q,m=!1,k,r,n,x;if(arguments[0]!==w){for(;(n=arguments[a++])&&(_type=(typeof n)[0]);)if("s"===_type?k?x=1:k=n:"f"===_type?q?r?x=1:r=n:q=n:"o"===_type&&(g.is(n,"array")?(f={requires:n},m=!0):f?q=n:f=n),x)throw new TypeError("define called with unrecognized signature; `"+Array.prototype.join.call(arguments,
 | 
			
		||||
", ")+"`.");f=f||{};k=k||f.UID;q=q||f.factory;r=r||f.onRejected}else{if(!(a=l.pop()))throw Error("Inconsistent naming queue");k=arguments[1];f=a[0];q=a[1];r=a[3]}if(!q)if(f)q=f,f={};else throw Error('Missing factory for module "'+k+'"');if(c[k])throw Error('Duplicate entry for module "'+k+'"');if(k)if(a=c[k]=f,a.UID=k,a.amdStyle=m,a.factory=q,a.state=1,a.requires=g.is(a.requires,"array")&&a.requires,a.inherits=g.is(a.inherits,"array")&&a.inherits,a.compiles=g.is(a.compiles,"array")&&a.compiles,a.instances||
 | 
			
		||||
(a.instances={instance1:{}}),a.requires||a.compiles||a.inherits){m=[a.requires,a.inherits,a.compiles];m=[];a.requires&&z.apply(m,a.requires);a.inherits&&z.apply(m,a.inherits);a.compiles&&z.apply(m,a.compiles);for(a=0;f=m[a++];)if(c[f]&&3===c[f].state)m.splice(--a,1);else if(B=u.shim[f])h=v(u.paths[f]||h),q=g.is(B.exports,"function")?B.exports:function(){return window[B.exports]},D([h]).done(function(a,b){return function(){e(a,b)}}(f,q));m.length?g.subordinate(k,m,d):b(k)}else b(k);else l.unshift([f,
 | 
			
		||||
q,r])}var c={},a={},l=[],w={sentinel:1},z=Array.prototype.push,v=function(a){var b=a.toLowerCase(),c=b[0];"/"===c||"\\"===c||"h"===c&&(y[b.slice(0,7)]||y[b.slice(0,8)])||"f"===c&&y[b.slice(0,7)]||(a=u.baseUrl+a);".js"!==a.slice(-3)&&(a+=".js");return a};e.amd={};return e}();E("fandango",function(){return g});var F=l.fandango,G=l.define,v={fn:g,define:E,require:function(f){var b,d,e,c,a=[];for(b=0;d=f[b++];)e=d.toLowerCase(),c=e.slice(0,1),(isAbsolutePath=!!("/"===c||"\\"===c||"h"===c&&(y[e.slice(0,
 | 
			
		||||
7)]||y[e.slice(0,8)])||"f"===c&&y[e.slice(0,7)]))||(d=u.baseUrl+d),e.slice(-3)&&(d+=".js"),a.push(d);return D(a)},noConflict:function(f){l.define===E&&(l.define=G);f&&l.fandango===v&&(l.fandango=F);return v},defaults:function(f){return f?g.merge(u,f):u}};l.define||(l.define=v.define);l.require||(l.require=v.require);l.fandango=v})(this);
 | 
			
		||||
							
								
								
									
										2
									
								
								public/js/vendor/socket.io.v0.9.16.min.js
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								public/js/vendor/socket.io.v0.9.16.min.js
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										39
									
								
								server.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								server.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,39 @@
 | 
			
		|||
var express = require('express.io'),
 | 
			
		||||
    uuid = require('node-uuid');
 | 
			
		||||
 | 
			
		||||
app = express();app.http().io();
 | 
			
		||||
 | 
			
		||||
app.use(express.static(__dirname + '/public'));
 | 
			
		||||
 | 
			
		||||
app.io.route('room', {
 | 
			
		||||
    create: function(req) {
 | 
			
		||||
      var room = uuid.v4();
 | 
			
		||||
      req.socket.emit('message:server', 'Room ' + room + ' created');
 | 
			
		||||
      req.socket.emit('room:created',room);
 | 
			
		||||
    },
 | 
			
		||||
    join: function(req) {
 | 
			
		||||
      if(req.data) {
 | 
			
		||||
        req.socket.emit('room:joined',req.data);
 | 
			
		||||
        req.socket.join(req.data);
 | 
			
		||||
        req.socket.broadcast.to(req.data).emit('message:server', 'A person joined this room');
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    leave: function(req) {
 | 
			
		||||
      if(req.data) {
 | 
			
		||||
        req.socket.emit('room:left');
 | 
			
		||||
        req.socket.leave(req.data);
 | 
			
		||||
        req.socket.broadcast.to(req.data).emit('message:server', 'A person left this room');
 | 
			
		||||
      }
 | 
			
		||||
    } 
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
app.io.route('message', {
 | 
			
		||||
    send: function(req) {
 | 
			
		||||
      if(req.data && req.data.room) req.socket.broadcast.to(req.data.room).emit('message:send', req.data.msg);
 | 
			
		||||
      req.socket.emit('message:send', req.data.msg);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
app.listen(8080, function(){
 | 
			
		||||
  console.log('listening on *:8080');
 | 
			
		||||
});
 | 
			
		||||
		Loading…
	
	Add table
		
		Reference in a new issue