/[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.3 by sysadm, Fri Jun 13 12:01:27 2025 UTC Revision 1.42 by sysadm, Mon Nov 10 14:22:18 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     */
 /***************************************************************************  
  *                                                                         *  
  *   This program is free software; you can redistribute it and/or modify  *  
  *   it under the terms of the GNU General Public License as published by  *  
  *   the Free Software Foundation; either version 3 of the License, or     *  
  *   (at your option) any later version.                                   *  
  *                                                                         *  
  ***************************************************************************/  
8    
 #include "article_post.h"  
9  #include "article_cache.h"  #include "article_cache.h"
10    #include "article_post.h"
11    #include "bbs.h"
12    #include "bwf.h"
13    #include "database.h"
14  #include "editor.h"  #include "editor.h"
 #include "screen.h"  
 #include "log.h"  
15  #include "io.h"  #include "io.h"
16    #include "log.h"
17    #include "lml.h"
18    #include "screen.h"
19    #include "user_priv.h"
20  #include <ctype.h>  #include <ctype.h>
21  #include <string.h>  #include <string.h>
22    #include <stdlib.h>
23    #include <time.h>
24    
25  #define STR_INPUT_LEN 74  enum _article_post_constant_t
26    {
27            TITLE_INPUT_MAX_LEN = 72,
28            ARTICLE_QUOTE_DEFAULT_LINES = 20,
29            MODIFY_DT_MAX_LEN = 50,
30    };
31    
32  int article_post(SECTION_LIST *p_section)  int article_post(const SECTION_LIST *p_section, ARTICLE *p_article_new)
33  {  {
34          EDITOR_DATA *p_editor_data;          MYSQL *db = NULL;
35          char title[BBS_article_title_max_len + 1] = "";          MYSQL_RES *rs = NULL;
36          char title_input[STR_INPUT_LEN + 1] = "";          MYSQL_ROW row;
37            char sql[SQL_BUFFER_LEN];
38            char *sql_content = NULL;
39            EDITOR_DATA *p_editor_data = NULL;
40            char title_input[BBS_article_title_max_len + 1];
41            char title_f[BBS_article_title_max_len * 2 + 1];
42            char *content = NULL;
43            char *content_f = NULL;
44            long len_content;
45            int content_display_length;
46            char nickname_f[BBS_nickname_max_len * 2 + 1];
47          int sign_id = 0;          int sign_id = 0;
48            int reply_note = 1;
49          long len;          long len;
50          int ch;          int ch;
51          char *p, *q;          char *p, *q;
52            long ret = 0;
53    
54          if (p_section == NULL)          if (p_section == NULL || p_article_new == NULL)
55          {          {
56                  log_error("NULL pointer error\n");                  log_error("NULL pointer error\n");
57          }          }
58    
59            if (!checkpriv(&BBS_priv, p_section->sid, S_POST))
60            {
61                    clearscr();
62                    moveto(1, 1);
63                    prints("您没有权限在本版块发表文章\n");
64                    press_any_key();
65    
66                    return 0;
67            }
68    
69            p_article_new->title[0] = '\0';
70            title_input[0] = '\0';
71            p_article_new->transship = 0;
72    
73          p_editor_data = editor_data_load("");          p_editor_data = editor_data_load("");
74          if (p_editor_data == NULL)          if (p_editor_data == NULL)
75          {          {
76                  log_error("editor_data_load() error\n");                  log_error("editor_data_load() error\n");
77                  return -2;                  ret = -1;
78                    goto cleanup;
79          }          }
80    
81          // Set title and sign          // Set title and sign
# Line 52  int article_post(SECTION_LIST *p_section Line 83  int article_post(SECTION_LIST *p_section
83          {          {
84                  clearscr();                  clearscr();
85                  moveto(21, 1);                  moveto(21, 1);
86                  prints(" %s[%s] ", p_section->stitle, p_section->sname);                  prints("发表文章于 %s[%s] 讨论区,类型: %s,回复通知: %s",
87                               p_section->stitle, p_section->sname,
88                               (p_article_new->transship ? "转载" : "原创"),
89                               (reply_note ? "开启" : "关闭"));
90                  moveto(22, 1);                  moveto(22, 1);
91                  prints("ʹñ: %s", (title[0] == '\0' ? "[趨]" : title));                  prints("标题: %s", (p_article_new->title[0] == '\0' ? "[无]" : p_article_new->title));
92                  moveto(23, 1);                  moveto(23, 1);
93                  prints("ʹõ %d ǩ", sign_id);                  prints("使用第 %d 个签名", sign_id);
94    
95                  if (toupper(ch) != 'T')                  if (toupper(ch) != 'T')
96                  {                  {
97                          prints("    0~3ѡǩ");                          prints("    按0~3选签名档(0表示不使用)");
98    
99                          moveto(24, 1);                          moveto(24, 1);
100                          prints("Tı, Cȡ, Enter: ");                          prints("T改标题, C取消, Z设为%s, N%s, Enter继续: ",
101                                       (p_article_new->transship ? "原创" : "转载"),
102                                       (reply_note ? "关闭回复通知" : "开启回复通知"));
103                          iflush();                          iflush();
104                          ch = 0;                          ch = 0;
105                  }                  }
106    
107                  for (; !SYS_server_exit; ch = igetch_t(MAX_DELAY_TIME))                  while (!SYS_server_exit)
108                  {                  {
109                          switch (toupper(ch))                          switch (toupper(ch))
110                          {                          {
111                            case KEY_NULL:
112                            case KEY_TIMEOUT:
113                                    goto cleanup;
114                          case CR:                          case CR:
                                 igetch_reset();  
115                                  break;                                  break;
116                          case 'T':                          case 'T':
117                                  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, STR_INPUT_LEN, 1);  
118                                  for (p = title_input; *p == ' '; p++)                                  for (p = title_input; *p == ' '; p++)
119                                          ;                                          ;
120                                  for (q = title_input + len; q > p && *(q - 1) == ' '; q--)                                  for (q = title_input + len; q > p && *(q - 1) == ' '; q--)
121                                          ;                                          ;
122                                  *q = '\0';                                  *q = '\0';
123                                  len = q - p;                                  len = q - p;
   
124                                  if (*p != '\0')                                  if (*p != '\0')
125                                  {                                  {
126                                          memcpy(title, p, (size_t)len + 1);                                          if ((ret = check_badwords(p, '*')) < 0)
127                                          memcpy(title_input, title, (size_t)len + 1);                                          {
128                                  }                                                  log_error("check_badwords(title) error\n");
129                                  if (title[0] != '\0') // title is valid                                          }
130                                  {                                          else if (ret > 0)
131                                          ch = 0;                                          {
132                                                    memcpy(title_input, p, (size_t)len + 1);
133                                                    continue;
134                                            }
135                                            memcpy(p_article_new->title, p, (size_t)len + 1);
136                                            memcpy(title_input, p_article_new->title, (size_t)len + 1);
137                                  }                                  }
138                                    ch = 0;
139                                  break;                                  break;
140                          case 'C':                          case 'C':
141                                  clearscr();                                  clearscr();
142                                  moveto(1, 1);                                  moveto(1, 1);
143                                  prints("ȡ...");                                  prints("取消...");
144                                  press_any_key();                                  press_any_key();
145                                  goto cleanup;                                  goto cleanup;
146                            case 'Z':
147                                    p_article_new->transship = (p_article_new->transship ? 0 : 1);
148                                    break;
149                            case 'N':
150                                    reply_note = (reply_note ? 0 : 1);
151                                    break;
152                          case '0':                          case '0':
153                          case '1':                          case '1':
154                          case '2':                          case '2':
# Line 109  int article_post(SECTION_LIST *p_section Line 156  int article_post(SECTION_LIST *p_section
156                                  sign_id = ch - '0';                                  sign_id = ch - '0';
157                                  break;                                  break;
158                          default: // Invalid selection                          default: // Invalid selection
159                                    ch = igetch_t(BBS_max_user_idle_time);
160                                  continue;                                  continue;
161                          }                          }
162    
163                          break;                          break;
164                  }                  }
165    
166                  if (ch != CR)                  if (ch != CR || p_article_new->title[0] == '\0')
167                  {                  {
168                          continue;                          continue;
169                  }                  }
# Line 126  int article_post(SECTION_LIST *p_section Line 174  int article_post(SECTION_LIST *p_section
174    
175                          clearscr();                          clearscr();
176                          moveto(1, 1);                          moveto(1, 1);
177                          prints("(S), (C)ȡ, (T)ı or (E)ٱ༭? [S]: ");                          prints("(S)发送, (C)取消, (T)更改标题 or (E)再编辑? [S]: ");
178                          iflush();                          iflush();
179    
180                          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))
181                          {                          {
182                                  switch (toupper(ch))                                  switch (toupper(ch))
183                                  {                                  {
184                                    case KEY_NULL:
185                                    case KEY_TIMEOUT:
186                                            goto cleanup;
187                                  case CR:                                  case CR:
                                         igetch_reset();  
188                                  case 'S':                                  case 'S':
189                                          break;                                          break;
190                                  case 'C':                                  case 'C':
191                                          clearscr();                                          clearscr();
192                                          moveto(1, 1);                                          moveto(1, 1);
193                                          prints("ȡ...");                                          prints("取消...");
194                                          press_any_key();                                          press_any_key();
195                                          goto cleanup;                                          goto cleanup;
196                                  case 'T':                                  case 'T':
# Line 154  int article_post(SECTION_LIST *p_section Line 204  int article_post(SECTION_LIST *p_section
204                                  break;                                  break;
205                          }                          }
206                  }                  }
207    
208                    if (toupper(ch) != 'T')
209                    {
210                            break;
211                    }
212          }          }
213    
214          // editor_data_save(p_editor_data, p_data_new, data_new_len);          if (SYS_server_exit) // Do not save data on shutdown
215          log_common("Debug: post article\n");          {
216                    goto cleanup;
217            }
218    
219            content = malloc(ARTICLE_CONTENT_MAX_LEN);
220            if (content == NULL)
221            {
222                    log_error("malloc(content) error: OOM\n");
223                    ret = -1;
224                    goto cleanup;
225            }
226    
227            len_content = editor_data_save(p_editor_data, content, ARTICLE_CONTENT_MAX_LEN);
228            if (len_content < 0)
229            {
230                    log_error("editor_data_save() error\n");
231                    ret = -1;
232                    goto cleanup;
233            }
234    
235            if (check_badwords(content, '*') < 0)
236            {
237                    log_error("check_badwords(content) error\n");
238                    ret = -1;
239                    goto cleanup;
240            }
241    
242            db = db_open();
243            if (db == NULL)
244            {
245                    log_error("db_open() error: %s\n", mysql_error(db));
246                    ret = -1;
247                    goto cleanup;
248            }
249    
250            if (sign_id > 0)
251            {
252                    snprintf(sql, sizeof(sql),
253                                     "SELECT sign_%d AS sign FROM user_pubinfo WHERE UID = %d",
254                                     sign_id, BBS_priv.uid);
255    
256                    if (mysql_query(db, sql) != 0)
257                    {
258                            log_error("Query sign error: %s\n", mysql_error(db));
259                            ret = -1;
260                            goto cleanup;
261                    }
262                    if ((rs = mysql_use_result(db)) == NULL)
263                    {
264                            log_error("Get sign data failed\n");
265                            ret = -1;
266                            goto cleanup;
267                    }
268    
269                    if ((row = mysql_fetch_row(rs)))
270                    {
271                            len_content += snprintf(content + len_content,
272                                                                            ARTICLE_CONTENT_MAX_LEN - (size_t)len_content,
273                                                                            "\n\n--\n%s\n", row[0]);
274                    }
275                    mysql_free_result(rs);
276                    rs = NULL;
277            }
278    
279            // Calculate display length of content
280            content_display_length = str_length(content, 1);
281    
282            // Begin transaction
283            if (mysql_query(db, "SET autocommit=0") != 0)
284            {
285                    log_error("SET autocommit=0 error: %s\n", mysql_error(db));
286                    ret = -1;
287                    goto cleanup;
288            }
289    
290            if (mysql_query(db, "BEGIN") != 0)
291            {
292                    log_error("Begin transaction error: %s\n", mysql_error(db));
293                    ret = -1;
294                    goto cleanup;
295            }
296    
297            // Secure SQL parameters
298            content_f = malloc((size_t)len_content * 2 + 1);
299            if (content_f == NULL)
300            {
301                    log_error("malloc(content_f) error: OOM\n");
302                    ret = -1;
303                    goto cleanup;
304            }
305    
306            mysql_real_escape_string(db, nickname_f, BBS_nickname, (unsigned long)strnlen(BBS_nickname, sizeof(BBS_nickname)));
307            mysql_real_escape_string(db, title_f, p_article_new->title, strnlen(p_article_new->title, sizeof(p_article_new->title)));
308            mysql_real_escape_string(db, content_f, content, (unsigned long)len_content);
309    
310            free(content);
311            content = NULL;
312    
313            // Add content
314            sql_content = malloc(SQL_BUFFER_LEN + (size_t)len_content * 2 + 1);
315            if (sql_content == NULL)
316            {
317                    log_error("malloc(sql_content) error: OOM\n");
318                    ret = -1;
319                    goto cleanup;
320            }
321    
322            snprintf(sql_content, SQL_BUFFER_LEN + (size_t)len_content * 2 + 1,
323                             "INSERT INTO bbs_content(AID, content) values(0, '%s')",
324                             content_f);
325    
326            free(content_f);
327            content_f = NULL;
328    
329            if (mysql_query(db, sql_content) != 0)
330            {
331                    log_error("Add article content error: %s\n", mysql_error(db));
332                    ret = -1;
333                    goto cleanup;
334            }
335    
336            p_article_new->cid = (int32_t)mysql_insert_id(db);
337    
338            free(sql_content);
339            sql_content = NULL;
340    
341            // Add article
342            snprintf(sql, sizeof(sql),
343                             "INSERT INTO bbs(SID, TID, UID, username, nickname, title, CID, transship, "
344                             "sub_dt, sub_ip, reply_note, exp, last_reply_dt, icon, length) "
345                             "VALUES(%d, 0, %d, '%s', '%s', '%s', %d, %d, NOW(), '%s', %d, %d, NOW(), 1, %d)",
346                             p_section->sid, BBS_priv.uid, BBS_username, nickname_f, title_f,
347                             p_article_new->cid, p_article_new->transship, hostaddr_client,
348                             reply_note, BBS_user_exp, content_display_length);
349    
350            if (mysql_query(db, sql) != 0)
351            {
352                    log_error("Add article error: %s\n", mysql_error(db));
353                    ret = -1;
354                    goto cleanup;
355            }
356    
357            p_article_new->aid = (int32_t)mysql_insert_id(db);
358    
359            // Link content to article
360            snprintf(sql, sizeof(sql),
361                             "UPDATE bbs_content SET AID = %d WHERE CID = %d",
362                             p_article_new->aid, p_article_new->cid);
363    
364            if (mysql_query(db, sql) != 0)
365            {
366                    log_error("Update content error: %s\n", mysql_error(db));
367                    ret = -1;
368                    goto cleanup;
369            }
370    
371            // Add exp
372            if (checkpriv(&BBS_priv, p_section->sid, S_GETEXP)) // Except in test section
373            {
374                    snprintf(sql, sizeof(sql),
375                                     "UPDATE user_pubinfo SET exp = exp + %d WHERE UID = %d",
376                                     (p_article_new->transship ? 5 : 15), BBS_priv.uid);
377    
378                    if (mysql_query(db, sql) != 0)
379                    {
380                            log_error("Update exp error: %s\n", mysql_error(db));
381                            ret = -1;
382                            goto cleanup;
383                    }
384            }
385    
386            // Add log
387            snprintf(sql, sizeof(sql),
388                             "INSERT INTO bbs_article_op(AID, UID, type, op_dt, op_ip)"
389                             "VALUES(%d, %d, 'A', NOW(), '%s')",
390                             p_article_new->aid, BBS_priv.uid, hostaddr_client);
391    
392            if (mysql_query(db, sql) != 0)
393            {
394                    log_error("Add log error: %s\n", mysql_error(db));
395                    ret = -1;
396                    goto cleanup;
397            }
398    
399            // Commit transaction
400            if (mysql_query(db, "COMMIT") != 0)
401            {
402                    log_error("Commit transaction error: %s\n", mysql_error(db));
403                    ret = -1;
404                    goto cleanup;
405            }
406    
407            mysql_close(db);
408            db = NULL;
409    
410            clearscr();
411            moveto(1, 1);
412            prints("发送完成,新文章通常会在%d秒后可见", BBS_section_list_load_interval);
413            press_any_key();
414            ret = 1; // Success
415    
416  cleanup:  cleanup:
417            mysql_close(db);
418    
419            // Cleanup buffers
420          editor_data_cleanup(p_editor_data);          editor_data_cleanup(p_editor_data);
421    
422          return 0;          free(sql_content);
423            free(content);
424            free(content_f);
425    
426            return (int)ret;
427  }  }
428    
429  int article_modify(SECTION_LIST *p_section, ARTICLE *p_article)  int article_modify(const SECTION_LIST *p_section, const ARTICLE *p_article, ARTICLE *p_article_new)
430  {  {
431          ARTICLE_CACHE cache;          MYSQL *db = NULL;
432          EDITOR_DATA *p_editor_data;          MYSQL_RES *rs = NULL;
433            MYSQL_ROW row;
434            char sql[SQL_BUFFER_LEN];
435            char *sql_content = NULL;
436            char *content = NULL;
437            char *content_f = NULL;
438            long len_content;
439            int content_display_length;
440            int reply_note = 1;
441            int ch;
442            long ret = 0;
443            time_t now;
444            struct tm tm_modify_dt;
445            char str_modify_dt[MODIFY_DT_MAX_LEN + 1];
446    
447            EDITOR_DATA *p_editor_data = NULL;
448    
449          if (p_section == NULL || p_article == NULL)          if (p_section == NULL || p_article == NULL)
450          {          {
451                  log_error("NULL pointer error\n");                  log_error("NULL pointer error\n");
452          }          }
453    
454          if (article_cache_load(&cache, VAR_ARTICLE_CACHE_DIR, p_article) < 0)          if (p_article->excerption) // Modify is not allowed
455          {          {
456                  log_error("article_cache_load(aid=%d, cid=%d) error\n", p_article->aid, p_article->cid);                  clearscr();
457                  return -2;                  moveto(1, 1);
458                    prints("该文章无法被编辑,请联系版主。");
459                    press_any_key();
460    
461                    return 0;
462          }          }
463          p_editor_data = editor_data_load(cache.p_data);  
464          if (p_editor_data == NULL)          db = db_open();
465            if (db == NULL)
466            {
467                    log_error("db_open() error: %s\n", mysql_error(db));
468                    ret = -1;
469                    goto cleanup;
470            }
471    
472            snprintf(sql, sizeof(sql),
473                             "SELECT bbs_content.CID, bbs_content.content, reply_note "
474                             "FROM bbs INNER JOIN bbs_content ON bbs.CID = bbs_content.CID "
475                             "WHERE bbs.AID = %d",
476                             p_article->aid);
477    
478            if (mysql_query(db, sql) != 0)
479            {
480                    log_error("Query article content error: %s\n", mysql_error(db));
481                    ret = -1;
482                    goto cleanup;
483            }
484            if ((rs = mysql_use_result(db)) == NULL)
485            {
486                    log_error("Get article content data failed\n");
487                    ret = -1;
488                    goto cleanup;
489            }
490    
491            if ((row = mysql_fetch_row(rs)))
492          {          {
493                  log_error("editor_data_load(aid=%d, cid=%d) error\n", p_article->aid, p_article->cid);                  content = malloc(ARTICLE_CONTENT_MAX_LEN);
494                  return -2;                  if (content == NULL)
495                    {
496                            log_error("malloc(content) error: OOM\n");
497                            ret = -1;
498                            goto cleanup;
499                    }
500    
501                    strncpy(content, row[1], ARTICLE_CONTENT_MAX_LEN - 1);
502                    content[ARTICLE_CONTENT_MAX_LEN - 1] = '\0';
503    
504                    // Remove control sequence
505                    len_content = str_filter(content, 0);
506    
507                    p_editor_data = editor_data_load(content);
508                    if (p_editor_data == NULL)
509                    {
510                            log_error("editor_data_load(aid=%d, cid=%d) error\n", p_article->aid, atoi(row[0]));
511                            ret = -1;
512                            goto cleanup;
513                    }
514    
515                    free(content);
516                    content = NULL;
517    
518                    reply_note = atoi(row[2]);
519          }          }
520          if (article_cache_unload(&cache) < 0)          mysql_free_result(rs);
521            rs = NULL;
522    
523            mysql_close(db);
524            db = NULL;
525    
526            for (ch = 'E'; !SYS_server_exit && toupper(ch) == 'E';)
527          {          {
528                  log_error("article_cache_unload(aid=%d, cid=%d) error\n", p_article->aid, p_article->cid);                  editor_display(p_editor_data);
529                  return -2;  
530                    while (!SYS_server_exit)
531                    {
532                            clearscr();
533                            moveto(1, 1);
534                            prints("(S)保存, (C)取消, (N)%s回复通知 or (E)再编辑? [S]: ",
535                                       (reply_note ? "关闭" : "开启"));
536                            iflush();
537    
538                            ch = igetch_t(BBS_max_user_idle_time);
539                            switch (toupper(ch))
540                            {
541                            case KEY_NULL:
542                            case KEY_TIMEOUT:
543                                    goto cleanup;
544                            case CR:
545                            case 'S':
546                                    break;
547                            case 'C':
548                                    clearscr();
549                                    moveto(1, 1);
550                                    prints("取消...");
551                                    press_any_key();
552                                    goto cleanup;
553                            case 'N':
554                                    reply_note = (reply_note ? 0 : 1);
555                                    continue;
556                            case 'E':
557                                    break;
558                            default: // Invalid selection
559                                    continue;
560                            }
561    
562                            break;
563                    }
564          }          }
565    
566          editor_display(p_editor_data);          if (SYS_server_exit) // Do not save data on shutdown
567            {
568                    goto cleanup;
569            }
570    
571            // Allocate buffers in big size
572            content = malloc(ARTICLE_CONTENT_MAX_LEN);
573            if (content == NULL)
574            {
575                    log_error("malloc(content) error: OOM\n");
576                    ret = -1;
577                    goto cleanup;
578            }
579    
580          // editor_data_save(p_editor_data, p_data_new, data_new_len);          len_content = editor_data_save(p_editor_data, content, ARTICLE_CONTENT_MAX_LEN - LINE_BUFFER_LEN);
581            if (len_content < 0)
582            {
583                    log_error("editor_data_save() error\n");
584                    ret = -1;
585                    goto cleanup;
586            }
587    
588            if (check_badwords(content, '*') < 0)
589            {
590                    log_error("check_badwords(content) error\n");
591                    ret = -1;
592                    goto cleanup;
593            }
594    
595            time(&now);
596            localtime_r(&now, &tm_modify_dt);
597            strftime(str_modify_dt, sizeof(str_modify_dt), "%Y-%m-%d %H:%M:%S (UTC %z)", &tm_modify_dt);
598    
599            len_content += snprintf(content + len_content, LINE_BUFFER_LEN,
600                                                            "\n--\n※ 作者已于 %s 修改本文※\n",
601                                                            str_modify_dt);
602    
603            // Calculate display length of content
604            content_display_length = str_length(content, 1);
605    
606            db = db_open();
607            if (db == NULL)
608            {
609                    log_error("db_open() error: %s\n", mysql_error(db));
610                    ret = -1;
611                    goto cleanup;
612            }
613    
614            // Begin transaction
615            if (mysql_query(db, "SET autocommit=0") != 0)
616            {
617                    log_error("SET autocommit=0 error: %s\n", mysql_error(db));
618                    ret = -1;
619                    goto cleanup;
620            }
621    
622            if (mysql_query(db, "BEGIN") != 0)
623            {
624                    log_error("Begin transaction error: %s\n", mysql_error(db));
625                    ret = -1;
626                    goto cleanup;
627            }
628    
629            // Secure SQL parameters
630            content_f = malloc((size_t)len_content * 2 + 1);
631            if (content_f == NULL)
632            {
633                    log_error("malloc(content_f) error: OOM\n");
634                    ret = -1;
635                    goto cleanup;
636            }
637    
638            mysql_real_escape_string(db, content_f, content, (unsigned long)len_content);
639    
640            free(content);
641            content = NULL;
642    
643            // Add content
644            sql_content = malloc(SQL_BUFFER_LEN + (size_t)len_content * 2 + 1);
645            if (sql_content == NULL)
646            {
647                    log_error("malloc(sql_content) error: OOM\n");
648                    ret = -1;
649                    goto cleanup;
650            }
651    
652            snprintf(sql_content, SQL_BUFFER_LEN + (size_t)len_content * 2 + 1,
653                             "INSERT INTO bbs_content(AID, content) values(%d, '%s')",
654                             p_article->aid, content_f);
655    
656            free(content_f);
657            content_f = NULL;
658    
659            if (mysql_query(db, sql_content) != 0)
660            {
661                    log_error("Add article content error: %s\n", mysql_error(db));
662                    ret = -1;
663                    goto cleanup;
664            }
665    
666            p_article_new->cid = (int32_t)mysql_insert_id(db);
667    
668            free(sql_content);
669            sql_content = NULL;
670    
671            // Update article
672            snprintf(sql, sizeof(sql),
673                             "UPDATE bbs SET CID = %d, length = %d, reply_note = %d, excerption = 0 WHERE AID = %d", // Set excerption = 0 explictly in case of rare condition
674                             p_article_new->cid, content_display_length, reply_note, p_article->aid);
675    
676            if (mysql_query(db, sql) != 0)
677            {
678                    log_error("Add article error: %s\n", mysql_error(db));
679                    ret = -1;
680                    goto cleanup;
681            }
682    
683            if (mysql_query(db, sql) != 0)
684            {
685                    log_error("Update content error: %s\n", mysql_error(db));
686                    ret = -1;
687                    goto cleanup;
688            }
689    
690            // Add log
691            snprintf(sql, sizeof(sql),
692                             "INSERT INTO bbs_article_op(AID, UID, type, op_dt, op_ip)"
693                             "VALUES(%d, %d, 'M', NOW(), '%s')",
694                             p_article->aid, BBS_priv.uid, hostaddr_client);
695    
696            if (mysql_query(db, sql) != 0)
697            {
698                    log_error("Add log error: %s\n", mysql_error(db));
699                    ret = -1;
700                    goto cleanup;
701            }
702    
703            // Commit transaction
704            if (mysql_query(db, "COMMIT") != 0)
705            {
706                    log_error("Commit transaction error: %s\n", mysql_error(db));
707                    ret = -1;
708                    goto cleanup;
709            }
710    
711            mysql_close(db);
712            db = NULL;
713    
714            clearscr();
715            moveto(1, 1);
716            prints("修改完成,新内容通常会在%d秒后可见", BBS_section_list_load_interval);
717            press_any_key();
718            ret = 1; // Success
719    
720    cleanup:
721            mysql_free_result(rs);
722            mysql_close(db);
723    
724            // Cleanup buffers
725          editor_data_cleanup(p_editor_data);          editor_data_cleanup(p_editor_data);
726    
727          return 0;          free(sql_content);
728            free(content);
729            free(content_f);
730    
731            return (int)ret;
732  }  }
733    
734  int article_reply(SECTION_LIST *p_section, ARTICLE *p_article)  int article_reply(const SECTION_LIST *p_section, const ARTICLE *p_article, ARTICLE *p_article_new)
735  {  {
736          ARTICLE_CACHE cache;          MYSQL *db = NULL;
737          EDITOR_DATA *p_editor_data;          MYSQL_RES *rs = NULL;
738            MYSQL_ROW row;
739            long line_offsets[MAX_EDITOR_DATA_LINES + 1];
740            char sql[SQL_BUFFER_LEN];
741            char *sql_content = NULL;
742            EDITOR_DATA *p_editor_data = NULL;
743            char title_input[BBS_article_title_max_len + sizeof("Re: ")];
744            char title_f[BBS_article_title_max_len * 2 + 1];
745            char *content = NULL;
746            char *content_f = NULL;
747            long len_content;
748            int content_display_length;
749            char nickname_f[BBS_nickname_max_len * 2 + 1];
750            int sign_id = 0;
751            int reply_note = 0;
752            int full_quote = 0;
753            long len;
754            int ch;
755            char *p, *q;
756            int eol;
757            int display_len;
758            long quote_content_lines;
759            long i;
760            long ret = 0;
761            int topic_locked = 0;
762            char msg[BBS_msg_max_len];
763            char msg_f[BBS_msg_max_len * 2 + 1];
764            int len_msg;
765    
766          if (p_section == NULL || p_article == NULL)          if (p_section == NULL || p_article == NULL)
767          {          {
768                  log_error("NULL pointer error\n");                  log_error("NULL pointer error\n");
769          }          }
770    
771          if (article_cache_load(&cache, VAR_ARTICLE_CACHE_DIR, p_article) < 0)          if (!checkpriv(&BBS_priv, p_section->sid, S_POST))
772          {          {
773                  log_error("article_cache_load(aid=%d, cid=%d) error\n", p_article->aid, p_article->cid);                  clearscr();
774                  return -2;                  moveto(1, 1);
775                    prints("您没有权限在本版块发表文章\n");
776                    press_any_key();
777    
778                    return 0;
779          }          }
780          p_editor_data = editor_data_load(cache.p_data);  
781          if (p_editor_data == NULL)          p_article_new->title[0] = '\0';
782            snprintf(title_input, sizeof(title_input), "Re: %s", p_article->title);
783            len = split_line(title_input, TITLE_INPUT_MAX_LEN, &eol, &display_len, 0);
784            title_input[len] = '\0';
785    
786            db = db_open();
787            if (db == NULL)
788            {
789                    log_error("db_open() error: %s\n", mysql_error(db));
790                    ret = -1;
791                    goto cleanup;
792            }
793    
794            snprintf(sql, sizeof(sql),
795                             "SELECT `lock` FROM bbs WHERE AID = %d",
796                             (p_article->tid == 0 ? p_article->aid : p_article->tid));
797    
798            if (mysql_query(db, sql) != 0)
799            {
800                    log_error("Query article status error: %s\n", mysql_error(db));
801                    ret = -1;
802                    goto cleanup;
803            }
804            if ((rs = mysql_store_result(db)) == NULL)
805            {
806                    log_error("Get article status data failed\n");
807                    ret = -1;
808                    goto cleanup;
809            }
810    
811            if ((row = mysql_fetch_row(rs)))
812            {
813                    if (atoi(row[0]) != 0)
814                    {
815                            topic_locked = 1;
816                    }
817            }
818            mysql_free_result(rs);
819            rs = NULL;
820    
821            if (topic_locked) // Reply is not allowed
822            {
823                    mysql_close(db);
824                    db = NULL;
825    
826                    clearscr();
827                    moveto(1, 1);
828                    prints("该主题谢绝回复");
829                    press_any_key();
830    
831                    goto cleanup;
832            }
833    
834            snprintf(sql, sizeof(sql),
835                             "SELECT bbs_content.CID, bbs_content.content "
836                             "FROM bbs INNER JOIN bbs_content ON bbs.CID = bbs_content.CID "
837                             "WHERE bbs.AID = %d",
838                             p_article->aid);
839    
840            if (mysql_query(db, sql) != 0)
841            {
842                    log_error("Query article content error: %s\n", mysql_error(db));
843                    ret = -1;
844                    goto cleanup;
845            }
846            if ((rs = mysql_use_result(db)) == NULL)
847            {
848                    log_error("Get article content data failed\n");
849                    ret = -1;
850                    goto cleanup;
851            }
852    
853            if ((row = mysql_fetch_row(rs)))
854            {
855                    content = malloc(ARTICLE_CONTENT_MAX_LEN);
856                    if (content == NULL)
857                    {
858                            log_error("malloc(content) error: OOM\n");
859                            ret = -1;
860                            goto cleanup;
861                    }
862    
863                    content_f = malloc(ARTICLE_CONTENT_MAX_LEN);
864                    if (content_f == NULL)
865                    {
866                            log_error("malloc(content_f) error: OOM\n");
867                            ret = -1;
868                            goto cleanup;
869                    }
870    
871                    // Apply LML render to content body
872                    len = lml_render(row[1], content_f, ARTICLE_CONTENT_MAX_LEN, MAX_EDITOR_DATA_LINE_LENGTH - 3, 1);
873                    content_f[len] = '\0';
874    
875                    // Remove control sequence
876                    len = str_filter(content_f, 0);
877            }
878            mysql_free_result(rs);
879            rs = NULL;
880    
881            mysql_close(db);
882            db = NULL;
883    
884            // Set title and sign
885            for (ch = 'T'; !SYS_server_exit;)
886            {
887                    clearscr();
888                    moveto(21, 1);
889                    prints("回复文章于 %s[%s] 讨论区, 回复通知: %s, 引用模式: %s",
890                               p_section->stitle, p_section->sname,
891                               (reply_note ? "开启" : "关闭"),
892                               (full_quote ? "完整" : "精简"));
893                    moveto(22, 1);
894                    prints("标题: %s", (p_article_new->title[0] == '\0' ? "[无]" : p_article_new->title));
895                    moveto(23, 1);
896                    prints("使用第 %d 个签名", sign_id);
897    
898                    if (toupper(ch) != 'T')
899                    {
900                            prints("    按0~3选签名档(0表示不使用)");
901    
902                            moveto(24, 1);
903                            prints("T改标题, C取消, N%s, Q%s, Enter继续: ",
904                                       (reply_note ? "关闭回复通知" : "开启回复通知"), (full_quote ? "精简引用" : "完整引用"));
905                            iflush();
906                            ch = 0;
907                    }
908    
909                    while (!SYS_server_exit)
910                    {
911                            switch (toupper(ch))
912                            {
913                            case KEY_NULL:
914                            case KEY_TIMEOUT:
915                                    goto cleanup;
916                            case CR:
917                                    break;
918                            case 'T':
919                                    len = get_data(24, 1, "标题: ", title_input, sizeof(title_input), TITLE_INPUT_MAX_LEN);
920                                    for (p = title_input; *p == ' '; p++)
921                                            ;
922                                    for (q = title_input + len; q > p && *(q - 1) == ' '; q--)
923                                            ;
924                                    *q = '\0';
925                                    len = q - p;
926                                    if (*p != '\0')
927                                    {
928                                            if ((ret = check_badwords(p, '*')) < 0)
929                                            {
930                                                    log_error("check_badwords(title) error\n");
931                                            }
932                                            else if (ret > 0)
933                                            {
934                                                    memcpy(title_input, p, (size_t)len + 1);
935                                                    continue;
936                                            }
937                                            memcpy(p_article_new->title, p, (size_t)len + 1);
938                                            memcpy(title_input, p_article_new->title, (size_t)len + 1);
939                                    }
940                                    ch = 0;
941                                    break;
942                            case 'C':
943                                    clearscr();
944                                    moveto(1, 1);
945                                    prints("取消...");
946                                    press_any_key();
947                                    goto cleanup;
948                            case 'N':
949                                    reply_note = (reply_note ? 0 : 1);
950                                    break;
951                            case 'Q':
952                                    full_quote = (full_quote ? 0 : 1);
953                                    break;
954                            case '0':
955                            case '1':
956                            case '2':
957                            case '3':
958                                    sign_id = ch - '0';
959                                    break;
960                            default: // Invalid selection
961                                    ch = igetch_t(BBS_max_user_idle_time);
962                                    continue;
963                            }
964    
965                            break;
966                    }
967    
968                    if (ch != CR || p_article_new->title[0] == '\0')
969                    {
970                            continue;
971                    }
972    
973                    len = snprintf(content, ARTICLE_CONTENT_MAX_LEN,
974                                               "\n\n【 在 %s (%s) 的大作中提到: 】\n",
975                                               p_article->username, p_article->nickname);
976    
977                    quote_content_lines = split_data_lines(content_f,
978                                                                                               MAX_EDITOR_DATA_LINE_LENGTH - 2, line_offsets,
979                                                                                               (full_quote ? MAX_EDITOR_DATA_LINES : ARTICLE_QUOTE_DEFAULT_LINES) + 1,
980                                                                                               0, NULL);
981                    for (i = 0; i < quote_content_lines; i++)
982                    {
983                            memcpy(content + len, ": ", 2); // quote line prefix
984                            len += 2;
985                            memcpy(content + len, content_f + line_offsets[i], (size_t)(line_offsets[i + 1] - line_offsets[i]));
986                            len += (line_offsets[i + 1] - line_offsets[i]);
987                            if (content[len - 1] != '\n') // Appennd \n if not exist
988                            {
989                                    content[len] = '\n';
990                                    len++;
991                            }
992                    }
993                    if (content[len - 1] != '\n') // Appennd \n if not exist
994                    {
995                            content[len] = '\n';
996                            len++;
997                    }
998                    content[len] = '\0';
999    
1000                    free(content_f);
1001                    content_f = NULL;
1002    
1003                    p_editor_data = editor_data_load(content);
1004                    if (p_editor_data == NULL)
1005                    {
1006                            log_error("editor_data_load(aid=%d, cid=%d) error\n", p_article->aid, atoi(row[0]));
1007                            ret = -1;
1008                            goto cleanup;
1009                    }
1010    
1011                    free(content);
1012                    content = NULL;
1013    
1014                    for (ch = 'E'; !SYS_server_exit && toupper(ch) == 'E';)
1015                    {
1016                            editor_display(p_editor_data);
1017    
1018                            clearscr();
1019                            moveto(1, 1);
1020                            prints("(S)发送, (C)取消, (T)更改标题 or (E)再编辑? [S]: ");
1021                            iflush();
1022    
1023                            for (ch = 0; !SYS_server_exit; ch = igetch_t(BBS_max_user_idle_time))
1024                            {
1025                                    switch (toupper(ch))
1026                                    {
1027                                    case KEY_NULL:
1028                                    case KEY_TIMEOUT:
1029                                            goto cleanup;
1030                                    case CR:
1031                                    case 'S':
1032                                            break;
1033                                    case 'C':
1034                                            clearscr();
1035                                            moveto(1, 1);
1036                                            prints("取消...");
1037                                            press_any_key();
1038                                            goto cleanup;
1039                                    case 'T':
1040                                            break;
1041                                    case 'E':
1042                                            break;
1043                                    default: // Invalid selection
1044                                            continue;
1045                                    }
1046    
1047                                    break;
1048                            }
1049                    }
1050    
1051                    if (toupper(ch) != 'T')
1052                    {
1053                            break;
1054                    }
1055            }
1056    
1057            if (SYS_server_exit) // Do not save data on shutdown
1058          {          {
1059                  log_error("editor_data_load(aid=%d, cid=%d) error\n", p_article->aid, p_article->cid);                  goto cleanup;
                 return -2;  
1060          }          }
1061          if (article_cache_unload(&cache) < 0)  
1062            content = malloc(ARTICLE_CONTENT_MAX_LEN);
1063            if (content == NULL)
1064          {          {
1065                  log_error("article_cache_unload(aid=%d, cid=%d) error\n", p_article->aid, p_article->cid);                  log_error("malloc(content) error: OOM\n");
1066                  return -2;                  ret = -1;
1067                    goto cleanup;
1068          }          }
1069    
1070          editor_display(p_editor_data);          len_content = editor_data_save(p_editor_data, content, ARTICLE_CONTENT_MAX_LEN);
1071            if (len_content < 0)
1072            {
1073                    log_error("editor_data_save() error\n");
1074                    ret = -1;
1075                    goto cleanup;
1076            }
1077    
1078            if (check_badwords(content, '*') < 0)
1079            {
1080                    log_error("check_badwords(content) error\n");
1081                    ret = -1;
1082                    goto cleanup;
1083            }
1084    
1085            db = db_open();
1086            if (db == NULL)
1087            {
1088                    log_error("db_open() error: %s\n", mysql_error(db));
1089                    ret = -1;
1090                    goto cleanup;
1091            }
1092    
1093            if (sign_id > 0)
1094            {
1095                    snprintf(sql, sizeof(sql),
1096                                     "SELECT sign_%d AS sign FROM user_pubinfo WHERE UID = %d",
1097                                     sign_id, BBS_priv.uid);
1098    
1099          // editor_data_save(p_editor_data, p_data_new, data_new_len);                  if (mysql_query(db, sql) != 0)
1100                    {
1101                            log_error("Query sign error: %s\n", mysql_error(db));
1102                            ret = -1;
1103                            goto cleanup;
1104                    }
1105                    if ((rs = mysql_use_result(db)) == NULL)
1106                    {
1107                            log_error("Get sign data failed\n");
1108                            ret = -1;
1109                            goto cleanup;
1110                    }
1111    
1112                    if ((row = mysql_fetch_row(rs)))
1113                    {
1114                            len_content += snprintf(content + len_content,
1115                                                                            ARTICLE_CONTENT_MAX_LEN - (size_t)len_content,
1116                                                                            "\n\n--\n%s\n", row[0]);
1117                    }
1118                    mysql_free_result(rs);
1119                    rs = NULL;
1120            }
1121    
1122            // Calculate display length of content
1123            content_display_length = str_length(content, 1);
1124    
1125            // Begin transaction
1126            if (mysql_query(db, "SET autocommit=0") != 0)
1127            {
1128                    log_error("SET autocommit=0 error: %s\n", mysql_error(db));
1129                    ret = -1;
1130                    goto cleanup;
1131            }
1132    
1133            if (mysql_query(db, "BEGIN") != 0)
1134            {
1135                    log_error("Begin transaction error: %s\n", mysql_error(db));
1136                    ret = -1;
1137                    goto cleanup;
1138            }
1139    
1140            // Secure SQL parameters
1141            content_f = malloc((size_t)len_content * 2 + 1);
1142            if (content_f == NULL)
1143            {
1144                    log_error("malloc(content_f) error: OOM\n");
1145                    ret = -1;
1146                    goto cleanup;
1147            }
1148    
1149            mysql_real_escape_string(db, nickname_f, BBS_nickname, (unsigned long)strnlen(BBS_nickname, sizeof(BBS_nickname)));
1150            mysql_real_escape_string(db, title_f, p_article_new->title, strnlen(p_article_new->title, sizeof(p_article_new->title)));
1151            mysql_real_escape_string(db, content_f, content, (unsigned long)len_content);
1152    
1153            free(content);
1154            content = NULL;
1155    
1156            // Add content
1157            sql_content = malloc(SQL_BUFFER_LEN + (size_t)len_content * 2 + 1);
1158            if (sql_content == NULL)
1159            {
1160                    log_error("malloc(sql_content) error: OOM\n");
1161                    ret = -1;
1162                    goto cleanup;
1163            }
1164    
1165            snprintf(sql_content, SQL_BUFFER_LEN + (size_t)len_content * 2 + 1,
1166                             "INSERT INTO bbs_content(AID, content) values(0, '%s')",
1167                             content_f);
1168    
1169            free(content_f);
1170            content_f = NULL;
1171    
1172            if (mysql_query(db, sql_content) != 0)
1173            {
1174                    log_error("Add article content error: %s\n", mysql_error(db));
1175                    ret = -1;
1176                    goto cleanup;
1177            }
1178    
1179            p_article_new->cid = (int32_t)mysql_insert_id(db);
1180    
1181            free(sql_content);
1182            sql_content = NULL;
1183    
1184            // Add article
1185            snprintf(sql, sizeof(sql),
1186                             "INSERT INTO bbs(SID, TID, UID, username, nickname, title, CID, transship, "
1187                             "sub_dt, sub_ip, reply_note, exp, last_reply_dt, icon, length) "
1188                             "VALUES(%d, %d, %d, '%s', '%s', '%s', %d, 0, NOW(), '%s', %d, %d, NOW(), 1, %d)",
1189                             p_section->sid, (p_article->tid == 0 ? p_article->aid : p_article->tid),
1190                             BBS_priv.uid, BBS_username, nickname_f, title_f,
1191                             p_article_new->cid, hostaddr_client,
1192                             reply_note, BBS_user_exp, content_display_length);
1193    
1194            if (mysql_query(db, sql) != 0)
1195            {
1196                    log_error("Add article error: %s\n", mysql_error(db));
1197                    ret = -1;
1198                    goto cleanup;
1199            }
1200    
1201            p_article_new->aid = (int32_t)mysql_insert_id(db);
1202    
1203            // Update topic article
1204            snprintf(sql, sizeof(sql),
1205                             "UPDATE bbs SET reply_count = reply_count + 1, "
1206                             "last_reply_dt = NOW(), last_reply_UID=%d, last_reply_username = '%s', "
1207                             "last_reply_nickname = '%s' WHERE AID = %d",
1208                             BBS_priv.uid, BBS_username, nickname_f,
1209                             (p_article->tid == 0 ? p_article->aid : p_article->tid));
1210    
1211            if (mysql_query(db, sql) != 0)
1212            {
1213                    log_error("Update topic article error: %s\n", mysql_error(db));
1214                    ret = -1;
1215                    goto cleanup;
1216            }
1217    
1218            // Link content to article
1219            snprintf(sql, sizeof(sql),
1220                             "UPDATE bbs_content SET AID = %d WHERE CID = %d",
1221                             p_article_new->aid, p_article_new->cid);
1222    
1223            if (mysql_query(db, sql) != 0)
1224            {
1225                    log_error("Update content error: %s\n", mysql_error(db));
1226                    ret = -1;
1227                    goto cleanup;
1228            }
1229    
1230            // Notify the authors of the topic / article which is replyed.
1231            snprintf(sql, sizeof(sql),
1232                             "SELECT DISTINCT UID FROM bbs WHERE (AID = %d OR AID = %d) "
1233                             "AND visible AND reply_note AND UID <> %d",
1234                             p_article->tid, p_article->aid, BBS_priv.uid);
1235    
1236            if (mysql_query(db, sql) != 0)
1237            {
1238                    log_error("Read reply info error: %s\n", mysql_error(db));
1239                    ret = -1;
1240                    goto cleanup;
1241            }
1242            if ((rs = mysql_store_result(db)) == NULL)
1243            {
1244                    log_error("Get reply info failed\n");
1245                    ret = -1;
1246                    goto cleanup;
1247            }
1248    
1249            while ((row = mysql_fetch_row(rs)))
1250            {
1251                    // Send notification message
1252                    len_msg = snprintf(msg, BBS_msg_max_len,
1253                                                       "有人回复了您所发表/回复的文章,快来"
1254                                                       "[article %d]看看[/article]《%s》吧!\n",
1255                                                       p_article_new->aid, title_f);
1256    
1257                    mysql_real_escape_string(db, msg_f, msg, (unsigned long)len_msg);
1258    
1259                    snprintf(sql, sizeof(sql),
1260                                     "INSERT INTO bbs_msg(fromUID, toUID, content, send_dt, send_ip) "
1261                                     "VALUES(%d, %d, '%s', NOW(), '%s')",
1262                                     BBS_sys_id, atoi(row[0]), msg_f, hostaddr_client);
1263    
1264                    if (mysql_query(db, sql) != 0)
1265                    {
1266                            log_error("Insert msg error: %s\n", mysql_error(db));
1267                            ret = -1;
1268                            goto cleanup;
1269                    }
1270            }
1271            mysql_free_result(rs);
1272            rs = NULL;
1273    
1274            // Add exp
1275            if (checkpriv(&BBS_priv, p_section->sid, S_GETEXP)) // Except in test section
1276            {
1277                    snprintf(sql, sizeof(sql),
1278                                     "UPDATE user_pubinfo SET exp = exp + %d WHERE UID = %d",
1279                                     3, BBS_priv.uid);
1280    
1281                    if (mysql_query(db, sql) != 0)
1282                    {
1283                            log_error("Update exp error: %s\n", mysql_error(db));
1284                            ret = -1;
1285                            goto cleanup;
1286                    }
1287            }
1288    
1289            // Add log
1290            snprintf(sql, sizeof(sql),
1291                             "INSERT INTO bbs_article_op(AID, UID, type, op_dt, op_ip)"
1292                             "VALUES(%d, %d, 'A', NOW(), '%s')",
1293                             p_article_new->aid, BBS_priv.uid, hostaddr_client);
1294    
1295            if (mysql_query(db, sql) != 0)
1296            {
1297                    log_error("Add log error: %s\n", mysql_error(db));
1298                    ret = -1;
1299                    goto cleanup;
1300            }
1301    
1302            // Commit transaction
1303            if (mysql_query(db, "COMMIT") != 0)
1304            {
1305                    log_error("Commit transaction error: %s\n", mysql_error(db));
1306                    ret = -1;
1307                    goto cleanup;
1308            }
1309    
1310            mysql_close(db);
1311            db = NULL;
1312    
1313            clearscr();
1314            moveto(1, 1);
1315            prints("发送完成,新文章通常会在%d秒后可见", BBS_section_list_load_interval);
1316            press_any_key();
1317            ret = 1; // Success
1318    
1319    cleanup:
1320            mysql_free_result(rs);
1321            mysql_close(db);
1322    
1323            // Cleanup buffers
1324          editor_data_cleanup(p_editor_data);          editor_data_cleanup(p_editor_data);
1325    
1326          return 0;          free(sql_content);
1327            free(content);
1328            free(content_f);
1329    
1330            return (int)ret;
1331  }  }


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

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