From 4beb7bbc16cfbfaceb383a728c5b22c9ed6ed517 Mon Sep 17 00:00:00 2001 From: Shu Chen Date: Wed, 4 Oct 2023 14:45:12 +0100 Subject: [PATCH] internal_link: Add decodeHashComponent function --- lib/model/internal_link.dart | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lib/model/internal_link.dart b/lib/model/internal_link.dart index 998c7cd1b1..ef2684ae5c 100644 --- a/lib/model/internal_link.dart +++ b/lib/model/internal_link.dart @@ -1,3 +1,4 @@ +import 'package:flutter/foundation.dart'; import '../api/model/narrow.dart'; import 'narrow.dart'; @@ -19,6 +20,22 @@ String _encodeHashComponent(String str) { .replaceAllMapped(_encodeHashComponentRegex, (Match m) => _hashReplacements[m[0]!]!); } +/// Decode a dot-encoded string; return null if malformed. +// The Zulip webapp uses this encoding in narrow-links: +// https://github.com/zulip/zulip/blob/1577662a6/static/js/hash_util.js#L18-L25 +@visibleForTesting +String? decodeHashComponent(String str) { + try { + return Uri.decodeComponent(str.replaceAll('.', '%')); + } on ArgumentError { + // as with '%1': Invalid argument(s): Truncated URI + return null; + } on FormatException { + // as with '%FF': FormatException: Invalid UTF-8 byte (at offset 0) + return null; + } +} + /// A URL to the given [Narrow], on `store`'s realm. /// /// To include /near/{messageId} in the link, pass a non-null [nearMessageId].