/[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.1 by sysadm, Thu Jun 12 12:14:28 2025 UTC Revision 1.6 by sysadm, Sat Jun 14 01:40:52 2025 UTC
# Line 19  Line 19 
19  #include "editor.h"  #include "editor.h"
20  #include "screen.h"  #include "screen.h"
21  #include "log.h"  #include "log.h"
22    #include "io.h"
23    #include "lml.h"
24    #include "database.h"
25    #include <ctype.h>
26    #include <string.h>
27    #include <stdlib.h>
28    
29  int article_post(SECTION_LIST *p_section, ARTICLE *p_article, ARTICLE_POST_TYPE type)  #define TITLE_INPUT_MAX_LEN 74
30    #define ARTICLE_CONTENT_MAX_LEN 1024 * 1024 * 4 // 4MB
31    #define ARTICLE_QUOTE_MAX_LINES 20
32    #define ARTICLE_QUOTE_LINE_MAX_LEN 76
33    
34    int article_post(SECTION_LIST *p_section)
35    {
36            EDITOR_DATA *p_editor_data = NULL;
37            char title[BBS_article_title_max_len + 1];
38            char title_input[TITLE_INPUT_MAX_LEN + 1];
39            int sign_id = 0;
40            long len;
41            int ch;
42            char *p, *q;
43    
44            if (p_section == NULL)
45            {
46                    log_error("NULL pointer error\n");
47            }
48    
49            title[0] = '\0';
50            title_input[0] = '\0';
51    
52            p_editor_data = editor_data_load("");
53            if (p_editor_data == NULL)
54            {
55                    log_error("editor_data_load() error\n");
56                    return -2;
57            }
58    
59            // Set title and sign
60            for (ch = 'T'; !SYS_server_exit;)
61            {
62                    clearscr();
63                    moveto(21, 1);
64                    prints("发表文章于 %s[%s] 讨论区", p_section->stitle, p_section->sname);
65                    moveto(22, 1);
66                    prints("标题: %s", (title[0] == '\0' ? "[无]" : title));
67                    moveto(23, 1);
68                    prints("使用第 %d 个签名", sign_id);
69    
70                    if (toupper(ch) != 'T')
71                    {
72                            prints("    按0~3选签名档(0表示不使用)");
73    
74                            moveto(24, 1);
75                            prints("T改标题, C取消, Enter继续: ");
76                            iflush();
77                            ch = 0;
78                    }
79    
80                    for (; !SYS_server_exit; ch = igetch_t(MAX_DELAY_TIME))
81                    {
82                            switch (toupper(ch))
83                            {
84                            case CR:
85                                    igetch_reset();
86                                    break;
87                            case 'T':
88                                    moveto(24, 1);
89                                    clrtoeol();
90                                    len = get_data(24, 1, "标题: ", title_input, TITLE_INPUT_MAX_LEN, 1);
91                                    for (p = title_input; *p == ' '; p++)
92                                            ;
93                                    for (q = title_input + len; q > p && *(q - 1) == ' '; q--)
94                                            ;
95                                    *q = '\0';
96                                    len = q - p;
97                                    if (*p != '\0')
98                                    {
99                                            memcpy(title, p, (size_t)len + 1);
100                                            memcpy(title_input, title, (size_t)len + 1);
101                                    }
102                                    ch = 0;
103                                    break;
104                            case 'C':
105                                    clearscr();
106                                    moveto(1, 1);
107                                    prints("取消...");
108                                    press_any_key();
109                                    goto cleanup;
110                            case '0':
111                            case '1':
112                            case '2':
113                            case '3':
114                                    sign_id = ch - '0';
115                                    break;
116                            default: // Invalid selection
117                                    continue;
118                            }
119    
120                            break;
121                    }
122    
123                    if (ch != CR || title[0] == '\0')
124                    {
125                            continue;
126                    }
127    
128                    for (ch = 'E'; !SYS_server_exit && toupper(ch) == 'E';)
129                    {
130                            editor_display(p_editor_data);
131    
132                            clearscr();
133                            moveto(1, 1);
134                            prints("(S)发送, (C)取消, (T)更改标题 or (E)再编辑? [S]: ");
135                            iflush();
136    
137                            for (ch = 0; !SYS_server_exit; ch = igetch_t(MAX_DELAY_TIME))
138                            {
139                                    switch (toupper(ch))
140                                    {
141                                    case CR:
142                                            igetch_reset();
143                                    case 'S':
144                                            break;
145                                    case 'C':
146                                            clearscr();
147                                            moveto(1, 1);
148                                            prints("取消...");
149                                            press_any_key();
150                                            goto cleanup;
151                                    case 'T':
152                                            break;
153                                    case 'E':
154                                            break;
155                                    default: // Invalid selection
156                                            continue;
157                                    }
158    
159                                    break;
160                            }
161                    }
162    
163                    if (toupper(ch) != 'T')
164                    {
165                            break;
166                    }
167            }
168    
169            // editor_data_save(p_editor_data, p_data_new, data_new_len);
170            log_common("Debug: post article\n");
171    
172    cleanup:
173            editor_data_cleanup(p_editor_data);
174    
175            return 0;
176    }
177    
178    int article_modify(SECTION_LIST *p_section, ARTICLE *p_article)
179    {
180            MYSQL *db;
181            MYSQL_RES *rs;
182            MYSQL_ROW row;
183            char sql[SQL_BUFFER_LEN];
184            int ch;
185    
186            EDITOR_DATA *p_editor_data = NULL;
187    
188            if (p_section == NULL || p_article == NULL)
189            {
190                    log_error("NULL pointer error\n");
191            }
192    
193            db = db_open();
194            if (db == NULL)
195            {
196                    log_error("db_open() error: %s\n", mysql_error(db));
197                    return -1;
198            }
199    
200            snprintf(sql, sizeof(sql),
201                             "SELECT bbs_content.CID, bbs_content.content "
202                             "FROM bbs INNER JOIN bbs_content ON bbs.CID = bbs_content.CID "
203                             "WHERE bbs.AID = %d",
204                             p_article->aid);
205    
206            if (mysql_query(db, sql) != 0)
207            {
208                    log_error("Query article content error: %s\n", mysql_error(db));
209                    return -2;
210            }
211            if ((rs = mysql_use_result(db)) == NULL)
212            {
213                    log_error("Get article content data failed\n");
214                    return -2;
215            }
216    
217            if ((row = mysql_fetch_row(rs)))
218            {
219                    p_editor_data = editor_data_load(row[1]);
220                    if (p_editor_data == NULL)
221                    {
222                            log_error("editor_data_load(aid=%d, cid=%d) error\n", p_article->aid, atoi(row[0]));
223                            mysql_free_result(rs);
224                            mysql_close(db);
225                            return -3;
226                    }
227            }
228            mysql_free_result(rs);
229            mysql_close(db);
230    
231            for (ch = 'E'; !SYS_server_exit && toupper(ch) == 'E';)
232            {
233                    editor_display(p_editor_data);
234    
235                    clearscr();
236                    moveto(1, 1);
237                    prints("(S)保存, (C)取消 or (E)再编辑? [S]: ");
238                    iflush();
239    
240                    for (ch = 0; !SYS_server_exit; ch = igetch_t(MAX_DELAY_TIME))
241                    {
242                            switch (toupper(ch))
243                            {
244                            case CR:
245                                    igetch_reset();
246                            case 'S':
247                                    break;
248                            case 'C':
249                                    clearscr();
250                                    moveto(1, 1);
251                                    prints("取消...");
252                                    press_any_key();
253                                    goto cleanup;
254                            case 'E':
255                                    break;
256                            default: // Invalid selection
257                                    continue;
258                            }
259    
260                            break;
261                    }
262            }
263    
264            // editor_data_save(p_editor_data, p_data_new, data_new_len);
265            log_common("Debug: modify article\n");
266    
267    cleanup:
268            editor_data_cleanup(p_editor_data);
269    
270            return 0;
271    }
272    
273    int article_reply(SECTION_LIST *p_section, ARTICLE *p_article)
274  {  {
275          log_common("Debug: sid=%d aid=%d type=%d\n",          MYSQL *db;
276                             p_section->sid, (p_article == NULL ? 0 : p_article->aid), type);          MYSQL_RES *rs;
277            MYSQL_ROW row;
278            char sql[SQL_BUFFER_LEN];
279            char content[LINE_BUFFER_LEN * ARTICLE_QUOTE_MAX_LINES + 1];
280            char content_f[ARTICLE_CONTENT_MAX_LEN];
281            long line_offsets[ARTICLE_QUOTE_MAX_LINES + 1];
282            EDITOR_DATA *p_editor_data = NULL;
283            char title[BBS_article_title_max_len + 1];
284            char title_input[BBS_article_title_max_len + 1 + 4]; // + "Re: "
285            int sign_id = 0;
286            long len;
287            int ch;
288            char *p, *q;
289            int eol;
290            int display_len;
291            long quote_content_lines;
292            long i;
293    
294            if (p_section == NULL || p_article == NULL)
295            {
296                    log_error("NULL pointer error\n");
297            }
298    
299            title[0] = '\0';
300            snprintf(title_input, sizeof(title_input), "Re: %s", p_article->title);
301            len = split_line(title_input, TITLE_INPUT_MAX_LEN, &eol, &display_len);
302            title_input[len] = '\0';
303    
304            db = db_open();
305            if (db == NULL)
306            {
307                    log_error("db_open() error: %s\n", mysql_error(db));
308                    return -1;
309            }
310    
311            snprintf(sql, sizeof(sql),
312                             "SELECT bbs_content.CID, bbs_content.content "
313                             "FROM bbs INNER JOIN bbs_content ON bbs.CID = bbs_content.CID "
314                             "WHERE bbs.AID = %d",
315                             p_article->aid);
316    
317            if (mysql_query(db, sql) != 0)
318            {
319                    log_error("Query article content error: %s\n", mysql_error(db));
320                    return -2;
321            }
322            if ((rs = mysql_use_result(db)) == NULL)
323            {
324                    log_error("Get article content data failed\n");
325                    return -2;
326            }
327    
328            if ((row = mysql_fetch_row(rs)))
329            {
330                    // Apply LML render to content body
331                    len = lml_plain(row[1], content_f, ARTICLE_CONTENT_MAX_LEN);
332                    content_f[len] = '\0';
333    
334                    quote_content_lines = split_data_lines(content_f, ARTICLE_QUOTE_LINE_MAX_LEN, line_offsets, ARTICLE_QUOTE_MAX_LINES + 1);
335                    for (i = 0, len = 0; i < quote_content_lines; i++)
336                    {
337                            memcpy(content + len, ": ", 2); // quote line prefix
338                            len += 2;
339                            memcpy(content + len, content_f + line_offsets[i], (size_t)(line_offsets[i + 1] - line_offsets[i]));
340                            len += (line_offsets[i + 1] - line_offsets[i]);
341                    }
342                    content[len] = '\0';
343            }
344            mysql_free_result(rs);
345            mysql_close(db);
346    
347            p_editor_data = editor_data_load(content);
348            if (p_editor_data == NULL)
349            {
350                    log_error("editor_data_load(aid=%d, cid=%d) error\n", p_article->aid, atoi(row[0]));
351                    return -3;
352            }
353    
354            // Set title and sign
355            for (ch = 'T'; !SYS_server_exit;)
356            {
357                    clearscr();
358                    moveto(21, 1);
359                    prints("回复文章于 %s[%s] 讨论区", p_section->stitle, p_section->sname);
360                    moveto(22, 1);
361                    prints("标题: %s", (title[0] == '\0' ? "[无]" : title));
362                    moveto(23, 1);
363                    prints("使用第 %d 个签名", sign_id);
364    
365                    if (toupper(ch) != 'T')
366                    {
367                            prints("    按0~3选签名档(0表示不使用)");
368    
369                            moveto(24, 1);
370                            prints("T改标题, C取消, Enter继续: ");
371                            iflush();
372                            ch = 0;
373                    }
374    
375                    for (; !SYS_server_exit; ch = igetch_t(MAX_DELAY_TIME))
376                    {
377                            switch (toupper(ch))
378                            {
379                            case CR:
380                                    igetch_reset();
381                                    break;
382                            case 'T':
383                                    moveto(24, 1);
384                                    clrtoeol();
385                                    len = get_data(24, 1, "标题: ", title_input, TITLE_INPUT_MAX_LEN, 1);
386                                    for (p = title_input; *p == ' '; p++)
387                                            ;
388                                    for (q = title_input + len; q > p && *(q - 1) == ' '; q--)
389                                            ;
390                                    *q = '\0';
391                                    len = q - p;
392                                    if (*p != '\0')
393                                    {
394                                            memcpy(title, p, (size_t)len + 1);
395                                            memcpy(title_input, title, (size_t)len + 1);
396                                    }
397                                    ch = 0;
398                                    break;
399                            case 'C':
400                                    clearscr();
401                                    moveto(1, 1);
402                                    prints("取消...");
403                                    press_any_key();
404                                    goto cleanup;
405                            case '0':
406                            case '1':
407                            case '2':
408                            case '3':
409                                    sign_id = ch - '0';
410                                    break;
411                            default: // Invalid selection
412                                    continue;
413                            }
414    
415                            break;
416                    }
417    
418                    if (ch != CR || title[0] == '\0')
419                    {
420                            continue;
421                    }
422    
423                    for (ch = 'E'; !SYS_server_exit && toupper(ch) == 'E';)
424                    {
425                            editor_display(p_editor_data);
426    
427                            clearscr();
428                            moveto(1, 1);
429                            prints("(S)发送, (C)取消, (T)更改标题 or (E)再编辑? [S]: ");
430                            iflush();
431    
432                            for (ch = 0; !SYS_server_exit; ch = igetch_t(MAX_DELAY_TIME))
433                            {
434                                    switch (toupper(ch))
435                                    {
436                                    case CR:
437                                            igetch_reset();
438                                    case 'S':
439                                            break;
440                                    case 'C':
441                                            clearscr();
442                                            moveto(1, 1);
443                                            prints("取消...");
444                                            press_any_key();
445                                            goto cleanup;
446                                    case 'T':
447                                            break;
448                                    case 'E':
449                                            break;
450                                    default: // Invalid selection
451                                            continue;
452                                    }
453    
454                                    break;
455                            }
456                    }
457    
458                    if (toupper(ch) != 'T')
459                    {
460                            break;
461                    }
462            }
463    
464            // editor_data_save(p_editor_data, p_data_new, data_new_len);
465            log_common("Debug: reply article\n");
466    
467    cleanup:
468            editor_data_cleanup(p_editor_data);
469    
470          return 0;          return 0;
471  }  }


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

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