feat(ui): replace atob with safeAtob for decoding device icons

This commit is contained in:
Jokob @NetAlertX committed 2026-08-21 23:46:20 +00:00
1 parent 7a8ea5d829
commit 26404bb5e2
4 files changed
+23 -8

No files matched your search

+1 -1
View File
@@ -13,7 +13,7 @@ function renderNetworkTabs(nodes) {
(node.devAlertDown == 1 ? "text-red" : "text-gray50"));
const portLabel = node.node_ports_count ? ` (${node.node_ports_count})` : '';
const icon = atob(node.devIcon);
const icon = safeAtob(node.devIcon);
const id = node.devMac.replace(/:/g, '_');
html += `
+17 -3
View File
@@ -971,6 +971,9 @@ function renderDeviceLink(data, container, useName = false) {
// Build and return badge parts
const badge = badgeFromDevice(device);
// Decode once (with a safe fallback) and reuse for both the chip and hover preview
const decodedIcon = safeAtob(device.devIcon);
// badge class and hover-info class to container
$(container)
.addClass(`${badge.cssClass} hover-node-info`)
@@ -990,13 +993,13 @@ function renderDeviceLink(data, container, useName = false) {
'data-sleeping': device.devIsSleeping || 0,
'data-archived': device.devIsArchived || 0,
'data-isnew': device.devIsNew || 0,
'data-icon': device.devIcon
'data-icon': decodedIcon
});
return `
<a href="${badge.url}" target="_blank">
<span class="custom-chip">
<span class="iconPreview">${device.devIcon ? atob(device.devIcon) : ''}</span>
<span class="iconPreview">${decodedIcon}</span>
${useName ? encodeSpecialChars(device.devName) : data.text}
<span>
(${badge.iconHtml})
@@ -1006,6 +1009,17 @@ function renderDeviceLink(data, container, useName = false) {
`;
}
// ------------------------------------------
// Base64-decode a devIcon value, tolerating missing/empty/malformed input
function safeAtob(value) {
if (!value) return '';
try {
return atob(value);
} catch (e) {
return '';
}
}
// ------------------------------------------
// Display device info on hover (attach only once)
function initHoverNodeInfo() {
@@ -1063,7 +1077,7 @@ function initHoverNodeInfo() {
const html = `
<div>
<b> <div class="iconPreview">${atob(icon)}</div> </b><b class="devName"> ${encodeSpecialChars(name)}</b><br>
<b> <div class="iconPreview">${icon || ''}</div> </b><b class="devName"> ${encodeSpecialChars(name)}</b><br>
</div>
<hr/>
<div class="line">
+3 -3
View File
@@ -228,7 +228,6 @@ class DB:
ensure_mac_lowercase_triggers(self.sql)
# Prevent/repair dangling devParentMAC references left by deleted devices
ensure_dangling_parentmac_cleanup_trigger(self.sql)
cleanup_existing_dangling_parentmac(self.sql)
# Device history table + audit triggers
@@ -246,9 +245,10 @@ class DB:
AppEvent_obj(self)
# AppEvent_obj.drop_all_triggers() wipes every trigger in the DB
# (including trg_devhist_*) as part of its clean-start routine.
# Re-create the device history audit triggers here so they survive.
# (including trg_devhist_* and trg_clear_dangling_parentmac_on_delete)
# as part of its clean-start routine. Re-create them here so they survive.
ensure_deviceshistory_triggers(self.sql)
ensure_dangling_parentmac_cleanup_trigger(self.sql)
self.commitDB()
def get_table_as_json(self, sqlQuery, parameters=None):
+2 -1
View File
@@ -10,6 +10,7 @@ from models.device_instance import DeviceInstance
from scan.name_resolution import NameResolver
from scan.device_heuristics import guess_icon, guess_type
from db.db_helper import sanitize_SQL_input, list_to_where, safe_int
from db.db_upgrade import PARENT_MAC_SENTINELS
from db.authoritative_handler import (
get_overwrite_sql_clause,
can_overwrite_field,
@@ -734,7 +735,7 @@ def create_new_devices(db):
# to a MAC that no longer exists (e.g. that device was since deleted) -
# falling back to unset rather than seeding new devices with a dangling reference.
default_parent_mac_setting = get_setting_value("NEWDEV_devParentMAC")
if default_parent_mac_setting:
if default_parent_mac_setting and default_parent_mac_setting.lower() not in PARENT_MAC_SENTINELS:
existing_device_macs = {
str(row[0]).lower() for row in sql.execute("SELECT devMac FROM Devices").fetchall() if row[0]
}