/[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.4 by sysadm, Fri Jun 13 12:17:21 2025 UTC Revision 1.7 by sysadm, Sat Jun 14 02:58:11 2025 UTC
# Line 20  Line 20 
20  #include "screen.h"  #include "screen.h"
21  #include "log.h"  #include "log.h"
22  #include "io.h"  #include "io.h"
23    #include "lml.h"
24    #include "database.h"
25  #include <ctype.h>  #include <ctype.h>
26  #include <string.h>  #include <string.h>
27    #include <stdlib.h>
28    
29  #define STR_INPUT_LEN 74  #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)  int article_post(SECTION_LIST *p_section)
35  {  {
36          EDITOR_DATA *p_editor_data;          EDITOR_DATA *p_editor_data = NULL;
37          char title[BBS_article_title_max_len + 1] = "";          char title[BBS_article_title_max_len + 1];
38          char title_input[STR_INPUT_LEN + 1] = "";          char title_input[TITLE_INPUT_MAX_LEN + 1];
39          int sign_id = 0;          int sign_id = 0;
40          long len;          long len;
41          int ch;          int ch;
# Line 40  int article_post(SECTION_LIST *p_section Line 46  int article_post(SECTION_LIST *p_section
46                  log_error("NULL pointer error\n");                  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("");          p_editor_data = editor_data_load("");
53          if (p_editor_data == NULL)          if (p_editor_data == NULL)
54          {          {
# Line 54  int article_post(SECTION_LIST *p_section Line 63  int article_post(SECTION_LIST *p_section
63                  moveto(21, 1);                  moveto(21, 1);
64                  prints("发表文章于 %s[%s] 讨论区", p_section->stitle, p_section->sname);                  prints("发表文章于 %s[%s] 讨论区", p_section->stitle, p_section->sname);
65                  moveto(22, 1);                  moveto(22, 1);
66                  prints("文章标题: %s", (title[0] == '\0' ? "[无]" : title));                  prints("标题: %s", (title[0] == '\0' ? "[无]" : title));
67                  moveto(23, 1);                  moveto(23, 1);
68                  prints("使用第 %d 个签名", sign_id);                  prints("使用第 %d 个签名", sign_id);
69    
# Line 78  int article_post(SECTION_LIST *p_section Line 87  int article_post(SECTION_LIST *p_section
87                          case 'T':                          case 'T':
88                                  moveto(24, 1);                                  moveto(24, 1);
89                                  clrtoeol();                                  clrtoeol();
90                                  len = get_data(24, 1, "标题:", title_input, STR_INPUT_LEN, 1);                                  len = get_data(24, 1, "标题: ", title_input, TITLE_INPUT_MAX_LEN, 1);
91                                  for (p = title_input; *p == ' '; p++)                                  for (p = title_input; *p == ' '; p++)
92                                          ;                                          ;
93                                  for (q = title_input + len; q > p && *(q - 1) == ' '; q--)                                  for (q = title_input + len; q > p && *(q - 1) == ' '; q--)
# Line 150  int article_post(SECTION_LIST *p_section Line 159  int article_post(SECTION_LIST *p_section
159                                  break;                                  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);          // editor_data_save(p_editor_data, p_data_new, data_new_len);
# Line 163  cleanup: Line 177  cleanup:
177    
178  int article_modify(SECTION_LIST *p_section, ARTICLE *p_article)  int article_modify(SECTION_LIST *p_section, ARTICLE *p_article)
179  {  {
180          ARTICLE_CACHE cache;          MYSQL *db;
181          EDITOR_DATA *p_editor_data;          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)          if (p_section == NULL || p_article == NULL)
189          {          {
190                  log_error("NULL pointer error\n");                  log_error("NULL pointer error\n");
191          }          }
192    
193          if (article_cache_load(&cache, VAR_ARTICLE_CACHE_DIR, p_article) < 0)          db = db_open();
194            if (db == NULL)
195          {          {
196                  log_error("article_cache_load(aid=%d, cid=%d) error\n", p_article->aid, p_article->cid);                  log_error("db_open() error: %s\n", mysql_error(db));
197                  return -2;                  return -1;
198          }          }
199          p_editor_data = editor_data_load(cache.p_data);  
200          if (p_editor_data == NULL)          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("editor_data_load(aid=%d, cid=%d) error\n", p_article->aid, p_article->cid);                  log_error("Query article content error: %s\n", mysql_error(db));
209                  return -2;                  return -2;
210          }          }
211          if (article_cache_unload(&cache) < 0)          if ((rs = mysql_use_result(db)) == NULL)
212          {          {
213                  log_error("article_cache_unload(aid=%d, cid=%d) error\n", p_article->aid, p_article->cid);                  log_error("Get article content data failed\n");
214                  return -2;                  return -2;
215          }          }
216    
217          editor_display(p_editor_data);          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);          // 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);          editor_data_cleanup(p_editor_data);
269    
270          return 0;          return 0;
# Line 199  int article_modify(SECTION_LIST *p_secti Line 272  int article_modify(SECTION_LIST *p_secti
272    
273  int article_reply(SECTION_LIST *p_section, ARTICLE *p_article)  int article_reply(SECTION_LIST *p_section, ARTICLE *p_article)
274  {  {
275          ARTICLE_CACHE cache;          MYSQL *db;
276          EDITOR_DATA *p_editor_data;          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)          if (p_section == NULL || p_article == NULL)
295          {          {
296                  log_error("NULL pointer error\n");                  log_error("NULL pointer error\n");
297          }          }
298    
299          if (article_cache_load(&cache, VAR_ARTICLE_CACHE_DIR, p_article) < 0)          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("article_cache_load(aid=%d, cid=%d) error\n", p_article->aid, p_article->cid);                  log_error("db_open() error: %s\n", mysql_error(db));
308                  return -2;                  return -1;
309          }          }
310          p_editor_data = editor_data_load(cache.p_data);  
311          if (p_editor_data == NULL)          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("editor_data_load(aid=%d, cid=%d) error\n", p_article->aid, p_article->cid);                  log_error("Query article content error: %s\n", mysql_error(db));
320                  return -2;                  return -2;
321          }          }
322          if (article_cache_unload(&cache) < 0)          if ((rs = mysql_use_result(db)) == NULL)
323          {          {
324                  log_error("article_cache_unload(aid=%d, cid=%d) error\n", p_article->aid, p_article->cid);                  log_error("Get article content data failed\n");
325                  return -2;                  return -2;
326          }          }
327    
328          editor_display(p_editor_data);          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                    // Remove control sequence
335                    len = ctrl_seq_filter(content_f);
336    
337                    len = snprintf(content, sizeof(content), "\n\n【 在 %s (%s) 的大作中提到: 】\n", p_article->username, p_article->nickname);
338    
339                    quote_content_lines = split_data_lines(content_f, ARTICLE_QUOTE_LINE_MAX_LEN, line_offsets, ARTICLE_QUOTE_MAX_LINES + 1);
340                    for (i = 0; i < quote_content_lines; i++)
341                    {
342                            memcpy(content + len, ": ", 2); // quote line prefix
343                            len += 2;
344                            memcpy(content + len, content_f + line_offsets[i], (size_t)(line_offsets[i + 1] - line_offsets[i]));
345                            len += (line_offsets[i + 1] - line_offsets[i]);
346                    }
347                    content[len] = '\0';
348            }
349            mysql_free_result(rs);
350            mysql_close(db);
351    
352            p_editor_data = editor_data_load(content);
353            if (p_editor_data == NULL)
354            {
355                    log_error("editor_data_load(aid=%d, cid=%d) error\n", p_article->aid, atoi(row[0]));
356                    return -3;
357            }
358    
359            // Set title and sign
360            for (ch = 'T'; !SYS_server_exit;)
361            {
362                    clearscr();
363                    moveto(21, 1);
364                    prints("回复文章于 %s[%s] 讨论区", p_section->stitle, p_section->sname);
365                    moveto(22, 1);
366                    prints("标题: %s", (title[0] == '\0' ? "[无]" : title));
367                    moveto(23, 1);
368                    prints("使用第 %d 个签名", sign_id);
369    
370                    if (toupper(ch) != 'T')
371                    {
372                            prints("    按0~3选签名档(0表示不使用)");
373    
374                            moveto(24, 1);
375                            prints("T改标题, C取消, Enter继续: ");
376                            iflush();
377                            ch = 0;
378                    }
379    
380                    for (; !SYS_server_exit; ch = igetch_t(MAX_DELAY_TIME))
381                    {
382                            switch (toupper(ch))
383                            {
384                            case CR:
385                                    igetch_reset();
386                                    break;
387                            case 'T':
388                                    moveto(24, 1);
389                                    clrtoeol();
390                                    len = get_data(24, 1, "标题: ", title_input, TITLE_INPUT_MAX_LEN, 1);
391                                    for (p = title_input; *p == ' '; p++)
392                                            ;
393                                    for (q = title_input + len; q > p && *(q - 1) == ' '; q--)
394                                            ;
395                                    *q = '\0';
396                                    len = q - p;
397                                    if (*p != '\0')
398                                    {
399                                            memcpy(title, p, (size_t)len + 1);
400                                            memcpy(title_input, title, (size_t)len + 1);
401                                    }
402                                    ch = 0;
403                                    break;
404                            case 'C':
405                                    clearscr();
406                                    moveto(1, 1);
407                                    prints("取消...");
408                                    press_any_key();
409                                    goto cleanup;
410                            case '0':
411                            case '1':
412                            case '2':
413                            case '3':
414                                    sign_id = ch - '0';
415                                    break;
416                            default: // Invalid selection
417                                    continue;
418                            }
419    
420                            break;
421                    }
422    
423                    if (ch != CR || title[0] == '\0')
424                    {
425                            continue;
426                    }
427    
428                    for (ch = 'E'; !SYS_server_exit && toupper(ch) == 'E';)
429                    {
430                            editor_display(p_editor_data);
431    
432                            clearscr();
433                            moveto(1, 1);
434                            prints("(S)发送, (C)取消, (T)更改标题 or (E)再编辑? [S]: ");
435                            iflush();
436    
437                            for (ch = 0; !SYS_server_exit; ch = igetch_t(MAX_DELAY_TIME))
438                            {
439                                    switch (toupper(ch))
440                                    {
441                                    case CR:
442                                            igetch_reset();
443                                    case 'S':
444                                            break;
445                                    case 'C':
446                                            clearscr();
447                                            moveto(1, 1);
448                                            prints("取消...");
449                                            press_any_key();
450                                            goto cleanup;
451                                    case 'T':
452                                            break;
453                                    case 'E':
454                                            break;
455                                    default: // Invalid selection
456                                            continue;
457                                    }
458    
459                                    break;
460                            }
461                    }
462    
463                    if (toupper(ch) != 'T')
464                    {
465                            break;
466                    }
467            }
468    
469          // editor_data_save(p_editor_data, p_data_new, data_new_len);          // editor_data_save(p_editor_data, p_data_new, data_new_len);
470            log_common("Debug: reply article\n");
471    
472    cleanup:
473          editor_data_cleanup(p_editor_data);          editor_data_cleanup(p_editor_data);
474    
475          return 0;          return 0;


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

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