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


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

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