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]);