Files
web/scripts/js/settings-teleporter.js
Austin Gilmour 1c621a53f8 fix: replace ES2024 regex v flag with u for WebKit compatibility (#3757)
WebKit-based browsers (Safari, DuckDuckGo on macOS) don't yet support
the ES2024 Unicode Sets `v` regex flag, causing a SyntaxError that
prevents all dashboard JavaScript from executing — stats show `---` and
charts spin indefinitely.

None of the affected patterns use v-exclusive features (set notation
`[A--B]`, `[A&&B]`), so downgrading to `u` is fully equivalent and
restores broad compatibility without any functional change.

Also updates xo.config.js to enforce `requireFlag: "u"` so the linter
stays consistent with the codebase.

Affected files (16 occurrences across 8 files):
- scripts/js/utils.js
- scripts/js/index.js
- scripts/js/footer.js
- scripts/js/groups-domains.js
- scripts/js/settings-teleporter.js
- scripts/js/gravity.js
- scripts/js/groups.js
- scripts/js/groups-clients.js
- scripts/js/groups-lists.js
- scripts/js/settings-dns-records.js
- scripts/js/network.js
- scripts/js/taillog.js

Signed-off-by: Austin Gilmour <gilmoursa@gmail.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 07:58:15 -04:00

109 lines
3.6 KiB
JavaScript

/* Pi-hole: A black hole for Internet advertisements
* (c) 2023 Pi-hole, LLC (https://pi-hole.net)
* Network-wide ad blocking via your own hardware.
*
* This file is copyright under the latest version of the EUPL.
* Please see LICENSE file for your rights under this license. */
/* global utils:false */
"use strict";
// Add event listener to import button
document.getElementById("submit-import").addEventListener("click", () => {
importZIP();
});
// Upload file to Pi-hole
function importZIP() {
const file = document.getElementById("file").files[0];
if (file === undefined) {
alert("Please select a file to import.");
return;
}
// Get the selected import options
const imports = {};
const gravity = {};
imports.config = document.getElementById("import.config").checked;
imports.dhcp_leases = document.getElementById("import.dhcp_leases").checked;
gravity.group = document.getElementById("import.gravity.group").checked;
gravity.adlist = document.getElementById("import.gravity.adlist").checked;
gravity.adlist_by_group = document.getElementById("import.gravity.adlist").checked;
gravity.domainlist = document.getElementById("import.gravity.domainlist").checked;
gravity.domainlist_by_group = document.getElementById("import.gravity.domainlist").checked;
gravity.client = document.getElementById("import.gravity.client").checked;
gravity.client_by_group = document.getElementById("import.gravity.client").checked;
imports.gravity = gravity;
const formData = new FormData();
formData.append("import", JSON.stringify(imports));
formData.append("file", file);
fetch(document.body.dataset.apiurl + "/teleporter", {
method: "POST",
body: formData,
headers: { "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content") },
})
.then(response => response.json())
.then(data => {
$("#import-spinner").hide();
$("#modal-import-success").hide();
$("#modal-import-error").hide();
$("#modal-import-info").hide();
if ("error" in data) {
$("#modal-import-error").show();
$("#modal-import-error-title").text("Error: " + data.error.message);
if (data.error.hint !== null) $("#modal-import-error-message").text(data.error.hint);
} else if ("files" in data) {
$("#modal-import-success").show();
$("#modal-import-success-title").text("Import successful");
let text = "<p>Processed files:</p><ul>";
for (const file of data.files) {
text += "<li>" + utils.escapeHtml(file) + "</li>";
}
text += "</ul>";
$("#modal-import-success-message").html(text);
$("#modal-import-gravity").show();
}
$("#modal-import").modal("show");
})
.catch(error => {
alert("An unexpected error occurred.");
console.error(error); // eslint-disable-line no-console
});
}
// Inspired by https://stackoverflow.com/a/59576416/2087442
$("#GETTeleporter").on("click", () => {
$.ajax({
url: document.body.dataset.apiurl + "/teleporter",
headers: { "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content") },
method: "GET",
xhrFields: {
responseType: "blob",
},
success(data, status, xhr) {
const a = document.createElement("a");
const url = globalThis.URL.createObjectURL(data);
a.href = url;
a.download = xhr.getResponseHeader("Content-Disposition").match(/filename="([^"]*)"/u)[1];
document.body.append(a);
a.click();
a.remove();
globalThis.URL.revokeObjectURL(url);
},
});
});
$(() => {
// Show warning if not accessed over HTTPS
if (location.protocol !== "https:") {
$("#encryption-warning").show();
}
});