Files
MeshCore/src/helpers/MQTTObserverValidation.h
T

92 lines
3.3 KiB
C

#pragma once
#include <stddef.h>
#include <stdint.h>
#include <string.h>
// Pure, dependency-free validators for the observer's CLI/web configuration
// inputs. Factored out of CommonCLI_Observer.cpp so the exact logic the setters
// enforce can be unit-tested on the host (see test/test_observer_validation)
// rather than only through the full CLI object.
// IATA region code: exactly three ASCII alphanumerics. The value is placed
// directly into MQTT topic paths (meshcore/{iata}/...), so anything else (wrong
// length, spaces, topic separators) is rejected. Case is preserved here; the
// setter uppercases after validation.
static inline bool mqttIataValid(const char* s) {
if (!s || strlen(s) != 3) return false;
for (int i = 0; i < 3; i++) {
char c = s[i];
if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'))) {
return false;
}
}
return true;
}
// Owner public key: exactly 64 hex characters (a 32-byte Ed25519 key), any case.
static inline bool mqttOwnerKeyValid(const char* s) {
if (!s || strlen(s) != 64) return false;
for (int i = 0; i < 64; i++) {
char c = s[i];
if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'))) {
return false;
}
}
return true;
}
// NTP hostname: non-empty, <= 63 chars, made of letters/digits/'.'/'-', with no
// leading or trailing dot. ("none" is handled as a clear by the caller.)
static inline bool mqttNtpHostnameValid(const char* host) {
if (!host || host[0] == '\0') return false;
size_t len = strlen(host);
if (len > 63) return false;
if (host[0] == '.' || host[len - 1] == '.') return false;
for (size_t i = 0; i < len; i++) {
char c = host[i];
if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
(c >= '0' && c <= '9') || c == '.' || c == '-')) {
return false;
}
}
return true;
}
// A value fits its fixed destination buffer, which must hold the string plus a
// NUL terminator (so the usable length is bufsize - 1). Used to reject an
// over-long submission up front instead of silently truncating it.
static inline bool mqttValueFits(const char* s, size_t bufsize) {
return s != NULL && bufsize > 0 && strlen(s) < bufsize;
}
// Strict decimal parser for bounded observer settings. Unlike atoi(), this
// rejects missing values, signs, whitespace, trailing text, and overflow.
static inline bool observerParseBoundedUint16(const char* text, uint16_t maximum,
uint16_t* result) {
if (text == NULL || result == NULL || *text == '\0') return false;
uint32_t value = 0;
for (const char* p = text; *p != '\0'; ++p) {
if (*p < '0' || *p > '9') return false;
value = value * 10u + static_cast<uint32_t>(*p - '0');
if (value > maximum) return false;
}
*result = static_cast<uint16_t>(value);
return true;
}
// `display.flip` accepts only complete, lower-case tokens so a typo cannot
// silently change persisted panel orientation.
static inline bool observerParseDisplayFlip(const char* text, uint8_t* result) {
if (text == NULL || result == NULL) return false;
if (strcmp(text, "0") == 0 || strcmp(text, "off") == 0) {
*result = 0;
return true;
}
if (strcmp(text, "1") == 0 || strcmp(text, "on") == 0) {
*result = 1;
return true;
}
return false;
}