diff --git a/pkg/service/handlers/web/js/script.js b/pkg/service/handlers/web/js/script.js index 05fc7ca..9ce47b1 100644 --- a/pkg/service/handlers/web/js/script.js +++ b/pkg/service/handlers/web/js/script.js @@ -364,7 +364,7 @@ async function fetchDevices() { fetchSpotifyStatus(); } } catch (error) { - document.getElementById("device-list").innerHTML = "Error loading devices: " + error; + document.getElementById("device-list").textContent = "Error loading devices: " + error; } } @@ -484,7 +484,7 @@ async function startSync() { status.style.backgroundColor = "#dfd"; status.textContent = "✅ Sync completed successfully for " + display + "!"; results.style.display = "block"; - log.innerHTML = "Data fetched and saved to local datastore for " + display + ".\nPresets: OK\nRecents: OK\nSources: OK"; + log.textContent = "Data fetched and saved to local datastore for " + display + ".\nPresets: OK\nRecents: OK\nSources: OK"; } else { const err = await response.text(); throw new Error(err); @@ -1709,7 +1709,7 @@ async function showSummary(deviceId) { statusDiv.style.backgroundColor = "#ffffcc"; const display = getDeviceDisplayName(deviceId); - statusDiv.innerHTML = "Fetching summary for " + display + "..."; + statusDiv.textContent = "Fetching summary for " + display + "..."; const outputBox = document.getElementById("command-output-box"); if (outputBox) outputBox.style.display = "none"; @@ -1872,7 +1872,7 @@ async function showSummary(deviceId) { document.getElementById("migration-summary").scrollIntoView(); } catch (error) { statusDiv.style.backgroundColor = "#ffcccc"; - statusDiv.innerHTML = "Error fetching summary for " + display + ": " + error; + statusDiv.textContent = "Error fetching summary for " + display + ": " + error; } } @@ -1910,7 +1910,7 @@ async function revert(deviceId, ip) { const statusDiv = document.getElementById("status"); statusDiv.style.display = "block"; statusDiv.style.backgroundColor = "#ffffcc"; - statusDiv.innerHTML = "Reverting " + display + " to defaults..."; + statusDiv.textContent = "Reverting " + display + " to defaults..."; try { const response = await fetch("/setup/revert/" + encodeURIComponent(deviceId), {method: "POST"},); @@ -1918,14 +1918,14 @@ async function revert(deviceId, ip) { showCommandOutput(result); if (result.ok) { statusDiv.style.backgroundColor = "#ccffcc"; - statusDiv.innerHTML = "Successfully started revert for " + display + "."; + statusDiv.textContent = "Successfully started revert for " + display + "."; } else { statusDiv.style.backgroundColor = "#ffcccc"; - statusDiv.innerHTML = "Revert failed for " + display + ": " + (result.message || "Unknown error"); + statusDiv.textContent = "Revert failed for " + display + ": " + (result.message || "Unknown error"); } } catch (error) { statusDiv.style.backgroundColor = "#ffcccc"; - statusDiv.innerHTML = "Error reverting " + display + ": " + error; + statusDiv.textContent = "Error reverting " + display + ": " + error; } } @@ -1958,14 +1958,14 @@ async function reboot(deviceId, ip) { showCommandOutput(result); if (result.ok) { statusDiv.style.backgroundColor = "#ccffcc"; - statusDiv.innerHTML = "Successfully started reboot for " + display + "."; + statusDiv.textContent = "Successfully started reboot for " + display + "."; } else { statusDiv.style.backgroundColor = "#ffcccc"; - statusDiv.innerHTML = "Reboot failed for " + display + ": " + (result.message || "Unknown error"); + statusDiv.textContent = "Reboot failed for " + display + ": " + (result.message || "Unknown error"); } } catch (error) { statusDiv.style.backgroundColor = "#ffcccc"; - statusDiv.innerHTML = "Error rebooting " + display + ": " + error; + statusDiv.textContent = "Error rebooting " + display + ": " + error; } } @@ -2110,7 +2110,7 @@ async function migrate(deviceId, ip) { statusDiv.style.display = "block"; statusDiv.style.backgroundColor = "#ffffcc"; const display = getDeviceDisplayName(deviceId); - statusDiv.innerHTML = "Migrating " + display + " using " + method + "..."; + statusDiv.textContent = "Migrating " + display + " using " + method + "..."; let query = "?method=" + encodeURIComponent(method) + "&target_url=" + encodeURIComponent(targetUrl); for (let k in opts) { @@ -2123,7 +2123,14 @@ async function migrate(deviceId, ip) { showCommandOutput(result); if (result.ok) { statusDiv.style.backgroundColor = "#ccffcc"; - statusDiv.innerHTML = "Successfully started migration for " + display + ". Please reboot the device to activate the changes."; + // replaceChildren keeps the user-controlled `display` outside any + // HTML-parsing context, while preserving the intentional . + statusDiv.replaceChildren( + document.createTextNode("Successfully started migration for " + display + ". "), + Object.assign(document.createElement("strong"), { + textContent: "Please reboot the device to activate the changes.", + }), + ); // Make reboot button available and prominent const rebootBtn = document.getElementById("reboot-speaker-btn"); @@ -2142,11 +2149,11 @@ async function migrate(deviceId, ip) { summaryDiv.style.display = "block"; } else { statusDiv.style.backgroundColor = "#ffcccc"; - statusDiv.innerHTML = "Migration failed for " + display + ": " + (result.message || "Unknown error"); + statusDiv.textContent = "Migration failed for " + display + ": " + (result.message || "Unknown error"); } } catch (error) { statusDiv.style.backgroundColor = "#ffcccc"; - statusDiv.innerHTML = "Error migrating " + display + ": " + error; + statusDiv.textContent = "Error migrating " + display + ": " + error; } } @@ -2159,7 +2166,7 @@ async function trustCA(deviceId, ip) { statusDiv.style.display = "block"; statusDiv.style.backgroundColor = "#ffffcc"; const display = getDeviceDisplayName(deviceId); - statusDiv.innerHTML = "Injecting Root CA into shared trust store on " + display + "..."; + statusDiv.textContent = "Injecting Root CA into shared trust store on " + display + "..."; try { const response = await fetch("/setup/trust-ca/" + encodeURIComponent(deviceId), {method: "POST"},); @@ -2167,15 +2174,15 @@ async function trustCA(deviceId, ip) { showCommandOutput(result); if (result.ok) { statusDiv.style.backgroundColor = "#ccffcc"; - statusDiv.innerHTML = "Successfully injected Root CA on " + display + "."; + statusDiv.textContent = "Successfully injected Root CA on " + display + "."; showSummary(deviceId); // Refresh to update status } else { statusDiv.style.backgroundColor = "#ffcccc"; - statusDiv.innerHTML = "Failed to trust CA on " + display + ": " + (result.message || "Unknown error"); + statusDiv.textContent = "Failed to trust CA on " + display + ": " + (result.message || "Unknown error"); } } catch (error) { statusDiv.style.backgroundColor = "#ffcccc"; - statusDiv.innerHTML = "Error trusting CA on " + display + ": " + error; + statusDiv.textContent = "Error trusting CA on " + display + ": " + error; } } @@ -2191,7 +2198,7 @@ async function ensureRemoteServices(deviceId, ip) { statusDiv.style.display = "block"; statusDiv.style.backgroundColor = "#ffffcc"; const display = getDeviceDisplayName(deviceId); - statusDiv.innerHTML = "Ensuring remote services for " + display + "..."; + statusDiv.textContent = "Ensuring remote services for " + display + "..."; try { const response = await fetch("/setup/ensure-remote-services/" + encodeURIComponent(deviceId), {method: "POST"},); @@ -2199,14 +2206,14 @@ async function ensureRemoteServices(deviceId, ip) { showCommandOutput(result); if (result.ok) { statusDiv.style.backgroundColor = "#ccffcc"; - statusDiv.innerHTML = "Successfully ensured remote services for " + display + "."; + statusDiv.textContent = "Successfully ensured remote services for " + display + "."; } else { statusDiv.style.backgroundColor = "#ffcccc"; - statusDiv.innerHTML = "Failed to ensure remote services for " + display + ": " + (result.message || "Unknown error"); + statusDiv.textContent = "Failed to ensure remote services for " + display + ": " + (result.message || "Unknown error"); } } catch (error) { statusDiv.style.backgroundColor = "#ffcccc"; - statusDiv.innerHTML = "Error ensuring remote services for " + display + ": " + error; + statusDiv.textContent = "Error ensuring remote services for " + display + ": " + error; } } @@ -2225,7 +2232,7 @@ async function removeRemoteServices(deviceId, ip) { const statusDiv = document.getElementById("status"); statusDiv.style.display = "block"; statusDiv.style.backgroundColor = "#ffffcc"; - statusDiv.innerHTML = "Removing remote services for " + display + "..."; + statusDiv.textContent = "Removing remote services for " + display + "..."; try { const response = await fetch("/setup/remove-remote-services/" + encodeURIComponent(deviceId), {method: "POST"},); @@ -2233,14 +2240,14 @@ async function removeRemoteServices(deviceId, ip) { showCommandOutput(result); if (result.ok) { statusDiv.style.backgroundColor = "#ccffcc"; - statusDiv.innerHTML = "Successfully removed remote services from " + display + "."; + statusDiv.textContent = "Successfully removed remote services from " + display + "."; } else { statusDiv.style.backgroundColor = "#ffcccc"; - statusDiv.innerHTML = "Failed to remove remote services for " + display + ": " + (result.message || "Unknown error"); + statusDiv.textContent = "Failed to remove remote services for " + display + ": " + (result.message || "Unknown error"); } } catch (error) { statusDiv.style.backgroundColor = "#ffcccc"; - statusDiv.innerHTML = "Error removing remote services for " + display + ": " + error; + statusDiv.textContent = "Error removing remote services for " + display + ": " + error; } } @@ -2253,7 +2260,7 @@ async function backupConfig(deviceId, ip) { statusDiv.style.display = "block"; statusDiv.style.backgroundColor = "#ffffcc"; const display = getDeviceDisplayName(deviceId); - statusDiv.innerHTML = "Creating backup for " + display + "..."; + statusDiv.textContent = "Creating backup for " + display + "..."; try { const response = await fetch("/setup/backup/" + encodeURIComponent(deviceId), {method: "POST"},); @@ -2261,15 +2268,15 @@ async function backupConfig(deviceId, ip) { showCommandOutput(result); if (result.ok) { statusDiv.style.backgroundColor = "#ccffcc"; - statusDiv.innerHTML = "Successfully created backup for " + display + "."; + statusDiv.textContent = "Successfully created backup for " + display + "."; showSummary(deviceId); // Refresh } else { statusDiv.style.backgroundColor = "#ffcccc"; - statusDiv.innerHTML = "Backup failed for " + display + ": " + (result.message || "Unknown error"); + statusDiv.textContent = "Backup failed for " + display + ": " + (result.message || "Unknown error"); } } catch (error) { statusDiv.style.backgroundColor = "#ffcccc"; - statusDiv.innerHTML = "Error creating backup for " + display + ": " + error; + statusDiv.textContent = "Error creating backup for " + display + ": " + error; } }