--- lbbs/src/article_favor.c 2025/10/15 02:25:13 1.2 +++ lbbs/src/article_favor.c 2026/01/03 10:27:14 1.13 @@ -1,18 +1,14 @@ -/*************************************************************************** - article_favor.c - description - ------------------- - Copyright : (C) 2004-2025 by Leaflet - Email : leaflet@leafok.com - ***************************************************************************/ - -/*************************************************************************** - * * - * This program 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. * - * * - ***************************************************************************/ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * article_favor + * - data model and basic operations of user favorite articles + * + * Copyright (C) 2004-2026 Leaflet + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include "article_favor.h" #include "common.h" @@ -20,6 +16,7 @@ #include "log.h" #include #include +#include ARTICLE_FAVOR BBS_article_favor; @@ -32,7 +29,7 @@ int article_favor_load(int uid, ARTICLE_ if (p_favor == NULL) { - log_error("NULL pointer error\n"); + log_error("NULL pointer error"); return -1; } @@ -52,7 +49,7 @@ int article_favor_load(int uid, ARTICLE_ if ((db = db_open()) == NULL) { - log_error("article_favor_load() error: Unable to open DB\n"); + log_error("article_favor_load() error: Unable to open DB"); return -2; } @@ -62,12 +59,12 @@ int article_favor_load(int uid, ARTICLE_ uid); if (mysql_query(db, sql) != 0) { - log_error("Query article_favorite error: %s\n", mysql_error(db)); + log_error("Query article_favorite error: %s", mysql_error(db)); return -3; } if ((rs = mysql_use_result(db)) == NULL) { - log_error("Get article_favorite data failed\n"); + log_error("Get article_favorite data failed"); return -3; } @@ -79,7 +76,7 @@ int article_favor_load(int uid, ARTICLE_ (p_favor->aid_base_cnt)++; if (p_favor->aid_base_cnt >= MAX_FAVOR_AID_BASE_CNT) { - log_error("Too many article_favorite records for uid=%d\n", + log_error("Too many article_favorite records for uid=%d", uid); break; } @@ -88,7 +85,7 @@ int article_favor_load(int uid, ARTICLE_ mysql_close(db); - log_common("Loaded %d article_favorite records for uid=%d\n", p_favor->aid_base_cnt, uid); + log_common("Loaded %d article_favorite records for uid=%d", p_favor->aid_base_cnt, uid); if (!keep_inc) { @@ -102,7 +99,7 @@ int article_favor_unload(ARTICLE_FAVOR * { if (p_favor == NULL) { - log_error("NULL pointer error\n"); + log_error("NULL pointer error"); return -1; } @@ -126,7 +123,7 @@ int article_favor_save_inc(const ARTICLE if (p_favor == NULL) { - log_error("NULL pointer error\n"); + log_error("NULL pointer error"); return -1; } @@ -137,7 +134,7 @@ int article_favor_save_inc(const ARTICLE if ((db = db_open()) == NULL) { - log_error("article_favor_load() error: Unable to open DB\n"); + log_error("article_favor_load() error: Unable to open DB"); return -2; } @@ -147,9 +144,9 @@ int article_favor_save_inc(const ARTICLE "DELETE FROM article_favorite WHERE UID = %d AND AID IN (", p_favor->uid); - for (i = 0, j = 0; i < p_favor->aid_base_cnt && j < p_favor->aid_inc_cnt;) + for (i = 0, j = 0; j < p_favor->aid_inc_cnt;) { - if (p_favor->aid_base[i] == p_favor->aid_inc[j]) // XOR - delete record + if (i < p_favor->aid_base_cnt && p_favor->aid_base[i] == p_favor->aid_inc[j]) // XOR - delete record { snprintf(tuple_tmp, sizeof(tuple_tmp), "%d, ", p_favor->aid_inc[j]); strncat(sql_del, tuple_tmp, sizeof(sql_del) - 1 - strnlen(sql_del, sizeof(sql_del))); @@ -158,11 +155,11 @@ int article_favor_save_inc(const ARTICLE i++; j++; } - else if (p_favor->aid_base[i] < p_favor->aid_inc[j]) // skip existing record + else if (i < p_favor->aid_base_cnt && p_favor->aid_base[i] < p_favor->aid_inc[j]) // skip existing record { i++; } - else // if (p_favor->aid_base[i] > p_favor->aid_inc[j]) + else // if (i >= p_favor->aid_base_cnt || p_favor->aid_base[i] > p_favor->aid_inc[j]) { snprintf(tuple_tmp, sizeof(tuple_tmp), "(%d, %d), ", @@ -180,8 +177,8 @@ int article_favor_save_inc(const ARTICLE if (mysql_query(db, sql_add) != 0) { - log_error("Add article_favorite error: %s\n", mysql_error(db)); - log_error("%s\n", sql_add); + log_error("Add article_favorite error: %s", mysql_error(db)); + log_error("%s", sql_add); mysql_close(db); return -3; } @@ -200,8 +197,8 @@ int article_favor_save_inc(const ARTICLE if (mysql_query(db, sql_del) != 0) { - log_error("Delete article_favorite error: %s\n", mysql_error(db)); - log_error("%s\n", sql_del); + log_error("Delete article_favorite error: %s", mysql_error(db)); + log_error("%s", sql_del); mysql_close(db); return -3; } @@ -215,7 +212,7 @@ int article_favor_save_inc(const ARTICLE } } - log_common("Saved %d and deleted %d article_favorite records for uid=%d\n", + log_common("Saved %d and deleted %d article_favorite records for uid=%d", cnt_total_add, cnt_total_del, p_favor->uid); mysql_close(db); @@ -227,10 +224,11 @@ int article_favor_merge_inc(ARTICLE_FAVO { int32_t aid_new[MAX_FAVOR_AID_BASE_CNT]; int i, j, k; + int len; if (p_favor == NULL) { - log_error("NULL pointer error\n"); + log_error("NULL pointer error"); return -1; } @@ -256,22 +254,30 @@ int article_favor_merge_inc(ARTICLE_FAVO } } - while (i < p_favor->aid_base_cnt && k < MAX_FAVOR_AID_BASE_CNT) + len = MIN(p_favor->aid_base_cnt - i, MAX_FAVOR_AID_BASE_CNT - k); + if (len > 0) { - aid_new[k++] = p_favor->aid_base[i++]; + memcpy(aid_new + k, p_favor->aid_base + i, + sizeof(int32_t) * (size_t)len); + i += len; + k += len; } if (i < p_favor->aid_base_cnt) { - log_error("Too many base aids, %d will be discarded\n", p_favor->aid_base_cnt - i); + log_error("Too many base aids, %d will be discarded", p_favor->aid_base_cnt - i); } - while (j < p_favor->aid_inc_cnt && k < MAX_FAVOR_AID_BASE_CNT) + len = MIN(p_favor->aid_inc_cnt - j, MAX_FAVOR_AID_BASE_CNT - k); + if (len > 0) { - aid_new[k++] = p_favor->aid_inc[j++]; + memcpy(aid_new + k, p_favor->aid_inc + j, + sizeof(int32_t) * (size_t)len); + j += len; + k += len; } if (j < p_favor->aid_inc_cnt) { - log_error("Too many inc aids, %d will be discarded\n", p_favor->aid_inc_cnt - j); + log_error("Too many inc aids, %d will be discarded", p_favor->aid_inc_cnt - j); } memcpy(p_favor->aid_base, aid_new, sizeof(int32_t) * (size_t)k); @@ -292,7 +298,7 @@ int article_favor_check(int32_t aid, con if (p_favor == NULL) { - log_error("NULL pointer error\n"); + log_error("NULL pointer error"); return -1; } @@ -311,7 +317,7 @@ int article_favor_check(int32_t aid, con mid = (left + right) / 2; if (aid < (i == 0 ? p_favor->aid_base[mid] : p_favor->aid_inc[mid])) { - right = mid; + right = mid - 1; } else if (aid > (i == 0 ? p_favor->aid_base[mid] : p_favor->aid_inc[mid])) { @@ -343,7 +349,7 @@ int article_favor_set(int32_t aid, ARTIC if (p_favor == NULL) { - log_error("NULL pointer error\n"); + log_error("NULL pointer error"); return -1; } @@ -362,7 +368,7 @@ int article_favor_set(int32_t aid, ARTIC mid = (left + right) / 2; if (aid < (i == 0 ? p_favor->aid_base[mid] : p_favor->aid_inc[mid])) { - right = mid; + right = mid - 1; } else if (aid > (i == 0 ? p_favor->aid_base[mid] : p_favor->aid_inc[mid])) { @@ -388,9 +394,11 @@ int article_favor_set(int32_t aid, ARTIC if (aid == p_favor->aid_inc[left] && p_favor->aid_inc_cnt > 0) // Unset { - for (i = left; i < p_favor->aid_inc_cnt - 1; i++) + if (p_favor->aid_inc_cnt > left + 1) { - p_favor->aid_inc[i] = p_favor->aid_inc[i + 1]; + memmove(p_favor->aid_inc + left, + p_favor->aid_inc + left + 1, + sizeof(int32_t) * (size_t)(p_favor->aid_inc_cnt - left - 1)); } (p_favor->aid_inc_cnt)--; @@ -404,7 +412,7 @@ int article_favor_set(int32_t aid, ARTIC // Save incremental article favorite if (article_favor_save_inc(p_favor) < 0) { - log_error("article_favor_save_inc() error\n"); + log_error("article_favor_save_inc() error"); return -2; } @@ -424,9 +432,11 @@ int article_favor_set(int32_t aid, ARTIC right = left + 1; } - for (i = p_favor->aid_inc_cnt - 1; i >= right; i--) + if (p_favor->aid_inc_cnt > right) { - p_favor->aid_inc[i + 1] = p_favor->aid_inc[i]; + memmove(p_favor->aid_inc + right + 1, + p_favor->aid_inc + right, + sizeof(int32_t) * (size_t)(p_favor->aid_inc_cnt - right)); } p_favor->aid_inc[right] = aid; @@ -435,7 +445,7 @@ int article_favor_set(int32_t aid, ARTIC return 1; // Set complete } -int query_favor_articles(ARTICLE_FAVOR *p_favor, int page_id, ARTICLE **p_articles, +int query_favor_articles(ARTICLE_FAVOR *p_favor, int page_id, const ARTICLE **p_articles, char p_snames[][BBS_section_name_max_len + 1], int *p_article_count, int *p_page_count) { SECTION_LIST *p_section; @@ -444,22 +454,22 @@ int query_favor_articles(ARTICLE_FAVOR * if (p_favor == NULL || p_articles == NULL || p_article_count == NULL || p_page_count == NULL) { - log_error("NULL pointer error\n"); + log_error("NULL pointer error"); return -1; } if (article_favor_save_inc(p_favor) < 0) { - log_error("article_favor_save_inc() error\n"); + log_error("article_favor_save_inc() error"); return -2; } if (article_favor_merge_inc(p_favor) < 0) { - log_error("article_favor_merge_inc() error\n"); + log_error("article_favor_merge_inc() error"); return -2; } - *p_page_count = p_favor->aid_base_cnt / BBS_article_limit_per_page + (p_favor->aid_base_cnt % BBS_article_limit_per_page == 0 ? 0 : 1); + *p_page_count = (p_favor->aid_base_cnt + BBS_article_limit_per_page - 1) / BBS_article_limit_per_page; *p_article_count = 0; if (p_favor->aid_base_cnt == 0) @@ -470,7 +480,7 @@ int query_favor_articles(ARTICLE_FAVOR * if (page_id < 0 || page_id >= *p_page_count) { - log_error("Invalid page_id = %d, not in range [0, %d)\n", page_id, *p_page_count); + log_error("Invalid page_id = %d, not in range [0, %d)", page_id, *p_page_count); return -1; } @@ -483,30 +493,20 @@ int query_favor_articles(ARTICLE_FAVOR * p_articles[i] = article_block_find_by_aid(aid); if (p_articles[i] == NULL) { - log_error("article_block_find_by_aid(aid=%d) error: page_id=%d, i=%d\n", aid, page_id, i); + log_error("article_block_find_by_aid(aid=%d) error: page_id=%d, i=%d", aid, page_id, i); return -3; } p_section = section_list_find_by_sid(p_articles[i]->sid); if (p_section == NULL) { - log_error("section_list_find_by_sid(%d) error\n", p_articles[i]->sid); + log_error("section_list_find_by_sid(%d) error", p_articles[i]->sid); return -3; } - // acquire lock of section - if (section_list_rd_lock(p_section) < 0) - { - log_error("section_list_rd_lock(sid = %d) error\n", p_section->sid); - return -4; - } - - memcpy(p_snames[i], p_section->sname, sizeof(p_snames[i])); - - // release lock of section - if (section_list_rd_unlock(p_section) < 0) + if (get_section_info(p_section, p_snames[i], NULL, NULL) < 0) { - log_error("section_list_rd_unlock(sid = %d) error\n", p_section->sid); + log_error("get_section_info(sid=%d) error", p_section->sid); return -4; } }