diff --git a/www/js/adminPanel.js b/www/js/adminPanel.js index 9dff996..cb78133 100644 --- a/www/js/adminPanel.js +++ b/www/js/adminPanel.js @@ -216,7 +216,7 @@ class adminUserBanList{ userNode.title = "Nuked" }else{ var userNode = document.createElement('p'); - userNode.innerHTML = user.user; + userNode.textContent = utils.unescapeEntities(user.user); } return userNode; } @@ -251,7 +251,7 @@ class adminUserBanList{ //Create a node const userNode = document.createElement('p'); //Fill it wit the ip - userNode.innerHTML = user; + userNode.textContent = utils.unescapeEntities(user); //Append it deadUsers.appendChild(userNode); } @@ -269,7 +269,7 @@ class adminUserBanList{ //Create a node const ipNode = document.createElement('p'); //Fill it wit the ip - ipNode.innerHTML = ip; + ipNode.textContent = utils.unescapeEntities(ip); //Append it ipList.appendChild(ipNode); } @@ -279,7 +279,7 @@ class adminUserBanList{ //Create a node const ipNode = document.createElement('p'); //List it as a hashed ip with the hash as alt text - ipNode.innerHTML = '[Hashed IP]'; + ipNode.textContent = utils.unescapeEntities('[Hashed IP]'); ipNode.title = hash; //Append the node ipList.appendChild(ipNode); @@ -372,7 +372,7 @@ class adminTokeCommandList{ //Create toke command label const tokeLabel = document.createElement('p'); - tokeLabel.innerHTML = `!${toke}`; + tokeLabel.textContent = utils.unescapeEntities(`!${toke}`); tokeLabel.classList.add('toke-command-list'); //Create toke command delete icon @@ -481,7 +481,7 @@ class adminEmoteList{ //Set title class emoteTitle.classList.add('emote-list-title'); //Set emote title - emoteTitle.innerHTML = `[${emote.name}]`; + emoteTitle.textContent = utils.unescapeEntities(`[${emote.name}]`); //Create delete icon const deleteIcon = document.createElement('i'); diff --git a/www/js/channel/chat.js b/www/js/channel/chat.js index dc7b9b7..f9898f0 100644 --- a/www/js/channel/chat.js +++ b/www/js/channel/chat.js @@ -109,7 +109,7 @@ class chatBox{ //Create high-level label var highLevel = document.createElement('p'); highLevel.classList.add("chat-panel-buffer","chat-entry-high-level","high-level"); - highLevel.innerHTML = `${data.highLevel}`; + highLevel.textContent = utils.unescapeEntities(`${data.highLevel}`); chatEntry.appendChild(highLevel); //Create username label @@ -125,8 +125,8 @@ class chatBox{ //Create color span var colorSpan = document.createElement('span'); colorSpan.classList.add("chat-entry-flair-span", flair); - colorSpan.innerHTML = `${data.user}`; - userLabel.innerHTML = `${colorSpan.outerHTML}: `; + colorSpan.textContent = utils.unescapeEntities(`${data.user}`); + userLabel.textContent = utils.unescapeEntities(`${colorSpan.outerHTML}: `); chatEntry.appendChild(userLabel); @@ -277,7 +277,7 @@ class chatBox{ var flairOption = document.createElement('option'); //Set the name and innerHTML flairOption.value = flair.name; - flairOption.innerHTML = flair.displayName; + flairOption.textContent = utils.unescapeEntities(flair.displayName); //Append it to the select this.flairSelect.appendChild(flairOption); diff --git a/www/js/channel/chatPostprocessor.js b/www/js/channel/chatPostprocessor.js index 920e4e5..e9c2518 100644 --- a/www/js/channel/chatPostprocessor.js +++ b/www/js/channel/chatPostprocessor.js @@ -73,9 +73,7 @@ class chatPostprocessor{ //Create an empty array to hold the body this.messageArray = []; - //First unescape char codes to keep from splitting on them - //This also means all text should be added to element via textContent and *NOT* innerHTML - //I'd rather not do this, but pre-processing everything while preserving codes is a fucking nightmare + //Escape any sanatized char codes as we use .textContent for double-safety, and to prevent splitting of char codes //Split string by word-boundries on words and non-word boundries around whitespace, with negative lookaheads to exclude file seperators so we don't split link placeholders //Also split by any invisble whitespace as a crutch to handle mushed links/emotes //If we can one day figure out how to split non-repeating special chars instead of special chars with whitespace, that would be perf, unfortunately my brain hasn't rotted enough to understand regex like that just yet. diff --git a/www/js/channel/panels/emotePanel.js b/www/js/channel/panels/emotePanel.js index 56bbe29..801d50b 100644 --- a/www/js/channel/panels/emotePanel.js +++ b/www/js/channel/panels/emotePanel.js @@ -220,7 +220,7 @@ class emotePanel extends panelObj{ //Set title class emoteTitle.classList.add('emote-list-title'); //Set emote title - emoteTitle.innerHTML = `[${emote.name}]`; + emoteTitle.textContent = utils.unescapeEntities(`[${emote.name}]`); //if we're rendering personal emotes if(personal){ diff --git a/www/js/channel/panels/queuePanel/queuePanel.js b/www/js/channel/panels/queuePanel/queuePanel.js index 18d5840..6372fca 100644 --- a/www/js/channel/panels/queuePanel/queuePanel.js +++ b/www/js/channel/panels/queuePanel/queuePanel.js @@ -833,6 +833,7 @@ class queuePanel extends panelObj{ timetip.moveToMouse(event); //Inject timetip label + //Normally wouldn't do innerHTML but these values are calculated serverside and it saves us making a
element timetip.tooltip.innerHTML = [ `Start Time: ${utils.ux.timeStringFromDate(start, true)}`, `End Time: ${utils.ux.timeStringFromDate(new Date(start.getTime() + (target.dataset['duration'] * 1000)), true)}` diff --git a/www/js/channel/userlist.js b/www/js/channel/userlist.js index 018b677..b72c394 100644 --- a/www/js/channel/userlist.js +++ b/www/js/channel/userlist.js @@ -100,7 +100,7 @@ class userList{ //Create high-level label var highLevel = document.createElement('p'); highLevel.classList.add("user-list-high-level","high-level"); - highLevel.innerHTML = `${user.highLevel}`; + highLevel.textContent = `${user.highLevel}`; //Create nameplate var userEntry = document.createElement('p'); diff --git a/www/js/channelSettings.js b/www/js/channelSettings.js index 9fec560..a98bd08 100644 --- a/www/js/channelSettings.js +++ b/www/js/channelSettings.js @@ -114,7 +114,7 @@ class rankList{ //Create an option for the given rank const rankOption = document.createElement('option'); rankOption.value = rank; - rankOption.innerHTML = rank; + rankOption.textContent = utils.unescapeEntities(rank); rankOption.selected = user.rank == rank; rankContent.appendChild(rankOption); }); @@ -343,7 +343,7 @@ class tokeCommandList{ //Create toke command label const tokeLabel = document.createElement('p'); - tokeLabel.innerHTML = `!${toke}`; + tokeLabel.textContent = utils.unescapeEntities(`!${toke}`); tokeLabel.classList.add('toke-command-list'); //Create toke command delete icon @@ -453,7 +453,7 @@ class emoteList{ //Set title class emoteTitle.classList.add('emote-list-title'); //Set emote title - emoteTitle.innerHTML = `[${emote.name}]`; + emoteTitle.textContent = utils.unescapeEntities(`[${emote.name}]`); //Create delete icon const deleteIcon = document.createElement('i'); @@ -504,7 +504,7 @@ class deleteAccountPopup{ this.label = document.querySelector("#delete-channel-popup-content"); //Fill channel label - this.label.innerHTML = this.label.innerHTML.replaceAll("[CHANNEL]", this.channel); + this.label.textContent = this.label.textContent.replaceAll("[CHANNEL]", utils.unescapeEntities(this.channel)); this.setupInput(); } diff --git a/www/js/popup/banPopup.js b/www/js/popup/banPopup.js index 0859bfa..85f513d 100644 --- a/www/js/popup/banPopup.js +++ b/www/js/popup/banPopup.js @@ -8,7 +8,7 @@ class banUserPopup{ asyncConstruction(){ this.title = document.querySelector(".popup-title"); //Setup title text real quick-like :P - this.title.innerHTML = `Ban ${this.target}`; + this.title.textContent = utils.unescapeEntities(`Ban ${this.target}`); this.ipBan = document.querySelector("#ban-popup-ip"); this.permBan = document.querySelector("#ban-popup-perm"); @@ -28,10 +28,10 @@ class banUserPopup{ permaBanLabel(event){ if(event.target.checked){ - this.expirationPrefix.innerHTML = "Account Deletion In: " + this.expirationPrefix.textContent = "Account Deletion In: " this.expiration.value = 30; }else{ - this.expirationPrefix.innerHTML = "Ban Expires In: " + this.expirationPrefix.textContent = "Ban Expires In: " this.expiration.value = 14; } } @@ -63,7 +63,7 @@ class chanBanUserPopup{ asyncConstruction(){ this.title = document.querySelector(".popup-title"); //Setup title text real quick-like :P - this.title.innerHTML = `Ban ${this.target}`; + this.title.textContent = utils.unescapeEntities(`Ban ${this.target}`); this.permBan = document.querySelector("#ban-popup-perm"); this.expiration = document.querySelector("#ban-popup-expiration"); diff --git a/www/js/profile.js b/www/js/profile.js index 7cc1e85..1506879 100644 --- a/www/js/profile.js +++ b/www/js/profile.js @@ -102,7 +102,7 @@ class profileUpdateTextPrompt extends profileUpdatePrompt{ const update = await utils.ajax.updateProfile(updateObj); //Fill content from update, make sure to add line breaks for the bio - this.contentNode.innerHTML = update[this.field].replaceAll('\n','
'); + this.contentNode.textContent = utils.unescapeEntities(update[this.field].replaceAll('\n','
')); } } } diff --git a/www/js/utils.js b/www/js/utils.js index 39eccc7..7191c1b 100644 --- a/www/js/utils.js +++ b/www/js/utils.js @@ -330,7 +330,7 @@ class canopyUXUtils{ //Create menu title const menuTitle = document.createElement('h2'); - menuTitle.innerHTML = this.title; + menuTitle.textContent = utils.unescapeEntities(this.title); //Append the title to the tooltip this.tooltip.append(menuTitle); @@ -338,7 +338,7 @@ class canopyUXUtils{ for(let choice of this.menuMap){ //Create button const button = document.createElement('button'); - button.innerHTML = choice[0]; + button.textContent = utils.unescapeEntities(choice[0]); //Add event listeners button.addEventListener('click', choice[1]);