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

Annotation of /lbbs/src/article_post.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.41 - (hide annotations)
Fri Nov 7 06:41:43 2025 UTC (4 months, 1 week ago) by sysadm
Branch: MAIN
Changes since 1.40: +44 -2 lines
Content type: text/x-csrc
Apply BWF to article post / reply / modify

1 sysadm 1.37 /* SPDX-License-Identifier: GPL-3.0-or-later */
2     /*
3     * article_post
4     * - user interactive feature to post / modify / reply article
5     *
6 sysadm 1.38 * Copyright (C) 2004-2025 Leaflet <leaflet@leafok.com>
7 sysadm 1.37 */
8 sysadm 1.1
9 sysadm 1.22 #include "article_cache.h"
10 sysadm 1.1 #include "article_post.h"
11 sysadm 1.22 #include "bbs.h"
12 sysadm 1.41 #include "bwf.h"
13 sysadm 1.22 #include "database.h"
14 sysadm 1.1 #include "editor.h"
15 sysadm 1.22 #include "io.h"
16 sysadm 1.1 #include "log.h"
17 sysadm 1.6 #include "lml.h"
18 sysadm 1.22 #include "screen.h"
19 sysadm 1.8 #include "user_priv.h"
20 sysadm 1.3 #include <ctype.h>
21     #include <string.h>
22 sysadm 1.6 #include <stdlib.h>
23 sysadm 1.8 #include <time.h>
24 sysadm 1.1
25 sysadm 1.40 enum _article_post_constant_t
26     {
27     TITLE_INPUT_MAX_LEN = 72,
28     ARTICLE_QUOTE_MAX_LINES = 20,
29     MODIFY_DT_MAX_LEN = 50,
30     };
31 sysadm 1.8
32     int article_post(const SECTION_LIST *p_section, ARTICLE *p_article_new)
33 sysadm 1.1 {
34 sysadm 1.8 MYSQL *db = NULL;
35     MYSQL_RES *rs = NULL;
36     MYSQL_ROW row;
37     char sql[SQL_BUFFER_LEN];
38     char *sql_content = NULL;
39 sysadm 1.6 EDITOR_DATA *p_editor_data = NULL;
40 sysadm 1.24 char title_input[BBS_article_title_max_len + 1];
41 sysadm 1.8 char title_f[BBS_article_title_max_len * 2 + 1];
42     char *content = NULL;
43     char *content_f = NULL;
44     long len_content;
45 sysadm 1.24 int content_display_length;
46 sysadm 1.8 char nickname_f[BBS_nickname_max_len * 2 + 1];
47 sysadm 1.3 int sign_id = 0;
48 sysadm 1.29 int reply_note = 1;
49 sysadm 1.3 long len;
50     int ch;
51     char *p, *q;
52 sysadm 1.8 long ret = 0;
53 sysadm 1.3
54 sysadm 1.8 if (p_section == NULL || p_article_new == NULL)
55 sysadm 1.3 {
56     log_error("NULL pointer error\n");
57     }
58 sysadm 1.2
59 sysadm 1.12 if (!checkpriv(&BBS_priv, p_section->sid, S_POST))
60     {
61     clearscr();
62     moveto(1, 1);
63 sysadm 1.24 prints("您没有权限在本版块发表文章\n");
64 sysadm 1.12 press_any_key();
65    
66     return 0;
67     }
68    
69 sysadm 1.8 p_article_new->title[0] = '\0';
70 sysadm 1.6 title_input[0] = '\0';
71 sysadm 1.8 p_article_new->transship = 0;
72 sysadm 1.6
73 sysadm 1.3 p_editor_data = editor_data_load("");
74     if (p_editor_data == NULL)
75     {
76     log_error("editor_data_load() error\n");
77 sysadm 1.16 ret = -1;
78     goto cleanup;
79 sysadm 1.3 }
80 sysadm 1.1
81 sysadm 1.3 // Set title and sign
82     for (ch = 'T'; !SYS_server_exit;)
83 sysadm 1.2 {
84 sysadm 1.3 clearscr();
85     moveto(21, 1);
86 sysadm 1.32 prints("发表文章于 %s[%s] 讨论区,类型: %s,回复通知:%s",
87 sysadm 1.29 p_section->stitle, p_section->sname,
88     (p_article_new->transship ? "转载" : "原创"),
89     (reply_note ? "开启" : "关闭"));
90 sysadm 1.3 moveto(22, 1);
91 sysadm 1.24 prints("标题: %s", (p_article_new->title[0] == '\0' ? "[无]" : p_article_new->title));
92 sysadm 1.3 moveto(23, 1);
93 sysadm 1.24 prints("使用第 %d 个签名", sign_id);
94 sysadm 1.3
95     if (toupper(ch) != 'T')
96 sysadm 1.2 {
97 sysadm 1.24 prints(" 按0~3选签名档(0表示不使用)");
98 sysadm 1.3
99     moveto(24, 1);
100 sysadm 1.29 prints("T改标题, C取消, Z设为%s, N%s, Enter继续: ",
101     (p_article_new->transship ? "原创" : "转载"),
102 sysadm 1.32 (reply_note ? "关闭回复通知" : "开启回复通知"));
103 sysadm 1.3 iflush();
104     ch = 0;
105 sysadm 1.2 }
106 sysadm 1.3
107 sysadm 1.41 while (!SYS_server_exit)
108 sysadm 1.2 {
109 sysadm 1.3 switch (toupper(ch))
110     {
111 sysadm 1.19 case KEY_NULL:
112     case KEY_TIMEOUT:
113     goto cleanup;
114 sysadm 1.3 case CR:
115     break;
116     case 'T':
117 sysadm 1.27 len = get_data(24, 1, "标题: ", title_input, sizeof(title_input), TITLE_INPUT_MAX_LEN);
118 sysadm 1.3 for (p = title_input; *p == ' '; p++)
119     ;
120     for (q = title_input + len; q > p && *(q - 1) == ' '; q--)
121     ;
122     *q = '\0';
123     len = q - p;
124     if (*p != '\0')
125     {
126 sysadm 1.41 if ((ret = check_badwords(p, '*')) < 0)
127     {
128     log_error("check_badwords(title) error\n");
129     }
130     else if (ret > 0)
131     {
132     memcpy(title_input, p, (size_t)len + 1);
133     continue;
134     }
135 sysadm 1.8 memcpy(p_article_new->title, p, (size_t)len + 1);
136     memcpy(title_input, p_article_new->title, (size_t)len + 1);
137 sysadm 1.3 }
138 sysadm 1.4 ch = 0;
139 sysadm 1.3 break;
140     case 'C':
141     clearscr();
142     moveto(1, 1);
143 sysadm 1.24 prints("取消...");
144 sysadm 1.3 press_any_key();
145     goto cleanup;
146 sysadm 1.29 case 'Z':
147     p_article_new->transship = (p_article_new->transship ? 0 : 1);
148 sysadm 1.8 break;
149 sysadm 1.29 case 'N':
150     reply_note = (reply_note ? 0 : 1);
151 sysadm 1.8 break;
152 sysadm 1.3 case '0':
153     case '1':
154     case '2':
155     case '3':
156     sign_id = ch - '0';
157     break;
158     default: // Invalid selection
159 sysadm 1.41 ch = igetch_t(BBS_max_user_idle_time);
160 sysadm 1.3 continue;
161     }
162    
163     break;
164 sysadm 1.2 }
165 sysadm 1.3
166 sysadm 1.8 if (ch != CR || p_article_new->title[0] == '\0')
167 sysadm 1.2 {
168 sysadm 1.3 continue;
169 sysadm 1.2 }
170 sysadm 1.3
171     for (ch = 'E'; !SYS_server_exit && toupper(ch) == 'E';)
172 sysadm 1.2 {
173 sysadm 1.3 editor_display(p_editor_data);
174    
175     clearscr();
176     moveto(1, 1);
177 sysadm 1.24 prints("(S)发送, (C)取消, (T)更改标题 or (E)再编辑? [S]: ");
178 sysadm 1.3 iflush();
179    
180 sysadm 1.39 for (ch = 0; !SYS_server_exit; ch = igetch_t(BBS_max_user_idle_time))
181 sysadm 1.3 {
182     switch (toupper(ch))
183     {
184 sysadm 1.19 case KEY_NULL:
185     case KEY_TIMEOUT:
186     goto cleanup;
187 sysadm 1.3 case CR:
188     case 'S':
189     break;
190     case 'C':
191     clearscr();
192     moveto(1, 1);
193 sysadm 1.24 prints("取消...");
194 sysadm 1.3 press_any_key();
195     goto cleanup;
196     case 'T':
197     break;
198     case 'E':
199     break;
200     default: // Invalid selection
201     continue;
202     }
203    
204     break;
205     }
206 sysadm 1.2 }
207 sysadm 1.5
208     if (toupper(ch) != 'T')
209     {
210     break;
211     }
212 sysadm 1.3 }
213    
214 sysadm 1.19 if (SYS_server_exit) // Do not save data on shutdown
215     {
216     goto cleanup;
217     }
218    
219 sysadm 1.8 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 sysadm 1.16 ret = -1;
232 sysadm 1.8 goto cleanup;
233     }
234    
235 sysadm 1.41 if (check_badwords(content, '*') < 0)
236     {
237     log_error("check_badwords(content) error\n");
238     ret = -1;
239     goto cleanup;
240     }
241    
242 sysadm 1.8 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 sysadm 1.24 // Calculate display length of content
280     content_display_length = str_length(content, 1);
281    
282 sysadm 1.8 // 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 sysadm 1.13 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 sysadm 1.8 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 sysadm 1.13 free(content);
311     content = NULL;
312    
313 sysadm 1.8 // Add content
314 sysadm 1.13 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 sysadm 1.8 "INSERT INTO bbs_content(AID, content) values(0, '%s')",
324     content_f);
325    
326 sysadm 1.13 free(content_f);
327     content_f = NULL;
328    
329     if (mysql_query(db, sql_content) != 0)
330 sysadm 1.8 {
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 sysadm 1.13 free(sql_content);
339     sql_content = NULL;
340    
341 sysadm 1.8 // 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 sysadm 1.29 "VALUES(%d, 0, %d, '%s', '%s', '%s', %d, %d, NOW(), '%s', %d, %d, NOW(), 1, %d)",
346 sysadm 1.8 p_section->sid, BBS_priv.uid, BBS_username, nickname_f, title_f,
347 sysadm 1.29 p_article_new->cid, p_article_new->transship, hostaddr_client,
348     reply_note, BBS_user_exp, content_display_length);
349 sysadm 1.8
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 sysadm 1.17 mysql_close(db);
408     db = NULL;
409    
410 sysadm 1.8 clearscr();
411     moveto(1, 1);
412 sysadm 1.24 prints("发送完成,新文章通常会在%d秒后可见", BBS_section_list_load_interval);
413 sysadm 1.8 press_any_key();
414     ret = 1; // Success
415 sysadm 1.3
416     cleanup:
417 sysadm 1.8 mysql_close(db);
418    
419     // Cleanup buffers
420 sysadm 1.3 editor_data_cleanup(p_editor_data);
421    
422 sysadm 1.8 free(sql_content);
423     free(content);
424     free(content_f);
425    
426     return (int)ret;
427 sysadm 1.3 }
428    
429 sysadm 1.8 int article_modify(const SECTION_LIST *p_section, const ARTICLE *p_article, ARTICLE *p_article_new)
430 sysadm 1.3 {
431 sysadm 1.8 MYSQL *db = NULL;
432     MYSQL_RES *rs = NULL;
433 sysadm 1.6 MYSQL_ROW row;
434     char sql[SQL_BUFFER_LEN];
435 sysadm 1.8 char *sql_content = NULL;
436     char *content = NULL;
437     char *content_f = NULL;
438     long len_content;
439 sysadm 1.24 int content_display_length;
440 sysadm 1.29 int reply_note = 1;
441 sysadm 1.6 int ch;
442 sysadm 1.8 long ret = 0;
443     time_t now;
444     struct tm tm_modify_dt;
445     char str_modify_dt[MODIFY_DT_MAX_LEN + 1];
446 sysadm 1.6
447     EDITOR_DATA *p_editor_data = NULL;
448 sysadm 1.3
449     if (p_section == NULL || p_article == NULL)
450     {
451     log_error("NULL pointer error\n");
452     }
453    
454 sysadm 1.8 if (p_article->excerption) // Modify is not allowed
455     {
456     clearscr();
457     moveto(1, 1);
458 sysadm 1.24 prints("该文章无法被编辑,请联系版主。");
459 sysadm 1.8 press_any_key();
460    
461     return 0;
462     }
463    
464 sysadm 1.6 db = db_open();
465     if (db == NULL)
466 sysadm 1.3 {
467 sysadm 1.6 log_error("db_open() error: %s\n", mysql_error(db));
468 sysadm 1.16 ret = -1;
469     goto cleanup;
470 sysadm 1.6 }
471    
472     snprintf(sql, sizeof(sql),
473 sysadm 1.29 "SELECT bbs_content.CID, bbs_content.content, reply_note "
474 sysadm 1.6 "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 sysadm 1.16 ret = -1;
482 sysadm 1.8 goto cleanup;
483 sysadm 1.3 }
484 sysadm 1.6 if ((rs = mysql_use_result(db)) == NULL)
485 sysadm 1.3 {
486 sysadm 1.6 log_error("Get article content data failed\n");
487 sysadm 1.16 ret = -1;
488 sysadm 1.8 goto cleanup;
489 sysadm 1.3 }
490 sysadm 1.5
491 sysadm 1.6 if ((row = mysql_fetch_row(rs)))
492 sysadm 1.3 {
493 sysadm 1.13 content = malloc(ARTICLE_CONTENT_MAX_LEN);
494     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 sysadm 1.20 len_content = str_filter(content, 0);
506 sysadm 1.13
507     p_editor_data = editor_data_load(content);
508 sysadm 1.6 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 sysadm 1.16 ret = -1;
512 sysadm 1.8 goto cleanup;
513 sysadm 1.6 }
514 sysadm 1.13
515     free(content);
516     content = NULL;
517 sysadm 1.29
518     reply_note = atoi(row[2]);
519 sysadm 1.3 }
520 sysadm 1.6 mysql_free_result(rs);
521 sysadm 1.8 rs = NULL;
522    
523 sysadm 1.6 mysql_close(db);
524 sysadm 1.8 db = NULL;
525 sysadm 1.3
526 sysadm 1.6 for (ch = 'E'; !SYS_server_exit && toupper(ch) == 'E';)
527     {
528     editor_display(p_editor_data);
529    
530 sysadm 1.29 while (!SYS_server_exit)
531     {
532     clearscr();
533     moveto(1, 1);
534 sysadm 1.32 prints("(S)保存, (C)取消, (N)%s回复通知 or (E)再编辑? [S]: ",
535 sysadm 1.29 (reply_note ? "关闭" : "开启"));
536     iflush();
537 sysadm 1.6
538 sysadm 1.39 ch = igetch_t(BBS_max_user_idle_time);
539 sysadm 1.6 switch (toupper(ch))
540     {
541 sysadm 1.19 case KEY_NULL:
542     case KEY_TIMEOUT:
543     goto cleanup;
544 sysadm 1.6 case CR:
545     case 'S':
546     break;
547     case 'C':
548     clearscr();
549     moveto(1, 1);
550 sysadm 1.24 prints("取消...");
551 sysadm 1.6 press_any_key();
552     goto cleanup;
553 sysadm 1.29 case 'N':
554     reply_note = (reply_note ? 0 : 1);
555     continue;
556 sysadm 1.6 case 'E':
557     break;
558     default: // Invalid selection
559     continue;
560     }
561    
562     break;
563     }
564     }
565 sysadm 1.3
566 sysadm 1.19 if (SYS_server_exit) // Do not save data on shutdown
567     {
568     goto cleanup;
569     }
570    
571 sysadm 1.8 // 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     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 sysadm 1.16 ret = -1;
585 sysadm 1.8 goto cleanup;
586     }
587    
588 sysadm 1.41 if (check_badwords(content, '*') < 0)
589     {
590     log_error("check_badwords(content) error\n");
591     ret = -1;
592     goto cleanup;
593     }
594    
595 sysadm 1.8 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 sysadm 1.24 "\n--\n※ 作者已于 %s 修改本文※\n",
601 sysadm 1.8 str_modify_dt);
602    
603 sysadm 1.24 // Calculate display length of content
604     content_display_length = str_length(content, 1);
605    
606 sysadm 1.8 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 sysadm 1.13 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 sysadm 1.8 mysql_real_escape_string(db, content_f, content, (unsigned long)len_content);
639    
640 sysadm 1.13 free(content);
641     content = NULL;
642    
643 sysadm 1.8 // Add content
644 sysadm 1.13 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 sysadm 1.8 "INSERT INTO bbs_content(AID, content) values(%d, '%s')",
654     p_article->aid, content_f);
655    
656 sysadm 1.13 free(content_f);
657     content_f = NULL;
658    
659     if (mysql_query(db, sql_content) != 0)
660 sysadm 1.8 {
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 sysadm 1.13 free(sql_content);
669     sql_content = NULL;
670    
671 sysadm 1.8 // Update article
672     snprintf(sql, sizeof(sql),
673 sysadm 1.29 "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 sysadm 1.8
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 sysadm 1.17 mysql_close(db);
712     db = NULL;
713    
714 sysadm 1.8 clearscr();
715     moveto(1, 1);
716 sysadm 1.24 prints("修改完成,新内容通常会在%d秒后可见", BBS_section_list_load_interval);
717 sysadm 1.8 press_any_key();
718     ret = 1; // Success
719 sysadm 1.3
720 sysadm 1.6 cleanup:
721 sysadm 1.13 mysql_free_result(rs);
722 sysadm 1.8 mysql_close(db);
723    
724     // Cleanup buffers
725 sysadm 1.3 editor_data_cleanup(p_editor_data);
726    
727 sysadm 1.8 free(sql_content);
728     free(content);
729     free(content_f);
730    
731     return (int)ret;
732 sysadm 1.3 }
733    
734 sysadm 1.8 int article_reply(const SECTION_LIST *p_section, const ARTICLE *p_article, ARTICLE *p_article_new)
735 sysadm 1.3 {
736 sysadm 1.8 MYSQL *db = NULL;
737     MYSQL_RES *rs = NULL;
738 sysadm 1.6 MYSQL_ROW row;
739 sysadm 1.8 long line_offsets[ARTICLE_QUOTE_MAX_LINES + 1];
740 sysadm 1.6 char sql[SQL_BUFFER_LEN];
741 sysadm 1.8 char *sql_content = NULL;
742 sysadm 1.6 EDITOR_DATA *p_editor_data = NULL;
743 sysadm 1.8 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 sysadm 1.24 int content_display_length;
749 sysadm 1.8 char nickname_f[BBS_nickname_max_len * 2 + 1];
750 sysadm 1.6 int sign_id = 0;
751 sysadm 1.30 int reply_note = 0;
752 sysadm 1.6 long len;
753     int ch;
754     char *p, *q;
755     int eol;
756     int display_len;
757     long quote_content_lines;
758     long i;
759 sysadm 1.8 long ret = 0;
760 sysadm 1.14 int topic_locked = 0;
761 sysadm 1.28 char msg[BBS_msg_max_len];
762     char msg_f[BBS_msg_max_len * 2 + 1];
763     int len_msg;
764 sysadm 1.3
765     if (p_section == NULL || p_article == NULL)
766     {
767     log_error("NULL pointer error\n");
768     }
769    
770 sysadm 1.12 if (!checkpriv(&BBS_priv, p_section->sid, S_POST))
771     {
772     clearscr();
773     moveto(1, 1);
774 sysadm 1.24 prints("您没有权限在本版块发表文章\n");
775 sysadm 1.12 press_any_key();
776    
777     return 0;
778     }
779    
780 sysadm 1.8 p_article_new->title[0] = '\0';
781 sysadm 1.6 snprintf(title_input, sizeof(title_input), "Re: %s", p_article->title);
782 sysadm 1.20 len = split_line(title_input, TITLE_INPUT_MAX_LEN, &eol, &display_len, 0);
783 sysadm 1.6 title_input[len] = '\0';
784    
785     db = db_open();
786     if (db == NULL)
787     {
788     log_error("db_open() error: %s\n", mysql_error(db));
789 sysadm 1.16 ret = -1;
790     goto cleanup;
791 sysadm 1.6 }
792    
793     snprintf(sql, sizeof(sql),
794 sysadm 1.14 "SELECT `lock` FROM bbs WHERE AID = %d",
795     (p_article->tid == 0 ? p_article->aid : p_article->tid));
796    
797     if (mysql_query(db, sql) != 0)
798     {
799     log_error("Query article status error: %s\n", mysql_error(db));
800 sysadm 1.16 ret = -1;
801     goto cleanup;
802 sysadm 1.14 }
803     if ((rs = mysql_store_result(db)) == NULL)
804     {
805     log_error("Get article status data failed\n");
806 sysadm 1.16 ret = -1;
807     goto cleanup;
808 sysadm 1.14 }
809    
810     if ((row = mysql_fetch_row(rs)))
811     {
812     if (atoi(row[0]) != 0)
813     {
814     topic_locked = 1;
815     }
816     }
817     mysql_free_result(rs);
818     rs = NULL;
819    
820     if (topic_locked) // Reply is not allowed
821     {
822 sysadm 1.17 mysql_close(db);
823     db = NULL;
824 sysadm 1.18
825 sysadm 1.14 clearscr();
826     moveto(1, 1);
827 sysadm 1.24 prints("该主题谢绝回复");
828 sysadm 1.14 press_any_key();
829    
830     goto cleanup;
831     }
832    
833     snprintf(sql, sizeof(sql),
834 sysadm 1.6 "SELECT bbs_content.CID, bbs_content.content "
835     "FROM bbs INNER JOIN bbs_content ON bbs.CID = bbs_content.CID "
836     "WHERE bbs.AID = %d",
837     p_article->aid);
838    
839     if (mysql_query(db, sql) != 0)
840 sysadm 1.3 {
841 sysadm 1.6 log_error("Query article content error: %s\n", mysql_error(db));
842 sysadm 1.16 ret = -1;
843     goto cleanup;
844 sysadm 1.6 }
845     if ((rs = mysql_use_result(db)) == NULL)
846     {
847     log_error("Get article content data failed\n");
848 sysadm 1.16 ret = -1;
849     goto cleanup;
850 sysadm 1.3 }
851 sysadm 1.5
852 sysadm 1.6 if ((row = mysql_fetch_row(rs)))
853     {
854 sysadm 1.8 content = malloc(ARTICLE_CONTENT_MAX_LEN);
855     if (content == NULL)
856     {
857     log_error("malloc(content) error: OOM\n");
858     ret = -1;
859     goto cleanup;
860     }
861    
862     content_f = malloc(ARTICLE_CONTENT_MAX_LEN);
863     if (content_f == NULL)
864     {
865     log_error("malloc(content_f) error: OOM\n");
866     ret = -1;
867     goto cleanup;
868     }
869    
870 sysadm 1.6 // Apply LML render to content body
871 sysadm 1.36 len = lml_render(row[1], content_f, ARTICLE_CONTENT_MAX_LEN, MAX_EDITOR_DATA_LINE_LENGTH - 3, 1);
872 sysadm 1.6 content_f[len] = '\0';
873    
874 sysadm 1.7 // Remove control sequence
875 sysadm 1.20 len = str_filter(content_f, 0);
876 sysadm 1.7
877 sysadm 1.8 len = snprintf(content, ARTICLE_CONTENT_MAX_LEN,
878 sysadm 1.24 "\n\n【 在 %s (%s) 的大作中提到: 】\n",
879 sysadm 1.8 p_article->username, p_article->nickname);
880 sysadm 1.7
881 sysadm 1.36 quote_content_lines = split_data_lines(content_f, MAX_EDITOR_DATA_LINE_LENGTH - 2, line_offsets, ARTICLE_QUOTE_MAX_LINES + 1, 0, NULL);
882 sysadm 1.7 for (i = 0; i < quote_content_lines; i++)
883 sysadm 1.6 {
884     memcpy(content + len, ": ", 2); // quote line prefix
885     len += 2;
886     memcpy(content + len, content_f + line_offsets[i], (size_t)(line_offsets[i + 1] - line_offsets[i]));
887     len += (line_offsets[i + 1] - line_offsets[i]);
888 sysadm 1.18 if (content[len - 1] != '\n') // Appennd \n if not exist
889     {
890     content[len] = '\n';
891     len++;
892     }
893 sysadm 1.6 }
894 sysadm 1.9 if (content[len - 1] != '\n') // Appennd \n if not exist
895     {
896     content[len] = '\n';
897     len++;
898     }
899 sysadm 1.6 content[len] = '\0';
900 sysadm 1.8
901     free(content_f);
902     content_f = NULL;
903    
904     p_editor_data = editor_data_load(content);
905     if (p_editor_data == NULL)
906     {
907     log_error("editor_data_load(aid=%d, cid=%d) error\n", p_article->aid, atoi(row[0]));
908 sysadm 1.16 ret = -1;
909 sysadm 1.8 goto cleanup;
910     }
911    
912     free(content);
913     content = NULL;
914 sysadm 1.6 }
915     mysql_free_result(rs);
916 sysadm 1.8 rs = NULL;
917    
918 sysadm 1.6 mysql_close(db);
919 sysadm 1.8 db = NULL;
920 sysadm 1.5
921 sysadm 1.6 // Set title and sign
922     for (ch = 'T'; !SYS_server_exit;)
923 sysadm 1.3 {
924 sysadm 1.6 clearscr();
925     moveto(21, 1);
926 sysadm 1.32 prints("回复文章于 %s[%s] 讨论区,回复通知:%s", p_section->stitle, p_section->sname, (reply_note ? "开启" : "关闭"));
927 sysadm 1.6 moveto(22, 1);
928 sysadm 1.24 prints("标题: %s", (p_article_new->title[0] == '\0' ? "[无]" : p_article_new->title));
929 sysadm 1.6 moveto(23, 1);
930 sysadm 1.24 prints("使用第 %d 个签名", sign_id);
931 sysadm 1.6
932     if (toupper(ch) != 'T')
933     {
934 sysadm 1.24 prints(" 按0~3选签名档(0表示不使用)");
935 sysadm 1.6
936     moveto(24, 1);
937 sysadm 1.29 prints("T改标题, C取消, N%s, Enter继续: ",
938 sysadm 1.32 (reply_note ? "关闭回复通知" : "开启回复通知"));
939 sysadm 1.6 iflush();
940     ch = 0;
941     }
942    
943 sysadm 1.41 while (!SYS_server_exit)
944 sysadm 1.6 {
945     switch (toupper(ch))
946     {
947 sysadm 1.19 case KEY_NULL:
948     case KEY_TIMEOUT:
949     goto cleanup;
950 sysadm 1.6 case CR:
951     break;
952     case 'T':
953 sysadm 1.27 len = get_data(24, 1, "标题: ", title_input, sizeof(title_input), TITLE_INPUT_MAX_LEN);
954 sysadm 1.6 for (p = title_input; *p == ' '; p++)
955     ;
956     for (q = title_input + len; q > p && *(q - 1) == ' '; q--)
957     ;
958     *q = '\0';
959     len = q - p;
960     if (*p != '\0')
961     {
962 sysadm 1.41 if ((ret = check_badwords(p, '*')) < 0)
963     {
964     log_error("check_badwords(title) error\n");
965     }
966     else if (ret > 0)
967     {
968     memcpy(title_input, p, (size_t)len + 1);
969     continue;
970     }
971 sysadm 1.8 memcpy(p_article_new->title, p, (size_t)len + 1);
972     memcpy(title_input, p_article_new->title, (size_t)len + 1);
973 sysadm 1.6 }
974     ch = 0;
975     break;
976     case 'C':
977     clearscr();
978     moveto(1, 1);
979 sysadm 1.24 prints("取消...");
980 sysadm 1.6 press_any_key();
981     goto cleanup;
982 sysadm 1.29 case 'N':
983     reply_note = (reply_note ? 0 : 1);
984     break;
985 sysadm 1.6 case '0':
986     case '1':
987     case '2':
988     case '3':
989     sign_id = ch - '0';
990     break;
991     default: // Invalid selection
992 sysadm 1.41 ch = igetch_t(BBS_max_user_idle_time);
993 sysadm 1.6 continue;
994     }
995    
996     break;
997     }
998    
999 sysadm 1.8 if (ch != CR || p_article_new->title[0] == '\0')
1000 sysadm 1.6 {
1001     continue;
1002     }
1003    
1004     for (ch = 'E'; !SYS_server_exit && toupper(ch) == 'E';)
1005     {
1006     editor_display(p_editor_data);
1007    
1008     clearscr();
1009     moveto(1, 1);
1010 sysadm 1.24 prints("(S)发送, (C)取消, (T)更改标题 or (E)再编辑? [S]: ");
1011 sysadm 1.6 iflush();
1012    
1013 sysadm 1.39 for (ch = 0; !SYS_server_exit; ch = igetch_t(BBS_max_user_idle_time))
1014 sysadm 1.6 {
1015     switch (toupper(ch))
1016     {
1017 sysadm 1.19 case KEY_NULL:
1018     case KEY_TIMEOUT:
1019     goto cleanup;
1020 sysadm 1.6 case CR:
1021     case 'S':
1022     break;
1023     case 'C':
1024     clearscr();
1025     moveto(1, 1);
1026 sysadm 1.24 prints("取消...");
1027 sysadm 1.6 press_any_key();
1028     goto cleanup;
1029     case 'T':
1030     break;
1031     case 'E':
1032     break;
1033     default: // Invalid selection
1034     continue;
1035     }
1036    
1037     break;
1038     }
1039     }
1040    
1041     if (toupper(ch) != 'T')
1042     {
1043     break;
1044     }
1045 sysadm 1.2 }
1046    
1047 sysadm 1.19 if (SYS_server_exit) // Do not save data on shutdown
1048     {
1049     goto cleanup;
1050     }
1051    
1052 sysadm 1.8 content = malloc(ARTICLE_CONTENT_MAX_LEN);
1053     if (content == NULL)
1054     {
1055     log_error("malloc(content) error: OOM\n");
1056     ret = -1;
1057     goto cleanup;
1058     }
1059    
1060     len_content = editor_data_save(p_editor_data, content, ARTICLE_CONTENT_MAX_LEN);
1061     if (len_content < 0)
1062     {
1063     log_error("editor_data_save() error\n");
1064 sysadm 1.16 ret = -1;
1065 sysadm 1.8 goto cleanup;
1066     }
1067    
1068 sysadm 1.41 if (check_badwords(content, '*') < 0)
1069     {
1070     log_error("check_badwords(content) error\n");
1071     ret = -1;
1072     goto cleanup;
1073     }
1074    
1075 sysadm 1.8 db = db_open();
1076     if (db == NULL)
1077     {
1078     log_error("db_open() error: %s\n", mysql_error(db));
1079     ret = -1;
1080     goto cleanup;
1081     }
1082    
1083     if (sign_id > 0)
1084     {
1085     snprintf(sql, sizeof(sql),
1086     "SELECT sign_%d AS sign FROM user_pubinfo WHERE UID = %d",
1087     sign_id, BBS_priv.uid);
1088    
1089     if (mysql_query(db, sql) != 0)
1090     {
1091     log_error("Query sign error: %s\n", mysql_error(db));
1092     ret = -1;
1093     goto cleanup;
1094     }
1095     if ((rs = mysql_use_result(db)) == NULL)
1096     {
1097     log_error("Get sign data failed\n");
1098     ret = -1;
1099     goto cleanup;
1100     }
1101    
1102     if ((row = mysql_fetch_row(rs)))
1103     {
1104     len_content += snprintf(content + len_content,
1105     ARTICLE_CONTENT_MAX_LEN - (size_t)len_content,
1106     "\n\n--\n%s\n", row[0]);
1107     }
1108     mysql_free_result(rs);
1109     rs = NULL;
1110     }
1111    
1112 sysadm 1.24 // Calculate display length of content
1113     content_display_length = str_length(content, 1);
1114    
1115 sysadm 1.8 // Begin transaction
1116     if (mysql_query(db, "SET autocommit=0") != 0)
1117     {
1118     log_error("SET autocommit=0 error: %s\n", mysql_error(db));
1119     ret = -1;
1120     goto cleanup;
1121     }
1122    
1123     if (mysql_query(db, "BEGIN") != 0)
1124     {
1125     log_error("Begin transaction error: %s\n", mysql_error(db));
1126     ret = -1;
1127     goto cleanup;
1128     }
1129    
1130     // Secure SQL parameters
1131 sysadm 1.13 content_f = malloc((size_t)len_content * 2 + 1);
1132     if (content_f == NULL)
1133     {
1134     log_error("malloc(content_f) error: OOM\n");
1135     ret = -1;
1136     goto cleanup;
1137     }
1138    
1139 sysadm 1.8 mysql_real_escape_string(db, nickname_f, BBS_nickname, (unsigned long)strnlen(BBS_nickname, sizeof(BBS_nickname)));
1140     mysql_real_escape_string(db, title_f, p_article_new->title, strnlen(p_article_new->title, sizeof(p_article_new->title)));
1141     mysql_real_escape_string(db, content_f, content, (unsigned long)len_content);
1142    
1143 sysadm 1.13 free(content);
1144     content = NULL;
1145    
1146 sysadm 1.8 // Add content
1147 sysadm 1.13 sql_content = malloc(SQL_BUFFER_LEN + (size_t)len_content * 2 + 1);
1148     if (sql_content == NULL)
1149     {
1150     log_error("malloc(sql_content) error: OOM\n");
1151     ret = -1;
1152     goto cleanup;
1153     }
1154    
1155     snprintf(sql_content, SQL_BUFFER_LEN + (size_t)len_content * 2 + 1,
1156 sysadm 1.8 "INSERT INTO bbs_content(AID, content) values(0, '%s')",
1157     content_f);
1158    
1159 sysadm 1.13 free(content_f);
1160     content_f = NULL;
1161    
1162     if (mysql_query(db, sql_content) != 0)
1163 sysadm 1.8 {
1164     log_error("Add article content error: %s\n", mysql_error(db));
1165     ret = -1;
1166     goto cleanup;
1167     }
1168    
1169     p_article_new->cid = (int32_t)mysql_insert_id(db);
1170    
1171 sysadm 1.13 free(sql_content);
1172     sql_content = NULL;
1173    
1174 sysadm 1.8 // Add article
1175     snprintf(sql, sizeof(sql),
1176     "INSERT INTO bbs(SID, TID, UID, username, nickname, title, CID, transship, "
1177     "sub_dt, sub_ip, reply_note, exp, last_reply_dt, icon, length) "
1178 sysadm 1.29 "VALUES(%d, %d, %d, '%s', '%s', '%s', %d, 0, NOW(), '%s', %d, %d, NOW(), 1, %d)",
1179 sysadm 1.11 p_section->sid, (p_article->tid == 0 ? p_article->aid : p_article->tid),
1180     BBS_priv.uid, BBS_username, nickname_f, title_f,
1181 sysadm 1.29 p_article_new->cid, hostaddr_client,
1182     reply_note, BBS_user_exp, content_display_length);
1183 sysadm 1.8
1184     if (mysql_query(db, sql) != 0)
1185     {
1186     log_error("Add article error: %s\n", mysql_error(db));
1187     ret = -1;
1188     goto cleanup;
1189     }
1190    
1191     p_article_new->aid = (int32_t)mysql_insert_id(db);
1192    
1193     // Update topic article
1194     snprintf(sql, sizeof(sql),
1195     "UPDATE bbs SET reply_count = reply_count + 1, "
1196     "last_reply_dt = NOW(), last_reply_UID=%d, last_reply_username = '%s', "
1197 sysadm 1.12 "last_reply_nickname = '%s' WHERE AID = %d",
1198     BBS_priv.uid, BBS_username, nickname_f,
1199     (p_article->tid == 0 ? p_article->aid : p_article->tid));
1200    
1201     if (mysql_query(db, sql) != 0)
1202     {
1203     log_error("Update topic article error: %s\n", mysql_error(db));
1204     ret = -1;
1205     goto cleanup;
1206     }
1207 sysadm 1.8
1208     // Link content to article
1209     snprintf(sql, sizeof(sql),
1210     "UPDATE bbs_content SET AID = %d WHERE CID = %d",
1211     p_article_new->aid, p_article_new->cid);
1212    
1213     if (mysql_query(db, sql) != 0)
1214     {
1215     log_error("Update content error: %s\n", mysql_error(db));
1216     ret = -1;
1217     goto cleanup;
1218     }
1219    
1220 sysadm 1.28 // Notify the authors of the topic / article which is replyed.
1221     snprintf(sql, sizeof(sql),
1222     "SELECT DISTINCT UID FROM bbs WHERE (AID = %d OR AID = %d) "
1223     "AND visible AND reply_note AND UID <> %d",
1224     p_article->tid, p_article->aid, BBS_priv.uid);
1225    
1226     if (mysql_query(db, sql) != 0)
1227     {
1228     log_error("Read reply info error: %s\n", mysql_error(db));
1229     ret = -1;
1230     goto cleanup;
1231     }
1232     if ((rs = mysql_store_result(db)) == NULL)
1233     {
1234     log_error("Get reply info failed\n");
1235     ret = -1;
1236     goto cleanup;
1237     }
1238    
1239     while ((row = mysql_fetch_row(rs)))
1240     {
1241     // Send notification message
1242     len_msg = snprintf(msg, BBS_msg_max_len,
1243 sysadm 1.31 "有人回复了您所发表/回复的文章,快来"
1244 sysadm 1.28 "[article %d]看看[/article]《%s》吧!\n",
1245     p_article_new->aid, title_f);
1246    
1247     mysql_real_escape_string(db, msg_f, msg, (unsigned long)len_msg);
1248    
1249     snprintf(sql, sizeof(sql),
1250     "INSERT INTO bbs_msg(fromUID, toUID, content, send_dt, send_ip) "
1251     "VALUES(%d, %d, '%s', NOW(), '%s')",
1252     BBS_sys_id, atoi(row[0]), msg_f, hostaddr_client);
1253    
1254     if (mysql_query(db, sql) != 0)
1255     {
1256     log_error("Insert msg error: %s\n", mysql_error(db));
1257     ret = -1;
1258     goto cleanup;
1259     }
1260     }
1261     mysql_free_result(rs);
1262     rs = NULL;
1263    
1264 sysadm 1.8 // Add exp
1265     if (checkpriv(&BBS_priv, p_section->sid, S_GETEXP)) // Except in test section
1266     {
1267     snprintf(sql, sizeof(sql),
1268     "UPDATE user_pubinfo SET exp = exp + %d WHERE UID = %d",
1269     3, BBS_priv.uid);
1270    
1271     if (mysql_query(db, sql) != 0)
1272     {
1273     log_error("Update exp error: %s\n", mysql_error(db));
1274     ret = -1;
1275     goto cleanup;
1276     }
1277     }
1278    
1279     // Add log
1280     snprintf(sql, sizeof(sql),
1281     "INSERT INTO bbs_article_op(AID, UID, type, op_dt, op_ip)"
1282     "VALUES(%d, %d, 'A', NOW(), '%s')",
1283     p_article_new->aid, BBS_priv.uid, hostaddr_client);
1284    
1285     if (mysql_query(db, sql) != 0)
1286     {
1287     log_error("Add log error: %s\n", mysql_error(db));
1288     ret = -1;
1289     goto cleanup;
1290     }
1291    
1292     // Commit transaction
1293     if (mysql_query(db, "COMMIT") != 0)
1294     {
1295     log_error("Commit transaction error: %s\n", mysql_error(db));
1296     ret = -1;
1297     goto cleanup;
1298     }
1299    
1300 sysadm 1.17 mysql_close(db);
1301     db = NULL;
1302    
1303 sysadm 1.8 clearscr();
1304     moveto(1, 1);
1305 sysadm 1.24 prints("发送完成,新文章通常会在%d秒后可见", BBS_section_list_load_interval);
1306 sysadm 1.8 press_any_key();
1307     ret = 1; // Success
1308 sysadm 1.2
1309 sysadm 1.6 cleanup:
1310 sysadm 1.8 mysql_free_result(rs);
1311     mysql_close(db);
1312    
1313     // Cleanup buffers
1314 sysadm 1.2 editor_data_cleanup(p_editor_data);
1315    
1316 sysadm 1.8 free(sql_content);
1317     free(content);
1318     free(content_f);
1319    
1320     return (int)ret;
1321 sysadm 1.1 }

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