|
1098 | 1098 | } |
1099 | 1099 |
|
1100 | 1100 |
|
1101 | | - function stripHtmlFunction(html) { |
1102 | | - let tmp = document.createElement("DIV"); |
1103 | | - tmp.innerHTML = html; |
1104 | | - return tmp.textContent || tmp.innerText || ""; |
1105 | | - } |
1106 | | - |
1107 | | - function upscaleImages(data) { |
| 1101 | + function removeHtmlTagsFromPlainTextField(value) { |
| 1102 | + return String(value || "") |
| 1103 | + .replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, "") |
| 1104 | + .replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, "") |
| 1105 | + .replace(/<noscript\b[^>]*>[\s\S]*?<\/noscript>/gi, "") |
| 1106 | + .replace(/<template\b[^>]*>[\s\S]*?<\/template>/gi, "") |
| 1107 | + .replace(/<[^>]*>/g, ""); |
| 1108 | + } |
| 1109 | + |
| 1110 | + function stripHtmlFunction(html) { |
| 1111 | + html = String(html == null ? "" : html); |
| 1112 | + try { |
| 1113 | + if (typeof DOMParser !== "undefined") { |
| 1114 | + let doc = new DOMParser().parseFromString(html, "text/html"); |
| 1115 | + if (doc && doc.body) { |
| 1116 | + doc.body.querySelectorAll("script,style,noscript,template").forEach(function (node) { |
| 1117 | + node.remove(); |
| 1118 | + }); |
| 1119 | + return removeHtmlTagsFromPlainTextField(doc.body.textContent || ""); |
| 1120 | + } |
| 1121 | + } |
| 1122 | + } catch (e) {} |
| 1123 | + let tmp = document.createElement("DIV"); |
| 1124 | + tmp.innerHTML = html; |
| 1125 | + return removeHtmlTagsFromPlainTextField(tmp.textContent || tmp.innerText || ""); |
| 1126 | + } |
| 1127 | + |
| 1128 | + function sanitizePlainTextAlertFields(data) { |
| 1129 | + if (!data) { |
| 1130 | + return; |
| 1131 | + } |
| 1132 | + ["hasDonation", "donation", "membership", "hasMembership", "subtitle", "title"].forEach(function (field) { |
| 1133 | + if (typeof data[field] === "string") { |
| 1134 | + data[field] = stripHtmlFunction(data[field]); |
| 1135 | + } |
| 1136 | + }); |
| 1137 | + } |
| 1138 | + |
| 1139 | + function plainTextToHtml(value) { |
| 1140 | + let span = document.createElement("span"); |
| 1141 | + span.textContent = value == null ? "" : String(value); |
| 1142 | + return span.innerHTML; |
| 1143 | + } |
| 1144 | + |
| 1145 | + function upscaleImages(data) { |
1108 | 1146 | // for third party APIs |
1109 | 1147 | let chatimg = ""; |
1110 | 1148 | if (data.type && (data.type == "twitch") && data.chatname && !data.chatimg) { |
|
2162 | 2200 | } |
2163 | 2201 | } else if (!data.chatname) { |
2164 | 2202 | data.chatname = ""; |
2165 | | - } else { |
2166 | | - data.chatname = data.chatname.toString(); |
2167 | | - } |
2168 | | - |
2169 | | - var memebershipHTML = ""; |
| 2203 | + } else { |
| 2204 | + data.chatname = data.chatname.toString(); |
| 2205 | + } |
| 2206 | + |
| 2207 | + sanitizePlainTextAlertFields(data); |
| 2208 | + |
| 2209 | + var memebershipHTML = ""; |
2170 | 2210 |
|
2171 | 2211 | if (data.hasMembership) { |
2172 | 2212 | if (data.hasMembership === true) { |
2173 | 2213 | data.hasMembership = getTranslation("membership", "Membership"); |
2174 | | - } |
2175 | | - // doesn't have subtitles; shouldn't at least. |
2176 | | - data.membership = data.hasMembership.toString(); |
2177 | | - memebershipHTML = data.membership; |
2178 | | - } else if (data.membership) { |
| 2214 | + } |
| 2215 | + // doesn't have subtitles; shouldn't at least. |
| 2216 | + data.membership = data.hasMembership.toString(); |
| 2217 | + memebershipHTML = plainTextToHtml(data.membership); |
| 2218 | + } else if (data.membership) { |
2179 | 2219 | if (data.membership === true) { |
2180 | 2220 | data.membership = getTranslation("membership", "Membership"); |
2181 | 2221 | } else { |
2182 | 2222 | data.membership = data.membership.toString(); |
2183 | 2223 | } |
2184 | 2224 |
|
2185 | | - if (data.subtitle) { |
2186 | | - memebershipHTML = '<div class="donation membership"><div class="donation-title">' + data.membership.toUpperCase() + "</div><div class='subtitle'>" + data.subtitle + "</div></div>"; |
2187 | | - } else { |
2188 | | - memebershipHTML = '<div class="donation membership"><div class="donation-title">' + data.membership.toUpperCase() + "</div></div>"; |
2189 | | - } |
2190 | | - } else if (data.subtitle) { |
2191 | | - memebershipHTML = '<div class="donation membership"><div class="subtitle">' + data.subtitle + "</div></div>"; |
| 2225 | + if (data.subtitle) { |
| 2226 | + memebershipHTML = '<div class="donation membership"><div class="donation-title">' + plainTextToHtml(data.membership.toUpperCase()) + "</div><div class='subtitle'>" + plainTextToHtml(data.subtitle) + "</div></div>"; |
| 2227 | + } else { |
| 2228 | + memebershipHTML = '<div class="donation membership"><div class="donation-title">' + plainTextToHtml(data.membership.toUpperCase()) + "</div></div>"; |
| 2229 | + } |
| 2230 | + } else if (data.subtitle) { |
| 2231 | + memebershipHTML = '<div class="donation membership"><div class="subtitle">' + plainTextToHtml(data.subtitle) + "</div></div>"; |
2192 | 2232 | } else { |
2193 | 2233 | data.membership = ""; |
2194 | 2234 | } |
|
2203 | 2243 | if (data.hasDonation) { |
2204 | 2244 | if (data.type === "twitch") { |
2205 | 2245 | let donationTitle = getTranslation("cheers", "CHEERS"); |
2206 | | - if ("title" in data) { |
2207 | | - donationTitle = data.title; |
2208 | | - } |
2209 | | - donationHTML = '<div class="donation"><div class="donation-title">'+ donationTitle +'</div><div class="subtitle">' + data.hasDonation + "</div></div>"; |
| 2246 | + if ("title" in data) { |
| 2247 | + donationTitle = data.title; |
| 2248 | + } |
| 2249 | + donationHTML = '<div class="donation"><div class="donation-title">'+ plainTextToHtml(donationTitle) +'</div><div class="subtitle">' + plainTextToHtml(data.hasDonation) + "</div></div>"; |
2210 | 2250 |
|
2211 | 2251 | } else if ((data.type == "youtube") || (data.type == "youtubeshorts")) { |
2212 | 2252 | let donationTitle = getTranslation("donation", "DONATION"); |
2213 | 2253 | if ("title" in data) { |
2214 | 2254 | donationTitle = data.title; |
2215 | 2255 | } |
2216 | | - if (memebershipHTML) { |
2217 | | - donationHTML = '<div class="donation">' + data.hasDonation + "</div>"; |
2218 | | - } else { |
2219 | | - donationHTML = '<div class="donation"><div class="donation-title">'+ donationTitle +'</div><div class="subtitle">' + data.hasDonation + "</div></div>"; |
2220 | | - } |
2221 | | - |
2222 | | - } else if (data.title) { |
2223 | | - donationHTML = '<div class="donation"><div class="donation-title">'+ data.title +'</div><div class="subtitle">' + data.hasDonation + "</div></div>"; |
2224 | | - |
2225 | | - } else { |
2226 | | - donationHTML = '<div class="donation">' + data.hasDonation + "</div>"; |
2227 | | - } |
| 2256 | + if (memebershipHTML) { |
| 2257 | + donationHTML = '<div class="donation">' + plainTextToHtml(data.hasDonation) + "</div>"; |
| 2258 | + } else { |
| 2259 | + donationHTML = '<div class="donation"><div class="donation-title">'+ plainTextToHtml(donationTitle) +'</div><div class="subtitle">' + plainTextToHtml(data.hasDonation) + "</div></div>"; |
| 2260 | + } |
| 2261 | + |
| 2262 | + } else if (data.title) { |
| 2263 | + donationHTML = '<div class="donation"><div class="donation-title">'+ plainTextToHtml(data.title) +'</div><div class="subtitle">' + plainTextToHtml(data.hasDonation) + "</div></div>"; |
| 2264 | + |
| 2265 | + } else { |
| 2266 | + donationHTML = '<div class="donation">' + plainTextToHtml(data.hasDonation) + "</div>"; |
| 2267 | + } |
2228 | 2268 | } else { |
2229 | 2269 | data.hasDonation = ""; |
2230 | 2270 | } |
|
2303 | 2343 | if (chatbadges) { |
2304 | 2344 | chatbadges = '<div class="hl-badges" >' + chatbadges + "</div>"; |
2305 | 2345 | } |
2306 | | - |
| 2346 | + |
2307 | 2347 | var renderChatMessageAsText = !!(data.textonly && !largeImage); |
| 2348 | + // Trusted relay HTML: chatname/chatmessage are sanitized upstream in background.js before rendering here. |
2308 | 2349 | var renderedChatMessage = renderChatMessageAsText ? "" : data.chatmessage; |
2309 | 2350 |
|
2310 | | - if (stacking) { |
| 2351 | + if (stacking) { |
2311 | 2352 | try { |
2312 | 2353 | document.getElementById("message").id = ""; |
2313 | 2354 | document.getElementById("nameDIV").id = ""; |
|
0 commit comments