aboutsummaryrefslogtreecommitdiffstats
path: root/src/threadcidmap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/threadcidmap.cpp')
-rw-r--r--src/threadcidmap.cpp51
1 files changed, 51 insertions, 0 deletions
diff --git a/src/threadcidmap.cpp b/src/threadcidmap.cpp
new file mode 100644
index 0000000..c6f1cc7
--- /dev/null
+++ b/src/threadcidmap.cpp
@@ -0,0 +1,51 @@
+#include "threadcidmap.h"
+
+#include "cidschemehandler.h"
+
+namespace {
+
+/// Removes '!' from a prefix without ever mapping two distinct prefixes onto
+/// one another.
+///
+/// A plain replace of '!' with '_' is NOT safe here: "m0!x" and "m0_x" would
+/// both become "m0_x", merging two messages into one key space, which is
+/// precisely the collision the namespacing exists to prevent. Escaping the
+/// escape character first keeps the transform injective: '_' doubles, and '!'
+/// becomes "_x", so no output is reachable from two different inputs.
+QString sanitizePrefix(const QString &prefix)
+{
+ if (!prefix.contains(QLatin1Char('!')) && !prefix.contains(QLatin1Char('_')))
+ return prefix;
+
+ QString result;
+ result.reserve(prefix.size() + 4);
+ for (const QChar c : prefix) {
+ if (c == QLatin1Char('_'))
+ result += QLatin1String("__");
+ else if (c == QLatin1Char('!'))
+ result += QLatin1String("_x");
+ else
+ result += c;
+ }
+ return result;
+}
+
+} // namespace
+
+ThreadCidMap buildThreadCidMap(const QList<ThreadRenderItem> &items)
+{
+ ThreadCidMap map;
+
+ for (const ThreadRenderItem &item : items) {
+ const QString prefix = sanitizePrefix(item.cidPrefix);
+
+ for (auto it = item.message.inlineParts.cbegin();
+ it != item.message.inlineParts.cend(); ++it) {
+ const QString key = CidSchemeHandler::namespacedKey(prefix, it.key());
+ map.parts.insert(key, it.value());
+ map.allowedCids.insert(key);
+ }
+ }
+
+ return map;
+}