feat(ui,db,cmd): reduce dublicate code in window subwin logic, unify SQLite helpers, NULL checks added
Some checks failed
CI Code / Check spelling (pull_request) Successful in 18s
CI Code / Linux (arch) (pull_request) Failing after 22s
CI Code / Check coding style (pull_request) Failing after 31s
CI Code / Linux (debian) (pull_request) Successful in 15m14s
CI Code / Linux (ubuntu) (pull_request) Successful in 15m36s

window.c: add _get_subwin_cols, _apply_split_resize, _check_subwin_width; refactor show/hide/resize/refresh/update
database.c: add _db_prepare_ctx, _db_teardown; safer init/queries with fallback timestamp
cmd_defs.c: guard fopen in docgen; inputwin.c: replace assert with runtime check
This commit is contained in:
2025-11-10 15:09:09 +03:00
parent 332cd243c6
commit 5f01f8f546
4 changed files with 83 additions and 52 deletions

View File

@@ -2987,8 +2987,19 @@ command_docgen(void)
cmds = g_list_insert_sorted(cmds, (gpointer)pcmd, (GCompareFunc)_cmp_command);
}
FILE* toc_fragment = fopen("toc_fragment.html", "w");
FILE* main_fragment = fopen("main_fragment.html", "w");
FILE* toc_fragment = fopen("toc_fragment.html", "w");
if (!toc_fragment) {
log_error("command_docgen(): unable to open toc_fragment.html for writing: %s", g_strerror(errno));
g_list_free(cmds);
return;
}
FILE* main_fragment = fopen("main_fragment.html", "w");
if (!main_fragment) {
log_error("command_docgen(): unable to open main_fragment.html for writing: %s", g_strerror(errno));
fclose(toc_fragment);
g_list_free(cmds);
return;
}
fputs("<ul><li><ul><li>\n", toc_fragment);
fputs("<hr>\n", main_fragment);
@@ -3056,8 +3067,8 @@ command_docgen(void)
fputs("</ul></ul>\n", toc_fragment);
fclose(toc_fragment);
fclose(main_fragment);
fclose(toc_fragment);
fclose(main_fragment);
printf("\nProcessed %d commands.\n\n", g_list_length(cmds));
g_list_free(cmds);
}
@@ -3092,7 +3103,12 @@ command_mangen(void)
log_error("command_mangen(): could not allocate memory");
return;
}
FILE* manpage = fopen(filename, "w");
FILE* manpage = fopen(filename, "w");
if (!manpage) {
log_error("command_mangen(): unable to open %s for writing: %s", filename, g_strerror(errno));
curr = g_list_next(curr);
continue;
}
fprintf(manpage, "%s\n", header);
fputs(".SH NAME\n", manpage);
@@ -3127,7 +3143,7 @@ command_mangen(void)
}
}
fclose(manpage);
fclose(manpage);
curr = g_list_next(curr);
}

View File

