fix(review): address PR #94 reviewer comments

Blockers:
- SPDX/CProof copyright headers (7 files)
- stanza-id non-uniqueness: warn-only, don't skip (matches SQLite)
- fopen → open(O_EXCL|O_NOFOLLOW, 0600) + fdopen in export

Medium:
- log_info → log_warning for SQLite fallback
- remove prefs_save() auto-save from backend switch
- vtable null → log_warning in 4 dispatch functions
- log_debug → log_warning + null error handling in export
- rename failure → cons_show_error to user
- remove unused total_skipped variable
- LMC respects PREF_CORRECTION_ALLOW

Low nits:
- man page .SS fix + jabber.space URL
- profrc.example simplified
- show flatfile path on /logging flatfile
- EXPORT_PROGRESS_INTERVAL constant (magic 500)
- FF_META_PREFIX_ID/AID constants + FF_INDEX_STEP comment
- buffer overflow guard on close[1]/close[2]
- for-loop → memchr for JID resource scan
- BOM check extracted to ff_skip_bom() (DRY)
- index building extracted to _ff_maybe_index_line()
- O_APPEND+O_EXCL comment rewritten
- Makefile.am spaces → tabs
This commit is contained in:
2026-03-28 12:38:39 +03:00
parent 58002409ff
commit a96a4ad41e
12 changed files with 192 additions and 196 deletions

View File

@@ -1,24 +1,12 @@
// SPDX-License-Identifier: GPL-3.0-or-later
//
// This file is part of CProof.
// See LICENSE for the full GPLv3 text and the special OpenSSL linking exception.
/*
* database_flatfile_parser.c
* vim: expandtab:ts=4:sts=4:sw=4
*
* Copyright (C) 2026 Profanity Contributors
*
* This file is part of Profanity.
*
* Profanity is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Profanity is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Profanity. If not, see <https://www.gnu.org/licenses/>.
*
* Flat-file backend: type helpers, path helpers, escape/unescape,
* line I/O, and the tolerant log-line parser.
*/
@@ -339,6 +327,24 @@ ff_unescape_meta_value(const char* val)
}
// =========================================================================
// BOM helper
// =========================================================================
//
// Skip UTF-8 BOM (EF BB BF) at the beginning of a file.
// Returns 3 if BOM was present, 0 otherwise. File position is set past
// the BOM (or rewound to the start).
int
ff_skip_bom(FILE* fp)
{
int c1 = fgetc(fp);
int c2 = fgetc(fp);
int c3 = fgetc(fp);
if (c1 == 0xEF && c2 == 0xBB && c3 == 0xBF)
return 3;
fseek(fp, 0, SEEK_SET);
return 0;
}
// Readline helper
// =========================================================================
//
@@ -658,18 +664,18 @@ ff_parse_line(const char* line)
result->type = g_strdup(parts[i]);
} else if (i == 1) {
result->enc = g_strdup(parts[i]);
} else if (g_str_has_prefix(parts[i], "id:")) {
result->stanza_id = ff_unescape_meta_value(parts[i] + 3);
} else if (g_str_has_prefix(parts[i], "aid:")) {
result->archive_id = ff_unescape_meta_value(parts[i] + 4);
} else if (g_str_has_prefix(parts[i], FF_META_PREFIX_ID)) {
result->stanza_id = ff_unescape_meta_value(parts[i] + strlen(FF_META_PREFIX_ID));
} else if (g_str_has_prefix(parts[i], FF_META_PREFIX_AID)) {
result->archive_id = ff_unescape_meta_value(parts[i] + strlen(FF_META_PREFIX_AID));
} else if (g_str_has_prefix(parts[i], "corrects:")) {
result->replace_id = ff_unescape_meta_value(parts[i] + 9);
result->replace_id = ff_unescape_meta_value(parts[i] + strlen("corrects:"));
} else if (g_str_has_prefix(parts[i], "to:")) {
result->to_jid = ff_unescape_meta_value(parts[i] + 3);
result->to_jid = ff_unescape_meta_value(parts[i] + strlen("to:"));
} else if (g_str_has_prefix(parts[i], "to_res:")) {
result->to_resource = ff_unescape_meta_value(parts[i] + 7);
result->to_resource = ff_unescape_meta_value(parts[i] + strlen("to_res:"));
} else if (g_str_has_prefix(parts[i], "read:")) {
result->marked_read = atoi(parts[i] + 5) ? 1 : 0;
result->marked_read = atoi(parts[i] + strlen("read:")) ? 1 : 0;
}
}
g_strfreev(parts);