--- lbbs/src/article_post.c 2025/06/14 12:30:15 1.12 +++ lbbs/src/article_post.c 2025/06/16 01:36:56 1.20 @@ -81,7 +81,8 @@ int article_post(const SECTION_LIST *p_s if (p_editor_data == NULL) { log_error("editor_data_load() error\n"); - return -2; + ret = -1; + goto cleanup; } // Set title and sign @@ -109,6 +110,9 @@ int article_post(const SECTION_LIST *p_s { switch (toupper(ch)) { + case KEY_NULL: + case KEY_TIMEOUT: + goto cleanup; case CR: igetch_reset(); break; @@ -172,6 +176,9 @@ int article_post(const SECTION_LIST *p_s { switch (toupper(ch)) { + case KEY_NULL: + case KEY_TIMEOUT: + goto cleanup; case CR: igetch_reset(); case 'S': @@ -200,6 +207,11 @@ int article_post(const SECTION_LIST *p_s } } + if (SYS_server_exit) // Do not save data on shutdown + { + goto cleanup; + } + content = malloc(ARTICLE_CONTENT_MAX_LEN); if (content == NULL) { @@ -212,7 +224,7 @@ int article_post(const SECTION_LIST *p_s if (len_content < 0) { log_error("editor_data_save() error\n"); - ret = -2; + ret = -1; goto cleanup; } @@ -253,22 +265,6 @@ int article_post(const SECTION_LIST *p_s rs = NULL; } - content_f = malloc((size_t)len_content * 2 + 1); - if (content_f == NULL) - { - log_error("malloc(content_f) error: OOM\n"); - ret = -1; - goto cleanup; - } - - sql_content = malloc(SQL_BUFFER_LEN + (size_t)len_content * 2 + 1); - if (sql_content == NULL) - { - log_error("malloc(sql_content) error: OOM\n"); - ret = -1; - goto cleanup; - } - // Begin transaction if (mysql_query(db, "SET autocommit=0") != 0) { @@ -285,16 +281,38 @@ int article_post(const SECTION_LIST *p_s } // Secure SQL parameters + content_f = malloc((size_t)len_content * 2 + 1); + if (content_f == NULL) + { + log_error("malloc(content_f) error: OOM\n"); + ret = -1; + goto cleanup; + } + mysql_real_escape_string(db, nickname_f, BBS_nickname, (unsigned long)strnlen(BBS_nickname, sizeof(BBS_nickname))); mysql_real_escape_string(db, title_f, p_article_new->title, strnlen(p_article_new->title, sizeof(p_article_new->title))); mysql_real_escape_string(db, content_f, content, (unsigned long)len_content); + free(content); + content = NULL; + // Add content - snprintf(sql, SQL_BUFFER_LEN + (size_t)len_content * 2 + 1, + sql_content = malloc(SQL_BUFFER_LEN + (size_t)len_content * 2 + 1); + if (sql_content == NULL) + { + log_error("malloc(sql_content) error: OOM\n"); + ret = -1; + goto cleanup; + } + + snprintf(sql_content, SQL_BUFFER_LEN + (size_t)len_content * 2 + 1, "INSERT INTO bbs_content(AID, content) values(0, '%s')", content_f); - if (mysql_query(db, sql) != 0) + free(content_f); + content_f = NULL; + + if (mysql_query(db, sql_content) != 0) { log_error("Add article content error: %s\n", mysql_error(db)); ret = -1; @@ -303,6 +321,9 @@ int article_post(const SECTION_LIST *p_s p_article_new->cid = (int32_t)mysql_insert_id(db); + free(sql_content); + sql_content = NULL; + // Add article snprintf(sql, sizeof(sql), "INSERT INTO bbs(SID, TID, UID, username, nickname, title, CID, transship, " @@ -368,6 +389,9 @@ int article_post(const SECTION_LIST *p_s goto cleanup; } + mysql_close(db); + db = NULL; + clearscr(); moveto(1, 1); prints("发送完成,新文章通常会在%d秒后可见", BBS_section_list_load_interval); @@ -420,21 +444,12 @@ int article_modify(const SECTION_LIST *p return 0; } - if (!checkpriv(&BBS_priv, p_section->sid, S_POST)) - { - clearscr(); - moveto(1, 1); - prints("您没有权限在本版块发表文章\n"); - press_any_key(); - - return 0; - } - db = db_open(); if (db == NULL) { log_error("db_open() error: %s\n", mysql_error(db)); - return -1; + ret = -1; + goto cleanup; } snprintf(sql, sizeof(sql), @@ -446,25 +461,42 @@ int article_modify(const SECTION_LIST *p if (mysql_query(db, sql) != 0) { log_error("Query article content error: %s\n", mysql_error(db)); - ret = -2; + ret = -1; goto cleanup; } if ((rs = mysql_use_result(db)) == NULL) { log_error("Get article content data failed\n"); - ret = -2; + ret = -1; goto cleanup; } if ((row = mysql_fetch_row(rs))) { - p_editor_data = editor_data_load(row[1]); + content = malloc(ARTICLE_CONTENT_MAX_LEN); + if (content == NULL) + { + log_error("malloc(content) error: OOM\n"); + ret = -1; + goto cleanup; + } + + strncpy(content, row[1], ARTICLE_CONTENT_MAX_LEN - 1); + content[ARTICLE_CONTENT_MAX_LEN - 1] = '\0'; + + // Remove control sequence + len_content = str_filter(content, 0); + + 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 = -3; + ret = -1; goto cleanup; } + + free(content); + content = NULL; } mysql_free_result(rs); rs = NULL; @@ -485,6 +517,9 @@ int article_modify(const SECTION_LIST *p { switch (toupper(ch)) { + case KEY_NULL: + case KEY_TIMEOUT: + goto cleanup; case CR: igetch_reset(); case 'S': @@ -505,6 +540,11 @@ int article_modify(const SECTION_LIST *p } } + if (SYS_server_exit) // Do not save data on shutdown + { + goto cleanup; + } + // Allocate buffers in big size content = malloc(ARTICLE_CONTENT_MAX_LEN); if (content == NULL) @@ -518,7 +558,7 @@ int article_modify(const SECTION_LIST *p if (len_content < 0) { log_error("editor_data_save() error\n"); - ret = -2; + ret = -1; goto cleanup; } @@ -530,22 +570,6 @@ int article_modify(const SECTION_LIST *p "\n--\n※ 作者已于 %s 修改本文※\n", str_modify_dt); - content_f = malloc((size_t)len_content * 2 + 1); - if (content_f == NULL) - { - log_error("malloc(content_f) error: OOM\n"); - ret = -1; - goto cleanup; - } - - sql_content = malloc(SQL_BUFFER_LEN + (size_t)len_content * 2 + 1); - if (sql_content == NULL) - { - log_error("malloc(sql_content) error: OOM\n"); - ret = -1; - goto cleanup; - } - db = db_open(); if (db == NULL) { @@ -570,14 +594,36 @@ int article_modify(const SECTION_LIST *p } // Secure SQL parameters + content_f = malloc((size_t)len_content * 2 + 1); + if (content_f == NULL) + { + log_error("malloc(content_f) error: OOM\n"); + ret = -1; + goto cleanup; + } + mysql_real_escape_string(db, content_f, content, (unsigned long)len_content); + free(content); + content = NULL; + // Add content - snprintf(sql, SQL_BUFFER_LEN + (size_t)len_content * 2 + 1, + sql_content = malloc(SQL_BUFFER_LEN + (size_t)len_content * 2 + 1); + if (sql_content == NULL) + { + log_error("malloc(sql_content) error: OOM\n"); + ret = -1; + goto cleanup; + } + + snprintf(sql_content, SQL_BUFFER_LEN + (size_t)len_content * 2 + 1, "INSERT INTO bbs_content(AID, content) values(%d, '%s')", p_article->aid, content_f); - if (mysql_query(db, sql) != 0) + free(content_f); + content_f = NULL; + + if (mysql_query(db, sql_content) != 0) { log_error("Add article content error: %s\n", mysql_error(db)); ret = -1; @@ -586,9 +632,12 @@ int article_modify(const SECTION_LIST *p p_article_new->cid = (int32_t)mysql_insert_id(db); + free(sql_content); + sql_content = NULL; + // Update article snprintf(sql, sizeof(sql), - "UPDATE bbs SET CID = %d, length = %ld WHERE AID = %d", + "UPDATE bbs SET CID = %d, length = %ld, excerption = 0 WHERE AID = %d", // Set excerption = 0 explictly in case of rare condition p_article_new->cid, len_content, p_article->aid); if (mysql_query(db, sql) != 0) @@ -626,6 +675,9 @@ int article_modify(const SECTION_LIST *p goto cleanup; } + mysql_close(db); + db = NULL; + clearscr(); moveto(1, 1); prints("修改完成,新内容通常会在%d秒后可见", BBS_section_list_load_interval); @@ -633,6 +685,7 @@ int article_modify(const SECTION_LIST *p ret = 1; // Success cleanup: + mysql_free_result(rs); mysql_close(db); // Cleanup buffers @@ -669,6 +722,7 @@ int article_reply(const SECTION_LIST *p_ long quote_content_lines; long i; long ret = 0; + int topic_locked = 0; if (p_section == NULL || p_article == NULL) { @@ -685,26 +739,57 @@ int article_reply(const SECTION_LIST *p_ return 0; } - if (p_article->lock) // Reply is not allowed - { - clearscr(); - moveto(1, 1); - prints("该文章谢绝回复"); - press_any_key(); - - return 0; - } - p_article_new->title[0] = '\0'; snprintf(title_input, sizeof(title_input), "Re: %s", p_article->title); - len = split_line(title_input, TITLE_INPUT_MAX_LEN, &eol, &display_len); + len = split_line(title_input, TITLE_INPUT_MAX_LEN, &eol, &display_len, 0); title_input[len] = '\0'; db = db_open(); if (db == NULL) { log_error("db_open() error: %s\n", mysql_error(db)); - return -1; + ret = -1; + goto cleanup; + } + + snprintf(sql, sizeof(sql), + "SELECT `lock` FROM bbs WHERE AID = %d", + (p_article->tid == 0 ? p_article->aid : p_article->tid)); + + if (mysql_query(db, sql) != 0) + { + log_error("Query article status error: %s\n", mysql_error(db)); + ret = -1; + goto cleanup; + } + if ((rs = mysql_store_result(db)) == NULL) + { + log_error("Get article status data failed\n"); + ret = -1; + goto cleanup; + } + + if ((row = mysql_fetch_row(rs))) + { + if (atoi(row[0]) != 0) + { + topic_locked = 1; + } + } + mysql_free_result(rs); + rs = NULL; + + if (topic_locked) // Reply is not allowed + { + mysql_close(db); + db = NULL; + + clearscr(); + moveto(1, 1); + prints("该主题谢绝回复"); + press_any_key(); + + goto cleanup; } snprintf(sql, sizeof(sql), @@ -716,12 +801,14 @@ int article_reply(const SECTION_LIST *p_ if (mysql_query(db, sql) != 0) { log_error("Query article content error: %s\n", mysql_error(db)); - return -2; + ret = -1; + goto cleanup; } if ((rs = mysql_use_result(db)) == NULL) { log_error("Get article content data failed\n"); - return -2; + ret = -1; + goto cleanup; } if ((row = mysql_fetch_row(rs))) @@ -747,19 +834,24 @@ int article_reply(const SECTION_LIST *p_ content_f[len] = '\0'; // Remove control sequence - len = ctrl_seq_filter(content_f); + 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); + quote_content_lines = split_data_lines(content_f, ARTICLE_QUOTE_LINE_MAX_LEN, line_offsets, ARTICLE_QUOTE_MAX_LINES + 1, 0); 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 { @@ -775,7 +867,7 @@ int article_reply(const SECTION_LIST *p_ if (p_editor_data == NULL) { log_error("editor_data_load(aid=%d, cid=%d) error\n", p_article->aid, atoi(row[0])); - ret = -3; + ret = -1; goto cleanup; } @@ -813,6 +905,9 @@ int article_reply(const SECTION_LIST *p_ { switch (toupper(ch)) { + case KEY_NULL: + case KEY_TIMEOUT: + goto cleanup; case CR: igetch_reset(); break; @@ -870,6 +965,9 @@ int article_reply(const SECTION_LIST *p_ { switch (toupper(ch)) { + case KEY_NULL: + case KEY_TIMEOUT: + goto cleanup; case CR: igetch_reset(); case 'S': @@ -898,6 +996,11 @@ int article_reply(const SECTION_LIST *p_ } } + if (SYS_server_exit) // Do not save data on shutdown + { + goto cleanup; + } + content = malloc(ARTICLE_CONTENT_MAX_LEN); if (content == NULL) { @@ -910,7 +1013,7 @@ int article_reply(const SECTION_LIST *p_ if (len_content < 0) { log_error("editor_data_save() error\n"); - ret = -2; + ret = -1; goto cleanup; } @@ -951,22 +1054,6 @@ int article_reply(const SECTION_LIST *p_ rs = NULL; } - content_f = malloc((size_t)len_content * 2 + 1); - if (content_f == NULL) - { - log_error("malloc(content_f) error: OOM\n"); - ret = -1; - goto cleanup; - } - - sql_content = malloc(SQL_BUFFER_LEN + (size_t)len_content * 2 + 1); - if (sql_content == NULL) - { - log_error("malloc(sql_content) error: OOM\n"); - ret = -1; - goto cleanup; - } - // Begin transaction if (mysql_query(db, "SET autocommit=0") != 0) { @@ -983,16 +1070,38 @@ int article_reply(const SECTION_LIST *p_ } // Secure SQL parameters + content_f = malloc((size_t)len_content * 2 + 1); + if (content_f == NULL) + { + log_error("malloc(content_f) error: OOM\n"); + ret = -1; + goto cleanup; + } + mysql_real_escape_string(db, nickname_f, BBS_nickname, (unsigned long)strnlen(BBS_nickname, sizeof(BBS_nickname))); mysql_real_escape_string(db, title_f, p_article_new->title, strnlen(p_article_new->title, sizeof(p_article_new->title))); mysql_real_escape_string(db, content_f, content, (unsigned long)len_content); + free(content); + content = NULL; + // Add content - snprintf(sql, SQL_BUFFER_LEN + (size_t)len_content * 2 + 1, + sql_content = malloc(SQL_BUFFER_LEN + (size_t)len_content * 2 + 1); + if (sql_content == NULL) + { + log_error("malloc(sql_content) error: OOM\n"); + ret = -1; + goto cleanup; + } + + snprintf(sql_content, SQL_BUFFER_LEN + (size_t)len_content * 2 + 1, "INSERT INTO bbs_content(AID, content) values(0, '%s')", content_f); - if (mysql_query(db, sql) != 0) + free(content_f); + content_f = NULL; + + if (mysql_query(db, sql_content) != 0) { log_error("Add article content error: %s\n", mysql_error(db)); ret = -1; @@ -1001,6 +1110,9 @@ int article_reply(const SECTION_LIST *p_ p_article_new->cid = (int32_t)mysql_insert_id(db); + free(sql_content); + sql_content = NULL; + // Add article snprintf(sql, sizeof(sql), "INSERT INTO bbs(SID, TID, UID, username, nickname, title, CID, transship, " @@ -1082,6 +1194,9 @@ int article_reply(const SECTION_LIST *p_ goto cleanup; } + mysql_close(db); + db = NULL; + clearscr(); moveto(1, 1); prints("发送完成,新文章通常会在%d秒后可见", BBS_section_list_load_interval);