@@ -65,6 +65,36 @@ static gboolean _check_available_space_for_db_migration(char* path_to_db);
static const int latest_version = 2;
// Helper: close DB handle (if any), warn on busy, and shutdown SQLite
static void
_db_teardown(const char* ctx)
{
if (g_chatlog_database) {
int rc = sqlite3_close_v2(g_chatlog_database);
if (rc != SQLITE_OK) {
log_warning("sqlite3_close_v2 in %s returned %d; database may still have active statements.",
ctx ? ctx : "db_teardown", rc);
}
g_chatlog_database = NULL;
}
sqlite3_shutdown();
}
// Helper: prepare a statement and log a contextual error on failure
static gboolean
_db_prepare_ctx(const char* query, sqlite3_stmt** stmt, const char* ctx)
{
int rc = sqlite3_prepare_v2(g_chatlog_database, query, -1, stmt, NULL);
if (rc != SQLITE_OK) {
log_error("SQLite error in %s: (error code: %d) %s",
ctx ? ctx : "sqlite3_prepare_v2",
rc,
sqlite3_errmsg(g_chatlog_database));
return FALSE;
}
return TRUE;
}
static char*
_db_strdup(const char* str)
{
@@ -106,11 +136,7 @@ log_database_init(ProfAccount* account)
if (ret != SQLITE_OK) {
const char* err_msg = g_chatlog_database ? sqlite3_errmsg(g_chatlog_database) : "(no handle)";
log_error("Error opening SQLite database: %s", err_msg);
if (g_chatlog_database) {
sqlite3_close(g_chatlog_database);
g_chatlog_database = NULL;
}
sqlite3_shutdown();
_db_teardown("log_database_init(open)");
return FALSE;
}
@@ -222,11 +248,7 @@ out:
} else {
log_error("Unknown SQLite error in log_database_init().");
}
if (g_chatlog_database) {
sqlite3_close(g_chatlog_database);
g_chatlog_database = NULL;
}
sqlite3_shutdown();
_db_teardown("log_database_init(out)");
return FALSE;
}
@@ -234,14 +256,7 @@ void
log_database_close(void)
{
log_debug("log_database_close() called");
if (g_chatlog_database) {
int rc = sqlite3_close_v2(g_chatlog_database);
if (rc != SQLITE_OK) {
log_warning("sqlite3_close_v2 returned %d; database may still have active statements.", rc);
}
sqlite3_shutdown();
g_chatlog_database = NULL;
}
_db_teardown("log_database_close");
}
void
@@ -320,9 +335,7 @@ log_database_get_limits_info(const gchar* const contact_barejid, gboolean is_las
return msg;
}
int rc = sqlite3_prepare_v2(g_chatlog_database, query, -1, &stmt, NULL);
if (rc != SQLITE_OK) {
log_error("Unknown SQLite error in log_database_get_limits_info().");
if (!_db_prepare_ctx(query, &stmt, "log_database_get_limits_info()")) {
if (is_last) {
msg->timestamp = g_date_time_new_now_utc();
}
@@ -387,9 +400,7 @@ log_database_get_previous_chat(const gchar* const contact_barejid, const gchar*
return DB_RESPONSE_ERROR;
}
int rc = sqlite3_prepare_v2(g_chatlog_database, query, -1, &stmt, NULL);
if (rc != SQLITE_OK) {
log_error("SQLite error in log_database_get_previous_chat(): (error code: %d) %s", rc, sqlite3_errmsg(g_chatlog_database));
if (!_db_prepare_ctx(query, &stmt, "log_database_get_previous_chat()")) {
return DB_RESPONSE_ERROR;
}
@@ -533,9 +544,7 @@ _add_to_db(ProfMessage* message, char* type, const Jid* const from_jid, const Ji
}
sqlite3_stmt* lmc_stmt = NULL;
if (SQLITE_OK != sqlite3_prepare_v2(g_chatlog_database, replace_check_query, -1, &lmc_stmt, NULL)) {
log_error("SQLite error in _add_to_db() on selecting original message: %s", sqlite3_errmsg(g_chatlog_database));
if (!_db_prepare_ctx(replace_check_query, &lmc_stmt, "_add_to_db(replace_check)")) {
return;
}
@@ -572,8 +581,7 @@ _add_to_db(ProfMessage* message, char* type, const Jid* const from_jid, const Ji
}
sqlite3_stmt* stmt;
if (SQLITE_OK == sqlite3_prepare_v2(g_chatlog_database, duplicate_check_query, -1, &stmt, NULL)) {
if (_db_prepare_ctx(duplicate_check_query, &stmt, "_add_to_db(duplicate_check)")) {
if (sqlite3_step(stmt) == SQLITE_ROW) {
log_error("Duplicate stanza-id found for the message. stanza_id: %s; archive_id: %s; sender: %s; content: %s", message->id, message->stanzaid, from_jid->barejid, message->plain);
cons_show_error("Got a message with duplicate (server-generated) stanza-id from %s.", from_jid->fulljid);
@@ -629,8 +637,7 @@ _get_db_version(void)
int current_version = -1;
const char* query = "SELECT `version` FROM `DbVersion` LIMIT 1";
sqlite3_stmt* statement;
if (sqlite3_prepare_v2(g_chatlog_database, query, -1, &statement, NULL) == SQLITE_OK) {
if (_db_prepare_ctx(query, &statement, "_get_db_version()")) {
if (sqlite3_step(statement) == SQLITE_ROW) {
current_version = sqlite3_column_int(statement, 0);
}

View File

@@ -144,10 +144,13 @@ void
create_input_window(void)
{
/* MB_CUR_MAX is evaluated at runtime depending on the current
* locale, therefore we check that our own version is big enough
* and bail out if it isn't.
* locale; ensure our own compiled-in maximum is sufficient.
* Fail gracefully instead of aborting in production.
*/
assert(MB_CUR_MAX <= PROF_MB_CUR_MAX);
if (MB_CUR_MAX > PROF_MB_CUR_MAX) {
cons_show_error("Your locale's MB_CUR_MAX (%zu) exceeds PROF_MB_CUR_MAX (%d); input window disabled.", (size_t)MB_CUR_MAX, PROF_MB_CUR_MAX);
return;
}
#ifdef NCURSES_REENTRANT
set_escdelay(25);
#else

View File

@@ -75,6 +75,21 @@ static void _win_print_internal(ProfWin* window, const char* show_char, int pad_
int flags, theme_item_t theme_item, const char* const from, const char* const message, DeliveryReceipt* receipt);
static void _win_print_wrapped(WINDOW* win, const char* const message, size_t indent, int pad_indent);
// Helper: clamp a subwindow width to a sane range [1, cols-1] if possible
static int
_check_subwin_width(int cols, int width)
{
if (cols > 1) {
if (width < 1)
width = 1;
if (width >= cols)
width = cols - 1;
} else {
width = 1;
}
return width;
}
int
win_roster_cols(void)
{
@@ -82,12 +97,7 @@ win_roster_cols(void)
int cols = getmaxx(stdscr);
int width = CEILING((((double)cols) / 100) * roster_win_percent);
// Clamp to a sane range to avoid zero/full-width pads
if (cols > 1) {
if (width < 1) width = 1;
if (width >= cols) width = cols - 1;
} else {
width = 1;
}
width = _check_subwin_width(cols, width);
return width;
}
@@ -98,12 +108,7 @@ win_occpuants_cols(void)
int cols = getmaxx(stdscr);
int width = CEILING((((double)cols) / 100) * occupants_win_percent);
// Clamp to a sane range to avoid zero/full-width pads
if (cols > 1) {
if (width < 1) width = 1;
if (width >= cols) width = cols - 1;
} else {
width = 1;
}
width = _check_subwin_width(cols, width);
return width;
}