/[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.42 - (hide annotations)
Mon Nov 10 14:22:18 2025 UTC (4 months ago) by sysadm
Branch: MAIN
Changes since 1.41: +54 -44 lines
Content type: text/x-csrc
Add selection of quote mode (Full / Abbr.)

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 sysadm 1.42 ARTICLE_QUOTE_DEFAULT_LINES = 20,
29 sysadm 1.40 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.42 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.42 long line_offsets[MAX_EDITOR_DATA_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.42 int full_quote = 0;
753 sysadm 1.6 long len;
754     int ch;
755     char *p, *q;
756     int eol;
757     int display_len;
758     long quote_content_lines;
759     long i;
760 sysadm 1.8 long ret = 0;
761 sysadm 1.14 int topic_locked = 0;
762 sysadm 1.28 char msg[BBS_msg_max_len];
763     char msg_f[BBS_msg_max_len * 2 + 1];
764     int len_msg;
765 sysadm 1.3
766     if (p_section == NULL || p_article == NULL)
767     {
768     log_error("NULL pointer error\n");
769     }
770    
771 sysadm 1.12 if (!checkpriv(&BBS_priv, p_section->sid, S_POST))
772     {
773     clearscr();
774     moveto(1, 1);
775 sysadm 1.24 prints("您没有权限在本版块发表文章\n");
776 sysadm 1.12 press_any_key();
777    
778     return 0;
779     }
780    
781 sysadm 1.8 p_article_new->title[0] = '\0';
782 sysadm 1.6 snprintf(title_input, sizeof(title_input), "Re: %s", p_article->title);
783 sysadm 1.20 len = split_line(title_input, TITLE_INPUT_MAX_LEN, &eol, &display_len, 0);
784 sysadm 1.6 title_input[len] = '\0';
785    
786     db = db_open();
787     if (db == NULL)
788     {
789     log_error("db_open() error: %s\n", mysql_error(db));
790 sysadm 1.16 ret = -1;
791     goto cleanup;
792 sysadm 1.6 }
793    
794     snprintf(sql, sizeof(sql),
795 sysadm 1.14 "SELECT `lock` FROM bbs WHERE AID = %d",
796     (p_article->tid == 0 ? p_article->aid : p_article->tid));
797    
798     if (mysql_query(db, sql) != 0)
799     {
800     log_error("Query article status error: %s\n", mysql_error(db));
801 sysadm 1.16 ret = -1;
802     goto cleanup;
803 sysadm 1.14 }
804     if ((rs = mysql_store_result(db)) == NULL)
805     {
806     log_error("Get article status data failed\n");
807 sysadm 1.16 ret = -1;
808     goto cleanup;
809 sysadm 1.14 }
810    
811     if ((row = mysql_fetch_row(rs)))
812     {
813     if (atoi(row[0]) != 0)
814     {
815     topic_locked = 1;
816     }
817     }
818     mysql_free_result(rs);
819     rs = NULL;
820    
821     if (topic_locked) // Reply is not allowed
822     {
823 sysadm 1.17 mysql_close(db);
824     db = NULL;
825 sysadm 1.18
826 sysadm 1.14 clearscr();
827     moveto(1, 1);
828 sysadm 1.24 prints("该主题谢绝回复");
829 sysadm 1.14 press_any_key();
830    
831     goto cleanup;
832     }
833    
834     snprintf(sql, sizeof(sql),
835 sysadm 1.6 "SELECT bbs_content.CID, bbs_content.content "
836     "FROM bbs INNER JOIN bbs_content ON bbs.CID = bbs_content.CID "
837     "WHERE bbs.AID = %d",
838     p_article->aid);
839    
840     if (mysql_query(db, sql) != 0)
841 sysadm 1.3 {
842 sysadm 1.6 log_error("Query article content error: %s\n", mysql_error(db));
843 sysadm 1.16 ret = -1;
844     goto cleanup;
845 sysadm 1.6 }
846     if ((rs = mysql_use_result(db)) == NULL)
847     {
848     log_error("Get article content data failed\n");
849 sysadm 1.16 ret = -1;
850     goto cleanup;
851 sysadm 1.3 }
852 sysadm 1.5
853 sysadm 1.6 if ((row = mysql_fetch_row(rs)))
854     {
855 sysadm 1.8 content = malloc(ARTICLE_CONTENT_MAX_LEN);
856     if (content == NULL)
857     {
858     log_error("malloc(content) error: OOM\n");
859     ret = -1;
860     goto cleanup;
861     }
862    
863     content_f = malloc(ARTICLE_CONTENT_MAX_LEN);
864     if (content_f == NULL)
865     {
866     log_error("malloc(content_f) error: OOM\n");
867     ret = -1;
868     goto cleanup;
869     }
870    
871 sysadm 1.6 // Apply LML render to content body
872 sysadm 1.36 len = lml_render(row[1], content_f, ARTICLE_CONTENT_MAX_LEN, MAX_EDITOR_DATA_LINE_LENGTH - 3, 1);
873 sysadm 1.6 content_f[len] = '\0';
874    
875 sysadm 1.7 // Remove control sequence
876 sysadm 1.20 len = str_filter(content_f, 0);
877 sysadm 1.6 }
878     mysql_free_result(rs);
879 sysadm 1.8 rs = NULL;
880    
881 sysadm 1.6 mysql_close(db);
882 sysadm 1.8 db = NULL;
883 sysadm 1.5
884 sysadm 1.6 // Set title and sign
885     for (ch = 'T'; !SYS_server_exit;)
886 sysadm 1.3 {
887 sysadm 1.6 clearscr();
888     moveto(21, 1);
889 sysadm 1.42 prints("回复文章于 %s[%s] 讨论区, 回复通知: %s, 引用模式: %s",
890     p_section->stitle, p_section->sname,
891     (reply_note ? "开启" : "关闭"),
892     (full_quote ? "完整" : "精简"));
893 sysadm 1.6 moveto(22, 1);
894 sysadm 1.24 prints("标题: %s", (p_article_new->title[0] == '\0' ? "[无]" : p_article_new->title));
895 sysadm 1.6 moveto(23, 1);
896 sysadm 1.24 prints("使用第 %d 个签名", sign_id);
897 sysadm 1.6
898     if (toupper(ch) != 'T')
899     {
900 sysadm 1.24 prints(" 按0~3选签名档(0表示不使用)");
901 sysadm 1.6
902     moveto(24, 1);
903 sysadm 1.42 prints("T改标题, C取消, N%s, Q%s, Enter继续: ",
904     (reply_note ? "关闭回复通知" : "开启回复通知"), (full_quote ? "精简引用" : "完整引用"));
905 sysadm 1.6 iflush();
906     ch = 0;
907     }
908    
909 sysadm 1.41 while (!SYS_server_exit)
910 sysadm 1.6 {
911     switch (toupper(ch))
912     {
913 sysadm 1.19 case KEY_NULL:
914     case KEY_TIMEOUT:
915     goto cleanup;
916 sysadm 1.6 case CR:
917     break;
918     case 'T':
919 sysadm 1.27 len = get_data(24, 1, "标题: ", title_input, sizeof(title_input), TITLE_INPUT_MAX_LEN);
920 sysadm 1.6 for (p = title_input; *p == ' '; p++)
921     ;
922     for (q = title_input + len; q > p && *(q - 1) == ' '; q--)
923     ;
924     *q = '\0';
925     len = q - p;
926     if (*p != '\0')
927     {
928 sysadm 1.41 if ((ret = check_badwords(p, '*')) < 0)
929     {
930     log_error("check_badwords(title) error\n");
931     }
932     else if (ret > 0)
933     {
934     memcpy(title_input, p, (size_t)len + 1);
935     continue;
936     }
937 sysadm 1.8 memcpy(p_article_new->title, p, (size_t)len + 1);
938     memcpy(title_input, p_article_new->title, (size_t)len + 1);
939 sysadm 1.6 }
940     ch = 0;
941     break;
942     case 'C':
943     clearscr();
944     moveto(1, 1);
945 sysadm 1.24 prints("取消...");
946 sysadm 1.6 press_any_key();
947     goto cleanup;
948 sysadm 1.29 case 'N':
949     reply_note = (reply_note ? 0 : 1);
950     break;
951 sysadm 1.42 case 'Q':
952     full_quote = (full_quote ? 0 : 1);
953     break;
954 sysadm 1.6 case '0':
955     case '1':
956     case '2':
957     case '3':
958     sign_id = ch - '0';
959     break;
960     default: // Invalid selection
961 sysadm 1.41 ch = igetch_t(BBS_max_user_idle_time);
962 sysadm 1.6 continue;
963     }
964    
965     break;
966     }
967    
968 sysadm 1.8 if (ch != CR || p_article_new->title[0] == '\0')
969 sysadm 1.6 {
970     continue;
971     }
972    
973 sysadm 1.42 len = snprintf(content, ARTICLE_CONTENT_MAX_LEN,
974     "\n\n【 在 %s (%s) 的大作中提到: 】\n",
975     p_article->username, p_article->nickname);
976    
977     quote_content_lines = split_data_lines(content_f,
978     MAX_EDITOR_DATA_LINE_LENGTH - 2, line_offsets,
979     (full_quote ? MAX_EDITOR_DATA_LINES : ARTICLE_QUOTE_DEFAULT_LINES) + 1,
980     0, NULL);
981     for (i = 0; i < quote_content_lines; i++)
982     {
983     memcpy(content + len, ": ", 2); // quote line prefix
984     len += 2;
985     memcpy(content + len, content_f + line_offsets[i], (size_t)(line_offsets[i + 1] - line_offsets[i]));
986     len += (line_offsets[i + 1] - line_offsets[i]);
987     if (content[len - 1] != '\n') // Appennd \n if not exist
988     {
989     content[len] = '\n';
990     len++;
991     }
992     }
993     if (content[len - 1] != '\n') // Appennd \n if not exist
994     {
995     content[len] = '\n';
996     len++;
997     }
998     content[len] = '\0';
999    
1000     free(content_f);
1001     content_f = NULL;
1002    
1003     p_editor_data = editor_data_load(content);
1004     if (p_editor_data == NULL)
1005     {
1006     log_error("editor_data_load(aid=%d, cid=%d) error\n", p_article->aid, atoi(row[0]));
1007     ret = -1;
1008     goto cleanup;
1009     }
1010    
1011     free(content);
1012     content = NULL;
1013    
1014 sysadm 1.6 for (ch = 'E'; !SYS_server_exit && toupper(ch) == 'E';)
1015     {
1016     editor_display(p_editor_data);
1017    
1018     clearscr();
1019     moveto(1, 1);
1020 sysadm 1.24 prints("(S)发送, (C)取消, (T)更改标题 or (E)再编辑? [S]: ");
1021 sysadm 1.6 iflush();
1022    
1023 sysadm 1.39 for (ch = 0; !SYS_server_exit; ch = igetch_t(BBS_max_user_idle_time))
1024 sysadm 1.6 {
1025     switch (toupper(ch))
1026     {
1027 sysadm 1.19 case KEY_NULL:
1028     case KEY_TIMEOUT:
1029     goto cleanup;
1030 sysadm 1.6 case CR:
1031     case 'S':
1032     break;
1033     case 'C':
1034     clearscr();
1035     moveto(1, 1);
1036 sysadm 1.24 prints("取消...");
1037 sysadm 1.6 press_any_key();
1038     goto cleanup;
1039     case 'T':
1040     break;
1041     case 'E':
1042     break;
1043     default: // Invalid selection
1044     continue;
1045     }
1046    
1047     break;
1048     }
1049     }
1050    
1051     if (toupper(ch) != 'T')
1052     {
1053     break;
1054     }
1055 sysadm 1.2 }
1056    
1057 sysadm 1.19 if (SYS_server_exit) // Do not save data on shutdown
1058     {
1059     goto cleanup;
1060     }
1061    
1062 sysadm 1.8 content = malloc(ARTICLE_CONTENT_MAX_LEN);
1063     if (content == NULL)
1064     {
1065     log_error("malloc(content) error: OOM\n");
1066     ret = -1;
1067     goto cleanup;
1068     }
1069    
1070     len_content = editor_data_save(p_editor_data, content, ARTICLE_CONTENT_MAX_LEN);
1071     if (len_content < 0)
1072     {
1073     log_error("editor_data_save() error\n");
1074 sysadm 1.16 ret = -1;
1075 sysadm 1.8 goto cleanup;
1076     }
1077    
1078 sysadm 1.41 if (check_badwords(content, '*') < 0)
1079     {
1080     log_error("check_badwords(content) error\n");
1081     ret = -1;
1082     goto cleanup;
1083     }
1084    
1085 sysadm 1.8 db = db_open();
1086     if (db == NULL)
1087     {
1088     log_error("db_open() error: %s\n", mysql_error(db));
1089     ret = -1;
1090     goto cleanup;
1091     }
1092    
1093     if (sign_id > 0)
1094     {
1095     snprintf(sql, sizeof(sql),
1096     "SELECT sign_%d AS sign FROM user_pubinfo WHERE UID = %d",
1097     sign_id, BBS_priv.uid);
1098    
1099     if (mysql_query(db, sql) != 0)
1100     {
1101     log_error("Query sign error: %s\n", mysql_error(db));
1102     ret = -1;
1103     goto cleanup;
1104     }
1105     if ((rs = mysql_use_result(db)) == NULL)
1106     {
1107     log_error("Get sign data failed\n");
1108     ret = -1;
1109     goto cleanup;
1110     }
1111    
1112     if ((row = mysql_fetch_row(rs)))
1113     {
1114     len_content += snprintf(content + len_content,
1115     ARTICLE_CONTENT_MAX_LEN - (size_t)len_content,
1116     "\n\n--\n%s\n", row[0]);
1117     }
1118     mysql_free_result(rs);
1119     rs = NULL;
1120     }
1121    
1122 sysadm 1.24 // Calculate display length of content
1123     content_display_length = str_length(content, 1);
1124    
1125 sysadm 1.8 // Begin transaction
1126     if (mysql_query(db, "SET autocommit=0") != 0)
1127     {
1128     log_error("SET autocommit=0 error: %s\n", mysql_error(db));
1129     ret = -1;
1130     goto cleanup;
1131     }
1132    
1133     if (mysql_query(db, "BEGIN") != 0)
1134     {
1135     log_error("Begin transaction error: %s\n", mysql_error(db));
1136     ret = -1;
1137     goto cleanup;
1138     }
1139    
1140     // Secure SQL parameters
1141 sysadm 1.13 content_f = malloc((size_t)len_content * 2 + 1);
1142     if (content_f == NULL)
1143     {
1144     log_error("malloc(content_f) error: OOM\n");
1145     ret = -1;
1146     goto cleanup;
1147     }
1148    
1149 sysadm 1.8 mysql_real_escape_string(db, nickname_f, BBS_nickname, (unsigned long)strnlen(BBS_nickname, sizeof(BBS_nickname)));
1150     mysql_real_escape_string(db, title_f, p_article_new->title, strnlen(p_article_new->title, sizeof(p_article_new->title)));
1151     mysql_real_escape_string(db, content_f, content, (unsigned long)len_content);
1152    
1153 sysadm 1.13 free(content);
1154     content = NULL;
1155    
1156 sysadm 1.8 // Add content
1157 sysadm 1.13 sql_content = malloc(SQL_BUFFER_LEN + (size_t)len_content * 2 + 1);
1158     if (sql_content == NULL)
1159     {
1160     log_error("malloc(sql_content) error: OOM\n");
1161     ret = -1;
1162     goto cleanup;
1163     }
1164    
1165     snprintf(sql_content, SQL_BUFFER_LEN + (size_t)len_content * 2 + 1,
1166 sysadm 1.8 "INSERT INTO bbs_content(AID, content) values(0, '%s')",
1167     content_f);
1168    
1169 sysadm 1.13 free(content_f);
1170     content_f = NULL;
1171    
1172     if (mysql_query(db, sql_content) != 0)
1173 sysadm 1.8 {
1174     log_error("Add article content error: %s\n", mysql_error(db));
1175     ret = -1;
1176     goto cleanup;
1177     }
1178    
1179     p_article_new->cid = (int32_t)mysql_insert_id(db);
1180    
1181 sysadm 1.13 free(sql_content);
1182     sql_content = NULL;
1183    
1184 sysadm 1.8 // Add article
1185     snprintf(sql, sizeof(sql),
1186     "INSERT INTO bbs(SID, TID, UID, username, nickname, title, CID, transship, "
1187     "sub_dt, sub_ip, reply_note, exp, last_reply_dt, icon, length) "
1188 sysadm 1.29 "VALUES(%d, %d, %d, '%s', '%s', '%s', %d, 0, NOW(), '%s', %d, %d, NOW(), 1, %d)",
1189 sysadm 1.11 p_section->sid, (p_article->tid == 0 ? p_article->aid : p_article->tid),
1190     BBS_priv.uid, BBS_username, nickname_f, title_f,
1191 sysadm 1.29 p_article_new->cid, hostaddr_client,
1192     reply_note, BBS_user_exp, content_display_length);
1193 sysadm 1.8
1194     if (mysql_query(db, sql) != 0)
1195     {
1196     log_error("Add article error: %s\n", mysql_error(db));
1197     ret = -1;
1198     goto cleanup;
1199     }
1200    
1201     p_article_new->aid = (int32_t)mysql_insert_id(db);
1202    
1203     // Update topic article
1204     snprintf(sql, sizeof(sql),
1205     "UPDATE bbs SET reply_count = reply_count + 1, "
1206     "last_reply_dt = NOW(), last_reply_UID=%d, last_reply_username = '%s', "
1207 sysadm 1.12 "last_reply_nickname = '%s' WHERE AID = %d",
1208     BBS_priv.uid, BBS_username, nickname_f,
1209     (p_article->tid == 0 ? p_article->aid : p_article->tid));
1210    
1211     if (mysql_query(db, sql) != 0)
1212     {
1213     log_error("Update topic article error: %s\n", mysql_error(db));
1214     ret = -1;
1215     goto cleanup;
1216     }
1217 sysadm 1.8
1218     // Link content to article
1219     snprintf(sql, sizeof(sql),
1220     "UPDATE bbs_content SET AID = %d WHERE CID = %d",
1221     p_article_new->aid, p_article_new->cid);
1222    
1223     if (mysql_query(db, sql) != 0)
1224     {
1225     log_error("Update content error: %s\n", mysql_error(db));
1226     ret = -1;
1227     goto cleanup;
1228     }
1229    
1230 sysadm 1.28 // Notify the authors of the topic / article which is replyed.
1231     snprintf(sql, sizeof(sql),
1232     "SELECT DISTINCT UID FROM bbs WHERE (AID = %d OR AID = %d) "
1233     "AND visible AND reply_note AND UID <> %d",
1234     p_article->tid, p_article->aid, BBS_priv.uid);
1235    
1236     if (mysql_query(db, sql) != 0)
1237     {
1238     log_error("Read reply info error: %s\n", mysql_error(db));
1239     ret = -1;
1240     goto cleanup;
1241     }
1242     if ((rs = mysql_store_result(db)) == NULL)
1243     {
1244     log_error("Get reply info failed\n");
1245     ret = -1;
1246     goto cleanup;
1247     }
1248    
1249     while ((row = mysql_fetch_row(rs)))
1250     {
1251     // Send notification message
1252     len_msg = snprintf(msg, BBS_msg_max_len,
1253 sysadm 1.31 "有人回复了您所发表/回复的文章,快来"
1254 sysadm 1.28 "[article %d]看看[/article]《%s》吧!\n",
1255     p_article_new->aid, title_f);
1256    
1257     mysql_real_escape_string(db, msg_f, msg, (unsigned long)len_msg);
1258    
1259     snprintf(sql, sizeof(sql),
1260     "INSERT INTO bbs_msg(fromUID, toUID, content, send_dt, send_ip) "
1261     "VALUES(%d, %d, '%s', NOW(), '%s')",
1262     BBS_sys_id, atoi(row[0]), msg_f, hostaddr_client);
1263    
1264     if (mysql_query(db, sql) != 0)
1265     {
1266     log_error("Insert msg error: %s\n", mysql_error(db));
1267     ret = -1;
1268     goto cleanup;
1269     }
1270     }
1271     mysql_free_result(rs);
1272     rs = NULL;
1273    
1274 sysadm 1.8 // Add exp
1275     if (checkpriv(&BBS_priv, p_section->sid, S_GETEXP)) // Except in test section
1276     {
1277     snprintf(sql, sizeof(sql),
1278     "UPDATE user_pubinfo SET exp = exp + %d WHERE UID = %d",
1279     3, BBS_priv.uid);
1280    
1281     if (mysql_query(db, sql) != 0)
1282     {
1283     log_error("Update exp error: %s\n", mysql_error(db));
1284     ret = -1;
1285     goto cleanup;
1286     }
1287     }
1288    
1289     // Add log
1290     snprintf(sql, sizeof(sql),
1291     "INSERT INTO bbs_article_op(AID, UID, type, op_dt, op_ip)"
1292     "VALUES(%d, %d, 'A', NOW(), '%s')",
1293     p_article_new->aid, BBS_priv.uid, hostaddr_client);
1294    
1295     if (mysql_query(db, sql) != 0)
1296     {
1297     log_error("Add log error: %s\n", mysql_error(db));
1298     ret = -1;
1299     goto cleanup;
1300     }
1301    
1302     // Commit transaction
1303     if (mysql_query(db, "COMMIT") != 0)
1304     {
1305     log_error("Commit transaction error: %s\n", mysql_error(db));
1306     ret = -1;
1307     goto cleanup;
1308     }
1309    
1310 sysadm 1.17 mysql_close(db);
1311     db = NULL;
1312    
1313 sysadm 1.8 clearscr();
1314     moveto(1, 1);
1315 sysadm 1.24 prints("发送完成,新文章通常会在%d秒后可见", BBS_section_list_load_interval);
1316 sysadm 1.8 press_any_key();
1317     ret = 1; // Success
1318 sysadm 1.2
1319 sysadm 1.6 cleanup:
1320 sysadm 1.8 mysql_free_result(rs);
1321     mysql_close(db);
1322    
1323     // Cleanup buffers
1324 sysadm 1.2 editor_data_cleanup(p_editor_data);
1325    
1326 sysadm 1.8 free(sql_content);
1327     free(content);
1328     free(content_f);
1329    
1330     return (int)ret;
1331 sysadm 1.1 }

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