92 lines
3.3 KiB
C
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;
|
|
}
|