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

Contents of /lbbs/src/section_list_display.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.52 - (show annotations)
Tue Oct 14 06:28:54 2025 UTC (5 months ago) by sysadm
Branch: MAIN
Changes since 1.51: +7 -0 lines
Content type: text/x-csrc
Prevent user from accessing unauthorized section from favorite article list

1 /***************************************************************************
2 section_list_display.c - description
3 -------------------
4 Copyright : (C) 2004-2025 by Leaflet
5 Email : leaflet@leafok.com
6 ***************************************************************************/
7
8 /***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 3 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
17 #include "article_cache.h"
18 #include "article_op.h"
19 #include "article_post.h"
20 #include "article_view_log.h"
21 #include "article_del.h"
22 #include "common.h"
23 #include "io.h"
24 #include "log.h"
25 #include "login.h"
26 #include "menu.h"
27 #include "menu_proc.h"
28 #include "section_list_display.h"
29 #include "section_list_loader.h"
30 #include "screen.h"
31 #include "str_process.h"
32 #include "user_priv.h"
33 #include <string.h>
34 #include <time.h>
35 #include <sys/param.h>
36
37 static int section_aid_locations[BBS_max_section] = {0};
38 static int section_topic_view_mode = 0;
39 static int section_topic_view_tid = -1;
40
41 enum select_cmd_t
42 {
43 EXIT_SECTION = 0,
44 VIEW_ARTICLE,
45 CHANGE_PAGE,
46 SHOW_HELP,
47 CHANGE_NAME_DISPLAY,
48 POST_ARTICLE,
49 EDIT_ARTICLE,
50 DELETE_ARTICLE,
51 QUERY_ARTICLE,
52 FIRST_TOPIC_ARTICLE,
53 LAST_TOPIC_ARTICLE,
54 SCAN_NEW_ARTICLE,
55 VIEW_EX_DIR,
56 SHOW_TOP10,
57 };
58
59 static int section_list_draw_items(int page_id, ARTICLE *p_articles[], int article_count, int display_nickname, int ontop_start_offset)
60 {
61 char str_time[LINE_BUFFER_LEN];
62 struct tm tm_sub;
63 char title_f[BBS_article_title_max_len + 1];
64 int title_f_len;
65 int eol;
66 int len;
67 int i;
68 size_t j;
69 char article_flag;
70 int is_viewed;
71 time_t tm_now;
72
73 time(&tm_now);
74
75 clrline(4, 23);
76
77 for (i = 0; i < article_count; i++)
78 {
79 if (p_articles[i]->uid == BBS_priv.uid)
80 {
81 is_viewed = 1;
82 }
83 else
84 {
85 is_viewed = article_view_log_is_viewed(p_articles[i]->aid, &BBS_article_view_log);
86 if (is_viewed < 0)
87 {
88 log_error("article_view_log_is_viewed(aid=%d) error\n", p_articles[i]->aid);
89 is_viewed = 0;
90 }
91 }
92
93 if (p_articles[i]->excerption)
94 {
95 article_flag = (is_viewed ? 'm' : 'M');
96 }
97 else if (p_articles[i]->lock && is_viewed)
98 {
99 article_flag = 'x';
100 }
101 else
102 {
103 article_flag = (is_viewed ? ' ' : 'N');
104 }
105
106 localtime_r(&p_articles[i]->sub_dt, &tm_sub);
107 if (tm_now - p_articles[i]->sub_dt < 3600 * 24 * 365)
108 {
109 strftime(str_time, sizeof(str_time), "%b %e ", &tm_sub);
110 }
111 else
112 {
113 strftime(str_time, sizeof(str_time), "%m/%Y", &tm_sub);
114 }
115
116 strncpy(title_f, (p_articles[i]->tid == 0 ? "● " : ""), sizeof(title_f) - 1);
117 title_f[sizeof(title_f) - 1] = '\0';
118 strncat(title_f, (p_articles[i]->transship ? "[转载]" : ""), sizeof(title_f) - 1 - strnlen(title_f, sizeof(title_f)));
119
120 // Rewrite title with "Re: Re: " prefix into "Re: ... "
121 j = 0;
122 if (p_articles[i]->tid != 0)
123 {
124 while (strncmp(p_articles[i]->title + j, "Re: ", strlen("Re: ")) == 0)
125 {
126 j += strlen("Re: ");
127 }
128 if (j >= strlen("Re: Re: "))
129 {
130 strncat(title_f, "Re: ... ", sizeof(title_f) - 1 - strnlen(title_f, sizeof(title_f)));
131 }
132 else
133 {
134 j = 0;
135 }
136 }
137 strncat(title_f, p_articles[i]->title + j, sizeof(title_f) - 1 - strnlen(title_f, sizeof(title_f)));
138
139 len = split_line(title_f, 59 - (display_nickname ? BBS_nickname_max_len / 2 : BBS_username_max_len), &eol, &title_f_len, 1);
140 if (title_f[len] != '\0')
141 {
142 title_f[len] = '\0';
143 }
144
145 moveto(4 + i, 1);
146 if (i >= ontop_start_offset)
147 {
148 prints(" \033[1;33m[提示]\033[m %c %s%*s %s %s%s\033[m",
149 article_flag,
150 (display_nickname ? p_articles[i]->nickname : p_articles[i]->username),
151 (display_nickname ? BBS_nickname_max_len / 2 - str_length(p_articles[i]->nickname, 1)
152 : BBS_username_max_len - str_length(p_articles[i]->username, 1)),
153 "",
154 str_time,
155 (p_articles[i]->aid == section_topic_view_tid
156 ? "\033[1;33m"
157 : (p_articles[i]->tid == section_topic_view_tid
158 ? "\033[1;36m"
159 : "")),
160 title_f);
161 }
162 else
163 {
164 prints(" %s%7d\033[m %c %s%*s %s %s%s\033[m",
165 (p_articles[i]->aid == section_topic_view_tid
166 ? "\033[1;33m"
167 : (p_articles[i]->tid == section_topic_view_tid
168 ? "\033[1;36m"
169 : "")),
170 p_articles[i]->aid,
171 article_flag,
172 (display_nickname ? p_articles[i]->nickname : p_articles[i]->username),
173 (display_nickname ? BBS_nickname_max_len / 2 - str_length(p_articles[i]->nickname, 1)
174 : BBS_username_max_len - str_length(p_articles[i]->username, 1)),
175 "",
176 str_time,
177 (p_articles[i]->aid == section_topic_view_tid
178 ? "\033[1;33m"
179 : (p_articles[i]->tid == section_topic_view_tid
180 ? "\033[1;36m"
181 : "")),
182 title_f);
183 }
184 }
185
186 return 0;
187 }
188
189 static int section_list_draw_screen(const char *sname, const char *stitle, const char *master_list, int display_nickname)
190 {
191 char str_section_master[LINE_BUFFER_LEN] = "诚征版主中";
192 char str_section_name[LINE_BUFFER_LEN];
193
194 if (master_list[0] != '\0')
195 {
196 snprintf(str_section_master, sizeof(str_section_master), "版主:%s", master_list);
197 }
198 snprintf(str_section_name, sizeof(str_section_name), "讨论区 [%s]", sname);
199
200 clearscr();
201 show_top(str_section_master, stitle, str_section_name);
202 moveto(2, 0);
203 prints("返回[\033[1;32m←\033[0;37m,\033[1;32mESC\033[0;37m] 选择[\033[1;32m↑\033[0;37m,\033[1;32m↓\033[0;37m] "
204 "阅读[\033[1;32m→\033[0;37m,\033[1;32mENTER\033[0;37m] 发表[\033[1;32mCtrl-P\033[0;37m] "
205 "%s[\033[1;32mn\033[0;37m] 精华区[\033[1;32mx\033[0;37m] 帮助[\033[1;32mh\033[0;37m]\033[m",
206 (display_nickname ? "用户名" : "昵称"));
207 moveto(3, 0);
208 if (display_nickname)
209 {
210 prints("\033[44;37m \033[1;37m 编 号 发布者昵称 日 期 文章标题 \033[m");
211 }
212 else
213 {
214 prints("\033[44;37m \033[1;37m 编 号 发 布 者 日 期 文章标题 \033[m");
215 }
216
217 return 0;
218 }
219
220 static enum select_cmd_t section_list_select(int total_page, int item_count, int *p_page_id, int *p_selected_index)
221 {
222 int old_page_id = *p_page_id;
223 int old_selected_index = *p_selected_index;
224 int ch;
225 time_t last_refresh_tm = time(NULL);
226
227 if (item_count > 0 && *p_selected_index >= 0)
228 {
229 moveto(4 + *p_selected_index, 1);
230 outc('>');
231 iflush();
232 }
233
234 while (!SYS_server_exit)
235 {
236 ch = igetch(100);
237
238 switch (ch)
239 {
240 case KEY_ESC:
241 case KEY_LEFT:
242 BBS_last_access_tm = time(NULL);
243 case KEY_NULL: // broken pipe
244 return EXIT_SECTION; // exit section
245 case KEY_TIMEOUT:
246 if (time(NULL) - BBS_last_access_tm >= MAX_DELAY_TIME)
247 {
248 return EXIT_SECTION; // exit section
249 }
250 continue;
251 case 'n':
252 BBS_last_access_tm = time(NULL);
253 return CHANGE_NAME_DISPLAY;
254 case CR:
255 igetch_reset();
256 case 'r':
257 case KEY_RIGHT:
258 if (item_count > 0)
259 {
260 BBS_last_access_tm = time(NULL);
261 return VIEW_ARTICLE;
262 }
263 break;
264 case Ctrl('P'):
265 return POST_ARTICLE;
266 case 'E':
267 if (item_count > 0)
268 {
269 return EDIT_ARTICLE;
270 }
271 break;
272 case 'd':
273 if (item_count > 0)
274 {
275 return DELETE_ARTICLE;
276 }
277 break;
278 case Ctrl('Q'):
279 if (item_count > 0)
280 {
281 return QUERY_ARTICLE;
282 }
283 break;
284 case KEY_HOME:
285 *p_page_id = 0;
286 case 'P':
287 case KEY_PGUP:
288 *p_selected_index = 0;
289 case 'k':
290 case KEY_UP:
291 if (*p_selected_index <= 0)
292 {
293 if (*p_page_id > 0)
294 {
295 (*p_page_id)--;
296 *p_selected_index = BBS_article_limit_per_page - 1;
297 }
298 else if (ch == KEY_UP || ch == 'k') // Rotate to the tail of section list
299 {
300 if (total_page > 0)
301 {
302 *p_page_id = total_page - 1;
303 }
304 if (item_count > 0)
305 {
306 *p_selected_index = item_count - 1;
307 }
308 }
309 }
310 else
311 {
312 (*p_selected_index)--;
313 }
314 break;
315 case '$':
316 case KEY_END:
317 if (total_page > 0)
318 {
319 *p_page_id = total_page - 1;
320 }
321 case 'N':
322 case KEY_PGDN:
323 if (item_count > 0)
324 {
325 *p_selected_index = item_count - 1;
326 }
327 case 'j':
328 case KEY_DOWN:
329 if (*p_selected_index + 1 >= item_count) // next page
330 {
331 if (*p_page_id + 1 < total_page)
332 {
333 (*p_page_id)++;
334 *p_selected_index = 0;
335 }
336 else if (ch == KEY_DOWN || ch == 'j') // Rotate to the head of section list
337 {
338 *p_page_id = 0;
339 *p_selected_index = 0;
340 }
341 }
342 else
343 {
344 (*p_selected_index)++;
345 }
346 break;
347 case '=':
348 if (item_count > 0)
349 {
350 return FIRST_TOPIC_ARTICLE;
351 }
352 break;
353 case '\\':
354 if (item_count > 0)
355 {
356 return LAST_TOPIC_ARTICLE;
357 }
358 break;
359 case 'S':
360 if (item_count > 0)
361 {
362 return SCAN_NEW_ARTICLE;
363 }
364 break;
365 case 'h':
366 return SHOW_HELP;
367 case 'x':
368 return VIEW_EX_DIR;
369 case 'H':
370 return SHOW_TOP10;
371 default:
372 }
373
374 if (old_page_id != *p_page_id)
375 {
376 return CHANGE_PAGE;
377 }
378
379 if (item_count > 0 && old_selected_index != *p_selected_index)
380 {
381 if (old_selected_index >= 0)
382 {
383 moveto(4 + old_selected_index, 1);
384 outc(' ');
385 }
386 if (*p_selected_index >= 0)
387 {
388 moveto(4 + *p_selected_index, 1);
389 outc('>');
390 }
391 iflush();
392
393 old_selected_index = *p_selected_index;
394 }
395
396 BBS_last_access_tm = time(NULL);
397 if (BBS_last_access_tm - last_refresh_tm >= BBS_section_list_load_interval)
398 {
399 return CHANGE_PAGE; // force section list refresh
400 }
401 }
402
403 return EXIT_SECTION;
404 }
405
406 static int display_article_key_handler(int *p_key, DISPLAY_CTX *p_ctx)
407 {
408 switch (*p_key)
409 {
410 case 'p':
411 case Ctrl('X'):
412 section_topic_view_mode = !section_topic_view_mode;
413 case 0: // Set msg
414 if (section_topic_view_mode)
415 {
416 snprintf(p_ctx->msg, sizeof(p_ctx->msg),
417 "| 返回[\033[32m←\033[33m,\033[32mESC\033[33m] "
418 "同主题阅读[\033[32m↑\033[33m/\033[32m↓\033[33m] "
419 "切换[\033[32mp\033[33m] 回复[\033[32mr\033[33m] 帮助[\033[32mh\033[33m] |");
420 }
421 else
422 {
423 snprintf(p_ctx->msg, sizeof(p_ctx->msg),
424 "| 返回[\033[32m←\033[33m,\033[32mESC\033[33m] "
425 "移动[\033[32m↑\033[33m/\033[32m↓\033[33m/\033[32mPgUp\033[33m/\033[32mPgDn\033[33m] "
426 "切换[\033[32mp\033[33m] 回复[\033[32mr\033[33m] 帮助[\033[32mh\033[33m] |");
427 }
428 *p_key = 0;
429 break;
430 case 'r': // Reply article
431 return 1;
432 case '=': // First topic article
433 return 1;
434 case '\\': // Last topic article
435 return 1;
436 case KEY_UP:
437 case KEY_PGUP:
438 case KEY_HOME:
439 if (p_ctx->reach_begin)
440 {
441 if (section_topic_view_mode)
442 {
443 *p_key = KEY_PGUP;
444 }
445 else
446 {
447 *p_key = KEY_UP;
448 }
449 return 1;
450 }
451 break;
452 case 'k':
453 if (section_topic_view_mode)
454 {
455 *p_key = KEY_PGUP;
456 }
457 else
458 {
459 *p_key = KEY_UP;
460 }
461 return 1;
462 case KEY_DOWN:
463 case KEY_PGDN:
464 case KEY_END:
465 if (p_ctx->reach_end)
466 {
467 if (section_topic_view_mode)
468 {
469 *p_key = KEY_PGDN;
470 }
471 else
472 {
473 *p_key = KEY_DOWN;
474 }
475 return 1;
476 }
477 break;
478 case 'j':
479 if (section_topic_view_mode)
480 {
481 *p_key = KEY_PGDN;
482 }
483 else
484 {
485 *p_key = KEY_DOWN;
486 }
487 return 1;
488 }
489
490 return 0;
491 }
492
493 int section_list_display(const char *sname, int32_t aid)
494 {
495 static int display_nickname = 0;
496
497 SECTION_LIST *p_section;
498 int64_t section_index;
499 int32_t aid_location;
500 char stitle[BBS_section_title_max_len + 1];
501 char master_list[(BBS_username_max_len + 1) * 3 + 1];
502 char page_info_str[LINE_BUFFER_LEN];
503 ARTICLE *p_articles[BBS_article_limit_per_page];
504 int article_count;
505 int page_count;
506 int ontop_start_offset;
507 int page_id = 0;
508 int selected_index = 0;
509 ARTICLE_CACHE cache;
510 int ret;
511 int loop;
512 int direction;
513 ARTICLE article_new;
514 int page_id_cur;
515 const ARTICLE *p_article_locate;
516
517 p_section = section_list_find_by_name(sname);
518 if (p_section == NULL)
519 {
520 log_error("Section %s not found\n", sname);
521 return -1;
522 }
523
524 if (!checkpriv(&BBS_priv, p_section->sid, S_LIST))
525 {
526 log_error("Forbid access to unauthorized section, sid=%d, uid=%d\n",
527 p_section->sid, BBS_priv.uid);
528 return -1;
529 }
530
531 section_index = get_section_index(p_section);
532
533 if ((ret = section_list_rd_lock(p_section)) < 0)
534 {
535 log_error("section_list_rd_lock(sid = 0) error\n");
536 return -2;
537 }
538
539 strncpy(stitle, p_section->stitle, sizeof(stitle) - 1);
540 stitle[sizeof(stitle) - 1] = '\0';
541 strncpy(master_list, p_section->master_list, sizeof(master_list) - 1);
542 master_list[sizeof(master_list) - 1] = '\0';
543
544 if ((ret = section_list_rd_unlock(p_section)) < 0)
545 {
546 log_error("section_list_rd_unlock(sid = 0) error\n");
547 return -2;
548 }
549
550 if (aid == 0)
551 {
552 aid_location = section_aid_locations[section_index];
553 }
554 else
555 {
556 aid_location = aid;
557 }
558
559 // Locate at article with aid_locate
560 if (aid_location > 0)
561 {
562 p_article_locate = article_block_find_by_aid(aid_location);
563 if (p_article_locate == NULL)
564 {
565 log_error("article_block_find_by_aid(%d) error\n", aid_location);
566 return -3;
567 }
568
569 ret = locate_article_in_section(p_section, p_article_locate, 0, 0,
570 &page_id, &selected_index, &article_count);
571 if (ret < 0)
572 {
573 log_error("locate_article_in_section(sid=%d, aid=%d, direction=0, step=0) error\n",
574 p_section->sid, p_article_locate->aid);
575 return -3;
576 }
577 }
578
579 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
580 {
581 log_error("section_list_draw_screen() error\n");
582 return -2;
583 }
584
585 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
586 if (ret < 0)
587 {
588 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
589 return -3;
590 }
591
592 section_topic_view_tid = -1;
593
594 if (article_count == 0) // empty section
595 {
596 selected_index = 0;
597 }
598 else if (aid > 0)
599 {
600 // Update current topic
601 section_topic_view_tid = (p_articles[selected_index]->tid == 0 ? p_articles[selected_index]->aid : p_articles[selected_index]->tid);
602
603 // Update current aid location
604 section_aid_locations[section_index] = p_articles[selected_index]->aid;
605 }
606
607 while (!SYS_server_exit)
608 {
609 ret = section_list_draw_items(page_id, p_articles, article_count, display_nickname, ontop_start_offset);
610 if (ret < 0)
611 {
612 log_error("section_list_draw_items(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
613 return -4;
614 }
615
616 snprintf(page_info_str, sizeof(page_info_str),
617 "\033[33m[第\033[36m%d\033[33m/\033[36m%d\033[33m页]",
618 page_id + 1, MAX(page_count, 1));
619
620 show_bottom(page_info_str);
621 iflush();
622
623 if (user_online_update(sname) < 0)
624 {
625 log_error("user_online_update(%s) error\n", sname);
626 }
627
628 ret = section_list_select(page_count, article_count, &page_id, &selected_index);
629 switch (ret)
630 {
631 case EXIT_SECTION:
632 return 0;
633 case CHANGE_PAGE:
634 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
635 if (ret < 0)
636 {
637 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
638 return -3;
639 }
640 if (article_count == 0) // empty section
641 {
642 selected_index = 0;
643 }
644 else if (selected_index >= article_count)
645 {
646 selected_index = article_count - 1;
647 }
648 break;
649 case VIEW_ARTICLE:
650 do
651 {
652 loop = 0;
653
654 if (article_cache_load(&cache, VAR_ARTICLE_CACHE_DIR, p_articles[selected_index]) < 0)
655 {
656 log_error("article_cache_load(aid=%d, cid=%d) error\n", p_articles[selected_index]->aid, p_articles[selected_index]->cid);
657 break;
658 }
659
660 if (user_online_update("VIEW_ARTICLE") < 0)
661 {
662 log_error("user_online_update(VIEW_ARTICLE) error\n");
663 }
664
665 ret = display_data(cache.p_data, cache.line_total, cache.line_offsets, 0,
666 display_article_key_handler, DATA_READ_HELP);
667
668 if (article_cache_unload(&cache) < 0)
669 {
670 log_error("article_cache_unload(aid=%d, cid=%d) error\n", p_articles[selected_index]->aid, p_articles[selected_index]->cid);
671 break;
672 }
673
674 // Update article_view_log
675 if (article_view_log_set_viewed(p_articles[selected_index]->aid, &BBS_article_view_log) < 0)
676 {
677 log_error("article_view_log_set_viewed(aid=%d) error\n", p_articles[selected_index]->aid);
678 }
679
680 switch (ret)
681 {
682 case KEY_UP:
683 if (selected_index <= 0)
684 {
685 if (page_id > 0)
686 {
687 page_id--;
688 selected_index = BBS_article_limit_per_page - 1;
689
690 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
691 if (ret < 0)
692 {
693 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
694 return -3;
695 }
696
697 if (article_count != BBS_article_limit_per_page) // page is not full
698 {
699 selected_index = MAX(0, article_count - 1);
700 }
701 else
702 {
703 loop = 1;
704 }
705 }
706 }
707 else
708 {
709 selected_index--;
710 loop = 1;
711 }
712 break;
713 case KEY_DOWN:
714 if (selected_index + 1 >= article_count) // next page
715 {
716 if (page_id + 1 < page_count)
717 {
718 page_id++;
719 selected_index = 0;
720
721 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
722 if (ret < 0)
723 {
724 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
725 return -3;
726 }
727
728 if (article_count == 0) // empty page
729 {
730 selected_index = 0;
731 }
732 else
733 {
734 loop = 1;
735 }
736 }
737 }
738 else
739 {
740 selected_index++;
741 loop = 1;
742 }
743 break;
744 case KEY_PGUP:
745 case KEY_PGDN:
746 direction = (ret == KEY_PGUP ? -1 : 1);
747 ret = locate_article_in_section(p_section, p_articles[selected_index], direction, 1,
748 &page_id, &selected_index, &article_count);
749 if (ret < 0)
750 {
751 log_error("locate_article_in_section(sid=%d, aid=%d, direction=%d, step=1) error\n",
752 p_section->sid, p_articles[selected_index]->aid, direction);
753 return -3;
754 }
755 else if (ret > 0) // found
756 {
757 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
758 if (ret < 0)
759 {
760 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
761 return -3;
762 }
763 loop = 1;
764 }
765 break;
766 case 'r': // Reply article
767 if (user_online_update("REPLY_ARTICLE") < 0)
768 {
769 log_error("user_online_update(REPLY_ARTICLE) error\n");
770 }
771
772 if (article_reply(p_section, p_articles[selected_index], &article_new) < 0)
773 {
774 log_error("article_reply(aid=%d) error\n", p_articles[selected_index]->aid);
775 }
776 loop = 1;
777 break;
778 case '=': // First topic article
779 case '\\': // Last topic article
780 page_id_cur = page_id;
781 direction = (ret == '=' ? -1 : 1);
782 ret = locate_article_in_section(p_section, p_articles[selected_index], direction, BBS_article_limit_per_section,
783 &page_id, &selected_index, &article_count);
784 if (ret < 0)
785 {
786 log_error("locate_article_in_section(sid=%d, aid=%d, direction=%d, step=%d) error\n",
787 p_section->sid, p_articles[selected_index]->aid, direction, BBS_article_limit_per_section);
788 return -3;
789 }
790 else if (ret > 0) // found
791 {
792 if (page_id != page_id_cur) // page changed
793 {
794 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
795 if (ret < 0)
796 {
797 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
798 return -3;
799 }
800 }
801 loop = 1;
802 }
803 break;
804 }
805 } while (loop);
806
807 // Update current topic
808 section_topic_view_tid = (p_articles[selected_index]->tid == 0 ? p_articles[selected_index]->aid : p_articles[selected_index]->tid);
809
810 // Update current aid location
811 section_aid_locations[section_index] = p_articles[selected_index]->aid;
812
813 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
814 {
815 log_error("section_list_draw_screen() error\n");
816 return -2;
817 }
818 break;
819 case CHANGE_NAME_DISPLAY:
820 display_nickname = !display_nickname;
821 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
822 {
823 log_error("section_list_draw_screen() error\n");
824 return -2;
825 }
826 break;
827 case POST_ARTICLE:
828 if (user_online_update("POST_ARTICLE") < 0)
829 {
830 log_error("user_online_update(POST_ARTICLE) error\n");
831 }
832
833 if ((ret = article_post(p_section, &article_new)) < 0)
834 {
835 log_error("article_post(sid=%d) error\n", p_section->sid);
836 }
837 else if (ret > 0) // New article posted
838 {
839 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
840 if (ret < 0)
841 {
842 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
843 return -3;
844 }
845 }
846 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
847 {
848 log_error("section_list_draw_screen() error\n");
849 return -2;
850 }
851 break;
852 case EDIT_ARTICLE:
853 if (!checkpriv(&BBS_priv, p_section->sid, S_POST) ||
854 p_articles[selected_index]->uid != BBS_priv.uid)
855 {
856 break; // No permission
857 }
858
859 if (user_online_update("EDIT_ARTICLE") < 0)
860 {
861 log_error("user_online_update() error\n");
862 }
863
864 if (article_modify(p_section, p_articles[selected_index], &article_new) < 0)
865 {
866 log_error("article_modify(aid=%d) error\n", p_articles[selected_index]->aid);
867 }
868 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
869 {
870 log_error("section_list_draw_screen() error\n");
871 return -2;
872 }
873 break;
874 case DELETE_ARTICLE:
875 if (!checkpriv(&BBS_priv, p_section->sid, S_POST) ||
876 (!checkpriv(&BBS_priv, p_section->sid, S_MAN_S) && p_articles[selected_index]->uid != BBS_priv.uid))
877 {
878 break; // No permission
879 }
880 if ((ret = article_del(p_section, p_articles[selected_index])) < 0)
881 {
882 log_error("article_del(aid=%d) error\n", p_articles[selected_index]->aid);
883 }
884 else if (ret > 0) // Article deleted
885 {
886 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
887 if (ret < 0)
888 {
889 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
890 return -3;
891 }
892 }
893 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
894 {
895 log_error("section_list_draw_screen() error\n");
896 return -2;
897 }
898 break;
899 case QUERY_ARTICLE:
900 if ((ret = display_article_meta(p_articles[selected_index]->aid)) < 0)
901 {
902 log_error("display_article_meta(aid=%d) error\n", p_articles[selected_index]->aid);
903 }
904 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
905 {
906 log_error("section_list_draw_screen() error\n");
907 return -2;
908 }
909 break;
910 case FIRST_TOPIC_ARTICLE:
911 case LAST_TOPIC_ARTICLE:
912 page_id_cur = page_id;
913 direction = (ret == FIRST_TOPIC_ARTICLE ? -1 : 1);
914 ret = locate_article_in_section(p_section, p_articles[selected_index], direction, BBS_article_limit_per_section,
915 &page_id, &selected_index, &article_count);
916 if (ret < 0)
917 {
918 log_error("locate_article_in_section(sid=%d, aid=%d, direction=%d, step=%d) error\n",
919 p_section->sid, p_articles[selected_index]->aid, direction, BBS_article_limit_per_section);
920 return -3;
921 }
922 else if (ret > 0 && page_id != page_id_cur) // found and page changed
923 {
924 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
925 if (ret < 0)
926 {
927 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
928 return -3;
929 }
930 }
931 break;
932 case SCAN_NEW_ARTICLE:
933 ret = scan_unread_article_in_section(p_section, p_articles[selected_index], &p_article_locate);
934 if (ret < 0)
935 {
936 log_error("scan_unread_article_in_section(sid=%d, aid=%d) error\n",
937 p_section->sid, p_articles[selected_index]->aid);
938 return -3;
939 }
940 else if (ret == 0) // not found
941 {
942 break;
943 }
944 page_id_cur = page_id;
945 ret = locate_article_in_section(p_section, p_article_locate, 0, 0,
946 &page_id, &selected_index, &article_count);
947 if (ret < 0)
948 {
949 log_error("locate_article_in_section(sid=%d, aid=%d, direction=0, step=0) error\n",
950 p_section->sid, p_article_locate->aid);
951 return -3;
952 }
953 else if (ret > 0 && page_id != page_id_cur) // found and page changed
954 {
955 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
956 if (ret < 0)
957 {
958 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
959 return -3;
960 }
961 }
962 break;
963 case SHOW_HELP:
964 // Display help information
965 display_file(DATA_READ_HELP, 1);
966 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
967 {
968 log_error("section_list_draw_screen() error\n");
969 return -2;
970 }
971 break;
972 case VIEW_EX_DIR:
973 if (section_list_ex_dir_display(p_section) < 0)
974 {
975 log_error("section_list_ex_dir_display(sid=%d) error\n", p_section->sid);
976 }
977 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
978 {
979 log_error("section_list_draw_screen() error\n");
980 return -2;
981 }
982 break;
983 case SHOW_TOP10:
984 show_top10_menu(NULL);
985 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
986 {
987 log_error("section_list_draw_screen() error\n");
988 return -2;
989 }
990 break;
991 default:
992 log_error("Unknown command %d\n", ret);
993 }
994 }
995
996 return 0;
997 }
998
999 int section_list_ex_dir_display(SECTION_LIST *p_section)
1000 {
1001 MENU_SET ex_menu_set;
1002 int ch = 0;
1003
1004 if (p_section == NULL)
1005 {
1006 log_error("NULL pointer error\n");
1007 return -1;
1008 }
1009
1010 if (p_section->ex_menu_tm == 0) // N/A
1011 {
1012 moveto(2, 1);
1013 clrtoeol();
1014 prints("该版块精华区未开放");
1015 press_any_key();
1016 return 0;
1017 }
1018
1019 if (get_section_ex_menu_set(p_section, &ex_menu_set) < 0)
1020 {
1021 log_error("get_section_ex_menu_set(sid=%d) error\n", p_section->sid);
1022 return -3;
1023 }
1024 if (get_menu_shm_readonly(&ex_menu_set) < 0)
1025 {
1026 log_error("get_menu_shm_readonly(sid=%d) error\n", p_section->sid);
1027 return -3;
1028 }
1029
1030 clearscr();
1031 show_bottom("");
1032
1033 if (display_menu(&ex_menu_set) == 0)
1034 {
1035 while (!SYS_server_exit)
1036 {
1037 iflush();
1038 ch = igetch(100);
1039 switch (ch)
1040 {
1041 case KEY_NULL: // broken pipe
1042 return 0;
1043 case KEY_TIMEOUT:
1044 if (time(NULL) - BBS_last_access_tm >= MAX_DELAY_TIME)
1045 {
1046 return 0;
1047 }
1048 continue;
1049 case CR:
1050 igetch_reset();
1051 default:
1052 switch (menu_control(&ex_menu_set, ch))
1053 {
1054 case EXITMENU:
1055 ch = EXITMENU;
1056 break;
1057 case REDRAW:
1058 clearscr();
1059 show_bottom("");
1060 display_menu(&ex_menu_set);
1061 break;
1062 case NOREDRAW:
1063 case UNKNOWN_CMD:
1064 default:
1065 break;
1066 }
1067 }
1068
1069 BBS_last_access_tm = time(NULL);
1070
1071 if (ch == EXITMENU)
1072 {
1073 break;
1074 }
1075 }
1076 }
1077
1078 detach_menu_shm(&ex_menu_set);
1079
1080 return 0;
1081 }

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