// We make use of this 'server' variable to provide the address of the// REST Janus API. By default, in this example we assume that Janus is// co-located with the web server hosting the HTML pages but listening// on a different port (8088, the default for HTTP in Janus), which is// why we make use of the 'window.location.hostname' base address. Since// Janus can also do HTTPS, and considering we don't really want to make// use of HTTP for Janus if your demos are served on HTTPS, we also rely// on the 'window.location.protocol' prefix to build the variable, in// particular to also change the port used to contact Janus (8088 for// HTTP and 8089 for HTTPS, if enabled).// In case you place Janus behind an Apache frontend (as we did on the// online demos at http://janus.conf.meetecho.com) you can just use a// relative path for the variable, e.g.://// 		var server = "/janus";//// which will take care of this on its own.////// If you want to use the WebSockets frontend to Janus, instead, you'll// have to pass a different kind of address, e.g.://// 		var server = "ws://" + window.location.hostname + ":8188";//// Of course this assumes that support for WebSockets has been built in// when compiling the server. WebSockets support has not been tested// as much as the REST API, so handle with care!////// If you have multiple options available, and want to let the library// autodetect the best way to contact your server (or pool of servers),// you can also pass an array of servers, e.g., to provide alternative// means of access (e.g., try WebSockets first and, if that fails, fall// back to plain HTTP) or just have failover servers:////		var server = [//			"ws://" + window.location.hostname + ":8188",//			"/janus"//		];//// This will tell the library to try connecting to each of the servers// in the presented order. The first working server will be used for// the whole session.//var server = null;if(window.location.protocol === 'http:')	server = "http://" + window.location.hostname + ":8088/janus";else	server = "https://" + window.location.hostname + ":8089/janus";var janus = null;var textroom = null;var opaqueId = "textroomtest-"+Janus.randomString(12);var myroom = 1234;	// Demo roomif(getQueryStringValue("room") !== "")	myroom = parseInt(getQueryStringValue("room"));var myusername = null;var myid = null;var participants = {}var transactions = {}$(document).ready(function() {	// Initialize the library (all console debuggers enabled)	Janus.init({debug: "all", callback: function() {		// Use a button to start the demo		$('#start').one('click', function() {			$(this).attr('disabled', true).unbind('click');			// Make sure the browser supports WebRTC			if(!Janus.isWebrtcSupported()) {				bootbox.alert("No WebRTC support... ");				return;			}			// Create session			janus = new Janus(				{					server: server,					success: function() {						// Attach to TextRoom plugin						janus.attach(							{								plugin: "janus.plugin.textroom",								opaqueId: opaqueId,								success: function(pluginHandle) {									$('#details').remove();									textroom = pluginHandle;									Janus.log("Plugin attached! (" + textroom.getPlugin() + ", id=" + textroom.getId() + ")");									// Setup the DataChannel									var body = { request: "setup" };									Janus.debug("Sending message:", body);									textroom.send({ message: body });									$('#start').removeAttr('disabled').html("Stop")										.click(function() {											$(this).attr('disabled', true);											janus.destroy();										});								},								error: function(error) {									console.error("  -- Error attaching plugin...", error);									bootbox.alert("Error attaching plugin... " + error);								},								iceState: function(state) {									Janus.log("ICE state changed to " + state);								},								mediaState: function(medium, on) {									Janus.log("Janus " + (on ? "started" : "stopped") + " receiving our " + medium);								},								webrtcState: function(on) {									Janus.log("Janus says our WebRTC PeerConnection is " + (on ? "up" : "down") + " now");								},								onmessage: function(msg, jsep) {									Janus.debug(" ::: Got a message :::", msg);									if(msg["error"]) {										bootbox.alert(msg["error"]);									}									if(jsep) {										// Answer										textroom.createAnswer(											{												jsep: jsep,												media: { audio: false, video: false, data: true },	// We only use datachannels												success: function(jsep) {													Janus.debug("Got SDP!", jsep);													var body = { request: "ack" };													textroom.send({ message: body, jsep: jsep });												},												error: function(error) {													Janus.error("WebRTC error:", error);													bootbox.alert("WebRTC error... " + error.message);												}											});									}								},								ondataopen: function(data) {									Janus.log("The DataChannel is available!");									// Prompt for a display name to join the default room									$('#roomjoin').removeClass('hide').show();									$('#registernow').removeClass('hide').show();									$('#register').click(registerUsername);									$('#username').focus();								},								ondata: function(data) {									Janus.debug("We got data from the DataChannel!", data);									//~ $('#datarecv').val(data);									var json = JSON.parse(data);									var transaction = json["transaction"];									if(transactions[transaction]) {										// Someone was waiting for this										transactions[transaction](json);										delete transactions[transaction];										return;									}									var what = json["textroom"];									if(what === "message") {										// Incoming message: public or private?										var msg = escapeXmlTags(json["text"]);										var from = json["from"];										var dateString = getDateString(json["date"]);										var whisper = json["whisper"];										var sender = participants[from] ? participants[from] : escapeXmlTags(json["display"]);										if(whisper === true) {											// Private message											$('#chatroom').append('<p style="color: purple;">[' + dateString + '] <b>[whisper from ' + sender + ']</b> ' + msg);											$('#chatroom').get(0).scrollTop = $('#chatroom').get(0).scrollHeight;										} else {											// Public message											$('#chatroom').append('<p>[' + dateString + '] <b>' + sender + ':</b> ' + msg);											$('#chatroom').get(0).scrollTop = $('#chatroom').get(0).scrollHeight;										}									} else if(what === "announcement") {										// Room announcement										var msg = escapeXmlTags(json["text"]);										var dateString = getDateString(json["date"]);										$('#chatroom').append('<p style="color: purple;">[' + dateString + '] <i>' + msg + '</i>');										$('#chatroom').get(0).scrollTop = $('#chatroom').get(0).scrollHeight;									} else if(what === "join") {										// Somebody joined										var username = json["username"];										var display = json["display"];										participants[username] = escapeXmlTags(display ? display : username);										if(username !== myid && $('#rp' + username).length === 0) {											// Add to the participants list											$('#list').append('<li id="rp' + username + '" class="list-group-item">' + participants[username] + '</li>');											$('#rp' + username).css('cursor', 'pointer').click(function() {												var username = $(this).attr('id').split("rp")[1];												sendPrivateMsg(username);											});										}										$('#chatroom').append('<p style="color: green;">[' + getDateString() + '] <i>' + participants[username] + ' joined</i></p>');										$('#chatroom').get(0).scrollTop = $('#chatroom').get(0).scrollHeight;									} else if(what === "leave") {										// Somebody left										var username = json["username"];										var when = new Date();										$('#rp' + username).remove();										$('#chatroom').append('<p style="color: green;">[' + getDateString() + '] <i>' + participants[username] + ' left</i></p>');										$('#chatroom').get(0).scrollTop = $('#chatroom').get(0).scrollHeight;										delete participants[username];									} else if(what === "kicked") {										// Somebody was kicked										var username = json["username"];										var when = new Date();										$('#rp' + username).remove();										$('#chatroom').append('<p style="color: green;">[' + getDateString() + '] <i>' + participants[username] + ' was kicked from the room</i></p>');										$('#chatroom').get(0).scrollTop = $('#chatroom').get(0).scrollHeight;										delete participants[username];										if(username === myid) {											bootbox.alert("You have been kicked from the room", function() {												window.location.reload();											});										}									} else if(what === "destroyed") {										if(json["room"] !== myroom)											return;										// Room was destroyed, goodbye!										Janus.warn("The room has been destroyed!");										bootbox.alert("The room has been destroyed", function() {											window.location.reload();										});									}								},								oncleanup: function() {									Janus.log(" ::: Got a cleanup notification :::");									$('#datasend').attr('disabled', true);								}							});					},					error: function(error) {						Janus.error(error);						bootbox.alert(error, function() {							window.location.reload();						});					},					destroyed: function() {						window.location.reload();					}				});		});	}});});function checkEnter(field, event) {	var theCode = event.keyCode ? event.keyCode : event.which ? event.which : event.charCode;	if(theCode == 13) {		if(field.id == 'username')			registerUsername();		else if(field.id == 'datasend')			sendData();		return false;	} else {		return true;	}}function registerUsername() {	if($('#username').length === 0) {		// Create fields to register		$('#register').click(registerUsername);		$('#username').focus();	} else {		// Try a registration		$('#username').attr('disabled', true);		$('#register').attr('disabled', true).unbind('click');		var username = $('#username').val();		if(username === "") {			$('#you')				.removeClass().addClass('label label-warning')				.html("Insert your display name (e.g., pippo)");			$('#username').removeAttr('disabled');			$('#register').removeAttr('disabled').click(registerUsername);			return;		}		myid = randomString(12);		var transaction = randomString(12);		var register = {			textroom: "join",			transaction: transaction,			room: myroom,			username: myid,			display: username		};		myusername = escapeXmlTags(username);		transactions[transaction] = function(response) {			if(response["textroom"] === "error") {				// Something went wrong				if(response["error_code"] === 417) {					// This is a "no such room" error: give a more meaningful description					bootbox.alert(						"<p>Apparently room <code>" + myroom + "</code> (the one this demo uses as a test room) " +						"does not exist...</p><p>Do you have an updated <code>janus.plugin.textroom.jcfg</code> " +						"configuration file? If not, make sure you copy the details of room <code>" + myroom + "</code> " +						"from that sample in your current configuration file, then restart Janus and try again."					);				} else {					bootbox.alert(response["error"]);				}				$('#username').removeAttr('disabled').val("");				$('#register').removeAttr('disabled').click(registerUsername);				return;			}			// We're in			$('#roomjoin').hide();			$('#room').removeClass('hide').show();			$('#participant').removeClass('hide').html(myusername).show();			$('#chatroom').css('height', ($(window).height()-420)+"px");			$('#datasend').removeAttr('disabled');			// Any participants already in?			console.log("Participants:", response.participants);			if(response.participants && response.participants.length > 0) {				for(var i in response.participants) {					var p = response.participants[i];					participants[p.username] = escapeXmlTags(p.display ? p.display : p.username);					if(p.username !== myid && $('#rp' + p.username).length === 0) {						// Add to the participants list						$('#list').append('<li id="rp' + p.username + '" class="list-group-item">' + participants[p.username] + '</li>');						$('#rp' + p.username).css('cursor', 'pointer').click(function() {							var username = $(this).attr('id').split("rp")[1];							sendPrivateMsg(username);						});					}					$('#chatroom').append('<p style="color: green;">[' + getDateString() + '] <i>' + participants[p.username] + ' joined</i></p>');					$('#chatroom').get(0).scrollTop = $('#chatroom').get(0).scrollHeight;				}			}		};		textroom.data({			text: JSON.stringify(register),			error: function(reason) {				bootbox.alert(reason);				$('#username').removeAttr('disabled').val("");				$('#register').removeAttr('disabled').click(registerUsername);			}		});	}}function sendPrivateMsg(username) {	var display = participants[username];	if(!display)		return;	bootbox.prompt("Private message to " + display, function(result) {		if(result && result !== "") {			var message = {				textroom: "message",				transaction: randomString(12),				room: myroom,				to: username,				text: result			};			textroom.data({				text: JSON.stringify(message),				error: function(reason) { bootbox.alert(reason); },				success: function() {					// BUG: CWE-79 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')					// $('#chatroom').append('<p style="color: purple;">[' + getDateString() + '] <b>[whisper to ' + display + ']</b> ' + result);					// FIXED: 					$('#chatroom').append('<p style="color: purple;">[' + getDateString() + '] <b>[whisper to ' + display + ']</b> ' + escapeXmlTags(result));					$('#chatroom').get(0).scrollTop = $('#chatroom').get(0).scrollHeight;				}			});		}	});	return;}function sendData() {	var data = $('#datasend').val();	if(data === "") {		bootbox.alert('Insert a message to send on the DataChannel');		return;	}	var message = {		textroom: "message",		transaction: randomString(12),		room: myroom, 		text: data,	};	// Note: messages are always acknowledged by default. This means that you'll	// always receive a confirmation back that the message has been received by the	// server and forwarded to the recipients. If you do not want this to happen,	// just add an ack:false property to the message above, and server won't send	// you a response (meaning you just have to hope it succeeded).	textroom.data({		text: JSON.stringify(message),		error: function(reason) { bootbox.alert(reason); },		success: function() { $('#datasend').val(''); }	});}// Helper to format timesfunction getDateString(jsonDate) {	var when = new Date();	if(jsonDate) {		when = new Date(Date.parse(jsonDate));	}	var dateString =			("0" + when.getUTCHours()).slice(-2) + ":" +			("0" + when.getUTCMinutes()).slice(-2) + ":" +			("0" + when.getUTCSeconds()).slice(-2);	return dateString;}// Just an helper to generate random usernamesfunction randomString(len, charSet) {    charSet = charSet || 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';    var randomString = '';    for (var i = 0; i < len; i++) {    	var randomPoz = Math.floor(Math.random() * charSet.length);    	randomString += charSet.substring(randomPoz,randomPoz+1);    }    return randomString;}// Helper to parse query stringfunction getQueryStringValue(name) {	name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");	var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),		results = regex.exec(location.search);	return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));}// Helper to escape XML tagsfunction escapeXmlTags(value) {	if(value) {		var escapedValue = value.replace(new RegExp('<', 'g'), '&lt');		escapedValue = escapedValue.replace(new RegExp('>', 'g'), '&gt');		return escapedValue;	}}