ESPSomfy-RTS/src/Secrets.h
cjkas 9383ebec2e fix: keep stored secrets when an older UI sends them empty
Firmware and UI files update separately, so an old index.js can run
against firmware that no longer returns secrets. It sends "" for the
field it can't fill in, which cleared the WiFi passphrase (reboot into
AP mode) or the MQTT password.

The firmware now decides: "" keeps the stored secret, unless the same
request changes the SSID or MQTT username, then it clears it (open
network). /setNetwork compares the settings after applying them, so a
kept passphrase no longer triggers a reboot. The UI cache-buster moves
to 3.0.14d.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 20:07:31 +02:00

30 lines
1.2 KiB
C

#ifndef secrets_h
#define secrets_h
#include <string.h>
// Stored secrets (WiFi passphrase, MQTT password, login password/PIN) are
// write-only: responses carry hasSecret() flags and logs carry maskSecret().
inline bool hasSecret(const char *s) { return s && s[0] != '\0'; }
inline const char *maskSecret(const char *s) { return hasSecret(s) ? "<set>" : "<empty>"; }
// Updates dest from an incoming value, truncating to size. Pass
// obj["key"].as<const char *>(), which is null when the key is absent.
// absent -> keep the stored secret.
// "" -> keep it too, unless identityChanged (a new SSID or username in
// the same request), then clear it. UIs older than write-only
// secrets send "" for a field the device no longer fills in.
// value -> replace it.
// Returns true when dest changed.
inline bool applySecret(const char *incoming, char *dest, size_t size, bool identityChanged = false) {
if(!incoming || size == 0) return false;
if(incoming[0] == '\0' && !identityChanged) return false;
size_t len = strlen(incoming);
if(len >= size) len = size - 1;
if(strncmp(dest, incoming, len) == 0 && dest[len] == '\0') return false;
memcpy(dest, incoming, len);
dest[len] = '\0';
return true;
}
#endif