diff --git a/scripts/pi-hole/js/footer.js b/scripts/pi-hole/js/footer.js index 380bc485..be54e1c1 100644 --- a/scripts/pi-hole/js/footer.js +++ b/scripts/pi-hole/js/footer.js @@ -121,6 +121,7 @@ function piholeChange(action, duration) { method: "POST", dataType: "json", processData: false, + contentType: "application/json; charset=utf-8", data: JSON.stringify({ blocking: action === "enable", timer: parseInt(duration, 10) > 0 ? parseInt(duration, 10) : null, diff --git a/scripts/pi-hole/js/groups-clients.js b/scripts/pi-hole/js/groups-clients.js index 8ec90033..dc2762d0 100644 --- a/scripts/pi-hole/js/groups-clients.js +++ b/scripts/pi-hole/js/groups-clients.js @@ -147,7 +147,7 @@ function initTable() { '" title="' + tooltip + '" class="breakall">' + - data.client + + utils.escapeHtml(data.client) + ""; if (data.name !== null && data.name.length > 0) ipName += @@ -156,13 +156,13 @@ function initTable() { '" title="' + tooltip + '" class="breakall">' + - data.name + + utils.escapeHtml(data.name) + ""; $("td:eq(1)", row).html(ipName); $("td:eq(2)", row).html(''); var commentEl = $("#comment_" + dataId, row); - commentEl.val(utils.unescapeHtml(data.comment)); + commentEl.val(data.comment); commentEl.on("change", editClient); $("td:eq(3)", row).empty(); @@ -403,11 +403,14 @@ function delItems(ids) { } function addClient() { - const comment = utils.escapeHtml($("#new_comment").val()); + const comment = $("#new_comment").val(); // Check if the user wants to add multiple IPs (space or newline separated) // If so, split the input and store it in an array - var ips = utils.escapeHtml($("#select").val().trim()).split(/[\s,]+/); + var ips = $("#select") + .val() + .trim() + .split(/[\s,]+/); // Remove empty elements ips = ips.filter(function (el) { return el !== ""; @@ -452,6 +455,7 @@ function addClient() { method: "post", dataType: "json", processData: false, + contentType: "application/json; charset=utf-8", data: JSON.stringify({ client: ips, comment: comment }), success: function (data) { utils.enableAll(); @@ -482,7 +486,7 @@ function editClient() { .find("#multiselect_" + client) .val() .map(Number); - const comment = utils.escapeHtml(tr.find("#comment_" + client).val()); + const comment = tr.find("#comment_" + client).val(); const enabled = tr.find("#enabled_" + client).is(":checked"); var done = "edited"; @@ -519,6 +523,7 @@ function editClient() { method: "put", dataType: "json", processData: false, + contentType: "application/json; charset=utf-8", data: JSON.stringify({ client: client, groups: groups, diff --git a/scripts/pi-hole/js/groups-common.js b/scripts/pi-hole/js/groups-common.js index 8ca1e99c..20cbdba9 100644 --- a/scripts/pi-hole/js/groups-common.js +++ b/scripts/pi-hole/js/groups-common.js @@ -36,11 +36,6 @@ function processGroupResult(data, type, done, notDone) { // Loop over errors and display them data.processed.errors.forEach(function (error) { console.log(error); // eslint-disable-line no-console - utils.showAlert( - "error", - "", - `Error while ${notDone} ${type} ${utils.escapeHtml(error.item)}`, - error.error - ); + utils.showAlert("error", "", `Error while ${notDone} ${type} ${error.item}`, error.error); }); } diff --git a/scripts/pi-hole/js/groups-domains.js b/scripts/pi-hole/js/groups-domains.js index 22248d45..ba80c931 100644 --- a/scripts/pi-hole/js/groups-domains.js +++ b/scripts/pi-hole/js/groups-domains.js @@ -151,8 +151,8 @@ function initTable() { '" title="' + tooltip + '" class="breakall">' + - data.unicode + - (data.domain !== data.unicode ? " (" + data.domain + ")" : "") + + utils.escapeHtml(data.unicode) + + (data.domain !== data.unicode ? " (" + utils.escapeHtml(data.domain) + ")" : "") + "" ); @@ -206,7 +206,7 @@ function initTable() { // Comment field $("td:eq(4)", row).html(''); var commentEl = $("#comment_" + dataId, row); - commentEl.val(utils.unescapeHtml(data.comment)); + commentEl.val(data.comment); commentEl.on("change", editDomain); // Group assignment field (multi-select) @@ -504,11 +504,11 @@ function addDomain() { commentEl = $("#new_regex_comment"); } - const comment = utils.escapeHtml(commentEl.val()); + const comment = commentEl.val(); // Check if the user wants to add multiple domains (space or newline separated) // If so, split the input and store it in an array - var domains = utils.escapeHtml(domainEl.val()).split(/\s+/); + var domains = domainEl.val().split(/\s+/); // Remove empty elements domains = domains.filter(function (el) { return el !== ""; @@ -543,6 +543,7 @@ function addDomain() { method: "post", dataType: "json", processData: false, + contentType: "application/json; charset=utf-8", data: JSON.stringify({ domain: domains, comment: comment, @@ -578,7 +579,7 @@ function editDomain() { const newTypestr = tr.find("#type_" + domain).val(); const oldTypeStr = tr.find("#old_type_" + domain).val(); const enabled = tr.find("#enabled_" + domain).is(":checked"); - const comment = utils.escapeHtml(tr.find("#comment_" + domain).val()); + const comment = tr.find("#comment_" + domain).val(); // Convert list of string integers to list of integers using map const groups = tr .find("#multiselect_" + domain) @@ -624,12 +625,13 @@ function editDomain() { utils.disableAll(); const domainDecoded = utils.hexDecode(domain.split("_")[0]); - utils.showAlert("info", "", "Editing domain...", domain); + utils.showAlert("info", "", "Editing domain...", domainDecoded); $.ajax({ url: "/api/domains/" + newTypestr + "/" + encodeURIComponent(domainDecoded), method: "put", dataType: "json", processData: false, + contentType: "application/json; charset=utf-8", data: JSON.stringify({ groups: groups, comment: comment, diff --git a/scripts/pi-hole/js/groups-lists.js b/scripts/pi-hole/js/groups-lists.js index dc8c11de..4a209e9b 100644 --- a/scripts/pi-hole/js/groups-lists.js +++ b/scripts/pi-hole/js/groups-lists.js @@ -194,16 +194,20 @@ function initTable() { // Local files cannot be downloaded from a distant client so don't show // a link to such a list here $("td:eq(2)", row).html( - '' + data.address + "" + '' + + utils.escapeHtml(data.address) + + "" ); } else { $("td:eq(2)", row).html( '' + - data.address + + utils.escapeHtml(data.address) + "" ); } @@ -227,7 +231,7 @@ function initTable() { $("td:eq(4)", row).html(''); var commentEl = $("#comment_" + dataId, row); - commentEl.val(utils.unescapeHtml(data.comment)); + commentEl.val(data.comment); commentEl.on("change", editList); $("td:eq(5)", row).empty(); @@ -497,11 +501,13 @@ function delItems(ids) { function addList(event) { const type = event.data.type; - const comment = utils.escapeHtml($("#new_comment").val()); + const comment = $("#new_comment").val(); // Check if the user wants to add multiple domains (space or newline separated) // If so, split the input and store it in an array - var addresses = utils.escapeHtml($("#new_address").val()).split(/[\s,]+/); + var addresses = $("#new_address") + .val() + .split(/[\s,]+/); // Remove empty elements addresses = addresses.filter(function (el) { return el !== ""; @@ -523,6 +529,7 @@ function addList(event) { method: "post", dataType: "json", processData: false, + contentType: "application/json; charset=utf-8", data: JSON.stringify({ address: addresses, comment: comment, type: type }), success: function (data) { utils.enableAll(); @@ -591,6 +598,7 @@ function editList() { method: "put", dataType: "json", processData: false, + contentType: "application/json; charset=utf-8", data: JSON.stringify({ groups: groups, comment: comment, diff --git a/scripts/pi-hole/js/groups.js b/scripts/pi-hole/js/groups.js index 63047a4c..9703d11a 100644 --- a/scripts/pi-hole/js/groups.js +++ b/scripts/pi-hole/js/groups.js @@ -75,7 +75,7 @@ $(function () { '' ); var nameEl = $("#name_" + data.id, row); - nameEl.val(utils.unescapeHtml(data.name)); + nameEl.val(data.name); nameEl.on("change", editGroup); $("td:eq(2)", row).html( @@ -98,7 +98,7 @@ $(function () { $("td:eq(3)", row).html(''); var comment = data.comment !== null ? data.comment : ""; var commentEl = $("#comment_" + data.id, row); - commentEl.val(utils.unescapeHtml(comment)); + commentEl.val(comment); commentEl.on("change", editGroup); $("td:eq(4)", row).empty(); @@ -277,7 +277,7 @@ function delItems(ids) { } function addGroup() { - const comment = utils.escapeHtml($("#new_comment").val()); + const comment = $("#new_comment").val(); // Check if the user wants to add multiple groups (space or newline separated) // If so, split the input and store it in an array @@ -306,6 +306,7 @@ function addGroup() { method: "post", dataType: "json", processData: false, + contentType: "application/json; charset=utf-8", data: JSON.stringify({ name: names, comment: comment, @@ -336,9 +337,9 @@ function editGroup() { const tr = $(this).closest("tr"); const id = tr.attr("data-id"); const oldName = idNames[id]; - const name = utils.escapeHtml(tr.find("#name_" + id).val()); + const name = tr.find("#name_" + id).val(); const enabled = tr.find("#enabled_" + id).is(":checked"); - const comment = utils.escapeHtml(tr.find("#comment_" + id).val()); + const comment = tr.find("#comment_" + id).val(); var done = "edited"; var notDone = "editing"; @@ -373,6 +374,7 @@ function editGroup() { method: "put", dataType: "json", processData: false, + contentType: "application/json; charset=utf-8", data: JSON.stringify({ name: name, comment: comment, diff --git a/scripts/pi-hole/js/index.js b/scripts/pi-hole/js/index.js index d70fe881..03371648 100644 --- a/scripts/pi-hole/js/index.js +++ b/scripts/pi-hole/js/index.js @@ -262,7 +262,7 @@ function updateForwardDestinationsPie() { } function updateTopClientsTable(blocked) { - var api, style, tablecontent, overlay, clienttable; + let api, style, tablecontent, overlay, clienttable; if (blocked) { api = "/api/stats/top_clients?blocked=true"; style = "queries-blocked"; @@ -280,9 +280,8 @@ function updateTopClientsTable(blocked) { $.getJSON(api, function (data) { // Clear tables before filling them with data tablecontent.remove(); - var url, - percentage, - sum = blocked ? data.blocked_queries : data.total_queries; + let url, percentage; + const sum = blocked ? data.blocked_queries : data.total_queries; // Add note if there are no results (e.g. privacy mode enabled) if (jQuery.isEmptyObject(data.clients)) { @@ -292,10 +291,14 @@ function updateTopClientsTable(blocked) { // Populate table with content data.clients.forEach(function (client) { // Sanitize client - var clientname = utils.escapeHtml(client.name); - var clientip = utils.escapeHtml(client.ip); - if (clientname.length === 0) clientname = clientip; - url = '' + clientname + ""; + let clientname = client.name; + if (clientname.length === 0) clientname = client.ip; + url = + '' + + utils.escapeHtml(clientname) + + ""; percentage = (client.count / sum) * 100; // Add row to table @@ -316,7 +319,7 @@ function updateTopClientsTable(blocked) { } function updateTopDomainsTable(blocked) { - var api, style, tablecontent, overlay, domaintable; + let api, style, tablecontent, overlay, domaintable; if (blocked) { api = "/api/stats/top_domains?blocked=true"; style = "queries-blocked"; @@ -334,11 +337,8 @@ function updateTopDomainsTable(blocked) { $.getJSON(api, function (data) { // Clear tables before filling them with data tablecontent.remove(); - var url, - domain, - percentage, - urlText, - sum = blocked ? data.blocked_queries : data.total_queries; + let url, domain, percentage, urlText; + const sum = blocked ? data.blocked_queries : data.total_queries; // Add note if there are no results (e.g. privacy mode enabled) if (jQuery.isEmptyObject(data.domains)) { @@ -348,7 +348,7 @@ function updateTopDomainsTable(blocked) { // Populate table with content data.domains.forEach(function (item) { // Sanitize domain - domain = utils.escapeHtml(item.domain); + domain = encodeURIComponent(item.domain); // Substitute "." for empty domain lookups urlText = domain === "" ? "." : domain; url = '' + urlText + ""; diff --git a/scripts/pi-hole/js/login.js b/scripts/pi-hole/js/login.js index a1e4b5ca..fdd3f0d1 100644 --- a/scripts/pi-hole/js/login.js +++ b/scripts/pi-hole/js/login.js @@ -110,6 +110,7 @@ function doLogin(password) { method: "POST", dataType: "json", processData: false, + contentType: "application/json; charset=utf-8", data: JSON.stringify({ password: password, totp: parseInt($("#totp").val(), 10) }), }) .done(function (data) { diff --git a/scripts/pi-hole/js/settings-advanced.js b/scripts/pi-hole/js/settings-advanced.js index bd514b56..6c657924 100644 --- a/scripts/pi-hole/js/settings-advanced.js +++ b/scripts/pi-hole/js/settings-advanced.js @@ -59,11 +59,11 @@ function generateRow(topic, key, value) { "" + '
' + '
'; - var defaultValueHint = ""; + let defaultValueHint = ""; if (value.modified) { defaultValueHint = ""; if (value.default !== null) { - var defVal = utils.escapeHtml(JSON.stringify(value.default)); + let defVal = utils.escapeHtml(JSON.stringify(value.default)); switch (defVal) { case "true": { defVal = "enabled"; diff --git a/scripts/pi-hole/js/settings-api.js b/scripts/pi-hole/js/settings-api.js index 251af7ef..77e5dacb 100644 --- a/scripts/pi-hole/js/settings-api.js +++ b/scripts/pi-hole/js/settings-api.js @@ -346,7 +346,7 @@ function setAppPassword() { dataType: "json", processData: false, data: JSON.stringify({ config: { webserver: { api: { app_pwhash: apppwhash } } } }), - contentType: "application/json", + contentType: "application/json; charset=utf-8", }) .done(function () { $("#modal-apppw").modal("hide"); @@ -399,7 +399,7 @@ function setTOTPSecret(secret) { dataType: "json", processData: false, data: JSON.stringify({ config: { webserver: { api: { totp_secret: secret } } } }), - contentType: "application/json", + contentType: "application/json; charset=utf-8", }) .done(function () { $("#button-enable-totp").addClass("hidden"); diff --git a/scripts/pi-hole/js/settings-dns-records.js b/scripts/pi-hole/js/settings-dns-records.js index cf288b5d..702f29a3 100644 --- a/scripts/pi-hole/js/settings-dns-records.js +++ b/scripts/pi-hole/js/settings-dns-records.js @@ -173,7 +173,7 @@ function delHosts(elem) { utils.showAlert( "error", "", - "Error while deleting DNS record: " + utils.escapeHtml(elem) + "", + "Error while deleting DNS record: " + elem + "", data.responseText ); console.log(exception); // eslint-disable-line no-console @@ -205,7 +205,7 @@ function delCNAME(elem) { utils.showAlert( "error", "", - "Error while deleting CNAME record: " + utils.escapeHtml(elem) + "", + "Error while deleting CNAME record: " + elem + "", data.responseText ); console.log(exception); // eslint-disable-line no-console diff --git a/scripts/pi-hole/js/settings-system.js b/scripts/pi-hole/js/settings-system.js index 4f0e280a..4a0844f4 100644 --- a/scripts/pi-hole/js/settings-system.js +++ b/scripts/pi-hole/js/settings-system.js @@ -298,6 +298,7 @@ $("#loggingButton").confirm({ type: "PATCH", dataType: "json", processData: false, + contentType: "application/json; charset=utf-8", data: JSON.stringify(data), }) .done(function (data) { diff --git a/scripts/pi-hole/js/utils.js b/scripts/pi-hole/js/utils.js index 63fc3ec8..3e1b8af7 100644 --- a/scripts/pi-hole/js/utils.js +++ b/scripts/pi-hole/js/utils.js @@ -86,8 +86,8 @@ function padNumber(num) { var showAlertBox = null; function showAlert(type, icon, title, message) { const options = { - title: " " + title + "
", - message: message, + title: " " + escapeHtml(title) + "
", + message: escapeHtml(message), icon: icon, }, settings = { @@ -123,9 +123,9 @@ function showAlert(type, icon, title, message) { var data = JSON.parse(message); console.log(data); // eslint-disable-line no-console if (data.error !== undefined) { - options.title = " " + data.error.message + "
"; + options.title = " " + escapeHtml(data.error.message) + "
"; - if (data.error.hint !== null) options.message = data.error.hint; + if (data.error.hint !== null) options.message = escapeHtml(data.error.hint); } } catch { // Do nothing @@ -319,6 +319,7 @@ function addFromQueryLog(domain, list) { method: "post", dataType: "json", processData: false, + contentType: "application/json; charset=utf-8", data: JSON.stringify({ domain: domain, comment: "Added from Query Log",