1*4882a593SmuzhiyunFrom ba166e9adebfe5343f826c6a9e02299d35414ffd Mon Sep 17 00:00:00 2001 2*4882a593SmuzhiyunFrom: Lorenzo Miniero <lminiero@gmail.com> 3*4882a593SmuzhiyunDate: Thu, 25 Nov 2021 17:20:53 +0100 4*4882a593SmuzhiyunSubject: [PATCH] Fix potential Cross-site Scripting (XSS) exploits in demos 5*4882a593Smuzhiyun (#2817) 6*4882a593Smuzhiyun 7*4882a593Smuzhiyun[Retrieved (and backported) from: 8*4882a593Smuzhiyunhttps://github.com/meetecho/janus-gateway/commit/ba166e9adebfe5343f826c6a9e02299d35414ffd] 9*4882a593SmuzhiyunSigned-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com> 10*4882a593Smuzhiyun--- 11*4882a593Smuzhiyun html/audiobridgetest.js | 17 +++++++++++++---- 12*4882a593Smuzhiyun html/recordplaytest.js | 13 +++++++++++-- 13*4882a593Smuzhiyun html/screensharingtest.js | 11 ++++++++++- 14*4882a593Smuzhiyun html/streamingtest.js | 13 +++++++++++-- 15*4882a593Smuzhiyun html/textroomtest.js | 23 ++++++++++++++--------- 16*4882a593Smuzhiyun html/videocalltest.js | 15 ++++++++++++--- 17*4882a593Smuzhiyun html/videoroomtest.js | 13 +++++++++++-- 18*4882a593Smuzhiyun html/vp9svctest.js | 13 +++++++++++-- 19*4882a593Smuzhiyun 8 files changed, 93 insertions(+), 25 deletions(-) 20*4882a593Smuzhiyun 21*4882a593Smuzhiyundiff --git a/html/audiobridgetest.js b/html/audiobridgetest.js 22*4882a593Smuzhiyunindex 18e1cc1839..f757789708 100644 23*4882a593Smuzhiyun--- a/html/audiobridgetest.js 24*4882a593Smuzhiyun+++ b/html/audiobridgetest.js 25*4882a593Smuzhiyun@@ -178,7 +178,7 @@ $(document).ready(function() { 26*4882a593Smuzhiyun Janus.debug("Got a list of participants:", list); 27*4882a593Smuzhiyun for(var f in list) { 28*4882a593Smuzhiyun var id = list[f]["id"]; 29*4882a593Smuzhiyun- var display = list[f]["display"]; 30*4882a593Smuzhiyun+ var display = escapeXmlTags(list[f]["display"]); 31*4882a593Smuzhiyun var setup = list[f]["setup"]; 32*4882a593Smuzhiyun var muted = list[f]["muted"]; 33*4882a593Smuzhiyun var spatial = list[f]["spatial_position"]; 34*4882a593Smuzhiyun@@ -222,7 +222,7 @@ $(document).ready(function() { 35*4882a593Smuzhiyun Janus.debug("Got a list of participants:", list); 36*4882a593Smuzhiyun for(var f in list) { 37*4882a593Smuzhiyun var id = list[f]["id"]; 38*4882a593Smuzhiyun- var display = list[f]["display"]; 39*4882a593Smuzhiyun+ var display = escapeXmlTags(list[f]["display"]); 40*4882a593Smuzhiyun var setup = list[f]["setup"]; 41*4882a593Smuzhiyun var muted = list[f]["muted"]; 42*4882a593Smuzhiyun var spatial = list[f]["spatial_position"]; 43*4882a593Smuzhiyun@@ -267,7 +267,7 @@ $(document).ready(function() { 44*4882a593Smuzhiyun Janus.debug("Got a list of participants:", list); 45*4882a593Smuzhiyun for(var f in list) { 46*4882a593Smuzhiyun var id = list[f]["id"]; 47*4882a593Smuzhiyun- var display = list[f]["display"]; 48*4882a593Smuzhiyun+ var display = escapeXmlTags(list[f]["display"]); 49*4882a593Smuzhiyun var setup = list[f]["setup"]; 50*4882a593Smuzhiyun var muted = list[f]["muted"]; 51*4882a593Smuzhiyun var spatial = list[f]["spatial_position"]; 52*4882a593Smuzhiyun@@ -429,7 +429,7 @@ function registerUsername() { 53*4882a593Smuzhiyun return; 54*4882a593Smuzhiyun } 55*4882a593Smuzhiyun var register = { request: "join", room: myroom, display: username }; 56*4882a593Smuzhiyun- myusername = username; 57*4882a593Smuzhiyun+ myusername = escapeXmlTags(username); 58*4882a593Smuzhiyun mixertest.send({ message: register}); 59*4882a593Smuzhiyun } 60*4882a593Smuzhiyun } 61*4882a593Smuzhiyun@@ -448,3 +448,12 @@ function getQueryStringValue(name) { 62*4882a593Smuzhiyun results = regex.exec(location.search); 63*4882a593Smuzhiyun return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " ")); 64*4882a593Smuzhiyun } 65*4882a593Smuzhiyun+ 66*4882a593Smuzhiyun+// Helper to escape XML tags 67*4882a593Smuzhiyun+function escapeXmlTags(value) { 68*4882a593Smuzhiyun+ if(value) { 69*4882a593Smuzhiyun+ var escapedValue = value.replace(new RegExp('<', 'g'), '<'); 70*4882a593Smuzhiyun+ escapedValue = escapedValue.replace(new RegExp('>', 'g'), '>'); 71*4882a593Smuzhiyun+ return escapedValue; 72*4882a593Smuzhiyun+ } 73*4882a593Smuzhiyun+} 74*4882a593Smuzhiyundiff --git a/html/recordplaytest.js b/html/recordplaytest.js 75*4882a593Smuzhiyunindex 74ee7bed95..52b5ccbc4c 100644 76*4882a593Smuzhiyun--- a/html/recordplaytest.js 77*4882a593Smuzhiyun+++ b/html/recordplaytest.js 78*4882a593Smuzhiyun@@ -423,11 +423,11 @@ function updateRecsList() { 79*4882a593Smuzhiyun Janus.debug("Got a list of available recordings:", list); 80*4882a593Smuzhiyun for(var mp in list) { 81*4882a593Smuzhiyun Janus.debug(" >> [" + list[mp]["id"] + "] " + list[mp]["name"] + " (" + list[mp]["date"] + ")"); 82*4882a593Smuzhiyun- $('#recslist').append("<li><a href='#' id='" + list[mp]["id"] + "'>" + list[mp]["name"] + " [" + list[mp]["date"] + "]" + "</a></li>"); 83*4882a593Smuzhiyun+ $('#recslist').append("<li><a href='#' id='" + list[mp]["id"] + "'>" + escapeXmlTags(list[mp]["name"]) + " [" + list[mp]["date"] + "]" + "</a></li>"); 84*4882a593Smuzhiyun } 85*4882a593Smuzhiyun $('#recslist a').unbind('click').click(function() { 86*4882a593Smuzhiyun selectedRecording = $(this).attr("id"); 87*4882a593Smuzhiyun- selectedRecordingInfo = $(this).text(); 88*4882a593Smuzhiyun+ selectedRecordingInfo = escapeXmlTags($(this).text()); 89*4882a593Smuzhiyun $('#recset').html($(this).html()).parent().removeClass('open'); 90*4882a593Smuzhiyun $('#play').removeAttr('disabled').click(startPlayout); 91*4882a593Smuzhiyun return false; 92*4882a593Smuzhiyun@@ -545,3 +545,12 @@ function getQueryStringValue(name) { 93*4882a593Smuzhiyun results = regex.exec(location.search); 94*4882a593Smuzhiyun return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " ")); 95*4882a593Smuzhiyun } 96*4882a593Smuzhiyun+ 97*4882a593Smuzhiyun+// Helper to escape XML tags 98*4882a593Smuzhiyun+function escapeXmlTags(value) { 99*4882a593Smuzhiyun+ if(value) { 100*4882a593Smuzhiyun+ var escapedValue = value.replace(new RegExp('<', 'g'), '<'); 101*4882a593Smuzhiyun+ escapedValue = escapedValue.replace(new RegExp('>', 'g'), '>'); 102*4882a593Smuzhiyun+ return escapedValue; 103*4882a593Smuzhiyun+ } 104*4882a593Smuzhiyun+} 105*4882a593Smuzhiyundiff --git a/html/screensharingtest.js b/html/screensharingtest.js 106*4882a593Smuzhiyunindex 61eac70f43..c64d8dbd67 100644 107*4882a593Smuzhiyun--- a/html/screensharingtest.js 108*4882a593Smuzhiyun+++ b/html/screensharingtest.js 109*4882a593Smuzhiyun@@ -161,7 +161,7 @@ $(document).ready(function() { 110*4882a593Smuzhiyun if(event === "joined") { 111*4882a593Smuzhiyun myid = msg["id"]; 112*4882a593Smuzhiyun $('#session').html(room); 113*4882a593Smuzhiyun- $('#title').html(msg["description"]); 114*4882a593Smuzhiyun+ $('#title').html(escapeXmlTags(msg["description"])); 115*4882a593Smuzhiyun Janus.log("Successfully joined room " + msg["room"] + " with ID " + myid); 116*4882a593Smuzhiyun if(role === "publisher") { 117*4882a593Smuzhiyun // This is our session, publish our stream 118*4882a593Smuzhiyun@@ -514,3 +514,12 @@ function newRemoteFeed(id, display) { 119*4882a593Smuzhiyun } 120*4882a593Smuzhiyun }); 121*4882a593Smuzhiyun } 122*4882a593Smuzhiyun+ 123*4882a593Smuzhiyun+// Helper to escape XML tags 124*4882a593Smuzhiyun+function escapeXmlTags(value) { 125*4882a593Smuzhiyun+ if(value) { 126*4882a593Smuzhiyun+ var escapedValue = value.replace(new RegExp('<', 'g'), '<'); 127*4882a593Smuzhiyun+ escapedValue = escapedValue.replace(new RegExp('>', 'g'), '>'); 128*4882a593Smuzhiyun+ return escapedValue; 129*4882a593Smuzhiyun+ } 130*4882a593Smuzhiyun+} 131*4882a593Smuzhiyundiff --git a/html/streamingtest.js b/html/streamingtest.js 132*4882a593Smuzhiyunindex 7dd2e1f681..3f9937f11c 100644 133*4882a593Smuzhiyun--- a/html/streamingtest.js 134*4882a593Smuzhiyun+++ b/html/streamingtest.js 135*4882a593Smuzhiyun@@ -323,7 +323,7 @@ function updateStreamsList() { 136*4882a593Smuzhiyun Janus.debug(list); 137*4882a593Smuzhiyun for(var mp in list) { 138*4882a593Smuzhiyun Janus.debug(" >> [" + list[mp]["id"] + "] " + list[mp]["description"] + " (" + list[mp]["type"] + ")"); 139*4882a593Smuzhiyun- $('#streamslist').append("<li><a href='#' id='" + list[mp]["id"] + "'>" + list[mp]["description"] + " (" + list[mp]["type"] + ")" + "</a></li>"); 140*4882a593Smuzhiyun+ $('#streamslist').append("<li><a href='#' id='" + list[mp]["id"] + "'>" + escapeXmlTags(list[mp]["description"]) + " (" + list[mp]["type"] + ")" + "</a></li>"); 141*4882a593Smuzhiyun } 142*4882a593Smuzhiyun $('#streamslist a').unbind('click').click(function() { 143*4882a593Smuzhiyun selectedStream = $(this).attr("id"); 144*4882a593Smuzhiyun@@ -345,7 +345,7 @@ function getStreamInfo() { 145*4882a593Smuzhiyun var body = { request: "info", id: parseInt(selectedStream) || selectedStream }; 146*4882a593Smuzhiyun streaming.send({ message: body, success: function(result) { 147*4882a593Smuzhiyun if(result && result.info && result.info.metadata) { 148*4882a593Smuzhiyun- $('#metadata').html(result.info.metadata); 149*4882a593Smuzhiyun+ $('#metadata').html(escapeXmlTags(result.info.metadata)); 150*4882a593Smuzhiyun $('#info').removeClass('hide').show(); 151*4882a593Smuzhiyun } 152*4882a593Smuzhiyun }}); 153*4882a593Smuzhiyun@@ -394,6 +394,15 @@ function stopStream() { 154*4882a593Smuzhiyun simulcastStarted = false; 155*4882a593Smuzhiyun } 156*4882a593Smuzhiyun 157*4882a593Smuzhiyun+// Helper to escape XML tags 158*4882a593Smuzhiyun+function escapeXmlTags(value) { 159*4882a593Smuzhiyun+ if(value) { 160*4882a593Smuzhiyun+ var escapedValue = value.replace(new RegExp('<', 'g'), '<'); 161*4882a593Smuzhiyun+ escapedValue = escapedValue.replace(new RegExp('>', 'g'), '>'); 162*4882a593Smuzhiyun+ return escapedValue; 163*4882a593Smuzhiyun+ } 164*4882a593Smuzhiyun+} 165*4882a593Smuzhiyun+ 166*4882a593Smuzhiyun // Helpers to create Simulcast-related UI, if enabled 167*4882a593Smuzhiyun function addSimulcastButtons() { 168*4882a593Smuzhiyun $('#curres').parent().append( 169*4882a593Smuzhiyundiff --git a/html/textroomtest.js b/html/textroomtest.js 170*4882a593Smuzhiyunindex 082ae44905..3d0697e35a 100644 171*4882a593Smuzhiyun--- a/html/textroomtest.js 172*4882a593Smuzhiyun+++ b/html/textroomtest.js 173*4882a593Smuzhiyun@@ -153,9 +153,7 @@ $(document).ready(function() { 174*4882a593Smuzhiyun var what = json["textroom"]; 175*4882a593Smuzhiyun if(what === "message") { 176*4882a593Smuzhiyun // Incoming message: public or private? 177*4882a593Smuzhiyun- var msg = json["text"]; 178*4882a593Smuzhiyun- msg = msg.replace(new RegExp('<', 'g'), '<'); 179*4882a593Smuzhiyun- msg = msg.replace(new RegExp('>', 'g'), '>'); 180*4882a593Smuzhiyun+ var msg = escapeXmlTags(json["text"]); 181*4882a593Smuzhiyun var from = json["from"]; 182*4882a593Smuzhiyun var dateString = getDateString(json["date"]); 183*4882a593Smuzhiyun var whisper = json["whisper"]; 184*4882a593Smuzhiyun@@ -170,9 +168,7 @@ $(document).ready(function() { 185*4882a593Smuzhiyun } 186*4882a593Smuzhiyun } else if(what === "announcement") { 187*4882a593Smuzhiyun // Room announcement 188*4882a593Smuzhiyun- var msg = json["text"]; 189*4882a593Smuzhiyun- msg = msg.replace(new RegExp('<', 'g'), '<'); 190*4882a593Smuzhiyun- msg = msg.replace(new RegExp('>', 'g'), '>'); 191*4882a593Smuzhiyun+ var msg = escapeXmlTags(json["text"]); 192*4882a593Smuzhiyun var dateString = getDateString(json["date"]); 193*4882a593Smuzhiyun $('#chatroom').append('<p style="color: purple;">[' + dateString + '] <i>' + msg + '</i>'); 194*4882a593Smuzhiyun $('#chatroom').get(0).scrollTop = $('#chatroom').get(0).scrollHeight; 195*4882a593Smuzhiyun@@ -180,7 +176,7 @@ $(document).ready(function() { 196*4882a593Smuzhiyun // Somebody joined 197*4882a593Smuzhiyun var username = json["username"]; 198*4882a593Smuzhiyun var display = json["display"]; 199*4882a593Smuzhiyun- participants[username] = display ? display : username; 200*4882a593Smuzhiyun+ participants[username] = escapeXmlTags(display ? display : username); 201*4882a593Smuzhiyun if(username !== myid && $('#rp' + username).length === 0) { 202*4882a593Smuzhiyun // Add to the participants list 203*4882a593Smuzhiyun $('#list').append('<li id="rp' + username + '" class="list-group-item">' + participants[username] + '</li>'); 204*4882a593Smuzhiyun@@ -282,7 +278,7 @@ function registerUsername() { 205*4882a593Smuzhiyun username: myid, 206*4882a593Smuzhiyun display: username 207*4882a593Smuzhiyun }; 208*4882a593Smuzhiyun- myusername = username; 209*4882a593Smuzhiyun+ myusername = escapeXmlTags(username); 210*4882a593Smuzhiyun transactions[transaction] = function(response) { 211*4882a593Smuzhiyun if(response["textroom"] === "error") { 212*4882a593Smuzhiyun // Something went wrong 213*4882a593Smuzhiyun@@ -312,7 +308,7 @@ function registerUsername() { 214*4882a593Smuzhiyun if(response.participants && response.participants.length > 0) { 215*4882a593Smuzhiyun for(var i in response.participants) { 216*4882a593Smuzhiyun var p = response.participants[i]; 217*4882a593Smuzhiyun- participants[p.username] = p.display ? p.display : p.username; 218*4882a593Smuzhiyun+ participants[p.username] = escapeXmlTags(p.display ? p.display : p.username); 219*4882a593Smuzhiyun if(p.username !== myid && $('#rp' + p.username).length === 0) { 220*4882a593Smuzhiyun // Add to the participants list 221*4882a593Smuzhiyun $('#list').append('<li id="rp' + p.username + '" class="list-group-item">' + participants[p.username] + '</li>'); 222*4882a593Smuzhiyun@@ -418,3 +414,12 @@ function getQueryStringValue(name) { 223*4882a593Smuzhiyun results = regex.exec(location.search); 224*4882a593Smuzhiyun return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " ")); 225*4882a593Smuzhiyun } 226*4882a593Smuzhiyun+ 227*4882a593Smuzhiyun+// Helper to escape XML tags 228*4882a593Smuzhiyun+function escapeXmlTags(value) { 229*4882a593Smuzhiyun+ if(value) { 230*4882a593Smuzhiyun+ var escapedValue = value.replace(new RegExp('<', 'g'), '<'); 231*4882a593Smuzhiyun+ escapedValue = escapedValue.replace(new RegExp('>', 'g'), '>'); 232*4882a593Smuzhiyun+ return escapedValue; 233*4882a593Smuzhiyun+ } 234*4882a593Smuzhiyun+} 235*4882a593Smuzhiyundiff --git a/html/videocalltest.js b/html/videocalltest.js 236*4882a593Smuzhiyunindex d1c1ab8d07..18ccbc2c47 100644 237*4882a593Smuzhiyun--- a/html/videocalltest.js 238*4882a593Smuzhiyun+++ b/html/videocalltest.js 239*4882a593Smuzhiyun@@ -148,7 +148,7 @@ $(document).ready(function() { 240*4882a593Smuzhiyun } else if(result["event"]) { 241*4882a593Smuzhiyun var event = result["event"]; 242*4882a593Smuzhiyun if(event === 'registered') { 243*4882a593Smuzhiyun- myusername = result["username"]; 244*4882a593Smuzhiyun+ myusername = escapeXmlTags(result["username"]); 245*4882a593Smuzhiyun Janus.log("Successfully registered as " + myusername + "!"); 246*4882a593Smuzhiyun $('#youok').removeClass('hide').show().html("Registered as '" + myusername + "'"); 247*4882a593Smuzhiyun // Get a list of available peers, just for fun 248*4882a593Smuzhiyun@@ -163,7 +163,7 @@ $(document).ready(function() { 249*4882a593Smuzhiyun bootbox.alert("Waiting for the peer to answer..."); 250*4882a593Smuzhiyun } else if(event === 'incomingcall') { 251*4882a593Smuzhiyun Janus.log("Incoming call from " + result["username"] + "!"); 252*4882a593Smuzhiyun- yourusername = result["username"]; 253*4882a593Smuzhiyun+ yourusername = escapeXmlTags(result["username"]); 254*4882a593Smuzhiyun // Notify user 255*4882a593Smuzhiyun bootbox.hideAll(); 256*4882a593Smuzhiyun incoming = bootbox.dialog({ 257*4882a593Smuzhiyun@@ -213,7 +213,7 @@ $(document).ready(function() { 258*4882a593Smuzhiyun }); 259*4882a593Smuzhiyun } else if(event === 'accepted') { 260*4882a593Smuzhiyun bootbox.hideAll(); 261*4882a593Smuzhiyun- var peer = result["username"]; 262*4882a593Smuzhiyun+ var peer = escapeXmlTags(result["username"]); 263*4882a593Smuzhiyun if(!peer) { 264*4882a593Smuzhiyun Janus.log("Call started!"); 265*4882a593Smuzhiyun } else { 266*4882a593Smuzhiyun@@ -598,6 +598,15 @@ function getQueryStringValue(name) { 267*4882a593Smuzhiyun return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " ")); 268*4882a593Smuzhiyun } 269*4882a593Smuzhiyun 270*4882a593Smuzhiyun+// Helper to escape XML tags 271*4882a593Smuzhiyun+function escapeXmlTags(value) { 272*4882a593Smuzhiyun+ if(value) { 273*4882a593Smuzhiyun+ var escapedValue = value.replace(new RegExp('<', 'g'), '<'); 274*4882a593Smuzhiyun+ escapedValue = escapedValue.replace(new RegExp('>', 'g'), '>'); 275*4882a593Smuzhiyun+ return escapedValue; 276*4882a593Smuzhiyun+ } 277*4882a593Smuzhiyun+} 278*4882a593Smuzhiyun+ 279*4882a593Smuzhiyun // Helpers to create Simulcast-related UI, if enabled 280*4882a593Smuzhiyun function addSimulcastButtons(temporal) { 281*4882a593Smuzhiyun $('#curres').parent().append( 282*4882a593Smuzhiyundiff --git a/html/videoroomtest.js b/html/videoroomtest.js 283*4882a593Smuzhiyunindex 6a566891d8..5a3ade9be9 100644 284*4882a593Smuzhiyun--- a/html/videoroomtest.js 285*4882a593Smuzhiyun+++ b/html/videoroomtest.js 286*4882a593Smuzhiyun@@ -400,7 +400,7 @@ function registerUsername() { 287*4882a593Smuzhiyun ptype: "publisher", 288*4882a593Smuzhiyun display: username 289*4882a593Smuzhiyun }; 290*4882a593Smuzhiyun- myusername = username; 291*4882a593Smuzhiyun+ myusername = escapeXmlTags(username); 292*4882a593Smuzhiyun sfutest.send({ message: register }); 293*4882a593Smuzhiyun } 294*4882a593Smuzhiyun } 295*4882a593Smuzhiyun@@ -530,7 +530,7 @@ function newRemoteFeed(id, display, audio, video) { 296*4882a593Smuzhiyun } 297*4882a593Smuzhiyun } 298*4882a593Smuzhiyun remoteFeed.rfid = msg["id"]; 299*4882a593Smuzhiyun- remoteFeed.rfdisplay = msg["display"]; 300*4882a593Smuzhiyun+ remoteFeed.rfdisplay = escapeXmlTags(msg["display"]); 301*4882a593Smuzhiyun if(!remoteFeed.spinner) { 302*4882a593Smuzhiyun var target = document.getElementById('videoremote'+remoteFeed.rfindex); 303*4882a593Smuzhiyun remoteFeed.spinner = new Spinner({top:100}).spin(target); 304*4882a593Smuzhiyun@@ -685,6 +685,15 @@ function getQueryStringValue(name) { 305*4882a593Smuzhiyun return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " ")); 306*4882a593Smuzhiyun } 307*4882a593Smuzhiyun 308*4882a593Smuzhiyun+// Helper to escape XML tags 309*4882a593Smuzhiyun+function escapeXmlTags(value) { 310*4882a593Smuzhiyun+ if(value) { 311*4882a593Smuzhiyun+ var escapedValue = value.replace(new RegExp('<', 'g'), '<'); 312*4882a593Smuzhiyun+ escapedValue = escapedValue.replace(new RegExp('>', 'g'), '>'); 313*4882a593Smuzhiyun+ return escapedValue; 314*4882a593Smuzhiyun+ } 315*4882a593Smuzhiyun+} 316*4882a593Smuzhiyun+ 317*4882a593Smuzhiyun // Helpers to create Simulcast-related UI, if enabled 318*4882a593Smuzhiyun function addSimulcastButtons(feed, temporal) { 319*4882a593Smuzhiyun var index = feed; 320*4882a593Smuzhiyundiff --git a/html/vp9svctest.js b/html/vp9svctest.js 321*4882a593Smuzhiyunindex eca0239c32..b22ccf3340 100644 322*4882a593Smuzhiyun--- a/html/vp9svctest.js 323*4882a593Smuzhiyun+++ b/html/vp9svctest.js 324*4882a593Smuzhiyun@@ -387,7 +387,7 @@ function registerUsername() { 325*4882a593Smuzhiyun ptype: "publisher", 326*4882a593Smuzhiyun display: username 327*4882a593Smuzhiyun }; 328*4882a593Smuzhiyun- myusername = username; 329*4882a593Smuzhiyun+ myusername = escapeXmlTags(username); 330*4882a593Smuzhiyun sfutest.send({ message: register }); 331*4882a593Smuzhiyun } 332*4882a593Smuzhiyun } 333*4882a593Smuzhiyun@@ -486,7 +486,7 @@ function newRemoteFeed(id, display, audio, video) { 334*4882a593Smuzhiyun } 335*4882a593Smuzhiyun } 336*4882a593Smuzhiyun remoteFeed.rfid = msg["id"]; 337*4882a593Smuzhiyun- remoteFeed.rfdisplay = msg["display"]; 338*4882a593Smuzhiyun+ remoteFeed.rfdisplay = escapeXmlTags(msg["display"]); 339*4882a593Smuzhiyun if(!remoteFeed.spinner) { 340*4882a593Smuzhiyun var target = document.getElementById('videoremote'+remoteFeed.rfindex); 341*4882a593Smuzhiyun remoteFeed.spinner = new Spinner({top:100}).spin(target); 342*4882a593Smuzhiyun@@ -630,6 +630,15 @@ function newRemoteFeed(id, display, audio, video) { 343*4882a593Smuzhiyun }); 344*4882a593Smuzhiyun } 345*4882a593Smuzhiyun 346*4882a593Smuzhiyun+// Helper to escape XML tags 347*4882a593Smuzhiyun+function escapeXmlTags(value) { 348*4882a593Smuzhiyun+ if(value) { 349*4882a593Smuzhiyun+ var escapedValue = value.replace(new RegExp('<', 'g'), '<'); 350*4882a593Smuzhiyun+ escapedValue = escapedValue.replace(new RegExp('>', 'g'), '>'); 351*4882a593Smuzhiyun+ return escapedValue; 352*4882a593Smuzhiyun+ } 353*4882a593Smuzhiyun+} 354*4882a593Smuzhiyun+ 355*4882a593Smuzhiyun // Helpers to create SVC-related UI for a new viewer 356*4882a593Smuzhiyun function addSvcButtons(feed) { 357*4882a593Smuzhiyun var index = feed; 358