fix(export): hash stanza_id with content instead of trusting it as sole dedup key
All checks were successful
CI Code / Check spelling (pull_request) Successful in 26s
CI Code / Check coding style (pull_request) Successful in 1m6s
CI Code / Code Coverage (pull_request) Successful in 2m44s
CI Code / Linux (ubuntu) (pull_request) Successful in 4m50s
CI Code / Linux (arch) (pull_request) Successful in 5m25s
CI Code / Linux (debian) (pull_request) Successful in 6m50s
All checks were successful
CI Code / Check spelling (pull_request) Successful in 26s
CI Code / Check coding style (pull_request) Successful in 1m6s
CI Code / Code Coverage (pull_request) Successful in 2m44s
CI Code / Linux (ubuntu) (pull_request) Successful in 4m50s
CI Code / Linux (arch) (pull_request) Successful in 5m25s
CI Code / Linux (debian) (pull_request) Successful in 6m50s
This commit is contained in:
@@ -90,18 +90,21 @@ _close_temp_sqlite(int opened)
|
||||
// =========================================================================
|
||||
|
||||
// Returns a g_strdup'd key — callers free with g_free (gchar* convention).
|
||||
//
|
||||
// stanza_id is mixed into the hash but is NOT used as the sole key, since
|
||||
// some clients (older Pidgin, Adium) reuse incremental ids per session and
|
||||
// servers echo them back unchanged. Trusting stanza_id alone silently drops
|
||||
// legitimate distinct messages on collision. By hashing id + timestamp +
|
||||
// from_jid + body together we preserve id as a disambiguator without making
|
||||
// it a single point of failure: true exact duplicates still dedup, but two
|
||||
// messages that share an id with different content (or different timestamps)
|
||||
// stay distinct.
|
||||
static gchar*
|
||||
_make_dedup_key(const char* stanza_id, const char* timestamp, const char* from_jid, const char* body)
|
||||
{
|
||||
if (stanza_id && stanza_id[0] != '\0')
|
||||
return g_strdup(stanza_id);
|
||||
|
||||
// Fallback for messages without stanza-id: SHA-256 over the FULL body,
|
||||
// not the first 256 bytes. The previous prefix-only hash collided on
|
||||
// legitimate near-identical templates (signatures, code blocks, paste-
|
||||
// bombs) — second occurrence was silently dropped on import. Hashing
|
||||
// whole body is microseconds of extra work per row.
|
||||
GChecksum* sum = g_checksum_new(G_CHECKSUM_SHA256);
|
||||
g_checksum_update(sum, (const guchar*)(stanza_id ? stanza_id : ""), -1);
|
||||
g_checksum_update(sum, (const guchar*)"|", 1);
|
||||
g_checksum_update(sum, (const guchar*)(timestamp ? timestamp : ""), -1);
|
||||
g_checksum_update(sum, (const guchar*)"|", 1);
|
||||
g_checksum_update(sum, (const guchar*)(from_jid ? from_jid : ""), -1);
|
||||
|
||||
Reference in New Issue
Block a user