/[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.16 by sysadm, Sun Jun 15 03:16:44 2025 UTC Revision 1.30 by sysadm, Fri Oct 10 04:33:40 2025 UTC
# Line 14  Line 14 
14   *                                                                         *   *                                                                         *
15   ***************************************************************************/   ***************************************************************************/
16    
 #define _POSIX_C_SOURCE 200809L  
   
 #include "article_post.h"  
17  #include "article_cache.h"  #include "article_cache.h"
18  #include "editor.h"  #include "article_post.h"
 #include "screen.h"  
19  #include "bbs.h"  #include "bbs.h"
20  #include "log.h"  #include "database.h"
21    #include "editor.h"
22  #include "io.h"  #include "io.h"
23    #include "log.h"
24  #include "lml.h"  #include "lml.h"
25  #include "database.h"  #include "screen.h"
26  #include "user_priv.h"  #include "user_priv.h"
27  #include <ctype.h>  #include <ctype.h>
28  #include <string.h>  #include <string.h>
29  #include <stdlib.h>  #include <stdlib.h>
30  #include <time.h>  #include <time.h>
31    
32  #define TITLE_INPUT_MAX_LEN 74  #define TITLE_INPUT_MAX_LEN 72
33  #define ARTICLE_CONTENT_MAX_LEN 1024 * 1024 * 4 // 4MB  #define ARTICLE_CONTENT_MAX_LEN 1024 * 1024 * 4 // 4MB
34  #define ARTICLE_QUOTE_MAX_LINES 20  #define ARTICLE_QUOTE_MAX_LINES 20
35  #define ARTICLE_QUOTE_LINE_MAX_LEN 76  #define ARTICLE_QUOTE_LINE_MAX_LEN 76
# Line 46  int article_post(const SECTION_LIST *p_s Line 44  int article_post(const SECTION_LIST *p_s
44          char sql[SQL_BUFFER_LEN];          char sql[SQL_BUFFER_LEN];
45          char *sql_content = NULL;          char *sql_content = NULL;
46          EDITOR_DATA *p_editor_data = NULL;          EDITOR_DATA *p_editor_data = NULL;
47          char title_input[TITLE_INPUT_MAX_LEN + 1];          char title_input[BBS_article_title_max_len + 1];
48          char title_f[BBS_article_title_max_len * 2 + 1];          char title_f[BBS_article_title_max_len * 2 + 1];
49          char *content = NULL;          char *content = NULL;
50          char *content_f = NULL;          char *content_f = NULL;
51          long len_content;          long len_content;
52            int content_display_length;
53          char nickname_f[BBS_nickname_max_len * 2 + 1];          char nickname_f[BBS_nickname_max_len * 2 + 1];
54          int sign_id = 0;          int sign_id = 0;
55            int reply_note = 1;
56          long len;          long len;
57          int ch;          int ch;
58          char *p, *q;          char *p, *q;
# Line 67  int article_post(const SECTION_LIST *p_s Line 67  int article_post(const SECTION_LIST *p_s
67          {          {
68                  clearscr();                  clearscr();
69                  moveto(1, 1);                  moveto(1, 1);
70                  prints("您没有权限在本版块发表文章\n");                  prints("鎮ㄦ病鏈夋潈闄愬湪鏈増鍧楀彂琛ㄦ枃绔燶n");
71                  press_any_key();                  press_any_key();
72    
73                  return 0;                  return 0;
# Line 90  int article_post(const SECTION_LIST *p_s Line 90  int article_post(const SECTION_LIST *p_s
90          {          {
91                  clearscr();                  clearscr();
92                  moveto(21, 1);                  moveto(21, 1);
93                  prints("发表文章于 %s[%s] 讨论区,类型: %s", p_section->stitle, p_section->sname, (p_article_new->transship ? "转载" : "原创"));                  prints("鍙戣〃鏂囩珷浜 %s[%s] 璁ㄨ鍖猴紝绫诲瀷: %s锛岄氱煡锛%s",
94                               p_section->stitle, p_section->sname,
95                               (p_article_new->transship ? "杞浇" : "鍘熷垱"),
96                               (reply_note ? "寮鍚" : "鍏抽棴"));
97                  moveto(22, 1);                  moveto(22, 1);
98                  prints("标题: %s", (p_article_new->title[0] == '\0' ? "[无]" : p_article_new->title));                  prints("鏍囬: %s", (p_article_new->title[0] == '\0' ? "[鏃燷" : p_article_new->title));
99                  moveto(23, 1);                  moveto(23, 1);
100                  prints("使用第 %d 个签名", sign_id);                  prints("浣跨敤绗 %d 涓鍚", sign_id);
101    
102                  if (toupper(ch) != 'T')                  if (toupper(ch) != 'T')
103                  {                  {
104                          prints("    按0~3选签名档(0表示不使用)");                          prints("    鎸0~3閫夌鍚嶆。(0琛ㄧず涓嶄娇鐢)");
105    
106                          moveto(24, 1);                          moveto(24, 1);
107                          prints("T改标题, C取消, Z设为转载, Y设为原创, Enter继续: ");                          prints("T鏀规爣棰, C鍙栨秷, Z璁句负%s, N%s, Enter缁х画: ",
108                                       (p_article_new->transship ? "鍘熷垱" : "杞浇"),
109                                       (reply_note ? "閫氱煡鍏抽棴" : "閫氱煡寮鍚"));
110                          iflush();                          iflush();
111                          ch = 0;                          ch = 0;
112                  }                  }
# Line 110  int article_post(const SECTION_LIST *p_s Line 115  int article_post(const SECTION_LIST *p_s
115                  {                  {
116                          switch (toupper(ch))                          switch (toupper(ch))
117                          {                          {
118                            case KEY_NULL:
119                            case KEY_TIMEOUT:
120                                    goto cleanup;
121                          case CR:                          case CR:
122                                  igetch_reset();                                  igetch_reset();
123                                  break;                                  break;
124                          case 'T':                          case 'T':
125                                  moveto(24, 1);                                  len = get_data(24, 1, "鏍囬: ", title_input, sizeof(title_input), TITLE_INPUT_MAX_LEN);
                                 clrtoeol();  
                                 len = get_data(24, 1, "标题: ", title_input, TITLE_INPUT_MAX_LEN, 1);  
126                                  for (p = title_input; *p == ' '; p++)                                  for (p = title_input; *p == ' '; p++)
127                                          ;                                          ;
128                                  for (q = title_input + len; q > p && *(q - 1) == ' '; q--)                                  for (q = title_input + len; q > p && *(q - 1) == ' '; q--)
# Line 133  int article_post(const SECTION_LIST *p_s Line 139  int article_post(const SECTION_LIST *p_s
139                          case 'C':                          case 'C':
140                                  clearscr();                                  clearscr();
141                                  moveto(1, 1);                                  moveto(1, 1);
142                                  prints("取消...");                                  prints("鍙栨秷...");
143                                  press_any_key();                                  press_any_key();
144                                  goto cleanup;                                  goto cleanup;
                         case 'Y':  
                                 p_article_new->transship = 0;  
                                 break;  
145                          case 'Z':                          case 'Z':
146                                  p_article_new->transship = 1;                                  p_article_new->transship = (p_article_new->transship ? 0 : 1);
147                                    break;
148                            case 'N':
149                                    reply_note = (reply_note ? 0 : 1);
150                                  break;                                  break;
151                          case '0':                          case '0':
152                          case '1':                          case '1':
# Line 166  int article_post(const SECTION_LIST *p_s Line 172  int article_post(const SECTION_LIST *p_s
172    
173                          clearscr();                          clearscr();
174                          moveto(1, 1);                          moveto(1, 1);
175                          prints("(S)发送, (C)取消, (T)更改标题 or (E)再编辑? [S]: ");                          prints("(S)鍙戦, (C)鍙栨秷, (T)鏇存敼鏍囬 or (E)鍐嶇紪杈? [S]: ");
176                          iflush();                          iflush();
177    
178                          for (ch = 0; !SYS_server_exit; ch = igetch_t(MAX_DELAY_TIME))                          for (ch = 0; !SYS_server_exit; ch = igetch_t(MAX_DELAY_TIME))
179                          {                          {
180                                  switch (toupper(ch))                                  switch (toupper(ch))
181                                  {                                  {
182                                    case KEY_NULL:
183                                    case KEY_TIMEOUT:
184                                            goto cleanup;
185                                  case CR:                                  case CR:
186                                          igetch_reset();                                          igetch_reset();
187                                  case 'S':                                  case 'S':
# Line 180  int article_post(const SECTION_LIST *p_s Line 189  int article_post(const SECTION_LIST *p_s
189                                  case 'C':                                  case 'C':
190                                          clearscr();                                          clearscr();
191                                          moveto(1, 1);                                          moveto(1, 1);
192                                          prints("取消...");                                          prints("鍙栨秷...");
193                                          press_any_key();                                          press_any_key();
194                                          goto cleanup;                                          goto cleanup;
195                                  case 'T':                                  case 'T':
# Line 201  int article_post(const SECTION_LIST *p_s Line 210  int article_post(const SECTION_LIST *p_s
210                  }                  }
211          }          }
212    
213            if (SYS_server_exit) // Do not save data on shutdown
214            {
215                    goto cleanup;
216            }
217    
218          content = malloc(ARTICLE_CONTENT_MAX_LEN);          content = malloc(ARTICLE_CONTENT_MAX_LEN);
219          if (content == NULL)          if (content == NULL)
220          {          {
# Line 254  int article_post(const SECTION_LIST *p_s Line 268  int article_post(const SECTION_LIST *p_s
268                  rs = NULL;                  rs = NULL;
269          }          }
270    
271            // Calculate display length of content
272            content_display_length = str_length(content, 1);
273    
274          // Begin transaction          // Begin transaction
275          if (mysql_query(db, "SET autocommit=0") != 0)          if (mysql_query(db, "SET autocommit=0") != 0)
276          {          {
# Line 317  int article_post(const SECTION_LIST *p_s Line 334  int article_post(const SECTION_LIST *p_s
334          snprintf(sql, sizeof(sql),          snprintf(sql, sizeof(sql),
335                           "INSERT INTO bbs(SID, TID, UID, username, nickname, title, CID, transship, "                           "INSERT INTO bbs(SID, TID, UID, username, nickname, title, CID, transship, "
336                           "sub_dt, sub_ip, reply_note, exp, last_reply_dt, icon, length) "                           "sub_dt, sub_ip, reply_note, exp, last_reply_dt, icon, length) "
337                           "VALUES(%d, 0, %d, '%s', '%s', '%s', %d, %d, NOW(), '%s', 1, %d, NOW(), 1, %ld)",                           "VALUES(%d, 0, %d, '%s', '%s', '%s', %d, %d, NOW(), '%s', %d, %d, NOW(), 1, %d)",
338                           p_section->sid, BBS_priv.uid, BBS_username, nickname_f, title_f,                           p_section->sid, BBS_priv.uid, BBS_username, nickname_f, title_f,
339                           p_article_new->cid, p_article_new->transship, hostaddr_client, BBS_user_exp, len_content);                           p_article_new->cid, p_article_new->transship, hostaddr_client,
340                             reply_note, BBS_user_exp, content_display_length);
341    
342          if (mysql_query(db, sql) != 0)          if (mysql_query(db, sql) != 0)
343          {          {
# Line 378  int article_post(const SECTION_LIST *p_s Line 396  int article_post(const SECTION_LIST *p_s
396                  goto cleanup;                  goto cleanup;
397          }          }
398    
399            mysql_close(db);
400            db = NULL;
401    
402          clearscr();          clearscr();
403          moveto(1, 1);          moveto(1, 1);
404          prints("发送完成,新文章通常会在%d秒后可见", BBS_section_list_load_interval);          prints("鍙戦佸畬鎴愶紝鏂版枃绔犻氬父浼氬湪%d绉掑悗鍙", BBS_section_list_load_interval);
405          press_any_key();          press_any_key();
406          ret = 1; // Success          ret = 1; // Success
407    
# Line 407  int article_modify(const SECTION_LIST *p Line 428  int article_modify(const SECTION_LIST *p
428          char *content = NULL;          char *content = NULL;
429          char *content_f = NULL;          char *content_f = NULL;
430          long len_content;          long len_content;
431            int content_display_length;
432            int reply_note = 1;
433          int ch;          int ch;
434          long ret = 0;          long ret = 0;
435          time_t now;          time_t now;
# Line 424  int article_modify(const SECTION_LIST *p Line 447  int article_modify(const SECTION_LIST *p
447          {          {
448                  clearscr();                  clearscr();
449                  moveto(1, 1);                  moveto(1, 1);
450                  prints("该文章无法被编辑,请联系版主。");                  prints("璇ユ枃绔犳棤娉曡缂栬緫锛岃鑱旂郴鐗堜富銆");
451                  press_any_key();                  press_any_key();
452    
453                  return 0;                  return 0;
# Line 439  int article_modify(const SECTION_LIST *p Line 462  int article_modify(const SECTION_LIST *p
462          }          }
463    
464          snprintf(sql, sizeof(sql),          snprintf(sql, sizeof(sql),
465                           "SELECT bbs_content.CID, bbs_content.content "                           "SELECT bbs_content.CID, bbs_content.content, reply_note "
466                           "FROM bbs INNER JOIN bbs_content ON bbs.CID = bbs_content.CID "                           "FROM bbs INNER JOIN bbs_content ON bbs.CID = bbs_content.CID "
467                           "WHERE bbs.AID = %d",                           "WHERE bbs.AID = %d",
468                           p_article->aid);                           p_article->aid);
# Line 471  int article_modify(const SECTION_LIST *p Line 494  int article_modify(const SECTION_LIST *p
494                  content[ARTICLE_CONTENT_MAX_LEN - 1] = '\0';                  content[ARTICLE_CONTENT_MAX_LEN - 1] = '\0';
495    
496                  // Remove control sequence                  // Remove control sequence
497                  len_content = ctrl_seq_filter(content);                  len_content = str_filter(content, 0);
498    
499                  p_editor_data = editor_data_load(content);                  p_editor_data = editor_data_load(content);
500                  if (p_editor_data == NULL)                  if (p_editor_data == NULL)
# Line 483  int article_modify(const SECTION_LIST *p Line 506  int article_modify(const SECTION_LIST *p
506    
507                  free(content);                  free(content);
508                  content = NULL;                  content = NULL;
509    
510                    reply_note = atoi(row[2]);
511          }          }
512          mysql_free_result(rs);          mysql_free_result(rs);
513          rs = NULL;          rs = NULL;
# Line 494  int article_modify(const SECTION_LIST *p Line 519  int article_modify(const SECTION_LIST *p
519          {          {
520                  editor_display(p_editor_data);                  editor_display(p_editor_data);
521    
522                  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))  
523                  {                  {
524                            clearscr();
525                            moveto(1, 1);
526                            prints("(S)淇濆瓨, (C)鍙栨秷, (N)閫氱煡%s or (E)鍐嶇紪杈? [S]: ",
527                                       (reply_note ? "鍏抽棴" : "寮鍚"));
528                            iflush();
529    
530                            ch = igetch_t(MAX_DELAY_TIME);
531                          switch (toupper(ch))                          switch (toupper(ch))
532                          {                          {
533                            case KEY_NULL:
534                            case KEY_TIMEOUT:
535                                    goto cleanup;
536                          case CR:                          case CR:
537                                  igetch_reset();                                  igetch_reset();
538                          case 'S':                          case 'S':
# Line 510  int article_modify(const SECTION_LIST *p Line 540  int article_modify(const SECTION_LIST *p
540                          case 'C':                          case 'C':
541                                  clearscr();                                  clearscr();
542                                  moveto(1, 1);                                  moveto(1, 1);
543                                  prints("取消...");                                  prints("鍙栨秷...");
544                                  press_any_key();                                  press_any_key();
545                                  goto cleanup;                                  goto cleanup;
546                            case 'N':
547                                    reply_note = (reply_note ? 0 : 1);
548                                    continue;
549                          case 'E':                          case 'E':
550                                  break;                                  break;
551                          default: // Invalid selection                          default: // Invalid selection
# Line 523  int article_modify(const SECTION_LIST *p Line 556  int article_modify(const SECTION_LIST *p
556                  }                  }
557          }          }
558    
559            if (SYS_server_exit) // Do not save data on shutdown
560            {
561                    goto cleanup;
562            }
563    
564          // Allocate buffers in big size          // Allocate buffers in big size
565          content = malloc(ARTICLE_CONTENT_MAX_LEN);          content = malloc(ARTICLE_CONTENT_MAX_LEN);
566          if (content == NULL)          if (content == NULL)
# Line 545  int article_modify(const SECTION_LIST *p Line 583  int article_modify(const SECTION_LIST *p
583          strftime(str_modify_dt, sizeof(str_modify_dt), "%Y-%m-%d %H:%M:%S (UTC %z)", &tm_modify_dt);          strftime(str_modify_dt, sizeof(str_modify_dt), "%Y-%m-%d %H:%M:%S (UTC %z)", &tm_modify_dt);
584    
585          len_content += snprintf(content + len_content, LINE_BUFFER_LEN,          len_content += snprintf(content + len_content, LINE_BUFFER_LEN,
586                                                          "\n--\n※ 作者已于 %s 修改本文※\n",                                                          "\n--\n鈥 浣滆呭凡浜 %s 淇敼鏈枃鈥籠n",
587                                                          str_modify_dt);                                                          str_modify_dt);
588    
589            // Calculate display length of content
590            content_display_length = str_length(content, 1);
591    
592          db = db_open();          db = db_open();
593          if (db == NULL)          if (db == NULL)
594          {          {
# Line 615  int article_modify(const SECTION_LIST *p Line 656  int article_modify(const SECTION_LIST *p
656    
657          // Update article          // Update article
658          snprintf(sql, sizeof(sql),          snprintf(sql, sizeof(sql),
659                           "UPDATE bbs SET CID = %d, length = %ld, 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
660                           p_article_new->cid, len_content, p_article->aid);                           p_article_new->cid, content_display_length, reply_note, p_article->aid);
661    
662          if (mysql_query(db, sql) != 0)          if (mysql_query(db, sql) != 0)
663          {          {
# Line 653  int article_modify(const SECTION_LIST *p Line 694  int article_modify(const SECTION_LIST *p
694                  goto cleanup;                  goto cleanup;
695          }          }
696    
697            mysql_close(db);
698            db = NULL;
699    
700          clearscr();          clearscr();
701          moveto(1, 1);          moveto(1, 1);
702          prints("修改完成,新内容通常会在%d秒后可见", BBS_section_list_load_interval);          prints("淇敼瀹屾垚锛屾柊鍐呭閫氬父浼氬湪%d绉掑悗鍙", BBS_section_list_load_interval);
703          press_any_key();          press_any_key();
704          ret = 1; // Success          ret = 1; // Success
705    
# Line 687  int article_reply(const SECTION_LIST *p_ Line 731  int article_reply(const SECTION_LIST *p_
731          char *content = NULL;          char *content = NULL;
732          char *content_f = NULL;          char *content_f = NULL;
733          long len_content;          long len_content;
734            int content_display_length;
735          char nickname_f[BBS_nickname_max_len * 2 + 1];          char nickname_f[BBS_nickname_max_len * 2 + 1];
736          int sign_id = 0;          int sign_id = 0;
737            int reply_note = 0;
738          long len;          long len;
739          int ch;          int ch;
740          char *p, *q;          char *p, *q;
# Line 698  int article_reply(const SECTION_LIST *p_ Line 744  int article_reply(const SECTION_LIST *p_
744          long i;          long i;
745          long ret = 0;          long ret = 0;
746          int topic_locked = 0;          int topic_locked = 0;
747            char msg[BBS_msg_max_len];
748            char msg_f[BBS_msg_max_len * 2 + 1];
749            int len_msg;
750    
751          if (p_section == NULL || p_article == NULL)          if (p_section == NULL || p_article == NULL)
752          {          {
# Line 708  int article_reply(const SECTION_LIST *p_ Line 757  int article_reply(const SECTION_LIST *p_
757          {          {
758                  clearscr();                  clearscr();
759                  moveto(1, 1);                  moveto(1, 1);
760                  prints("您没有权限在本版块发表文章\n");                  prints("鎮ㄦ病鏈夋潈闄愬湪鏈増鍧楀彂琛ㄦ枃绔燶n");
761                  press_any_key();                  press_any_key();
762    
763                  return 0;                  return 0;
# Line 716  int article_reply(const SECTION_LIST *p_ Line 765  int article_reply(const SECTION_LIST *p_
765    
766          p_article_new->title[0] = '\0';          p_article_new->title[0] = '\0';
767          snprintf(title_input, sizeof(title_input), "Re: %s", p_article->title);          snprintf(title_input, sizeof(title_input), "Re: %s", p_article->title);
768          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);
769          title_input[len] = '\0';          title_input[len] = '\0';
770    
771          db = db_open();          db = db_open();
# Line 756  int article_reply(const SECTION_LIST *p_ Line 805  int article_reply(const SECTION_LIST *p_
805    
806          if (topic_locked) // Reply is not allowed          if (topic_locked) // Reply is not allowed
807          {          {
808                    mysql_close(db);
809                    db = NULL;
810    
811                  clearscr();                  clearscr();
812                  moveto(1, 1);                  moveto(1, 1);
813                  prints("该主题谢绝回复");                  prints("璇ヤ富棰樿阿缁濆洖澶");
814                  press_any_key();                  press_any_key();
815    
816                  goto cleanup;                  goto cleanup;
# Line 802  int article_reply(const SECTION_LIST *p_ Line 854  int article_reply(const SECTION_LIST *p_
854                  }                  }
855    
856                  // Apply LML render to content body                  // Apply LML render to content body
857                  len = lml_plain(row[1], content_f, ARTICLE_CONTENT_MAX_LEN);                  len = lml_render(row[1], content_f, ARTICLE_CONTENT_MAX_LEN, 0);
858                  content_f[len] = '\0';                  content_f[len] = '\0';
859    
860                  // Remove control sequence                  // Remove control sequence
861                  len = ctrl_seq_filter(content_f);                  len = str_filter(content_f, 0);
862    
863                  len = snprintf(content, ARTICLE_CONTENT_MAX_LEN,                  len = snprintf(content, ARTICLE_CONTENT_MAX_LEN,
864                                             "\n\n【 在 %s (%s) 的大作中提到: 】\n",                                             "\n\n銆 鍦 %s (%s) 鐨勫ぇ浣滀腑鎻愬埌: 銆慭n",
865                                             p_article->username, p_article->nickname);                                             p_article->username, p_article->nickname);
866    
867                  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, NULL);
868                  for (i = 0; i < quote_content_lines; i++)                  for (i = 0; i < quote_content_lines; i++)
869                  {                  {
870                          memcpy(content + len, ": ", 2); // quote line prefix                          memcpy(content + len, ": ", 2); // quote line prefix
871                          len += 2;                          len += 2;
872                          memcpy(content + len, content_f + line_offsets[i], (size_t)(line_offsets[i + 1] - line_offsets[i]));                          memcpy(content + len, content_f + line_offsets[i], (size_t)(line_offsets[i + 1] - line_offsets[i]));
873                          len += (line_offsets[i + 1] - line_offsets[i]);                          len += (line_offsets[i + 1] - line_offsets[i]);
874                            if (content[len - 1] != '\n') // Appennd \n if not exist
875                            {
876                                    content[len] = '\n';
877                                    len++;
878                            }
879                  }                  }
880                  if (content[len - 1] != '\n') // Appennd \n if not exist                  if (content[len - 1] != '\n') // Appennd \n if not exist
881                  {                  {
# Line 852  int article_reply(const SECTION_LIST *p_ Line 909  int article_reply(const SECTION_LIST *p_
909          {          {
910                  clearscr();                  clearscr();
911                  moveto(21, 1);                  moveto(21, 1);
912                  prints("回复文章于 %s[%s] 讨论区", p_section->stitle, p_section->sname);                  prints("鍥炲鏂囩珷浜 %s[%s] 璁ㄨ鍖猴紝閫氱煡锛%s", p_section->stitle, p_section->sname, (reply_note ? "寮鍚" : "鍏抽棴"));
913                  moveto(22, 1);                  moveto(22, 1);
914                  prints("标题: %s", (p_article_new->title[0] == '\0' ? "[无]" : p_article_new->title));                  prints("鏍囬: %s", (p_article_new->title[0] == '\0' ? "[鏃燷" : p_article_new->title));
915                  moveto(23, 1);                  moveto(23, 1);
916                  prints("使用第 %d 个签名", sign_id);                  prints("浣跨敤绗 %d 涓鍚", sign_id);
917    
918                  if (toupper(ch) != 'T')                  if (toupper(ch) != 'T')
919                  {                  {
920                          prints("    按0~3选签名档(0表示不使用)");                          prints("    鎸0~3閫夌鍚嶆。(0琛ㄧず涓嶄娇鐢)");
921    
922                          moveto(24, 1);                          moveto(24, 1);
923                          prints("T改标题, C取消, Enter继续: ");                          prints("T鏀规爣棰, C鍙栨秷, N%s, Enter缁х画: ",
924                                       (reply_note ? "閫氱煡鍏抽棴" : "閫氱煡寮鍚"));
925                          iflush();                          iflush();
926                          ch = 0;                          ch = 0;
927                  }                  }
# Line 872  int article_reply(const SECTION_LIST *p_ Line 930  int article_reply(const SECTION_LIST *p_
930                  {                  {
931                          switch (toupper(ch))                          switch (toupper(ch))
932                          {                          {
933                            case KEY_NULL:
934                            case KEY_TIMEOUT:
935                                    goto cleanup;
936                          case CR:                          case CR:
937                                  igetch_reset();                                  igetch_reset();
938                                  break;                                  break;
939                          case 'T':                          case 'T':
940                                  moveto(24, 1);                                  len = get_data(24, 1, "鏍囬: ", title_input, sizeof(title_input), TITLE_INPUT_MAX_LEN);
                                 clrtoeol();  
                                 len = get_data(24, 1, "标题: ", title_input, TITLE_INPUT_MAX_LEN, 1);  
941                                  for (p = title_input; *p == ' '; p++)                                  for (p = title_input; *p == ' '; p++)
942                                          ;                                          ;
943                                  for (q = title_input + len; q > p && *(q - 1) == ' '; q--)                                  for (q = title_input + len; q > p && *(q - 1) == ' '; q--)
# Line 895  int article_reply(const SECTION_LIST *p_ Line 954  int article_reply(const SECTION_LIST *p_
954                          case 'C':                          case 'C':
955                                  clearscr();                                  clearscr();
956                                  moveto(1, 1);                                  moveto(1, 1);
957                                  prints("取消...");                                  prints("鍙栨秷...");
958                                  press_any_key();                                  press_any_key();
959                                  goto cleanup;                                  goto cleanup;
960                            case 'N':
961                                    reply_note = (reply_note ? 0 : 1);
962                                    break;
963                          case '0':                          case '0':
964                          case '1':                          case '1':
965                          case '2':                          case '2':
# Line 922  int article_reply(const SECTION_LIST *p_ Line 984  int article_reply(const SECTION_LIST *p_
984    
985                          clearscr();                          clearscr();
986                          moveto(1, 1);                          moveto(1, 1);
987                          prints("(S)发送, (C)取消, (T)更改标题 or (E)再编辑? [S]: ");                          prints("(S)鍙戦, (C)鍙栨秷, (T)鏇存敼鏍囬 or (E)鍐嶇紪杈? [S]: ");
988                          iflush();                          iflush();
989    
990                          for (ch = 0; !SYS_server_exit; ch = igetch_t(MAX_DELAY_TIME))                          for (ch = 0; !SYS_server_exit; ch = igetch_t(MAX_DELAY_TIME))
991                          {                          {
992                                  switch (toupper(ch))                                  switch (toupper(ch))
993                                  {                                  {
994                                    case KEY_NULL:
995                                    case KEY_TIMEOUT:
996                                            goto cleanup;
997                                  case CR:                                  case CR:
998                                          igetch_reset();                                          igetch_reset();
999                                  case 'S':                                  case 'S':
# Line 936  int article_reply(const SECTION_LIST *p_ Line 1001  int article_reply(const SECTION_LIST *p_
1001                                  case 'C':                                  case 'C':
1002                                          clearscr();                                          clearscr();
1003                                          moveto(1, 1);                                          moveto(1, 1);
1004                                          prints("取消...");                                          prints("鍙栨秷...");
1005                                          press_any_key();                                          press_any_key();
1006                                          goto cleanup;                                          goto cleanup;
1007                                  case 'T':                                  case 'T':
# Line 957  int article_reply(const SECTION_LIST *p_ Line 1022  int article_reply(const SECTION_LIST *p_
1022                  }                  }
1023          }          }
1024    
1025            if (SYS_server_exit) // Do not save data on shutdown
1026            {
1027                    goto cleanup;
1028            }
1029    
1030          content = malloc(ARTICLE_CONTENT_MAX_LEN);          content = malloc(ARTICLE_CONTENT_MAX_LEN);
1031          if (content == NULL)          if (content == NULL)
1032          {          {
# Line 1010  int article_reply(const SECTION_LIST *p_ Line 1080  int article_reply(const SECTION_LIST *p_
1080                  rs = NULL;                  rs = NULL;
1081          }          }
1082    
1083            // Calculate display length of content
1084            content_display_length = str_length(content, 1);
1085    
1086          // Begin transaction          // Begin transaction
1087          if (mysql_query(db, "SET autocommit=0") != 0)          if (mysql_query(db, "SET autocommit=0") != 0)
1088          {          {
# Line 1073  int article_reply(const SECTION_LIST *p_ Line 1146  int article_reply(const SECTION_LIST *p_
1146          snprintf(sql, sizeof(sql),          snprintf(sql, sizeof(sql),
1147                           "INSERT INTO bbs(SID, TID, UID, username, nickname, title, CID, transship, "                           "INSERT INTO bbs(SID, TID, UID, username, nickname, title, CID, transship, "
1148                           "sub_dt, sub_ip, reply_note, exp, last_reply_dt, icon, length) "                           "sub_dt, sub_ip, reply_note, exp, last_reply_dt, icon, length) "
1149                           "VALUES(%d, %d, %d, '%s', '%s', '%s', %d, 0, NOW(), '%s', 1, %d, NOW(), 1, %ld)",                           "VALUES(%d, %d, %d, '%s', '%s', '%s', %d, 0, NOW(), '%s', %d, %d, NOW(), 1, %d)",
1150                           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),
1151                           BBS_priv.uid, BBS_username, nickname_f, title_f,                           BBS_priv.uid, BBS_username, nickname_f, title_f,
1152                           p_article_new->cid, hostaddr_client, BBS_user_exp, len_content);                           p_article_new->cid, hostaddr_client,
1153                             reply_note, BBS_user_exp, content_display_length);
1154    
1155          if (mysql_query(db, sql) != 0)          if (mysql_query(db, sql) != 0)
1156          {          {
# Line 1114  int article_reply(const SECTION_LIST *p_ Line 1188  int article_reply(const SECTION_LIST *p_
1188                  goto cleanup;                  goto cleanup;
1189          }          }
1190    
1191            // Notify the authors of the topic / article which is replyed.
1192            snprintf(sql, sizeof(sql),
1193                             "SELECT DISTINCT UID FROM bbs WHERE (AID = %d OR AID = %d) "
1194                             "AND visible AND reply_note AND UID <> %d",
1195                             p_article->tid, p_article->aid, BBS_priv.uid);
1196    
1197            if (mysql_query(db, sql) != 0)
1198            {
1199                    log_error("Read reply info error: %s\n", mysql_error(db));
1200                    ret = -1;
1201                    goto cleanup;
1202            }
1203            if ((rs = mysql_store_result(db)) == NULL)
1204            {
1205                    log_error("Get reply info failed\n");
1206                    ret = -1;
1207                    goto cleanup;
1208            }
1209    
1210            while ((row = mysql_fetch_row(rs)))
1211            {
1212                    // Send notification message
1213                    len_msg = snprintf(msg, BBS_msg_max_len,
1214                                                       "[hide]SYS_Reply_Article[/hide]鏈変汉鍥炲浜嗘偍鎵鍙戣〃/鍥炲鐨勬枃绔狅紝蹇潵"
1215                                                       "[article %d]鐪嬬湅[/article]銆%s銆嬪惂锛乗n",
1216                                                       p_article_new->aid, title_f);
1217    
1218                    mysql_real_escape_string(db, msg_f, msg, (unsigned long)len_msg);
1219    
1220                    snprintf(sql, sizeof(sql),
1221                                     "INSERT INTO bbs_msg(fromUID, toUID, content, send_dt, send_ip) "
1222                                     "VALUES(%d, %d, '%s', NOW(), '%s')",
1223                                     BBS_sys_id, atoi(row[0]), msg_f, hostaddr_client);
1224    
1225                    if (mysql_query(db, sql) != 0)
1226                    {
1227                            log_error("Insert msg error: %s\n", mysql_error(db));
1228                            ret = -1;
1229                            goto cleanup;
1230                    }
1231            }
1232            mysql_free_result(rs);
1233            rs = NULL;
1234    
1235          // Add exp          // Add exp
1236          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
1237          {          {
# Line 1150  int article_reply(const SECTION_LIST *p_ Line 1268  int article_reply(const SECTION_LIST *p_
1268                  goto cleanup;                  goto cleanup;
1269          }          }
1270    
1271            mysql_close(db);
1272            db = NULL;
1273    
1274          clearscr();          clearscr();
1275          moveto(1, 1);          moveto(1, 1);
1276          prints("发送完成,新文章通常会在%d秒后可见", BBS_section_list_load_interval);          prints("鍙戦佸畬鎴愶紝鏂版枃绔犻氬父浼氬湪%d绉掑悗鍙", BBS_section_list_load_interval);
1277          press_any_key();          press_any_key();
1278          ret = 1; // Success          ret = 1; // Success
1279    


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

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