--- lbbs/src/article_post.c 2025/10/10 01:55:06 1.28 +++ lbbs/src/article_post.c 2026/01/03 10:27:14 1.45 @@ -1,22 +1,19 @@ -/*************************************************************************** - article_post.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_post + * - user interactive feature to post / modify / reply article + * + * Copyright (C) 2004-2026 Leaflet + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include "article_cache.h" #include "article_post.h" #include "bbs.h" +#include "bwf.h" #include "database.h" #include "editor.h" #include "io.h" @@ -29,12 +26,12 @@ #include #include -#define TITLE_INPUT_MAX_LEN 72 -#define ARTICLE_CONTENT_MAX_LEN 1024 * 1024 * 4 // 4MB -#define ARTICLE_QUOTE_MAX_LINES 20 -#define ARTICLE_QUOTE_LINE_MAX_LEN 76 - -#define MODIFY_DT_MAX_LEN 50 +enum _article_post_constant_t +{ + TITLE_INPUT_MAX_LEN = 72, + ARTICLE_QUOTE_DEFAULT_LINES = 20, + MODIFY_DT_MAX_LEN = 50, +}; int article_post(const SECTION_LIST *p_section, ARTICLE *p_article_new) { @@ -52,6 +49,7 @@ int article_post(const SECTION_LIST *p_s int content_display_length; char nickname_f[BBS_nickname_max_len * 2 + 1]; int sign_id = 0; + int reply_note = 1; long len; int ch; char *p, *q; @@ -59,7 +57,7 @@ int article_post(const SECTION_LIST *p_s if (p_section == NULL || p_article_new == NULL) { - log_error("NULL pointer error\n"); + log_error("NULL pointer error"); } if (!checkpriv(&BBS_priv, p_section->sid, S_POST)) @@ -79,7 +77,7 @@ int article_post(const SECTION_LIST *p_s p_editor_data = editor_data_load(""); if (p_editor_data == NULL) { - log_error("editor_data_load() error\n"); + log_error("editor_data_load() error"); ret = -1; goto cleanup; } @@ -89,7 +87,10 @@ int article_post(const SECTION_LIST *p_s { clearscr(); moveto(21, 1); - prints("发表文章于 %s[%s] 讨论区,类型: %s", p_section->stitle, p_section->sname, (p_article_new->transship ? "转载" : "原创")); + prints("发表文章于 %s[%s] 讨论区,类型: %s,回复通知: %s", + p_section->stitle, p_section->sname, + (p_article_new->transship ? "转载" : "原创"), + (reply_note ? "开启" : "关闭")); moveto(22, 1); prints("标题: %s", (p_article_new->title[0] == '\0' ? "[无]" : p_article_new->title)); moveto(23, 1); @@ -100,12 +101,14 @@ int article_post(const SECTION_LIST *p_s prints(" 按0~3选签名档(0表示不使用)"); moveto(24, 1); - prints("T改标题, C取消, Z设为转载, Y设为原创, Enter继续: "); + prints("T改标题, C取消, Z设为%s, N%s, Enter继续: ", + (p_article_new->transship ? "原创" : "转载"), + (reply_note ? "关闭回复通知" : "开启回复通知")); iflush(); ch = 0; } - for (; !SYS_server_exit; ch = igetch_t(MAX_DELAY_TIME)) + while (!SYS_server_exit) { switch (toupper(ch)) { @@ -113,11 +116,8 @@ int article_post(const SECTION_LIST *p_s case KEY_TIMEOUT: goto cleanup; case CR: - igetch_reset(); break; case 'T': - moveto(24, 1); - clrtoeol(); len = get_data(24, 1, "标题: ", title_input, sizeof(title_input), TITLE_INPUT_MAX_LEN); for (p = title_input; *p == ' '; p++) ; @@ -127,6 +127,15 @@ int article_post(const SECTION_LIST *p_s len = q - p; if (*p != '\0') { + if ((ret = check_badwords(p, '*')) < 0) + { + log_error("check_badwords(title) error"); + } + else if (ret > 0) + { + memcpy(title_input, p, (size_t)len + 1); + continue; + } memcpy(p_article_new->title, p, (size_t)len + 1); memcpy(title_input, p_article_new->title, (size_t)len + 1); } @@ -138,11 +147,11 @@ int article_post(const SECTION_LIST *p_s prints("取消..."); press_any_key(); goto cleanup; - case 'Y': - p_article_new->transship = 0; - break; case 'Z': - p_article_new->transship = 1; + p_article_new->transship = (p_article_new->transship ? 0 : 1); + break; + case 'N': + reply_note = (reply_note ? 0 : 1); break; case '0': case '1': @@ -151,6 +160,7 @@ int article_post(const SECTION_LIST *p_s sign_id = ch - '0'; break; default: // Invalid selection + ch = igetch_t(BBS_max_user_idle_time); continue; } @@ -171,7 +181,7 @@ int article_post(const SECTION_LIST *p_s prints("(S)发送, (C)取消, (T)更改标题 or (E)再编辑? [S]: "); iflush(); - for (ch = 0; !SYS_server_exit; ch = igetch_t(MAX_DELAY_TIME)) + for (ch = 0; !SYS_server_exit; ch = igetch_t(BBS_max_user_idle_time)) { switch (toupper(ch)) { @@ -179,7 +189,6 @@ int article_post(const SECTION_LIST *p_s case KEY_TIMEOUT: goto cleanup; case CR: - igetch_reset(); case 'S': break; case 'C': @@ -214,7 +223,7 @@ int article_post(const SECTION_LIST *p_s content = malloc(ARTICLE_CONTENT_MAX_LEN); if (content == NULL) { - log_error("malloc(content) error: OOM\n"); + log_error("malloc(content) error: OOM"); ret = -1; goto cleanup; } @@ -222,7 +231,14 @@ int article_post(const SECTION_LIST *p_s len_content = editor_data_save(p_editor_data, content, ARTICLE_CONTENT_MAX_LEN); if (len_content < 0) { - log_error("editor_data_save() error\n"); + log_error("editor_data_save() error"); + ret = -1; + goto cleanup; + } + + if (check_badwords(content, '*') < 0) + { + log_error("check_badwords(content) error"); ret = -1; goto cleanup; } @@ -230,7 +246,7 @@ int article_post(const SECTION_LIST *p_s db = db_open(); if (db == NULL) { - log_error("db_open() error: %s\n", mysql_error(db)); + log_error("db_open() error: %s", mysql_error(db)); ret = -1; goto cleanup; } @@ -243,13 +259,13 @@ int article_post(const SECTION_LIST *p_s if (mysql_query(db, sql) != 0) { - log_error("Query sign error: %s\n", mysql_error(db)); + log_error("Query sign error: %s", mysql_error(db)); ret = -1; goto cleanup; } if ((rs = mysql_use_result(db)) == NULL) { - log_error("Get sign data failed\n"); + log_error("Get sign data failed"); ret = -1; goto cleanup; } @@ -270,14 +286,14 @@ int article_post(const SECTION_LIST *p_s // Begin transaction if (mysql_query(db, "SET autocommit=0") != 0) { - log_error("SET autocommit=0 error: %s\n", mysql_error(db)); + log_error("SET autocommit=0 error: %s", mysql_error(db)); ret = -1; goto cleanup; } if (mysql_query(db, "BEGIN") != 0) { - log_error("Begin transaction error: %s\n", mysql_error(db)); + log_error("Begin transaction error: %s", mysql_error(db)); ret = -1; goto cleanup; } @@ -286,7 +302,7 @@ int article_post(const SECTION_LIST *p_s content_f = malloc((size_t)len_content * 2 + 1); if (content_f == NULL) { - log_error("malloc(content_f) error: OOM\n"); + log_error("malloc(content_f) error: OOM"); ret = -1; goto cleanup; } @@ -302,7 +318,7 @@ int article_post(const SECTION_LIST *p_s sql_content = malloc(SQL_BUFFER_LEN + (size_t)len_content * 2 + 1); if (sql_content == NULL) { - log_error("malloc(sql_content) error: OOM\n"); + log_error("malloc(sql_content) error: OOM"); ret = -1; goto cleanup; } @@ -316,7 +332,7 @@ int article_post(const SECTION_LIST *p_s if (mysql_query(db, sql_content) != 0) { - log_error("Add article content error: %s\n", mysql_error(db)); + log_error("Add article content error: %s", mysql_error(db)); ret = -1; goto cleanup; } @@ -330,13 +346,14 @@ int article_post(const SECTION_LIST *p_s snprintf(sql, sizeof(sql), "INSERT INTO bbs(SID, TID, UID, username, nickname, title, CID, transship, " "sub_dt, sub_ip, reply_note, exp, last_reply_dt, icon, length) " - "VALUES(%d, 0, %d, '%s', '%s', '%s', %d, %d, NOW(), '%s', 1, %d, NOW(), 1, %d)", + "VALUES(%d, 0, %d, '%s', '%s', '%s', %d, %d, NOW(), '%s', %d, %d, NOW(), 1, %d)", p_section->sid, BBS_priv.uid, BBS_username, nickname_f, title_f, - p_article_new->cid, p_article_new->transship, hostaddr_client, BBS_user_exp, content_display_length); + p_article_new->cid, p_article_new->transship, hostaddr_client, + reply_note, BBS_user_exp, content_display_length); if (mysql_query(db, sql) != 0) { - log_error("Add article error: %s\n", mysql_error(db)); + log_error("Add article error: %s", mysql_error(db)); ret = -1; goto cleanup; } @@ -350,7 +367,7 @@ int article_post(const SECTION_LIST *p_s if (mysql_query(db, sql) != 0) { - log_error("Update content error: %s\n", mysql_error(db)); + log_error("Update content error: %s", mysql_error(db)); ret = -1; goto cleanup; } @@ -364,7 +381,7 @@ int article_post(const SECTION_LIST *p_s if (mysql_query(db, sql) != 0) { - log_error("Update exp error: %s\n", mysql_error(db)); + log_error("Update exp error: %s", mysql_error(db)); ret = -1; goto cleanup; } @@ -378,7 +395,7 @@ int article_post(const SECTION_LIST *p_s if (mysql_query(db, sql) != 0) { - log_error("Add log error: %s\n", mysql_error(db)); + log_error("Add log error: %s", mysql_error(db)); ret = -1; goto cleanup; } @@ -386,7 +403,7 @@ int article_post(const SECTION_LIST *p_s // Commit transaction if (mysql_query(db, "COMMIT") != 0) { - log_error("Commit transaction error: %s\n", mysql_error(db)); + log_error("Commit transaction error: %s", mysql_error(db)); ret = -1; goto cleanup; } @@ -424,6 +441,7 @@ int article_modify(const SECTION_LIST *p char *content_f = NULL; long len_content; int content_display_length; + int reply_note = 1; int ch; long ret = 0; time_t now; @@ -434,7 +452,7 @@ int article_modify(const SECTION_LIST *p if (p_section == NULL || p_article == NULL) { - log_error("NULL pointer error\n"); + log_error("NULL pointer error"); } if (p_article->excerption) // Modify is not allowed @@ -450,26 +468,26 @@ int article_modify(const SECTION_LIST *p db = db_open(); if (db == NULL) { - log_error("db_open() error: %s\n", mysql_error(db)); + log_error("db_open() error: %s", mysql_error(db)); ret = -1; goto cleanup; } snprintf(sql, sizeof(sql), - "SELECT bbs_content.CID, bbs_content.content " + "SELECT bbs_content.CID, bbs_content.content, reply_note " "FROM bbs INNER JOIN bbs_content ON bbs.CID = bbs_content.CID " "WHERE bbs.AID = %d", p_article->aid); if (mysql_query(db, sql) != 0) { - log_error("Query article content error: %s\n", mysql_error(db)); + log_error("Query article content error: %s", mysql_error(db)); ret = -1; goto cleanup; } if ((rs = mysql_use_result(db)) == NULL) { - log_error("Get article content data failed\n"); + log_error("Get article content data failed"); ret = -1; goto cleanup; } @@ -479,7 +497,7 @@ int article_modify(const SECTION_LIST *p content = malloc(ARTICLE_CONTENT_MAX_LEN); if (content == NULL) { - log_error("malloc(content) error: OOM\n"); + log_error("malloc(content) error: OOM"); ret = -1; goto cleanup; } @@ -493,13 +511,15 @@ int article_modify(const SECTION_LIST *p p_editor_data = editor_data_load(content); if (p_editor_data == NULL) { - log_error("editor_data_load(aid=%d, cid=%d) error\n", p_article->aid, atoi(row[0])); + log_error("editor_data_load(aid=%d, cid=%d) error", p_article->aid, atoi(row[0])); ret = -1; goto cleanup; } free(content); content = NULL; + + reply_note = atoi(row[2]); } mysql_free_result(rs); rs = NULL; @@ -511,20 +531,21 @@ int article_modify(const SECTION_LIST *p { editor_display(p_editor_data); - clearscr(); - moveto(1, 1); - prints("(S)保存, (C)取消 or (E)再编辑? [S]: "); - iflush(); - - for (ch = 0; !SYS_server_exit; ch = igetch_t(MAX_DELAY_TIME)) + while (!SYS_server_exit) { + clearscr(); + moveto(1, 1); + prints("(S)保存, (C)取消, (N)%s回复通知 or (E)再编辑? [S]: ", + (reply_note ? "关闭" : "开启")); + iflush(); + + ch = igetch_t(BBS_max_user_idle_time); switch (toupper(ch)) { case KEY_NULL: case KEY_TIMEOUT: goto cleanup; case CR: - igetch_reset(); case 'S': break; case 'C': @@ -533,6 +554,9 @@ int article_modify(const SECTION_LIST *p prints("取消..."); press_any_key(); goto cleanup; + case 'N': + reply_note = (reply_note ? 0 : 1); + continue; case 'E': break; default: // Invalid selection @@ -552,7 +576,7 @@ int article_modify(const SECTION_LIST *p content = malloc(ARTICLE_CONTENT_MAX_LEN); if (content == NULL) { - log_error("malloc(content) error: OOM\n"); + log_error("malloc(content) error: OOM"); ret = -1; goto cleanup; } @@ -560,7 +584,14 @@ int article_modify(const SECTION_LIST *p len_content = editor_data_save(p_editor_data, content, ARTICLE_CONTENT_MAX_LEN - LINE_BUFFER_LEN); if (len_content < 0) { - log_error("editor_data_save() error\n"); + log_error("editor_data_save() error"); + ret = -1; + goto cleanup; + } + + if (check_badwords(content, '*') < 0) + { + log_error("check_badwords(content) error"); ret = -1; goto cleanup; } @@ -579,7 +610,7 @@ int article_modify(const SECTION_LIST *p db = db_open(); if (db == NULL) { - log_error("db_open() error: %s\n", mysql_error(db)); + log_error("db_open() error: %s", mysql_error(db)); ret = -1; goto cleanup; } @@ -587,14 +618,14 @@ int article_modify(const SECTION_LIST *p // Begin transaction if (mysql_query(db, "SET autocommit=0") != 0) { - log_error("SET autocommit=0 error: %s\n", mysql_error(db)); + log_error("SET autocommit=0 error: %s", mysql_error(db)); ret = -1; goto cleanup; } if (mysql_query(db, "BEGIN") != 0) { - log_error("Begin transaction error: %s\n", mysql_error(db)); + log_error("Begin transaction error: %s", mysql_error(db)); ret = -1; goto cleanup; } @@ -603,7 +634,7 @@ int article_modify(const SECTION_LIST *p content_f = malloc((size_t)len_content * 2 + 1); if (content_f == NULL) { - log_error("malloc(content_f) error: OOM\n"); + log_error("malloc(content_f) error: OOM"); ret = -1; goto cleanup; } @@ -617,7 +648,7 @@ int article_modify(const SECTION_LIST *p sql_content = malloc(SQL_BUFFER_LEN + (size_t)len_content * 2 + 1); if (sql_content == NULL) { - log_error("malloc(sql_content) error: OOM\n"); + log_error("malloc(sql_content) error: OOM"); ret = -1; goto cleanup; } @@ -631,7 +662,7 @@ int article_modify(const SECTION_LIST *p if (mysql_query(db, sql_content) != 0) { - log_error("Add article content error: %s\n", mysql_error(db)); + log_error("Add article content error: %s", mysql_error(db)); ret = -1; goto cleanup; } @@ -643,19 +674,19 @@ int article_modify(const SECTION_LIST *p // Update article snprintf(sql, sizeof(sql), - "UPDATE bbs SET CID = %d, length = %d, excerption = 0 WHERE AID = %d", // Set excerption = 0 explictly in case of rare condition - p_article_new->cid, content_display_length, p_article->aid); + "UPDATE bbs SET CID = %d, length = %d, reply_note = %d, excerption = 0 WHERE AID = %d", // Set excerption = 0 explictly in case of rare condition + p_article_new->cid, content_display_length, reply_note, p_article->aid); if (mysql_query(db, sql) != 0) { - log_error("Add article error: %s\n", mysql_error(db)); + log_error("Add article error: %s", mysql_error(db)); ret = -1; goto cleanup; } if (mysql_query(db, sql) != 0) { - log_error("Update content error: %s\n", mysql_error(db)); + log_error("Update content error: %s", mysql_error(db)); ret = -1; goto cleanup; } @@ -668,7 +699,7 @@ int article_modify(const SECTION_LIST *p if (mysql_query(db, sql) != 0) { - log_error("Add log error: %s\n", mysql_error(db)); + log_error("Add log error: %s", mysql_error(db)); ret = -1; goto cleanup; } @@ -676,7 +707,7 @@ int article_modify(const SECTION_LIST *p // Commit transaction if (mysql_query(db, "COMMIT") != 0) { - log_error("Commit transaction error: %s\n", mysql_error(db)); + log_error("Commit transaction error: %s", mysql_error(db)); ret = -1; goto cleanup; } @@ -709,7 +740,7 @@ int article_reply(const SECTION_LIST *p_ MYSQL *db = NULL; MYSQL_RES *rs = NULL; MYSQL_ROW row; - long line_offsets[ARTICLE_QUOTE_MAX_LINES + 1]; + long line_offsets[MAX_EDITOR_DATA_LINES + 1]; char sql[SQL_BUFFER_LEN]; char *sql_content = NULL; EDITOR_DATA *p_editor_data = NULL; @@ -721,6 +752,8 @@ int article_reply(const SECTION_LIST *p_ int content_display_length; char nickname_f[BBS_nickname_max_len * 2 + 1]; int sign_id = 0; + int reply_note = 0; + int full_quote = 0; long len; int ch; char *p, *q; @@ -736,7 +769,7 @@ int article_reply(const SECTION_LIST *p_ if (p_section == NULL || p_article == NULL) { - log_error("NULL pointer error\n"); + log_error("NULL pointer error"); } if (!checkpriv(&BBS_priv, p_section->sid, S_POST)) @@ -757,7 +790,7 @@ int article_reply(const SECTION_LIST *p_ db = db_open(); if (db == NULL) { - log_error("db_open() error: %s\n", mysql_error(db)); + log_error("db_open() error: %s", mysql_error(db)); ret = -1; goto cleanup; } @@ -768,13 +801,13 @@ int article_reply(const SECTION_LIST *p_ if (mysql_query(db, sql) != 0) { - log_error("Query article status error: %s\n", mysql_error(db)); + log_error("Query article status error: %s", mysql_error(db)); ret = -1; goto cleanup; } if ((rs = mysql_store_result(db)) == NULL) { - log_error("Get article status data failed\n"); + log_error("Get article status data failed"); ret = -1; goto cleanup; } @@ -810,13 +843,13 @@ int article_reply(const SECTION_LIST *p_ if (mysql_query(db, sql) != 0) { - log_error("Query article content error: %s\n", mysql_error(db)); + log_error("Query article content error: %s", mysql_error(db)); ret = -1; goto cleanup; } if ((rs = mysql_use_result(db)) == NULL) { - log_error("Get article content data failed\n"); + log_error("Get article content data failed"); ret = -1; goto cleanup; } @@ -826,7 +859,7 @@ int article_reply(const SECTION_LIST *p_ content = malloc(ARTICLE_CONTENT_MAX_LEN); if (content == NULL) { - log_error("malloc(content) error: OOM\n"); + log_error("malloc(content) error: OOM"); ret = -1; goto cleanup; } @@ -834,55 +867,17 @@ int article_reply(const SECTION_LIST *p_ content_f = malloc(ARTICLE_CONTENT_MAX_LEN); if (content_f == NULL) { - log_error("malloc(content_f) error: OOM\n"); + log_error("malloc(content_f) error: OOM"); ret = -1; goto cleanup; } // Apply LML render to content body - len = lml_render(row[1], content_f, ARTICLE_CONTENT_MAX_LEN, 0); + len = lml_render(row[1], content_f, ARTICLE_CONTENT_MAX_LEN, MAX_EDITOR_DATA_LINE_LENGTH - 3, 1); content_f[len] = '\0'; // Remove control sequence len = str_filter(content_f, 0); - - len = snprintf(content, ARTICLE_CONTENT_MAX_LEN, - "\n\n【 在 %s (%s) 的大作中提到: 】\n", - p_article->username, p_article->nickname); - - quote_content_lines = split_data_lines(content_f, ARTICLE_QUOTE_LINE_MAX_LEN, line_offsets, ARTICLE_QUOTE_MAX_LINES + 1, 0, NULL); - for (i = 0; i < quote_content_lines; i++) - { - memcpy(content + len, ": ", 2); // quote line prefix - len += 2; - memcpy(content + len, content_f + line_offsets[i], (size_t)(line_offsets[i + 1] - line_offsets[i])); - len += (line_offsets[i + 1] - line_offsets[i]); - if (content[len - 1] != '\n') // Appennd \n if not exist - { - content[len] = '\n'; - len++; - } - } - if (content[len - 1] != '\n') // Appennd \n if not exist - { - content[len] = '\n'; - len++; - } - content[len] = '\0'; - - free(content_f); - content_f = NULL; - - p_editor_data = editor_data_load(content); - if (p_editor_data == NULL) - { - log_error("editor_data_load(aid=%d, cid=%d) error\n", p_article->aid, atoi(row[0])); - ret = -1; - goto cleanup; - } - - free(content); - content = NULL; } mysql_free_result(rs); rs = NULL; @@ -895,7 +890,10 @@ int article_reply(const SECTION_LIST *p_ { clearscr(); moveto(21, 1); - prints("回复文章于 %s[%s] 讨论区", p_section->stitle, p_section->sname); + prints("回复文章于 %s[%s] 讨论区, 回复通知: %s, 引用模式: %s", + p_section->stitle, p_section->sname, + (reply_note ? "开启" : "关闭"), + (full_quote ? "完整" : "精简")); moveto(22, 1); prints("标题: %s", (p_article_new->title[0] == '\0' ? "[无]" : p_article_new->title)); moveto(23, 1); @@ -906,12 +904,13 @@ int article_reply(const SECTION_LIST *p_ prints(" 按0~3选签名档(0表示不使用)"); moveto(24, 1); - prints("T改标题, C取消, Enter继续: "); + prints("T改标题, C取消, N%s, Q%s, Enter继续: ", + (reply_note ? "关闭回复通知" : "开启回复通知"), (full_quote ? "精简引用" : "完整引用")); iflush(); ch = 0; } - for (; !SYS_server_exit; ch = igetch_t(MAX_DELAY_TIME)) + while (!SYS_server_exit) { switch (toupper(ch)) { @@ -919,11 +918,8 @@ int article_reply(const SECTION_LIST *p_ case KEY_TIMEOUT: goto cleanup; case CR: - igetch_reset(); break; case 'T': - moveto(24, 1); - clrtoeol(); len = get_data(24, 1, "标题: ", title_input, sizeof(title_input), TITLE_INPUT_MAX_LEN); for (p = title_input; *p == ' '; p++) ; @@ -933,6 +929,15 @@ int article_reply(const SECTION_LIST *p_ len = q - p; if (*p != '\0') { + if ((ret = check_badwords(p, '*')) < 0) + { + log_error("check_badwords(title) error"); + } + else if (ret > 0) + { + memcpy(title_input, p, (size_t)len + 1); + continue; + } memcpy(p_article_new->title, p, (size_t)len + 1); memcpy(title_input, p_article_new->title, (size_t)len + 1); } @@ -944,6 +949,12 @@ int article_reply(const SECTION_LIST *p_ prints("取消..."); press_any_key(); goto cleanup; + case 'N': + reply_note = (reply_note ? 0 : 1); + break; + case 'Q': + full_quote = (full_quote ? 0 : 1); + break; case '0': case '1': case '2': @@ -951,6 +962,7 @@ int article_reply(const SECTION_LIST *p_ sign_id = ch - '0'; break; default: // Invalid selection + ch = igetch_t(BBS_max_user_idle_time); continue; } @@ -962,6 +974,47 @@ int article_reply(const SECTION_LIST *p_ continue; } + len = snprintf(content, ARTICLE_CONTENT_MAX_LEN, + "\n\n【 在 %s (%s) 的大作中提到: 】\n", + p_article->username, p_article->nickname); + + quote_content_lines = split_data_lines(content_f, + MAX_EDITOR_DATA_LINE_LENGTH - 2, line_offsets, + (full_quote ? MAX_EDITOR_DATA_LINES : ARTICLE_QUOTE_DEFAULT_LINES) + 1, + 0, NULL); + for (i = 0; i < quote_content_lines; i++) + { + memcpy(content + len, ": ", 2); // quote line prefix + len += 2; + memcpy(content + len, content_f + line_offsets[i], (size_t)(line_offsets[i + 1] - line_offsets[i])); + len += (line_offsets[i + 1] - line_offsets[i]); + if (content[len - 1] != '\n') // Appennd \n if not exist + { + content[len] = '\n'; + len++; + } + } + if (content[len - 1] != '\n') // Appennd \n if not exist + { + content[len] = '\n'; + len++; + } + content[len] = '\0'; + + free(content_f); + content_f = NULL; + + p_editor_data = editor_data_load(content); + if (p_editor_data == NULL) + { + log_error("editor_data_load(aid=%d, cid=%d) error", p_article->aid, atoi(row[0])); + ret = -1; + goto cleanup; + } + + free(content); + content = NULL; + for (ch = 'E'; !SYS_server_exit && toupper(ch) == 'E';) { editor_display(p_editor_data); @@ -971,7 +1024,7 @@ int article_reply(const SECTION_LIST *p_ prints("(S)发送, (C)取消, (T)更改标题 or (E)再编辑? [S]: "); iflush(); - for (ch = 0; !SYS_server_exit; ch = igetch_t(MAX_DELAY_TIME)) + for (ch = 0; !SYS_server_exit; ch = igetch_t(BBS_max_user_idle_time)) { switch (toupper(ch)) { @@ -979,7 +1032,6 @@ int article_reply(const SECTION_LIST *p_ case KEY_TIMEOUT: goto cleanup; case CR: - igetch_reset(); case 'S': break; case 'C': @@ -1014,7 +1066,7 @@ int article_reply(const SECTION_LIST *p_ content = malloc(ARTICLE_CONTENT_MAX_LEN); if (content == NULL) { - log_error("malloc(content) error: OOM\n"); + log_error("malloc(content) error: OOM"); ret = -1; goto cleanup; } @@ -1022,7 +1074,14 @@ int article_reply(const SECTION_LIST *p_ len_content = editor_data_save(p_editor_data, content, ARTICLE_CONTENT_MAX_LEN); if (len_content < 0) { - log_error("editor_data_save() error\n"); + log_error("editor_data_save() error"); + ret = -1; + goto cleanup; + } + + if (check_badwords(content, '*') < 0) + { + log_error("check_badwords(content) error"); ret = -1; goto cleanup; } @@ -1030,7 +1089,7 @@ int article_reply(const SECTION_LIST *p_ db = db_open(); if (db == NULL) { - log_error("db_open() error: %s\n", mysql_error(db)); + log_error("db_open() error: %s", mysql_error(db)); ret = -1; goto cleanup; } @@ -1043,13 +1102,13 @@ int article_reply(const SECTION_LIST *p_ if (mysql_query(db, sql) != 0) { - log_error("Query sign error: %s\n", mysql_error(db)); + log_error("Query sign error: %s", mysql_error(db)); ret = -1; goto cleanup; } if ((rs = mysql_use_result(db)) == NULL) { - log_error("Get sign data failed\n"); + log_error("Get sign data failed"); ret = -1; goto cleanup; } @@ -1070,14 +1129,14 @@ int article_reply(const SECTION_LIST *p_ // Begin transaction if (mysql_query(db, "SET autocommit=0") != 0) { - log_error("SET autocommit=0 error: %s\n", mysql_error(db)); + log_error("SET autocommit=0 error: %s", mysql_error(db)); ret = -1; goto cleanup; } if (mysql_query(db, "BEGIN") != 0) { - log_error("Begin transaction error: %s\n", mysql_error(db)); + log_error("Begin transaction error: %s", mysql_error(db)); ret = -1; goto cleanup; } @@ -1086,7 +1145,7 @@ int article_reply(const SECTION_LIST *p_ content_f = malloc((size_t)len_content * 2 + 1); if (content_f == NULL) { - log_error("malloc(content_f) error: OOM\n"); + log_error("malloc(content_f) error: OOM"); ret = -1; goto cleanup; } @@ -1102,7 +1161,7 @@ int article_reply(const SECTION_LIST *p_ sql_content = malloc(SQL_BUFFER_LEN + (size_t)len_content * 2 + 1); if (sql_content == NULL) { - log_error("malloc(sql_content) error: OOM\n"); + log_error("malloc(sql_content) error: OOM"); ret = -1; goto cleanup; } @@ -1116,7 +1175,7 @@ int article_reply(const SECTION_LIST *p_ if (mysql_query(db, sql_content) != 0) { - log_error("Add article content error: %s\n", mysql_error(db)); + log_error("Add article content error: %s", mysql_error(db)); ret = -1; goto cleanup; } @@ -1130,14 +1189,15 @@ int article_reply(const SECTION_LIST *p_ snprintf(sql, sizeof(sql), "INSERT INTO bbs(SID, TID, UID, username, nickname, title, CID, transship, " "sub_dt, sub_ip, reply_note, exp, last_reply_dt, icon, length) " - "VALUES(%d, %d, %d, '%s', '%s', '%s', %d, 0, NOW(), '%s', 1, %d, NOW(), 1, %d)", + "VALUES(%d, %d, %d, '%s', '%s', '%s', %d, 0, NOW(), '%s', %d, %d, NOW(), 1, %d)", p_section->sid, (p_article->tid == 0 ? p_article->aid : p_article->tid), BBS_priv.uid, BBS_username, nickname_f, title_f, - p_article_new->cid, hostaddr_client, BBS_user_exp, content_display_length); + p_article_new->cid, hostaddr_client, + reply_note, BBS_user_exp, content_display_length); if (mysql_query(db, sql) != 0) { - log_error("Add article error: %s\n", mysql_error(db)); + log_error("Add article error: %s", mysql_error(db)); ret = -1; goto cleanup; } @@ -1154,7 +1214,7 @@ int article_reply(const SECTION_LIST *p_ if (mysql_query(db, sql) != 0) { - log_error("Update topic article error: %s\n", mysql_error(db)); + log_error("Update topic article error: %s", mysql_error(db)); ret = -1; goto cleanup; } @@ -1166,7 +1226,7 @@ int article_reply(const SECTION_LIST *p_ if (mysql_query(db, sql) != 0) { - log_error("Update content error: %s\n", mysql_error(db)); + log_error("Update content error: %s", mysql_error(db)); ret = -1; goto cleanup; } @@ -1179,13 +1239,13 @@ int article_reply(const SECTION_LIST *p_ if (mysql_query(db, sql) != 0) { - log_error("Read reply info error: %s\n", mysql_error(db)); + log_error("Read reply info error: %s", mysql_error(db)); ret = -1; goto cleanup; } if ((rs = mysql_store_result(db)) == NULL) { - log_error("Get reply info failed\n"); + log_error("Get reply info failed"); ret = -1; goto cleanup; } @@ -1194,7 +1254,7 @@ int article_reply(const SECTION_LIST *p_ { // Send notification message len_msg = snprintf(msg, BBS_msg_max_len, - "[hide]SYS_Reply_Article[/hide]有人回复了您所发表/回复的文章,快来" + "有人回复了您所发表/回复的文章,快来" "[article %d]看看[/article]《%s》吧!\n", p_article_new->aid, title_f); @@ -1207,7 +1267,7 @@ int article_reply(const SECTION_LIST *p_ if (mysql_query(db, sql) != 0) { - log_error("Insert msg error: %s\n", mysql_error(db)); + log_error("Insert msg error: %s", mysql_error(db)); ret = -1; goto cleanup; } @@ -1224,7 +1284,7 @@ int article_reply(const SECTION_LIST *p_ if (mysql_query(db, sql) != 0) { - log_error("Update exp error: %s\n", mysql_error(db)); + log_error("Update exp error: %s", mysql_error(db)); ret = -1; goto cleanup; } @@ -1238,7 +1298,7 @@ int article_reply(const SECTION_LIST *p_ if (mysql_query(db, sql) != 0) { - log_error("Add log error: %s\n", mysql_error(db)); + log_error("Add log error: %s", mysql_error(db)); ret = -1; goto cleanup; } @@ -1246,7 +1306,7 @@ int article_reply(const SECTION_LIST *p_ // Commit transaction if (mysql_query(db, "COMMIT") != 0) { - log_error("Commit transaction error: %s\n", mysql_error(db)); + log_error("Commit transaction error: %s", mysql_error(db)); ret = -1; goto cleanup; }