fix: preserve UTF-8 advert names

This commit is contained in:
Alexander Hoffer
2026-07-20 15:47:03 +01:00
parent da67328017
commit 79dc1de6fc
4 changed files with 103 additions and 7 deletions
+8 -6
View File
@@ -1,4 +1,5 @@
#include <helpers/AdvertDataHelpers.h>
#include <helpers/UTF8Helpers.h>
uint8_t AdvertDataBuilder::encodeTo(uint8_t app_data[]) {
app_data[0] = _type;
@@ -16,11 +17,12 @@
app_data[0] |= ADV_FEAT2_MASK;
memcpy(&app_data[i], &_extra2, 2); i += 2;
}
if (_name && *_name != 0) {
app_data[0] |= ADV_NAME_MASK;
const char* sp = _name;
while (*sp && i < MAX_ADVERT_DATA_SIZE) {
app_data[i++] = *sp++;
if (_name && *_name != 0) {
size_t name_len = mesh::validUtf8PrefixLength(_name, MAX_ADVERT_DATA_SIZE - i);
if (name_len > 0) {
app_data[0] |= ADV_NAME_MASK;
memcpy(&app_data[i], _name, name_len);
i += name_len;
}
}
return i;
@@ -84,4 +86,4 @@ void AdvertTimeHelper::formatRelativeTimeDiff(char dest[], int32_t seconds_from_
}
}
}
}
}
+56
View File
@@ -0,0 +1,56 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
namespace mesh {
inline bool isUtf8Continuation(uint8_t byte) {
return (byte & 0xC0) == 0x80;
}
inline size_t validUtf8PrefixLength(const char* text, size_t max_bytes) {
if (text == nullptr) return 0;
size_t offset = 0;
while (text[offset] != '\0') {
const uint8_t first = static_cast<uint8_t>(text[offset]);
size_t sequence_length = 0;
if (first <= 0x7F) {
sequence_length = 1;
} else if (first >= 0xC2 && first <= 0xDF) {
sequence_length = 2;
} else if (first >= 0xE0 && first <= 0xEF) {
sequence_length = 3;
} else if (first >= 0xF0 && first <= 0xF4) {
sequence_length = 4;
} else {
break;
}
if (offset + sequence_length > max_bytes) break;
bool complete = true;
for (size_t i = 1; i < sequence_length; i++) {
if (text[offset + i] == '\0' || !isUtf8Continuation(static_cast<uint8_t>(text[offset + i]))) {
complete = false;
break;
}
}
if (!complete) break;
if (sequence_length == 3) {
const uint8_t second = static_cast<uint8_t>(text[offset + 1]);
if ((first == 0xE0 && second < 0xA0) || (first == 0xED && second > 0x9F)) break;
} else if (sequence_length == 4) {
const uint8_t second = static_cast<uint8_t>(text[offset + 1]);
if ((first == 0xF0 && second < 0x90) || (first == 0xF4 && second > 0x8F)) break;
}
offset += sequence_length;
}
return offset;
}
} // namespace mesh