diff --git a/src/database_export.c b/src/database_export.c index 87bd5f03..38eb8aea 100644 --- a/src/database_export.c +++ b/src/database_export.c @@ -50,7 +50,8 @@ // Dedup key: stanza_id if present, else hash of timestamp+from+body // ========================================================================= -static char* +// Returns a g_strdup'd key — callers free with g_free (gchar* convention). +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') @@ -67,7 +68,7 @@ _make_dedup_key(const char* stanza_id, const char* timestamp, const char* from_j g_checksum_update(sum, (const guchar*)(from_jid ? from_jid : ""), -1); g_checksum_update(sum, (const guchar*)"|", 1); g_checksum_update(sum, (const guchar*)(body ? body : ""), -1); - char* key = g_strdup(g_checksum_get_string(sum)); + gchar* key = g_strdup(g_checksum_get_string(sum)); g_checksum_free(sum); return key; } @@ -75,14 +76,21 @@ _make_dedup_key(const char* stanza_id, const char* timestamp, const char* from_j // ========================================================================= // Helper: reverse ff_jid_to_dir (best-effort) // '_at_' -> '@' +// Returns a g_strdup'd jid — callers free with g_free (gchar* convention). +// str_replace allocates via libc malloc, so we hand over to g_-allocated. // ========================================================================= -static char* +static gchar* _dir_to_jid(const char* dirname) { if (!dirname) return NULL; - return str_replace(dirname, "_at_", "@"); + char* raw = str_replace(dirname, "_at_", "@"); + if (!raw) + return NULL; + gchar* gres = g_strdup(raw); + free(raw); + return gres; } // ========================================================================= @@ -118,7 +126,7 @@ _ff_list_contacts(void) while ((entry = g_dir_read_name(dir)) != NULL) { auto_gchar gchar* full_path = g_strdup_printf("%s/%s/history.log", base_dir, entry); if (g_file_test(full_path, G_FILE_TEST_IS_REGULAR)) { - char* jid = _dir_to_jid(entry); + gchar* jid = _dir_to_jid(entry); if (jid) { contacts = g_slist_prepend(contacts, jid); } @@ -168,20 +176,15 @@ _ff_read_all_lines(const char* contact_barejid) while (1) { gboolean truncated = FALSE; - char* buf = ff_readline(fp, &truncated); + auto_char char* buf = ff_readline(fp, &truncated); if (!buf) break; - if (truncated) { - free(buf); + if (truncated) break; - } - if (buf[0] == '\0' || buf[0] == '#') { - free(buf); + if (buf[0] == '\0' || buf[0] == '#') continue; - } ff_parsed_line_t* pl = ff_parse_line(buf); - free(buf); if (pl) { lines = g_slist_prepend(lines, pl); } @@ -234,7 +237,7 @@ _export_one_contact(const char* contact) GSList* existing = _ff_read_all_lines(contact); for (GSList* l = existing; l; l = l->next) { ff_parsed_line_t* pl = l->data; - char* key = _make_dedup_key(pl->stanza_id, pl->timestamp_str, pl->from_jid, pl->message); + gchar* key = _make_dedup_key(pl->stanza_id, pl->timestamp_str, pl->from_jid, pl->message); g_hash_table_add(seen_keys, key); } int existing_count = g_slist_length(existing); @@ -330,7 +333,7 @@ _export_one_contact(const char* contact) const char* body = msg->plain ? msg->plain : ""; const char* sid = msg->id ? msg->id : ""; - char* key = _make_dedup_key(sid, ts, from_jid, body); + gchar* key = _make_dedup_key(sid, ts, from_jid, body); if (g_hash_table_contains(seen_keys, key)) { g_free(key); contact_skipped++; @@ -509,7 +512,7 @@ log_database_import_from_flatfile(const gchar* const contact_jid) if (!msg) continue; auto_gchar gchar* ts = msg->timestamp ? g_date_time_format_iso8601(msg->timestamp) : g_strdup(""); - char* key = _make_dedup_key(msg->id, ts, msg->from_jid ? msg->from_jid->barejid : "", msg->plain); + gchar* key = _make_dedup_key(msg->id, ts, msg->from_jid ? msg->from_jid->barejid : "", msg->plain); g_hash_table_add(seen_keys, key); } g_slist_free_full(existing_msgs, (GDestroyNotify)message_free); @@ -529,7 +532,7 @@ log_database_import_from_flatfile(const gchar* const contact_jid) continue; auto_gchar gchar* ts = g_date_time_format_iso8601(pl->timestamp); - char* key = _make_dedup_key(pl->stanza_id, ts, pl->from_jid, pl->message); + gchar* key = _make_dedup_key(pl->stanza_id, ts, pl->from_jid, pl->message); if (g_hash_table_contains(seen_keys, key)) { g_free(key); diff --git a/src/database_flatfile.c b/src/database_flatfile.c index 395ab5c5..cdb34a10 100644 --- a/src/database_flatfile.c +++ b/src/database_flatfile.c @@ -145,7 +145,7 @@ _ff_maybe_index_line(ff_contact_state_t* state, const char* buf, off_t pos) char* ts_str = g_strndup(buf, space - buf); GDateTime* dt = g_date_time_new_from_iso8601(ts_str, NULL); if (!dt) { - log_warning("flatfile: unparseable timestamp in %s at offset %ld: %s", + log_warning("flatfile: unparsable timestamp in %s at offset %ld: %s", state->filepath, (long)pos, ts_str); g_free(ts_str); return; diff --git a/src/database_flatfile.h b/src/database_flatfile.h index c1e50983..c0785328 100644 --- a/src/database_flatfile.h +++ b/src/database_flatfile.h @@ -64,8 +64,8 @@ typedef struct // --- Metadata field prefixes (used in _ff_cache_line_ids and ff_parse_line) --- -#define FF_META_PREFIX_ID "id:" -#define FF_META_PREFIX_AID "aid:" +#define FF_META_PREFIX_ID "id:" +#define FF_META_PREFIX_AID "aid:" typedef struct { diff --git a/src/database_flatfile_verify.c b/src/database_flatfile_verify.c index 8a136b6a..2e37e83b 100644 --- a/src/database_flatfile_verify.c +++ b/src/database_flatfile_verify.c @@ -77,8 +77,8 @@ _collect_contact_dirs(const gchar* const contact_barejid, GSList** issues) contact_dirs = g_slist_prepend(contact_dirs, g_strdup(cdir)); } else { *issues = g_slist_prepend(*issues, - _issue_new(INTEGRITY_INFO, contact_barejid, 0, - g_strdup("No log files found for this contact"))); + _issue_new(INTEGRITY_INFO, contact_barejid, 0, + g_strdup("No log files found for this contact"))); } return contact_dirs; } @@ -117,9 +117,9 @@ _check_permissions(const char* filepath, const char* basename, GSList** issues) if ((st.st_mode & 0777) == (S_IRUSR | S_IWUSR)) return; *issues = g_slist_prepend(*issues, - _issue_new(INTEGRITY_WARNING, basename, 0, - g_strdup_printf("File permissions are %o, expected 600 (sensitive data)", - st.st_mode & 0777))); + _issue_new(INTEGRITY_WARNING, basename, 0, + g_strdup_printf("File permissions are %o, expected 600 (sensitive data)", + st.st_mode & 0777))); } // ========================================================================= @@ -144,8 +144,8 @@ _first_pass(FILE* fp, const char* basename, { if (ff_skip_bom(fp)) { *issues = g_slist_prepend(*issues, - _issue_new(INTEGRITY_INFO, basename, 0, - g_strdup("File has UTF-8 BOM — harmless but unnecessary"))); + _issue_new(INTEGRITY_INFO, basename, 0, + g_strdup("File has UTF-8 BOM — harmless but unnecessary"))); } char* buf = NULL; @@ -172,8 +172,8 @@ _first_pass(FILE* fp, const char* basename, const gchar* end; if (!g_utf8_validate(buf, -1, &end)) { *issues = g_slist_prepend(*issues, - _issue_new(INTEGRITY_ERROR, basename, lineno, - g_strdup_printf("Invalid UTF-8 at byte offset %ld", (long)(end - buf)))); + _issue_new(INTEGRITY_ERROR, basename, lineno, + g_strdup_printf("Invalid UTF-8 at byte offset %ld", (long)(end - buf)))); free(buf); continue; } @@ -182,8 +182,8 @@ _first_pass(FILE* fp, const char* basename, unsigned char ch = (unsigned char)buf[i]; if (ch < 0x20 && ch != '\t') { *issues = g_slist_prepend(*issues, - _issue_new(INTEGRITY_WARNING, basename, lineno, - g_strdup_printf("Contains control character 0x%02x", ch))); + _issue_new(INTEGRITY_WARNING, basename, lineno, + g_strdup_printf("Contains control character 0x%02x", ch))); break; } } @@ -191,8 +191,8 @@ _first_pass(FILE* fp, const char* basename, ff_parsed_line_t* pl = ff_parse_line(buf); if (!pl) { *issues = g_slist_prepend(*issues, - _issue_new(INTEGRITY_ERROR, basename, lineno, - g_strdup("Unparsable line"))); + _issue_new(INTEGRITY_ERROR, basename, lineno, + g_strdup("Unparsable line"))); free(buf); continue; } @@ -202,8 +202,8 @@ _first_pass(FILE* fp, const char* basename, auto_gchar gchar* ts_cur = g_date_time_format_iso8601(pl->timestamp); auto_gchar gchar* ts_prev = g_date_time_format_iso8601(prev_ts); *issues = g_slist_prepend(*issues, - _issue_new(INTEGRITY_WARNING, basename, lineno, - g_strdup_printf("Timestamp out of order (%s after %s)", ts_cur, ts_prev))); + _issue_new(INTEGRITY_WARNING, basename, lineno, + g_strdup_printf("Timestamp out of order (%s after %s)", ts_cur, ts_prev))); } if (prev_ts) g_date_time_unref(prev_ts); @@ -212,8 +212,8 @@ _first_pass(FILE* fp, const char* basename, if (pl->stanza_id && pl->stanza_id[0] != '\0') { if (g_hash_table_contains(seen_stanza_ids, pl->stanza_id)) { *issues = g_slist_prepend(*issues, - _issue_new(INTEGRITY_WARNING, basename, lineno, - g_strdup_printf("Duplicate stanza-id \"%s\"", pl->stanza_id))); + _issue_new(INTEGRITY_WARNING, basename, lineno, + g_strdup_printf("Duplicate stanza-id \"%s\"", pl->stanza_id))); } else { g_hash_table_insert(seen_stanza_ids, g_strdup(pl->stanza_id), GINT_TO_POINTER(lineno)); } @@ -222,8 +222,8 @@ _first_pass(FILE* fp, const char* basename, if (pl->archive_id && pl->archive_id[0] != '\0') { if (g_hash_table_contains(seen_archive_ids, pl->archive_id)) { *issues = g_slist_prepend(*issues, - _issue_new(INTEGRITY_WARNING, basename, lineno, - g_strdup_printf("Duplicate archive-id \"%s\"", pl->archive_id))); + _issue_new(INTEGRITY_WARNING, basename, lineno, + g_strdup_printf("Duplicate archive-id \"%s\"", pl->archive_id))); } else { g_hash_table_insert(seen_archive_ids, g_strdup(pl->archive_id), GINT_TO_POINTER(lineno)); } @@ -237,13 +237,13 @@ _first_pass(FILE* fp, const char* basename, if (has_crlf) { *issues = g_slist_prepend(*issues, - _issue_new(INTEGRITY_WARNING, basename, 0, - g_strdup("File uses Windows line endings (CRLF) — consider converting to LF"))); + _issue_new(INTEGRITY_WARNING, basename, 0, + g_strdup("File uses Windows line endings (CRLF) — consider converting to LF"))); } if (is_empty) { *issues = g_slist_prepend(*issues, - _issue_new(INTEGRITY_INFO, basename, 0, - g_strdup("File is empty (no message lines)"))); + _issue_new(INTEGRITY_INFO, basename, 0, + g_strdup("File is empty (no message lines)"))); } } @@ -281,9 +281,9 @@ _lmc_pass(FILE* fp, const char* basename, GHashTable* all_stanza_ids, GSList** i if (pl->replace_id && pl->replace_id[0] != '\0' && !g_hash_table_contains(all_stanza_ids, pl->replace_id)) { *issues = g_slist_prepend(*issues, - _issue_new(INTEGRITY_ERROR, basename, lineno, - g_strdup_printf("Broken correction reference: corrects:%s not found", - pl->replace_id))); + _issue_new(INTEGRITY_ERROR, basename, lineno, + g_strdup_printf("Broken correction reference: corrects:%s not found", + pl->replace_id))); } ff_parsed_line_free(pl); } @@ -344,8 +344,8 @@ ff_verify_integrity(const gchar* const contact_barejid) if (!g_flatfile_account_jid) { issues = g_slist_prepend(issues, - _issue_new(INTEGRITY_ERROR, "N/A", 0, - g_strdup("Flat-file backend not initialized"))); + _issue_new(INTEGRITY_ERROR, "N/A", 0, + g_strdup("Flat-file backend not initialized"))); return issues; } diff --git a/tests/unittests/test_database_stress.c b/tests/unittests/test_database_stress.c index a1c614a4..ed1db22b 100644 --- a/tests/unittests/test_database_stress.c +++ b/tests/unittests/test_database_stress.c @@ -893,7 +893,7 @@ test_stress_mixed_types_and_encodings(void** state) /* Parse and verify type/enc distribution */ fp = fopen(tmppath, "r"); assert_non_null(fp); - int counts[3] = { 0 }; /* chat, muc, mucpm */ + int counts[3] = { 0 }; /* chat, muc, mucpm */ int enc_counts[5] = { 0 }; /* none, omemo, otr, pgp, ox */ int parsed = 0; @@ -911,15 +911,23 @@ test_stress_mixed_types_and_encodings(void** state) continue; parsed++; - if (g_strcmp0(pl->type, "chat") == 0) counts[0]++; - else if (g_strcmp0(pl->type, "muc") == 0) counts[1]++; - else if (g_strcmp0(pl->type, "mucpm") == 0) counts[2]++; + if (g_strcmp0(pl->type, "chat") == 0) + counts[0]++; + else if (g_strcmp0(pl->type, "muc") == 0) + counts[1]++; + else if (g_strcmp0(pl->type, "mucpm") == 0) + counts[2]++; - if (g_strcmp0(pl->enc, "none") == 0) enc_counts[0]++; - else if (g_strcmp0(pl->enc, "omemo") == 0) enc_counts[1]++; - else if (g_strcmp0(pl->enc, "otr") == 0) enc_counts[2]++; - else if (g_strcmp0(pl->enc, "pgp") == 0) enc_counts[3]++; - else if (g_strcmp0(pl->enc, "ox") == 0) enc_counts[4]++; + if (g_strcmp0(pl->enc, "none") == 0) + enc_counts[0]++; + else if (g_strcmp0(pl->enc, "omemo") == 0) + enc_counts[1]++; + else if (g_strcmp0(pl->enc, "otr") == 0) + enc_counts[2]++; + else if (g_strcmp0(pl->enc, "pgp") == 0) + enc_counts[3]++; + else if (g_strcmp0(pl->enc, "ox") == 0) + enc_counts[4]++; ff_parsed_line_free(pl); }