fix multibyte path in private message and repeter

This commit is contained in:
PacoX
2026-05-23 13:32:11 +02:00
parent 945a118853
commit 5486ae8ccb
5 changed files with 195 additions and 19 deletions
+15 -3
View File
@@ -2797,11 +2797,15 @@ class MeshCoreConnector extends ChangeNotifier {
try {
if (!isConnected) return;
final mode = _pathHashByteWidth - 1;
final encodedPathLen = (pathLen >= 0 && pathLen != 0xFF)
? (pathLen | (mode << 6))
: pathLen;
await sendFrame(
buildUpdateContactPathFrame(
contact.publicKey,
customPath,
pathLen,
encodedPathLen,
type: contact.type,
flags: contact.flags,
name: contact.name,
@@ -2858,11 +2862,15 @@ class MeshCoreConnector extends ChangeNotifier {
: (updatedFlags & ~contactFlagTeleEnv))
: updatedFlags;
final mode = _pathHashByteWidth - 1;
final encodedPathLen = (latestContact.pathLength >= 0 && latestContact.pathLength != 0xFF)
? (latestContact.pathLength | (mode << 6))
: latestContact.pathLength;
await sendFrame(
buildUpdateContactPathFrame(
latestContact.publicKey,
latestContact.path,
latestContact.pathLength,
encodedPathLen,
type: latestContact.type,
flags: updatedFlags,
name: latestContact.name,
@@ -3198,11 +3206,15 @@ class MeshCoreConnector extends ChangeNotifier {
Future<void> importDiscoveredContact(Contact contact) async {
if (!isConnected) return;
final mode = _pathHashByteWidth - 1;
final encodedPathLen = (contact.pathLength >= 0 && contact.pathLength != 0xFF)
? (contact.pathLength | (mode << 6))
: contact.pathLength;
await sendFrame(
buildUpdateContactPathFrame(
contact.publicKey,
contact.path,
contact.pathLength,
encodedPathLen,
type: contact.type,
flags: contact.flags,
name: contact.name,
+13 -3
View File
@@ -166,8 +166,18 @@ class Contact {
final type = reader.readByte();
final flags = reader.readByte();
final pathLen = reader.readByte();
final safePathLen = pathLen > 0
? (pathLen > maxPathSize ? maxPathSize : pathLen)
int hopCount = 0;
int byteLen = 0;
if (pathLen == 0xFF) {
hopCount = -1;
} else {
final mode = (pathLen & 0xC0) >> 6;
hopCount = pathLen & 0x3F;
final width = mode + 1;
byteLen = hopCount * width;
}
final safePathLen = byteLen > 0
? (byteLen > maxPathSize ? maxPathSize : byteLen)
: 0;
final pathBytes = reader.readBytes(maxPathSize).sublist(0, safePathLen);
final name = reader.readCStringGreedy(maxNameSize);
@@ -213,7 +223,7 @@ class Contact {
name: name.isEmpty ? 'Unknown' : name,
type: type,
flags: flags,
pathLength: (pathLen == 0xFF || pathLen > maxPathSize) ? -1 : pathLen,
pathLength: hopCount,
path: pathBytes,
latitude: lat,
longitude: lon,
+29 -4
View File
@@ -88,15 +88,40 @@ class ContactStore {
final lastSeenMs = json['lastSeen'] as int? ?? 0;
final lastMessageMs = json['lastMessageAt'] as int?;
final lastModifiedMs = json['lastModified'] as int?;
final rawPathLength = json['pathLength'] as int? ?? -1;
final rawPath = json['path'] != null
? Uint8List.fromList(base64Decode(json['path'] as String))
: Uint8List(0);
int decodedPathLength = rawPathLength;
Uint8List decodedPath = rawPath;
if (rawPathLength == 0xFF || rawPathLength < 0) {
decodedPathLength = -1;
decodedPath = Uint8List(0);
} else if (rawPathLength >= 64) {
final mode = (rawPathLength & 0xC0) >> 6;
final hopCount = rawPathLength & 0x3F;
final width = mode + 1;
final byteLen = hopCount * width;
decodedPathLength = hopCount;
if (byteLen <= rawPath.length) {
decodedPath = rawPath.sublist(0, byteLen);
} else {
decodedPath = Uint8List(0);
}
} else if (rawPathLength == 0) {
decodedPath = Uint8List(0);
}
return Contact(
publicKey: Uint8List.fromList(base64Decode(json['publicKey'] as String)),
name: json['name'] as String? ?? 'Unknown',
type: json['type'] as int? ?? 0,
flags: json['flags'] as int? ?? 0,
pathLength: json['pathLength'] as int? ?? -1,
path: json['path'] != null
? Uint8List.fromList(base64Decode(json['path'] as String))
: Uint8List(0),
pathLength: decodedPathLength,
path: decodedPath,
pathOverride: json['pathOverride'] as int?,
pathOverrideBytes: json['pathOverrideBytes'] != null
? Uint8List.fromList(
+31 -4
View File
@@ -113,6 +113,35 @@ class MessageStore {
final decodedText = isCli
? rawText
: (Smaz.tryDecodePrefixed(rawText) ?? rawText);
final rawPathLength = json['pathLength'] as int?;
final rawPathBytes = json['pathBytes'] != null
? Uint8List.fromList(base64Decode(json['pathBytes'] as String))
: Uint8List(0);
int? decodedPathLength = rawPathLength;
Uint8List decodedPathBytes = rawPathBytes;
if (rawPathLength != null) {
if (rawPathLength == 0xFF || rawPathLength < 0) {
decodedPathLength = -1;
decodedPathBytes = Uint8List(0);
} else if (rawPathLength >= 64) {
final mode = (rawPathLength & 0xC0) >> 6;
final hopCount = rawPathLength & 0x3F;
final width = mode + 1;
final byteLen = hopCount * width;
decodedPathLength = hopCount;
if (byteLen <= rawPathBytes.length) {
decodedPathBytes = rawPathBytes.sublist(0, byteLen);
} else {
decodedPathBytes = Uint8List(0);
}
} else if (rawPathLength == 0) {
decodedPathBytes = Uint8List(0);
}
}
return Message(
senderKey: Uint8List.fromList(base64Decode(json['senderKey'] as String)),
text: decodedText,
@@ -138,10 +167,8 @@ class MessageStore {
? DateTime.fromMillisecondsSinceEpoch(json['deliveredAt'] as int)
: null,
tripTimeMs: json['tripTimeMs'] as int?,
pathLength: json['pathLength'] as int?,
pathBytes: json['pathBytes'] != null
? Uint8List.fromList(base64Decode(json['pathBytes'] as String))
: Uint8List(0),
pathLength: decodedPathLength,
pathBytes: decodedPathBytes,
reactions:
(json['reactions'] as Map<String, dynamic>?)?.map(
(key, value) => MapEntry(key, value as int),