/[LeafOK_CVS]/lbbs/src/article_post.c
ViewVC logotype

Diff of /lbbs/src/article_post.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 1.27 by sysadm, Thu Oct 9 12:20:31 2025 UTC Revision 1.44 by sysadm, Fri Dec 19 06:16:26 2025 UTC
# Line 1  Line 1 
1  /***************************************************************************  /* SPDX-License-Identifier: GPL-3.0-or-later */
2                                                  article_post.c  -  description  /*
3                                                           -------------------   * article_post
4          copyright            : (C) 2004-2025 by Leaflet   *   - user interactive feature to post / modify / reply article
5          email                : leaflet@leafok.com   *
6   ***************************************************************************/   * Copyright (C) 2004-2025  Leaflet <leaflet@leafok.com>
7     */
8  /***************************************************************************  
9   *                                                                         *  #ifdef HAVE_CONFIG_H
10   *   This program is free software; you can redistribute it and/or modify  *  #include "config.h"
11   *   it under the terms of the GNU General Public License as published by  *  #endif
  *   the Free Software Foundation; either version 3 of the License, or     *  
  *   (at your option) any later version.                                   *  
  *                                                                         *  
  ***************************************************************************/  
12    
13  #include "article_cache.h"  #include "article_cache.h"
14  #include "article_post.h"  #include "article_post.h"
15  #include "bbs.h"  #include "bbs.h"
16    #include "bwf.h"
17  #include "database.h"  #include "database.h"
18  #include "editor.h"  #include "editor.h"
19  #include "io.h"  #include "io.h"
# Line 29  Line 26 
26  #include <stdlib.h>  #include <stdlib.h>
27  #include <time.h>  #include <time.h>
28    
29  #define TITLE_INPUT_MAX_LEN 72  enum _article_post_constant_t
30  #define ARTICLE_CONTENT_MAX_LEN 1024 * 1024 * 4 // 4MB  {
31  #define ARTICLE_QUOTE_MAX_LINES 20          TITLE_INPUT_MAX_LEN = 72,
32  #define ARTICLE_QUOTE_LINE_MAX_LEN 76          ARTICLE_QUOTE_DEFAULT_LINES = 20,
33            MODIFY_DT_MAX_LEN = 50,
34  #define MODIFY_DT_MAX_LEN 50  };
35    
36  int article_post(const SECTION_LIST *p_section, ARTICLE *p_article_new)  int article_post(const SECTION_LIST *p_section, ARTICLE *p_article_new)
37  {  {
# Line 52  int article_post(const SECTION_LIST *p_s Line 49  int article_post(const SECTION_LIST *p_s
49          int content_display_length;          int content_display_length;
50          char nickname_f[BBS_nickname_max_len * 2 + 1];          char nickname_f[BBS_nickname_max_len * 2 + 1];
51          int sign_id = 0;          int sign_id = 0;
52            int reply_note = 1;
53          long len;          long len;
54          int ch;          int ch;
55          char *p, *q;          char *p, *q;
# Line 59  int article_post(const SECTION_LIST *p_s Line 57  int article_post(const SECTION_LIST *p_s
57    
58          if (p_section == NULL || p_article_new == NULL)          if (p_section == NULL || p_article_new == NULL)
59          {          {
60                  log_error("NULL pointer error\n");                  log_error("NULL pointer error");
61          }          }
62    
63          if (!checkpriv(&BBS_priv, p_section->sid, S_POST))          if (!checkpriv(&BBS_priv, p_section->sid, S_POST))
# Line 79  int article_post(const SECTION_LIST *p_s Line 77  int article_post(const SECTION_LIST *p_s
77          p_editor_data = editor_data_load("");          p_editor_data = editor_data_load("");
78          if (p_editor_data == NULL)          if (p_editor_data == NULL)
79          {          {
80                  log_error("editor_data_load() error\n");                  log_error("editor_data_load() error");
81                  ret = -1;                  ret = -1;
82                  goto cleanup;                  goto cleanup;
83          }          }
# Line 89  int article_post(const SECTION_LIST *p_s Line 87  int article_post(const SECTION_LIST *p_s
87          {          {
88                  clearscr();                  clearscr();
89                  moveto(21, 1);                  moveto(21, 1);
90                  prints("发表文章于 %s[%s] 讨论区,类型: %s", p_section->stitle, p_section->sname, (p_article_new->transship ? "转载" : "原创"));                  prints("发表文章于 %s[%s] 讨论区,类型: %s,回复通知: %s",
91                               p_section->stitle, p_section->sname,
92                               (p_article_new->transship ? "转载" : "原创"),
93                               (reply_note ? "开启" : "关闭"));
94                  moveto(22, 1);                  moveto(22, 1);
95                  prints("标题: %s", (p_article_new->title[0] == '\0' ? "[无]" : p_article_new->title));                  prints("标题: %s", (p_article_new->title[0] == '\0' ? "[无]" : p_article_new->title));
96                  moveto(23, 1);                  moveto(23, 1);
# Line 100  int article_post(const SECTION_LIST *p_s Line 101  int article_post(const SECTION_LIST *p_s
101                          prints("    按0~3选签名档(0表示不使用)");                          prints("    按0~3选签名档(0表示不使用)");
102    
103                          moveto(24, 1);                          moveto(24, 1);
104                          prints("T改标题, C取消, Z设为转载, Y设为原创, Enter继续: ");                          prints("T改标题, C取消, Z设为%s, N%s, Enter继续: ",
105                                       (p_article_new->transship ? "原创" : "转载"),
106                                       (reply_note ? "关闭回复通知" : "开启回复通知"));
107                          iflush();                          iflush();
108                          ch = 0;                          ch = 0;
109                  }                  }
110    
111                  for (; !SYS_server_exit; ch = igetch_t(MAX_DELAY_TIME))                  while (!SYS_server_exit)
112                  {                  {
113                          switch (toupper(ch))                          switch (toupper(ch))
114                          {                          {
# Line 113  int article_post(const SECTION_LIST *p_s Line 116  int article_post(const SECTION_LIST *p_s
116                          case KEY_TIMEOUT:                          case KEY_TIMEOUT:
117                                  goto cleanup;                                  goto cleanup;
118                          case CR:                          case CR:
                                 igetch_reset();  
119                                  break;                                  break;
120                          case 'T':                          case 'T':
                                 moveto(24, 1);  
                                 clrtoeol();  
121                                  len = get_data(24, 1, "标题: ", title_input, sizeof(title_input), TITLE_INPUT_MAX_LEN);                                  len = get_data(24, 1, "标题: ", title_input, sizeof(title_input), TITLE_INPUT_MAX_LEN);
122                                  for (p = title_input; *p == ' '; p++)                                  for (p = title_input; *p == ' '; p++)
123                                          ;                                          ;
# Line 127  int article_post(const SECTION_LIST *p_s Line 127  int article_post(const SECTION_LIST *p_s
127                                  len = q - p;                                  len = q - p;
128                                  if (*p != '\0')                                  if (*p != '\0')
129                                  {                                  {
130                                            if ((ret = check_badwords(p, '*')) < 0)
131                                            {
132                                                    log_error("check_badwords(title) error");
133                                            }
134                                            else if (ret > 0)
135                                            {
136                                                    memcpy(title_input, p, (size_t)len + 1);
137                                                    continue;
138                                            }
139                                          memcpy(p_article_new->title, p, (size_t)len + 1);                                          memcpy(p_article_new->title, p, (size_t)len + 1);
140                                          memcpy(title_input, p_article_new->title, (size_t)len + 1);                                          memcpy(title_input, p_article_new->title, (size_t)len + 1);
141                                  }                                  }
# Line 138  int article_post(const SECTION_LIST *p_s Line 147  int article_post(const SECTION_LIST *p_s
147                                  prints("取消...");                                  prints("取消...");
148                                  press_any_key();                                  press_any_key();
149                                  goto cleanup;                                  goto cleanup;
                         case 'Y':  
                                 p_article_new->transship = 0;  
                                 break;  
150                          case 'Z':                          case 'Z':
151                                  p_article_new->transship = 1;                                  p_article_new->transship = (p_article_new->transship ? 0 : 1);
152                                    break;
153                            case 'N':
154                                    reply_note = (reply_note ? 0 : 1);
155                                  break;                                  break;
156                          case '0':                          case '0':
157                          case '1':                          case '1':
# Line 151  int article_post(const SECTION_LIST *p_s Line 160  int article_post(const SECTION_LIST *p_s
160                                  sign_id = ch - '0';                                  sign_id = ch - '0';
161                                  break;                                  break;
162                          default: // Invalid selection                          default: // Invalid selection
163                                    ch = igetch_t(BBS_max_user_idle_time);
164                                  continue;                                  continue;
165                          }                          }
166    
# Line 171  int article_post(const SECTION_LIST *p_s Line 181  int article_post(const SECTION_LIST *p_s
181                          prints("(S)发送, (C)取消, (T)更改标题 or (E)再编辑? [S]: ");                          prints("(S)发送, (C)取消, (T)更改标题 or (E)再编辑? [S]: ");
182                          iflush();                          iflush();
183    
184                          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))
185                          {                          {
186                                  switch (toupper(ch))                                  switch (toupper(ch))
187                                  {                                  {
# Line 179  int article_post(const SECTION_LIST *p_s Line 189  int article_post(const SECTION_LIST *p_s
189                                  case KEY_TIMEOUT:                                  case KEY_TIMEOUT:
190                                          goto cleanup;                                          goto cleanup;
191                                  case CR:                                  case CR:
                                         igetch_reset();  
192                                  case 'S':                                  case 'S':
193                                          break;                                          break;
194                                  case 'C':                                  case 'C':
# Line 214  int article_post(const SECTION_LIST *p_s Line 223  int article_post(const SECTION_LIST *p_s
223          content = malloc(ARTICLE_CONTENT_MAX_LEN);          content = malloc(ARTICLE_CONTENT_MAX_LEN);
224          if (content == NULL)          if (content == NULL)
225          {          {
226                  log_error("malloc(content) error: OOM\n");                  log_error("malloc(content) error: OOM");
227                  ret = -1;                  ret = -1;
228                  goto cleanup;                  goto cleanup;
229          }          }
# Line 222  int article_post(const SECTION_LIST *p_s Line 231  int article_post(const SECTION_LIST *p_s
231          len_content = editor_data_save(p_editor_data, content, ARTICLE_CONTENT_MAX_LEN);          len_content = editor_data_save(p_editor_data, content, ARTICLE_CONTENT_MAX_LEN);
232          if (len_content < 0)          if (len_content < 0)
233          {          {
234                  log_error("editor_data_save() error\n");                  log_error("editor_data_save() error");
235                    ret = -1;
236                    goto cleanup;
237            }
238    
239            if (check_badwords(content, '*') < 0)
240            {
241                    log_error("check_badwords(content) error");
242                  ret = -1;                  ret = -1;
243                  goto cleanup;                  goto cleanup;
244          }          }
# Line 230  int article_post(const SECTION_LIST *p_s Line 246  int article_post(const SECTION_LIST *p_s
246          db = db_open();          db = db_open();
247          if (db == NULL)          if (db == NULL)
248          {          {
249                  log_error("db_open() error: %s\n", mysql_error(db));                  log_error("db_open() error: %s", mysql_error(db));
250                  ret = -1;                  ret = -1;
251                  goto cleanup;                  goto cleanup;
252          }          }
# Line 243  int article_post(const SECTION_LIST *p_s Line 259  int article_post(const SECTION_LIST *p_s
259    
260                  if (mysql_query(db, sql) != 0)                  if (mysql_query(db, sql) != 0)
261                  {                  {
262                          log_error("Query sign error: %s\n", mysql_error(db));                          log_error("Query sign error: %s", mysql_error(db));
263                          ret = -1;                          ret = -1;
264                          goto cleanup;                          goto cleanup;
265                  }                  }
266                  if ((rs = mysql_use_result(db)) == NULL)                  if ((rs = mysql_use_result(db)) == NULL)
267                  {                  {
268                          log_error("Get sign data failed\n");                          log_error("Get sign data failed");
269                          ret = -1;                          ret = -1;
270                          goto cleanup;                          goto cleanup;
271                  }                  }
# Line 270  int article_post(const SECTION_LIST *p_s Line 286  int article_post(const SECTION_LIST *p_s
286          // Begin transaction          // Begin transaction
287          if (mysql_query(db, "SET autocommit=0") != 0)          if (mysql_query(db, "SET autocommit=0") != 0)
288          {          {
289                  log_error("SET autocommit=0 error: %s\n", mysql_error(db));                  log_error("SET autocommit=0 error: %s", mysql_error(db));
290                  ret = -1;                  ret = -1;
291                  goto cleanup;                  goto cleanup;
292          }          }
293    
294          if (mysql_query(db, "BEGIN") != 0)          if (mysql_query(db, "BEGIN") != 0)
295          {          {
296                  log_error("Begin transaction error: %s\n", mysql_error(db));                  log_error("Begin transaction error: %s", mysql_error(db));
297                  ret = -1;                  ret = -1;
298                  goto cleanup;                  goto cleanup;
299          }          }
# Line 286  int article_post(const SECTION_LIST *p_s Line 302  int article_post(const SECTION_LIST *p_s
302          content_f = malloc((size_t)len_content * 2 + 1);          content_f = malloc((size_t)len_content * 2 + 1);
303          if (content_f == NULL)          if (content_f == NULL)
304          {          {
305                  log_error("malloc(content_f) error: OOM\n");                  log_error("malloc(content_f) error: OOM");
306                  ret = -1;                  ret = -1;
307                  goto cleanup;                  goto cleanup;
308          }          }
# Line 302  int article_post(const SECTION_LIST *p_s Line 318  int article_post(const SECTION_LIST *p_s
318          sql_content = malloc(SQL_BUFFER_LEN + (size_t)len_content * 2 + 1);          sql_content = malloc(SQL_BUFFER_LEN + (size_t)len_content * 2 + 1);
319          if (sql_content == NULL)          if (sql_content == NULL)
320          {          {
321                  log_error("malloc(sql_content) error: OOM\n");                  log_error("malloc(sql_content) error: OOM");
322                  ret = -1;                  ret = -1;
323                  goto cleanup;                  goto cleanup;
324          }          }
# Line 316  int article_post(const SECTION_LIST *p_s Line 332  int article_post(const SECTION_LIST *p_s
332    
333          if (mysql_query(db, sql_content) != 0)          if (mysql_query(db, sql_content) != 0)
334          {          {
335                  log_error("Add article content error: %s\n", mysql_error(db));                  log_error("Add article content error: %s", mysql_error(db));
336                  ret = -1;                  ret = -1;
337                  goto cleanup;                  goto cleanup;
338          }          }
# Line 330  int article_post(const SECTION_LIST *p_s Line 346  int article_post(const SECTION_LIST *p_s
346          snprintf(sql, sizeof(sql),          snprintf(sql, sizeof(sql),
347                           "INSERT INTO bbs(SID, TID, UID, username, nickname, title, CID, transship, "                           "INSERT INTO bbs(SID, TID, UID, username, nickname, title, CID, transship, "
348                           "sub_dt, sub_ip, reply_note, exp, last_reply_dt, icon, length) "                           "sub_dt, sub_ip, reply_note, exp, last_reply_dt, icon, length) "
349                           "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)",
350                           p_section->sid, BBS_priv.uid, BBS_username, nickname_f, title_f,                           p_section->sid, BBS_priv.uid, BBS_username, nickname_f, title_f,
351                           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,
352                             reply_note, BBS_user_exp, content_display_length);
353    
354          if (mysql_query(db, sql) != 0)          if (mysql_query(db, sql) != 0)
355          {          {
356                  log_error("Add article error: %s\n", mysql_error(db));                  log_error("Add article error: %s", mysql_error(db));
357                  ret = -1;                  ret = -1;
358                  goto cleanup;                  goto cleanup;
359          }          }
# Line 350  int article_post(const SECTION_LIST *p_s Line 367  int article_post(const SECTION_LIST *p_s
367    
368          if (mysql_query(db, sql) != 0)          if (mysql_query(db, sql) != 0)
369          {          {
370                  log_error("Update content error: %s\n", mysql_error(db));                  log_error("Update content error: %s", mysql_error(db));
371                  ret = -1;                  ret = -1;
372                  goto cleanup;                  goto cleanup;
373          }          }
# Line 364  int article_post(const SECTION_LIST *p_s Line 381  int article_post(const SECTION_LIST *p_s
381    
382                  if (mysql_query(db, sql) != 0)                  if (mysql_query(db, sql) != 0)
383                  {                  {
384                          log_error("Update exp error: %s\n", mysql_error(db));                          log_error("Update exp error: %s", mysql_error(db));
385                          ret = -1;                          ret = -1;
386                          goto cleanup;                          goto cleanup;
387                  }                  }
# Line 378  int article_post(const SECTION_LIST *p_s Line 395  int article_post(const SECTION_LIST *p_s
395    
396          if (mysql_query(db, sql) != 0)          if (mysql_query(db, sql) != 0)
397          {          {
398                  log_error("Add log error: %s\n", mysql_error(db));                  log_error("Add log error: %s", mysql_error(db));
399                  ret = -1;                  ret = -1;
400                  goto cleanup;                  goto cleanup;
401          }          }
# Line 386  int article_post(const SECTION_LIST *p_s Line 403  int article_post(const SECTION_LIST *p_s
403          // Commit transaction          // Commit transaction
404          if (mysql_query(db, "COMMIT") != 0)          if (mysql_query(db, "COMMIT") != 0)
405          {          {
406                  log_error("Commit transaction error: %s\n", mysql_error(db));                  log_error("Commit transaction error: %s", mysql_error(db));
407                  ret = -1;                  ret = -1;
408                  goto cleanup;                  goto cleanup;
409          }          }
# Line 424  int article_modify(const SECTION_LIST *p Line 441  int article_modify(const SECTION_LIST *p
441          char *content_f = NULL;          char *content_f = NULL;
442          long len_content;          long len_content;
443          int content_display_length;          int content_display_length;
444            int reply_note = 1;
445          int ch;          int ch;
446          long ret = 0;          long ret = 0;
447          time_t now;          time_t now;
# Line 434  int article_modify(const SECTION_LIST *p Line 452  int article_modify(const SECTION_LIST *p
452    
453          if (p_section == NULL || p_article == NULL)          if (p_section == NULL || p_article == NULL)
454          {          {
455                  log_error("NULL pointer error\n");                  log_error("NULL pointer error");
456          }          }
457    
458          if (p_article->excerption) // Modify is not allowed          if (p_article->excerption) // Modify is not allowed
# Line 450  int article_modify(const SECTION_LIST *p Line 468  int article_modify(const SECTION_LIST *p
468          db = db_open();          db = db_open();
469          if (db == NULL)          if (db == NULL)
470          {          {
471                  log_error("db_open() error: %s\n", mysql_error(db));                  log_error("db_open() error: %s", mysql_error(db));
472                  ret = -1;                  ret = -1;
473                  goto cleanup;                  goto cleanup;
474          }          }
475    
476          snprintf(sql, sizeof(sql),          snprintf(sql, sizeof(sql),
477                           "SELECT bbs_content.CID, bbs_content.content "                           "SELECT bbs_content.CID, bbs_content.content, reply_note "
478                           "FROM bbs INNER JOIN bbs_content ON bbs.CID = bbs_content.CID "                           "FROM bbs INNER JOIN bbs_content ON bbs.CID = bbs_content.CID "
479                           "WHERE bbs.AID = %d",                           "WHERE bbs.AID = %d",
480                           p_article->aid);                           p_article->aid);
481    
482          if (mysql_query(db, sql) != 0)          if (mysql_query(db, sql) != 0)
483          {          {
484                  log_error("Query article content error: %s\n", mysql_error(db));                  log_error("Query article content error: %s", mysql_error(db));
485                  ret = -1;                  ret = -1;
486                  goto cleanup;                  goto cleanup;
487          }          }
488          if ((rs = mysql_use_result(db)) == NULL)          if ((rs = mysql_use_result(db)) == NULL)
489          {          {
490                  log_error("Get article content data failed\n");                  log_error("Get article content data failed");
491                  ret = -1;                  ret = -1;
492                  goto cleanup;                  goto cleanup;
493          }          }
# Line 479  int article_modify(const SECTION_LIST *p Line 497  int article_modify(const SECTION_LIST *p
497                  content = malloc(ARTICLE_CONTENT_MAX_LEN);                  content = malloc(ARTICLE_CONTENT_MAX_LEN);
498                  if (content == NULL)                  if (content == NULL)
499                  {                  {
500                          log_error("malloc(content) error: OOM\n");                          log_error("malloc(content) error: OOM");
501                          ret = -1;                          ret = -1;
502                          goto cleanup;                          goto cleanup;
503                  }                  }
# Line 493  int article_modify(const SECTION_LIST *p Line 511  int article_modify(const SECTION_LIST *p
511                  p_editor_data = editor_data_load(content);                  p_editor_data = editor_data_load(content);
512                  if (p_editor_data == NULL)                  if (p_editor_data == NULL)
513                  {                  {
514                          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]));
515                          ret = -1;                          ret = -1;
516                          goto cleanup;                          goto cleanup;
517                  }                  }
518    
519                  free(content);                  free(content);
520                  content = NULL;                  content = NULL;
521    
522                    reply_note = atoi(row[2]);
523          }          }
524          mysql_free_result(rs);          mysql_free_result(rs);
525          rs = NULL;          rs = NULL;
# Line 511  int article_modify(const SECTION_LIST *p Line 531  int article_modify(const SECTION_LIST *p
531          {          {
532                  editor_display(p_editor_data);                  editor_display(p_editor_data);
533    
534                  clearscr();                  while (!SYS_server_exit)
                 moveto(1, 1);  
                 prints("(S)保存, (C)取消 or (E)再编辑? [S]: ");  
                 iflush();  
   
                 for (ch = 0; !SYS_server_exit; ch = igetch_t(MAX_DELAY_TIME))  
535                  {                  {
536                            clearscr();
537                            moveto(1, 1);
538                            prints("(S)保存, (C)取消, (N)%s回复通知 or (E)再编辑? [S]: ",
539                                       (reply_note ? "关闭" : "开启"));
540                            iflush();
541    
542                            ch = igetch_t(BBS_max_user_idle_time);
543                          switch (toupper(ch))                          switch (toupper(ch))
544                          {                          {
545                          case KEY_NULL:                          case KEY_NULL:
546                          case KEY_TIMEOUT:                          case KEY_TIMEOUT:
547                                  goto cleanup;                                  goto cleanup;
548                          case CR:                          case CR:
                                 igetch_reset();  
549                          case 'S':                          case 'S':
550                                  break;                                  break;
551                          case 'C':                          case 'C':
# Line 533  int article_modify(const SECTION_LIST *p Line 554  int article_modify(const SECTION_LIST *p
554                                  prints("取消...");                                  prints("取消...");
555                                  press_any_key();                                  press_any_key();
556                                  goto cleanup;                                  goto cleanup;
557                            case 'N':
558                                    reply_note = (reply_note ? 0 : 1);
559                                    continue;
560                          case 'E':                          case 'E':
561                                  break;                                  break;
562                          default: // Invalid selection                          default: // Invalid selection
# Line 552  int article_modify(const SECTION_LIST *p Line 576  int article_modify(const SECTION_LIST *p
576          content = malloc(ARTICLE_CONTENT_MAX_LEN);          content = malloc(ARTICLE_CONTENT_MAX_LEN);
577          if (content == NULL)          if (content == NULL)
578          {          {
579                  log_error("malloc(content) error: OOM\n");                  log_error("malloc(content) error: OOM");
580                  ret = -1;                  ret = -1;
581                  goto cleanup;                  goto cleanup;
582          }          }
# Line 560  int article_modify(const SECTION_LIST *p Line 584  int article_modify(const SECTION_LIST *p
584          len_content = editor_data_save(p_editor_data, content, ARTICLE_CONTENT_MAX_LEN - LINE_BUFFER_LEN);          len_content = editor_data_save(p_editor_data, content, ARTICLE_CONTENT_MAX_LEN - LINE_BUFFER_LEN);
585          if (len_content < 0)          if (len_content < 0)
586          {          {
587                  log_error("editor_data_save() error\n");                  log_error("editor_data_save() error");
588                    ret = -1;
589                    goto cleanup;
590            }
591    
592            if (check_badwords(content, '*') < 0)
593            {
594                    log_error("check_badwords(content) error");
595                  ret = -1;                  ret = -1;
596                  goto cleanup;                  goto cleanup;
597          }          }
# Line 579  int article_modify(const SECTION_LIST *p Line 610  int article_modify(const SECTION_LIST *p
610          db = db_open();          db = db_open();
611          if (db == NULL)          if (db == NULL)
612          {          {
613                  log_error("db_open() error: %s\n", mysql_error(db));                  log_error("db_open() error: %s", mysql_error(db));
614                  ret = -1;                  ret = -1;
615                  goto cleanup;                  goto cleanup;
616          }          }
# Line 587  int article_modify(const SECTION_LIST *p Line 618  int article_modify(const SECTION_LIST *p
618          // Begin transaction          // Begin transaction
619          if (mysql_query(db, "SET autocommit=0") != 0)          if (mysql_query(db, "SET autocommit=0") != 0)
620          {          {
621                  log_error("SET autocommit=0 error: %s\n", mysql_error(db));                  log_error("SET autocommit=0 error: %s", mysql_error(db));
622                  ret = -1;                  ret = -1;
623                  goto cleanup;                  goto cleanup;
624          }          }
625    
626          if (mysql_query(db, "BEGIN") != 0)          if (mysql_query(db, "BEGIN") != 0)
627          {          {
628                  log_error("Begin transaction error: %s\n", mysql_error(db));                  log_error("Begin transaction error: %s", mysql_error(db));
629                  ret = -1;                  ret = -1;
630                  goto cleanup;                  goto cleanup;
631          }          }
# Line 603  int article_modify(const SECTION_LIST *p Line 634  int article_modify(const SECTION_LIST *p
634          content_f = malloc((size_t)len_content * 2 + 1);          content_f = malloc((size_t)len_content * 2 + 1);
635          if (content_f == NULL)          if (content_f == NULL)
636          {          {
637                  log_error("malloc(content_f) error: OOM\n");                  log_error("malloc(content_f) error: OOM");
638                  ret = -1;                  ret = -1;
639                  goto cleanup;                  goto cleanup;
640          }          }
# Line 617  int article_modify(const SECTION_LIST *p Line 648  int article_modify(const SECTION_LIST *p
648          sql_content = malloc(SQL_BUFFER_LEN + (size_t)len_content * 2 + 1);          sql_content = malloc(SQL_BUFFER_LEN + (size_t)len_content * 2 + 1);
649          if (sql_content == NULL)          if (sql_content == NULL)
650          {          {
651                  log_error("malloc(sql_content) error: OOM\n");                  log_error("malloc(sql_content) error: OOM");
652                  ret = -1;                  ret = -1;
653                  goto cleanup;                  goto cleanup;
654          }          }
# Line 631  int article_modify(const SECTION_LIST *p Line 662  int article_modify(const SECTION_LIST *p
662    
663          if (mysql_query(db, sql_content) != 0)          if (mysql_query(db, sql_content) != 0)
664          {          {
665                  log_error("Add article content error: %s\n", mysql_error(db));                  log_error("Add article content error: %s", mysql_error(db));
666                  ret = -1;                  ret = -1;
667                  goto cleanup;                  goto cleanup;
668          }          }
# Line 643  int article_modify(const SECTION_LIST *p Line 674  int article_modify(const SECTION_LIST *p
674    
675          // Update article          // Update article
676          snprintf(sql, sizeof(sql),          snprintf(sql, sizeof(sql),
677                           "UPDATE bbs SET CID = %d, length = %d, excerption = 0 WHERE AID = %d", // Set excerption = 0 explictly in case of rare condition                           "UPDATE bbs SET CID = %d, length = %d, reply_note = %d, excerption = 0 WHERE AID = %d", // Set excerption = 0 explictly in case of rare condition
678                           p_article_new->cid, content_display_length, p_article->aid);                           p_article_new->cid, content_display_length, reply_note, p_article->aid);
679    
680          if (mysql_query(db, sql) != 0)          if (mysql_query(db, sql) != 0)
681          {          {
682                  log_error("Add article error: %s\n", mysql_error(db));                  log_error("Add article error: %s", mysql_error(db));
683                  ret = -1;                  ret = -1;
684                  goto cleanup;                  goto cleanup;
685          }          }
686    
687          if (mysql_query(db, sql) != 0)          if (mysql_query(db, sql) != 0)
688          {          {
689                  log_error("Update content error: %s\n", mysql_error(db));                  log_error("Update content error: %s", mysql_error(db));
690                  ret = -1;                  ret = -1;
691                  goto cleanup;                  goto cleanup;
692          }          }
# Line 668  int article_modify(const SECTION_LIST *p Line 699  int article_modify(const SECTION_LIST *p
699    
700          if (mysql_query(db, sql) != 0)          if (mysql_query(db, sql) != 0)
701          {          {
702                  log_error("Add log error: %s\n", mysql_error(db));                  log_error("Add log error: %s", mysql_error(db));
703                  ret = -1;                  ret = -1;
704                  goto cleanup;                  goto cleanup;
705          }          }
# Line 676  int article_modify(const SECTION_LIST *p Line 707  int article_modify(const SECTION_LIST *p
707          // Commit transaction          // Commit transaction
708          if (mysql_query(db, "COMMIT") != 0)          if (mysql_query(db, "COMMIT") != 0)
709          {          {
710                  log_error("Commit transaction error: %s\n", mysql_error(db));                  log_error("Commit transaction error: %s", mysql_error(db));
711                  ret = -1;                  ret = -1;
712                  goto cleanup;                  goto cleanup;
713          }          }
# Line 709  int article_reply(const SECTION_LIST *p_ Line 740  int article_reply(const SECTION_LIST *p_
740          MYSQL *db = NULL;          MYSQL *db = NULL;
741          MYSQL_RES *rs = NULL;          MYSQL_RES *rs = NULL;
742          MYSQL_ROW row;          MYSQL_ROW row;
743          long line_offsets[ARTICLE_QUOTE_MAX_LINES + 1];          long line_offsets[MAX_EDITOR_DATA_LINES + 1];
744          char sql[SQL_BUFFER_LEN];          char sql[SQL_BUFFER_LEN];
745          char *sql_content = NULL;          char *sql_content = NULL;
746          EDITOR_DATA *p_editor_data = NULL;          EDITOR_DATA *p_editor_data = NULL;
# Line 721  int article_reply(const SECTION_LIST *p_ Line 752  int article_reply(const SECTION_LIST *p_
752          int content_display_length;          int content_display_length;
753          char nickname_f[BBS_nickname_max_len * 2 + 1];          char nickname_f[BBS_nickname_max_len * 2 + 1];
754          int sign_id = 0;          int sign_id = 0;
755            int reply_note = 0;
756            int full_quote = 0;
757          long len;          long len;
758          int ch;          int ch;
759          char *p, *q;          char *p, *q;
# Line 730  int article_reply(const SECTION_LIST *p_ Line 763  int article_reply(const SECTION_LIST *p_
763          long i;          long i;
764          long ret = 0;          long ret = 0;
765          int topic_locked = 0;          int topic_locked = 0;
766            char msg[BBS_msg_max_len];
767            char msg_f[BBS_msg_max_len * 2 + 1];
768            int len_msg;
769    
770          if (p_section == NULL || p_article == NULL)          if (p_section == NULL || p_article == NULL)
771          {          {
772                  log_error("NULL pointer error\n");                  log_error("NULL pointer error");
773          }          }
774    
775          if (!checkpriv(&BBS_priv, p_section->sid, S_POST))          if (!checkpriv(&BBS_priv, p_section->sid, S_POST))
# Line 754  int article_reply(const SECTION_LIST *p_ Line 790  int article_reply(const SECTION_LIST *p_
790          db = db_open();          db = db_open();
791          if (db == NULL)          if (db == NULL)
792          {          {
793                  log_error("db_open() error: %s\n", mysql_error(db));                  log_error("db_open() error: %s", mysql_error(db));
794                  ret = -1;                  ret = -1;
795                  goto cleanup;                  goto cleanup;
796          }          }
# Line 765  int article_reply(const SECTION_LIST *p_ Line 801  int article_reply(const SECTION_LIST *p_
801    
802          if (mysql_query(db, sql) != 0)          if (mysql_query(db, sql) != 0)
803          {          {
804                  log_error("Query article status error: %s\n", mysql_error(db));                  log_error("Query article status error: %s", mysql_error(db));
805                  ret = -1;                  ret = -1;
806                  goto cleanup;                  goto cleanup;
807          }          }
808          if ((rs = mysql_store_result(db)) == NULL)          if ((rs = mysql_store_result(db)) == NULL)
809          {          {
810                  log_error("Get article status data failed\n");                  log_error("Get article status data failed");
811                  ret = -1;                  ret = -1;
812                  goto cleanup;                  goto cleanup;
813          }          }
# Line 807  int article_reply(const SECTION_LIST *p_ Line 843  int article_reply(const SECTION_LIST *p_
843    
844          if (mysql_query(db, sql) != 0)          if (mysql_query(db, sql) != 0)
845          {          {
846                  log_error("Query article content error: %s\n", mysql_error(db));                  log_error("Query article content error: %s", mysql_error(db));
847                  ret = -1;                  ret = -1;
848                  goto cleanup;                  goto cleanup;
849          }          }
850          if ((rs = mysql_use_result(db)) == NULL)          if ((rs = mysql_use_result(db)) == NULL)
851          {          {
852                  log_error("Get article content data failed\n");                  log_error("Get article content data failed");
853                  ret = -1;                  ret = -1;
854                  goto cleanup;                  goto cleanup;
855          }          }
# Line 823  int article_reply(const SECTION_LIST *p_ Line 859  int article_reply(const SECTION_LIST *p_
859                  content = malloc(ARTICLE_CONTENT_MAX_LEN);                  content = malloc(ARTICLE_CONTENT_MAX_LEN);
860                  if (content == NULL)                  if (content == NULL)
861                  {                  {
862                          log_error("malloc(content) error: OOM\n");                          log_error("malloc(content) error: OOM");
863                          ret = -1;                          ret = -1;
864                          goto cleanup;                          goto cleanup;
865                  }                  }
# Line 831  int article_reply(const SECTION_LIST *p_ Line 867  int article_reply(const SECTION_LIST *p_
867                  content_f = malloc(ARTICLE_CONTENT_MAX_LEN);                  content_f = malloc(ARTICLE_CONTENT_MAX_LEN);
868                  if (content_f == NULL)                  if (content_f == NULL)
869                  {                  {
870                          log_error("malloc(content_f) error: OOM\n");                          log_error("malloc(content_f) error: OOM");
871                          ret = -1;                          ret = -1;
872                          goto cleanup;                          goto cleanup;
873                  }                  }
874    
875                  // Apply LML render to content body                  // Apply LML render to content body
876                  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);
877                  content_f[len] = '\0';                  content_f[len] = '\0';
878    
879                  // Remove control sequence                  // Remove control sequence
880                  len = str_filter(content_f, 0);                  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;  
881          }          }
882          mysql_free_result(rs);          mysql_free_result(rs);
883          rs = NULL;          rs = NULL;
# Line 892  int article_reply(const SECTION_LIST *p_ Line 890  int article_reply(const SECTION_LIST *p_
890          {          {
891                  clearscr();                  clearscr();
892                  moveto(21, 1);                  moveto(21, 1);
893                  prints("回复文章于 %s[%s] 讨论区", p_section->stitle, p_section->sname);                  prints("回复文章于 %s[%s] 讨论区, 回复通知: %s, 引用模式: %s",
894                               p_section->stitle, p_section->sname,
895                               (reply_note ? "开启" : "关闭"),
896                               (full_quote ? "完整" : "精简"));
897                  moveto(22, 1);                  moveto(22, 1);
898                  prints("标题: %s", (p_article_new->title[0] == '\0' ? "[无]" : p_article_new->title));                  prints("标题: %s", (p_article_new->title[0] == '\0' ? "[无]" : p_article_new->title));
899                  moveto(23, 1);                  moveto(23, 1);
# Line 903  int article_reply(const SECTION_LIST *p_ Line 904  int article_reply(const SECTION_LIST *p_
904                          prints("    按0~3选签名档(0表示不使用)");                          prints("    按0~3选签名档(0表示不使用)");
905    
906                          moveto(24, 1);                          moveto(24, 1);
907                          prints("T改标题, C取消, Enter继续: ");                          prints("T改标题, C取消, N%s, Q%s, Enter继续: ",
908                                       (reply_note ? "关闭回复通知" : "开启回复通知"), (full_quote ? "精简引用" : "完整引用"));
909                          iflush();                          iflush();
910                          ch = 0;                          ch = 0;
911                  }                  }
912    
913                  for (; !SYS_server_exit; ch = igetch_t(MAX_DELAY_TIME))                  while (!SYS_server_exit)
914                  {                  {
915                          switch (toupper(ch))                          switch (toupper(ch))
916                          {                          {
# Line 916  int article_reply(const SECTION_LIST *p_ Line 918  int article_reply(const SECTION_LIST *p_
918                          case KEY_TIMEOUT:                          case KEY_TIMEOUT:
919                                  goto cleanup;                                  goto cleanup;
920                          case CR:                          case CR:
                                 igetch_reset();  
921                                  break;                                  break;
922                          case 'T':                          case 'T':
                                 moveto(24, 1);  
                                 clrtoeol();  
923                                  len = get_data(24, 1, "标题: ", title_input, sizeof(title_input), TITLE_INPUT_MAX_LEN);                                  len = get_data(24, 1, "标题: ", title_input, sizeof(title_input), TITLE_INPUT_MAX_LEN);
924                                  for (p = title_input; *p == ' '; p++)                                  for (p = title_input; *p == ' '; p++)
925                                          ;                                          ;
# Line 930  int article_reply(const SECTION_LIST *p_ Line 929  int article_reply(const SECTION_LIST *p_
929                                  len = q - p;                                  len = q - p;
930                                  if (*p != '\0')                                  if (*p != '\0')
931                                  {                                  {
932                                            if ((ret = check_badwords(p, '*')) < 0)
933                                            {
934                                                    log_error("check_badwords(title) error");
935                                            }
936                                            else if (ret > 0)
937                                            {
938                                                    memcpy(title_input, p, (size_t)len + 1);
939                                                    continue;
940                                            }
941                                          memcpy(p_article_new->title, p, (size_t)len + 1);                                          memcpy(p_article_new->title, p, (size_t)len + 1);
942                                          memcpy(title_input, p_article_new->title, (size_t)len + 1);                                          memcpy(title_input, p_article_new->title, (size_t)len + 1);
943                                  }                                  }
# Line 941  int article_reply(const SECTION_LIST *p_ Line 949  int article_reply(const SECTION_LIST *p_
949                                  prints("取消...");                                  prints("取消...");
950                                  press_any_key();                                  press_any_key();
951                                  goto cleanup;                                  goto cleanup;
952                            case 'N':
953                                    reply_note = (reply_note ? 0 : 1);
954                                    break;
955                            case 'Q':
956                                    full_quote = (full_quote ? 0 : 1);
957                                    break;
958                          case '0':                          case '0':
959                          case '1':                          case '1':
960                          case '2':                          case '2':
# Line 948  int article_reply(const SECTION_LIST *p_ Line 962  int article_reply(const SECTION_LIST *p_
962                                  sign_id = ch - '0';                                  sign_id = ch - '0';
963                                  break;                                  break;
964                          default: // Invalid selection                          default: // Invalid selection
965                                    ch = igetch_t(BBS_max_user_idle_time);
966                                  continue;                                  continue;
967                          }                          }
968    
# Line 959  int article_reply(const SECTION_LIST *p_ Line 974  int article_reply(const SECTION_LIST *p_
974                          continue;                          continue;
975                  }                  }
976    
977                    len = snprintf(content, ARTICLE_CONTENT_MAX_LEN,
978                                               "\n\n【 在 %s (%s) 的大作中提到: 】\n",
979                                               p_article->username, p_article->nickname);
980    
981                    quote_content_lines = split_data_lines(content_f,
982                                                                                               MAX_EDITOR_DATA_LINE_LENGTH - 2, line_offsets,
983                                                                                               (full_quote ? MAX_EDITOR_DATA_LINES : ARTICLE_QUOTE_DEFAULT_LINES) + 1,
984                                                                                               0, NULL);
985                    for (i = 0; i < quote_content_lines; i++)
986                    {
987                            memcpy(content + len, ": ", 2); // quote line prefix
988                            len += 2;
989                            memcpy(content + len, content_f + line_offsets[i], (size_t)(line_offsets[i + 1] - line_offsets[i]));
990                            len += (line_offsets[i + 1] - line_offsets[i]);
991                            if (content[len - 1] != '\n') // Appennd \n if not exist
992                            {
993                                    content[len] = '\n';
994                                    len++;
995                            }
996                    }
997                    if (content[len - 1] != '\n') // Appennd \n if not exist
998                    {
999                            content[len] = '\n';
1000                            len++;
1001                    }
1002                    content[len] = '\0';
1003    
1004                    free(content_f);
1005                    content_f = NULL;
1006    
1007                    p_editor_data = editor_data_load(content);
1008                    if (p_editor_data == NULL)
1009                    {
1010                            log_error("editor_data_load(aid=%d, cid=%d) error", p_article->aid, atoi(row[0]));
1011                            ret = -1;
1012                            goto cleanup;
1013                    }
1014    
1015                    free(content);
1016                    content = NULL;
1017    
1018                  for (ch = 'E'; !SYS_server_exit && toupper(ch) == 'E';)                  for (ch = 'E'; !SYS_server_exit && toupper(ch) == 'E';)
1019                  {                  {
1020                          editor_display(p_editor_data);                          editor_display(p_editor_data);
# Line 968  int article_reply(const SECTION_LIST *p_ Line 1024  int article_reply(const SECTION_LIST *p_
1024                          prints("(S)发送, (C)取消, (T)更改标题 or (E)再编辑? [S]: ");                          prints("(S)发送, (C)取消, (T)更改标题 or (E)再编辑? [S]: ");
1025                          iflush();                          iflush();
1026    
1027                          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))
1028                          {                          {
1029                                  switch (toupper(ch))                                  switch (toupper(ch))
1030                                  {                                  {
# Line 976  int article_reply(const SECTION_LIST *p_ Line 1032  int article_reply(const SECTION_LIST *p_
1032                                  case KEY_TIMEOUT:                                  case KEY_TIMEOUT:
1033                                          goto cleanup;                                          goto cleanup;
1034                                  case CR:                                  case CR:
                                         igetch_reset();  
1035                                  case 'S':                                  case 'S':
1036                                          break;                                          break;
1037                                  case 'C':                                  case 'C':
# Line 1011  int article_reply(const SECTION_LIST *p_ Line 1066  int article_reply(const SECTION_LIST *p_
1066          content = malloc(ARTICLE_CONTENT_MAX_LEN);          content = malloc(ARTICLE_CONTENT_MAX_LEN);
1067          if (content == NULL)          if (content == NULL)
1068          {          {
1069                  log_error("malloc(content) error: OOM\n");                  log_error("malloc(content) error: OOM");
1070                  ret = -1;                  ret = -1;
1071                  goto cleanup;                  goto cleanup;
1072          }          }
# Line 1019  int article_reply(const SECTION_LIST *p_ Line 1074  int article_reply(const SECTION_LIST *p_
1074          len_content = editor_data_save(p_editor_data, content, ARTICLE_CONTENT_MAX_LEN);          len_content = editor_data_save(p_editor_data, content, ARTICLE_CONTENT_MAX_LEN);
1075          if (len_content < 0)          if (len_content < 0)
1076          {          {
1077                  log_error("editor_data_save() error\n");                  log_error("editor_data_save() error");
1078                    ret = -1;
1079                    goto cleanup;
1080            }
1081    
1082            if (check_badwords(content, '*') < 0)
1083            {
1084                    log_error("check_badwords(content) error");
1085                  ret = -1;                  ret = -1;
1086                  goto cleanup;                  goto cleanup;
1087          }          }
# Line 1027  int article_reply(const SECTION_LIST *p_ Line 1089  int article_reply(const SECTION_LIST *p_
1089          db = db_open();          db = db_open();
1090          if (db == NULL)          if (db == NULL)
1091          {          {
1092                  log_error("db_open() error: %s\n", mysql_error(db));                  log_error("db_open() error: %s", mysql_error(db));
1093                  ret = -1;                  ret = -1;
1094                  goto cleanup;                  goto cleanup;
1095          }          }
# Line 1040  int article_reply(const SECTION_LIST *p_ Line 1102  int article_reply(const SECTION_LIST *p_
1102    
1103                  if (mysql_query(db, sql) != 0)                  if (mysql_query(db, sql) != 0)
1104                  {                  {
1105                          log_error("Query sign error: %s\n", mysql_error(db));                          log_error("Query sign error: %s", mysql_error(db));
1106                          ret = -1;                          ret = -1;
1107                          goto cleanup;                          goto cleanup;
1108                  }                  }
1109                  if ((rs = mysql_use_result(db)) == NULL)                  if ((rs = mysql_use_result(db)) == NULL)
1110                  {                  {
1111                          log_error("Get sign data failed\n");                          log_error("Get sign data failed");
1112                          ret = -1;                          ret = -1;
1113                          goto cleanup;                          goto cleanup;
1114                  }                  }
# Line 1067  int article_reply(const SECTION_LIST *p_ Line 1129  int article_reply(const SECTION_LIST *p_
1129          // Begin transaction          // Begin transaction
1130          if (mysql_query(db, "SET autocommit=0") != 0)          if (mysql_query(db, "SET autocommit=0") != 0)
1131          {          {
1132                  log_error("SET autocommit=0 error: %s\n", mysql_error(db));                  log_error("SET autocommit=0 error: %s", mysql_error(db));
1133                  ret = -1;                  ret = -1;
1134                  goto cleanup;                  goto cleanup;
1135          }          }
1136    
1137          if (mysql_query(db, "BEGIN") != 0)          if (mysql_query(db, "BEGIN") != 0)
1138          {          {
1139                  log_error("Begin transaction error: %s\n", mysql_error(db));                  log_error("Begin transaction error: %s", mysql_error(db));
1140                  ret = -1;                  ret = -1;
1141                  goto cleanup;                  goto cleanup;
1142          }          }
# Line 1083  int article_reply(const SECTION_LIST *p_ Line 1145  int article_reply(const SECTION_LIST *p_
1145          content_f = malloc((size_t)len_content * 2 + 1);          content_f = malloc((size_t)len_content * 2 + 1);
1146          if (content_f == NULL)          if (content_f == NULL)
1147          {          {
1148                  log_error("malloc(content_f) error: OOM\n");                  log_error("malloc(content_f) error: OOM");
1149                  ret = -1;                  ret = -1;
1150                  goto cleanup;                  goto cleanup;
1151          }          }
# Line 1099  int article_reply(const SECTION_LIST *p_ Line 1161  int article_reply(const SECTION_LIST *p_
1161          sql_content = malloc(SQL_BUFFER_LEN + (size_t)len_content * 2 + 1);          sql_content = malloc(SQL_BUFFER_LEN + (size_t)len_content * 2 + 1);
1162          if (sql_content == NULL)          if (sql_content == NULL)
1163          {          {
1164                  log_error("malloc(sql_content) error: OOM\n");                  log_error("malloc(sql_content) error: OOM");
1165                  ret = -1;                  ret = -1;
1166                  goto cleanup;                  goto cleanup;
1167          }          }
# Line 1113  int article_reply(const SECTION_LIST *p_ Line 1175  int article_reply(const SECTION_LIST *p_
1175    
1176          if (mysql_query(db, sql_content) != 0)          if (mysql_query(db, sql_content) != 0)
1177          {          {
1178                  log_error("Add article content error: %s\n", mysql_error(db));                  log_error("Add article content error: %s", mysql_error(db));
1179                  ret = -1;                  ret = -1;
1180                  goto cleanup;                  goto cleanup;
1181          }          }
# Line 1127  int article_reply(const SECTION_LIST *p_ Line 1189  int article_reply(const SECTION_LIST *p_
1189          snprintf(sql, sizeof(sql),          snprintf(sql, sizeof(sql),
1190                           "INSERT INTO bbs(SID, TID, UID, username, nickname, title, CID, transship, "                           "INSERT INTO bbs(SID, TID, UID, username, nickname, title, CID, transship, "
1191                           "sub_dt, sub_ip, reply_note, exp, last_reply_dt, icon, length) "                           "sub_dt, sub_ip, reply_note, exp, last_reply_dt, icon, length) "
1192                           "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)",
1193                           p_section->sid, (p_article->tid == 0 ? p_article->aid : p_article->tid),                           p_section->sid, (p_article->tid == 0 ? p_article->aid : p_article->tid),
1194                           BBS_priv.uid, BBS_username, nickname_f, title_f,                           BBS_priv.uid, BBS_username, nickname_f, title_f,
1195                           p_article_new->cid, hostaddr_client, BBS_user_exp, content_display_length);                           p_article_new->cid, hostaddr_client,
1196                             reply_note, BBS_user_exp, content_display_length);
1197    
1198          if (mysql_query(db, sql) != 0)          if (mysql_query(db, sql) != 0)
1199          {          {
1200                  log_error("Add article error: %s\n", mysql_error(db));                  log_error("Add article error: %s", mysql_error(db));
1201                  ret = -1;                  ret = -1;
1202                  goto cleanup;                  goto cleanup;
1203          }          }
# Line 1151  int article_reply(const SECTION_LIST *p_ Line 1214  int article_reply(const SECTION_LIST *p_
1214    
1215          if (mysql_query(db, sql) != 0)          if (mysql_query(db, sql) != 0)
1216          {          {
1217                  log_error("Update topic article error: %s\n", mysql_error(db));                  log_error("Update topic article error: %s", mysql_error(db));
1218                  ret = -1;                  ret = -1;
1219                  goto cleanup;                  goto cleanup;
1220          }          }
# Line 1163  int article_reply(const SECTION_LIST *p_ Line 1226  int article_reply(const SECTION_LIST *p_
1226    
1227          if (mysql_query(db, sql) != 0)          if (mysql_query(db, sql) != 0)
1228          {          {
1229                  log_error("Update content error: %s\n", mysql_error(db));                  log_error("Update content error: %s", mysql_error(db));
1230                    ret = -1;
1231                    goto cleanup;
1232            }
1233    
1234            // Notify the authors of the topic / article which is replyed.
1235            snprintf(sql, sizeof(sql),
1236                             "SELECT DISTINCT UID FROM bbs WHERE (AID = %d OR AID = %d) "
1237                             "AND visible AND reply_note AND UID <> %d",
1238                             p_article->tid, p_article->aid, BBS_priv.uid);
1239    
1240            if (mysql_query(db, sql) != 0)
1241            {
1242                    log_error("Read reply info error: %s", mysql_error(db));
1243                    ret = -1;
1244                    goto cleanup;
1245            }
1246            if ((rs = mysql_store_result(db)) == NULL)
1247            {
1248                    log_error("Get reply info failed");
1249                  ret = -1;                  ret = -1;
1250                  goto cleanup;                  goto cleanup;
1251          }          }
1252    
1253            while ((row = mysql_fetch_row(rs)))
1254            {
1255                    // Send notification message
1256                    len_msg = snprintf(msg, BBS_msg_max_len,
1257                                                       "有人回复了您所发表/回复的文章,快来"
1258                                                       "[article %d]看看[/article]《%s》吧!\n",
1259                                                       p_article_new->aid, title_f);
1260    
1261                    mysql_real_escape_string(db, msg_f, msg, (unsigned long)len_msg);
1262    
1263                    snprintf(sql, sizeof(sql),
1264                                     "INSERT INTO bbs_msg(fromUID, toUID, content, send_dt, send_ip) "
1265                                     "VALUES(%d, %d, '%s', NOW(), '%s')",
1266                                     BBS_sys_id, atoi(row[0]), msg_f, hostaddr_client);
1267    
1268                    if (mysql_query(db, sql) != 0)
1269                    {
1270                            log_error("Insert msg error: %s", mysql_error(db));
1271                            ret = -1;
1272                            goto cleanup;
1273                    }
1274            }
1275            mysql_free_result(rs);
1276            rs = NULL;
1277    
1278          // Add exp          // Add exp
1279          if (checkpriv(&BBS_priv, p_section->sid, S_GETEXP)) // Except in test section          if (checkpriv(&BBS_priv, p_section->sid, S_GETEXP)) // Except in test section
1280          {          {
# Line 1177  int article_reply(const SECTION_LIST *p_ Line 1284  int article_reply(const SECTION_LIST *p_
1284    
1285                  if (mysql_query(db, sql) != 0)                  if (mysql_query(db, sql) != 0)
1286                  {                  {
1287                          log_error("Update exp error: %s\n", mysql_error(db));                          log_error("Update exp error: %s", mysql_error(db));
1288                          ret = -1;                          ret = -1;
1289                          goto cleanup;                          goto cleanup;
1290                  }                  }
# Line 1191  int article_reply(const SECTION_LIST *p_ Line 1298  int article_reply(const SECTION_LIST *p_
1298    
1299          if (mysql_query(db, sql) != 0)          if (mysql_query(db, sql) != 0)
1300          {          {
1301                  log_error("Add log error: %s\n", mysql_error(db));                  log_error("Add log error: %s", mysql_error(db));
1302                  ret = -1;                  ret = -1;
1303                  goto cleanup;                  goto cleanup;
1304          }          }
# Line 1199  int article_reply(const SECTION_LIST *p_ Line 1306  int article_reply(const SECTION_LIST *p_
1306          // Commit transaction          // Commit transaction
1307          if (mysql_query(db, "COMMIT") != 0)          if (mysql_query(db, "COMMIT") != 0)
1308          {          {
1309                  log_error("Commit transaction error: %s\n", mysql_error(db));                  log_error("Commit transaction error: %s", mysql_error(db));
1310                  ret = -1;                  ret = -1;
1311                  goto cleanup;                  goto cleanup;
1312          }          }


Legend:
Removed lines/characters  
Changed lines/characters
  Added lines/characters

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1