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

Annotation of /lbbs/src/section_list_display.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.52 - (hide 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 sysadm 1.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 sysadm 1.9 #include "article_cache.h"
18 sysadm 1.41 #include "article_op.h"
19 sysadm 1.20 #include "article_post.h"
20 sysadm 1.34 #include "article_view_log.h"
21 sysadm 1.26 #include "article_del.h"
22 sysadm 1.1 #include "common.h"
23     #include "io.h"
24 sysadm 1.34 #include "log.h"
25     #include "login.h"
26 sysadm 1.37 #include "menu.h"
27 sysadm 1.48 #include "menu_proc.h"
28 sysadm 1.34 #include "section_list_display.h"
29     #include "section_list_loader.h"
30 sysadm 1.1 #include "screen.h"
31 sysadm 1.34 #include "str_process.h"
32 sysadm 1.18 #include "user_priv.h"
33 sysadm 1.29 #include <string.h>
34 sysadm 1.1 #include <time.h>
35 sysadm 1.6 #include <sys/param.h>
36 sysadm 1.1
37 sysadm 1.46 static int section_aid_locations[BBS_max_section] = {0};
38 sysadm 1.11 static int section_topic_view_mode = 0;
39 sysadm 1.13 static int section_topic_view_tid = -1;
40 sysadm 1.11
41 sysadm 1.1 enum select_cmd_t
42     {
43     EXIT_SECTION = 0,
44 sysadm 1.41 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 sysadm 1.45 SCAN_NEW_ARTICLE,
55 sysadm 1.41 VIEW_EX_DIR,
56 sysadm 1.48 SHOW_TOP10,
57 sysadm 1.1 };
58    
59 sysadm 1.36 static int section_list_draw_items(int page_id, ARTICLE *p_articles[], int article_count, int display_nickname, int ontop_start_offset)
60 sysadm 1.1 {
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 sysadm 1.42 size_t j;
69 sysadm 1.3 char article_flag;
70 sysadm 1.17 int is_viewed;
71 sysadm 1.3 time_t tm_now;
72    
73     time(&tm_now);
74 sysadm 1.1
75     clrline(4, 23);
76    
77     for (i = 0; i < article_count; i++)
78     {
79 sysadm 1.18 if (p_articles[i]->uid == BBS_priv.uid)
80 sysadm 1.17 {
81 sysadm 1.18 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 sysadm 1.17 }
92    
93 sysadm 1.3 if (p_articles[i]->excerption)
94     {
95 sysadm 1.17 article_flag = (is_viewed ? 'm' : 'M');
96 sysadm 1.3 }
97 sysadm 1.17 else if (p_articles[i]->lock && is_viewed)
98 sysadm 1.3 {
99     article_flag = 'x';
100     }
101 sysadm 1.35 else
102     {
103     article_flag = (is_viewed ? ' ' : 'N');
104     }
105 sysadm 1.3
106 sysadm 1.1 localtime_r(&p_articles[i]->sub_dt, &tm_sub);
107 sysadm 1.3 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 sysadm 1.40 strncpy(title_f, (p_articles[i]->tid == 0 ? "● " : ""), sizeof(title_f) - 1);
117 sysadm 1.1 title_f[sizeof(title_f) - 1] = '\0';
118 sysadm 1.40 strncat(title_f, (p_articles[i]->transship ? "[转载]" : ""), sizeof(title_f) - 1 - strnlen(title_f, sizeof(title_f)));
119 sysadm 1.42
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 sysadm 1.51 len = split_line(title_f, 59 - (display_nickname ? BBS_nickname_max_len / 2 : BBS_username_max_len), &eol, &title_f_len, 1);
140 sysadm 1.1 if (title_f[len] != '\0')
141     {
142     title_f[len] = '\0';
143     }
144    
145     moveto(4 + i, 1);
146 sysadm 1.36 if (i >= ontop_start_offset)
147     {
148 sysadm 1.40 prints(" \033[1;33m[提示]\033[m %c %s%*s %s %s%s\033[m",
149 sysadm 1.36 article_flag,
150     (display_nickname ? p_articles[i]->nickname : p_articles[i]->username),
151 sysadm 1.43 (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 sysadm 1.36 "",
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 sysadm 1.43 (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 sysadm 1.36 "",
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 sysadm 1.1 }
185    
186     return 0;
187     }
188    
189 sysadm 1.5 static int section_list_draw_screen(const char *sname, const char *stitle, const char *master_list, int display_nickname)
190 sysadm 1.1 {
191 sysadm 1.40 char str_section_master[LINE_BUFFER_LEN] = "诚征版主中";
192 sysadm 1.1 char str_section_name[LINE_BUFFER_LEN];
193    
194 sysadm 1.5 if (master_list[0] != '\0')
195 sysadm 1.1 {
196 sysadm 1.40 snprintf(str_section_master, sizeof(str_section_master), "版主:%s", master_list);
197 sysadm 1.1 }
198 sysadm 1.40 snprintf(str_section_name, sizeof(str_section_name), "讨论区 [%s]", sname);
199 sysadm 1.1
200     clearscr();
201 sysadm 1.5 show_top(str_section_master, stitle, str_section_name);
202 sysadm 1.1 moveto(2, 0);
203 sysadm 1.40 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 sysadm 1.1 moveto(3, 0);
208 sysadm 1.4 if (display_nickname)
209     {
210 sysadm 1.40 prints("\033[44;37m \033[1;37m 编 号 发布者昵称 日 期 文章标题 \033[m");
211 sysadm 1.4 }
212     else
213     {
214 sysadm 1.40 prints("\033[44;37m \033[1;37m 编 号 发 布 者 日 期 文章标题 \033[m");
215 sysadm 1.4 }
216 sysadm 1.1
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 sysadm 1.30 time_t last_refresh_tm = time(NULL);
226 sysadm 1.1
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 sysadm 1.30 BBS_last_access_tm = time(NULL);
243     case KEY_NULL: // broken pipe
244 sysadm 1.1 return EXIT_SECTION; // exit section
245     case KEY_TIMEOUT:
246 sysadm 1.30 if (time(NULL) - BBS_last_access_tm >= MAX_DELAY_TIME)
247 sysadm 1.1 {
248     return EXIT_SECTION; // exit section
249     }
250     continue;
251 sysadm 1.4 case 'n':
252 sysadm 1.30 BBS_last_access_tm = time(NULL);
253 sysadm 1.4 return CHANGE_NAME_DISPLAY;
254 sysadm 1.1 case CR:
255     igetch_reset();
256 sysadm 1.28 case 'r':
257 sysadm 1.1 case KEY_RIGHT:
258     if (item_count > 0)
259     {
260 sysadm 1.30 BBS_last_access_tm = time(NULL);
261 sysadm 1.1 return VIEW_ARTICLE;
262     }
263     break;
264 sysadm 1.20 case Ctrl('P'):
265     return POST_ARTICLE;
266     case 'E':
267 sysadm 1.41 if (item_count > 0)
268     {
269     return EDIT_ARTICLE;
270     }
271     break;
272 sysadm 1.26 case 'd':
273 sysadm 1.41 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 sysadm 1.1 case KEY_HOME:
285     *p_page_id = 0;
286 sysadm 1.28 case 'P':
287 sysadm 1.1 case KEY_PGUP:
288     *p_selected_index = 0;
289 sysadm 1.28 case 'k':
290 sysadm 1.1 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 sysadm 1.44 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 sysadm 1.1 }
310     else
311     {
312     (*p_selected_index)--;
313     }
314     break;
315 sysadm 1.28 case '$':
316 sysadm 1.1 case KEY_END:
317     if (total_page > 0)
318     {
319     *p_page_id = total_page - 1;
320     }
321 sysadm 1.28 case 'N':
322 sysadm 1.1 case KEY_PGDN:
323     if (item_count > 0)
324     {
325     *p_selected_index = item_count - 1;
326     }
327 sysadm 1.28 case 'j':
328 sysadm 1.1 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 sysadm 1.44 else if (ch == KEY_DOWN || ch == 'j') // Rotate to the head of section list
337 sysadm 1.25 {
338 sysadm 1.44 *p_page_id = 0;
339     *p_selected_index = 0;
340 sysadm 1.25 }
341 sysadm 1.1 }
342     else
343     {
344     (*p_selected_index)++;
345     }
346     break;
347 sysadm 1.31 case '=':
348 sysadm 1.41 if (item_count > 0)
349     {
350     return FIRST_TOPIC_ARTICLE;
351     }
352     break;
353 sysadm 1.31 case '\\':
354 sysadm 1.41 if (item_count > 0)
355     {
356     return LAST_TOPIC_ARTICLE;
357     }
358     break;
359 sysadm 1.45 case 'S':
360     if (item_count > 0)
361     {
362     return SCAN_NEW_ARTICLE;
363     }
364     break;
365 sysadm 1.28 case 'h':
366     return SHOW_HELP;
367 sysadm 1.37 case 'x':
368     return VIEW_EX_DIR;
369 sysadm 1.49 case 'H':
370 sysadm 1.48 return SHOW_TOP10;
371 sysadm 1.1 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 sysadm 1.30 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 sysadm 1.1 }
402    
403     return EXIT_SECTION;
404     }
405    
406 sysadm 1.11 static int display_article_key_handler(int *p_key, DISPLAY_CTX *p_ctx)
407 sysadm 1.10 {
408 sysadm 1.11 switch (*p_key)
409 sysadm 1.10 {
410 sysadm 1.11 case 'p':
411 sysadm 1.28 case Ctrl('X'):
412 sysadm 1.11 section_topic_view_mode = !section_topic_view_mode;
413 sysadm 1.10 case 0: // Set msg
414 sysadm 1.11 if (section_topic_view_mode)
415 sysadm 1.10 {
416 sysadm 1.11 snprintf(p_ctx->msg, sizeof(p_ctx->msg),
417 sysadm 1.40 "| 返回[\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 sysadm 1.10 }
421     else
422     {
423 sysadm 1.11 snprintf(p_ctx->msg, sizeof(p_ctx->msg),
424 sysadm 1.40 "| 返回[\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 sysadm 1.10 }
428 sysadm 1.11 *p_key = 0;
429 sysadm 1.10 break;
430 sysadm 1.20 case 'r': // Reply article
431     return 1;
432 sysadm 1.31 case '=': // First topic article
433     return 1;
434     case '\\': // Last topic article
435     return 1;
436 sysadm 1.12 case KEY_UP:
437 sysadm 1.16 case KEY_PGUP:
438     case KEY_HOME:
439 sysadm 1.12 if (p_ctx->reach_begin)
440     {
441     if (section_topic_view_mode)
442     {
443     *p_key = KEY_PGUP;
444     }
445 sysadm 1.16 else
446     {
447     *p_key = KEY_UP;
448     }
449 sysadm 1.12 return 1;
450     }
451     break;
452 sysadm 1.28 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 sysadm 1.12 case KEY_DOWN:
463 sysadm 1.16 case KEY_PGDN:
464     case KEY_END:
465 sysadm 1.12 if (p_ctx->reach_end)
466     {
467     if (section_topic_view_mode)
468     {
469     *p_key = KEY_PGDN;
470     }
471 sysadm 1.16 else
472     {
473     *p_key = KEY_DOWN;
474     }
475 sysadm 1.12 return 1;
476     }
477     break;
478 sysadm 1.28 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 sysadm 1.10 }
489    
490     return 0;
491     }
492    
493 sysadm 1.46 int section_list_display(const char *sname, int32_t aid)
494 sysadm 1.1 {
495 sysadm 1.4 static int display_nickname = 0;
496    
497 sysadm 1.1 SECTION_LIST *p_section;
498 sysadm 1.46 int64_t section_index;
499     int32_t aid_location;
500 sysadm 1.5 char stitle[BBS_section_title_max_len + 1];
501     char master_list[(BBS_username_max_len + 1) * 3 + 1];
502 sysadm 1.6 char page_info_str[LINE_BUFFER_LEN];
503 sysadm 1.1 ARTICLE *p_articles[BBS_article_limit_per_page];
504     int article_count;
505 sysadm 1.6 int page_count;
506 sysadm 1.36 int ontop_start_offset;
507 sysadm 1.1 int page_id = 0;
508     int selected_index = 0;
509 sysadm 1.10 ARTICLE_CACHE cache;
510 sysadm 1.1 int ret;
511 sysadm 1.12 int loop;
512     int direction;
513 sysadm 1.24 ARTICLE article_new;
514 sysadm 1.31 int page_id_cur;
515 sysadm 1.46 const ARTICLE *p_article_locate;
516 sysadm 1.1
517 sysadm 1.50 p_section = section_list_find_by_name(sname);
518 sysadm 1.1 if (p_section == NULL)
519     {
520     log_error("Section %s not found\n", sname);
521     return -1;
522     }
523    
524 sysadm 1.52 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 sysadm 1.50 section_index = get_section_index(p_section);
532    
533 sysadm 1.5 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 sysadm 1.46 if (aid == 0)
551     {
552     aid_location = section_aid_locations[section_index];
553     }
554     else
555     {
556     aid_location = aid;
557 sysadm 1.51 }
558 sysadm 1.46
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 sysadm 1.5 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
580 sysadm 1.1 {
581     log_error("section_list_draw_screen() error\n");
582     return -2;
583     }
584    
585 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
586 sysadm 1.5 if (ret < 0)
587 sysadm 1.1 {
588 sysadm 1.5 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
589     return -3;
590 sysadm 1.1 }
591 sysadm 1.5
592 sysadm 1.46 section_topic_view_tid = -1;
593    
594 sysadm 1.5 if (article_count == 0) // empty section
595 sysadm 1.1 {
596     selected_index = 0;
597     }
598 sysadm 1.46 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 sysadm 1.1
607     while (!SYS_server_exit)
608     {
609 sysadm 1.36 ret = section_list_draw_items(page_id, p_articles, article_count, display_nickname, ontop_start_offset);
610 sysadm 1.1 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 sysadm 1.6
616 sysadm 1.7 snprintf(page_info_str, sizeof(page_info_str),
617 sysadm 1.40 "\033[33m[第\033[36m%d\033[33m/\033[36m%d\033[33m页]",
618 sysadm 1.7 page_id + 1, MAX(page_count, 1));
619 sysadm 1.8
620 sysadm 1.6 show_bottom(page_info_str);
621 sysadm 1.1 iflush();
622    
623 sysadm 1.33 if (user_online_update(sname) < 0)
624     {
625     log_error("user_online_update(%s) error\n", sname);
626     }
627    
628 sysadm 1.6 ret = section_list_select(page_count, article_count, &page_id, &selected_index);
629 sysadm 1.1 switch (ret)
630     {
631     case EXIT_SECTION:
632     return 0;
633     case CHANGE_PAGE:
634 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
635 sysadm 1.5 if (ret < 0)
636 sysadm 1.1 {
637 sysadm 1.5 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
638     return -3;
639 sysadm 1.1 }
640 sysadm 1.5 if (article_count == 0) // empty section
641 sysadm 1.1 {
642     selected_index = 0;
643     }
644 sysadm 1.5 else if (selected_index >= article_count)
645 sysadm 1.1 {
646     selected_index = article_count - 1;
647     }
648     break;
649     case VIEW_ARTICLE:
650 sysadm 1.12 do
651 sysadm 1.9 {
652 sysadm 1.12 loop = 0;
653 sysadm 1.9
654 sysadm 1.12 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 sysadm 1.33 if (user_online_update("VIEW_ARTICLE") < 0)
661     {
662     log_error("user_online_update(VIEW_ARTICLE) error\n");
663     }
664    
665 sysadm 1.19 ret = display_data(cache.p_data, cache.line_total, cache.line_offsets, 0,
666 sysadm 1.12 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 sysadm 1.17 // 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 sysadm 1.12 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 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
691 sysadm 1.12 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 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
722 sysadm 1.12 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 sysadm 1.31 ret = locate_article_in_section(p_section, p_articles[selected_index], direction, 1,
748     &page_id, &selected_index, &article_count);
749 sysadm 1.12 if (ret < 0)
750     {
751 sysadm 1.31 log_error("locate_article_in_section(sid=%d, aid=%d, direction=%d, step=1) error\n",
752 sysadm 1.12 p_section->sid, p_articles[selected_index]->aid, direction);
753     return -3;
754     }
755 sysadm 1.31 else if (ret > 0) // found
756 sysadm 1.12 {
757 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
758 sysadm 1.12 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 sysadm 1.20 case 'r': // Reply article
767 sysadm 1.33 if (user_online_update("REPLY_ARTICLE") < 0)
768     {
769     log_error("user_online_update(REPLY_ARTICLE) error\n");
770     }
771    
772 sysadm 1.24 if (article_reply(p_section, p_articles[selected_index], &article_new) < 0)
773 sysadm 1.20 {
774 sysadm 1.33 log_error("article_reply(aid=%d) error\n", p_articles[selected_index]->aid);
775 sysadm 1.20 }
776     loop = 1;
777     break;
778 sysadm 1.31 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 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
795 sysadm 1.31 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 sysadm 1.12 }
805     } while (loop);
806 sysadm 1.13
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 sysadm 1.46
810     // Update current aid location
811     section_aid_locations[section_index] = p_articles[selected_index]->aid;
812 sysadm 1.35
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 sysadm 1.4 case CHANGE_NAME_DISPLAY:
820     display_nickname = !display_nickname;
821 sysadm 1.5 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
822 sysadm 1.1 {
823     log_error("section_list_draw_screen() error\n");
824     return -2;
825     }
826     break;
827 sysadm 1.20 case POST_ARTICLE:
828 sysadm 1.33 if (user_online_update("POST_ARTICLE") < 0)
829     {
830     log_error("user_online_update(POST_ARTICLE) error\n");
831     }
832    
833 sysadm 1.30 if ((ret = article_post(p_section, &article_new)) < 0)
834 sysadm 1.20 {
835 sysadm 1.26 log_error("article_post(sid=%d) error\n", p_section->sid);
836 sysadm 1.20 }
837 sysadm 1.24 else if (ret > 0) // New article posted
838     {
839 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
840 sysadm 1.24 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 sysadm 1.20 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 sysadm 1.26 if (!checkpriv(&BBS_priv, p_section->sid, S_POST) ||
854     p_articles[selected_index]->uid != BBS_priv.uid)
855 sysadm 1.20 {
856 sysadm 1.26 break; // No permission
857 sysadm 1.20 }
858 sysadm 1.33
859     if (user_online_update("EDIT_ARTICLE") < 0)
860     {
861     log_error("user_online_update() error\n");
862     }
863    
864 sysadm 1.24 if (article_modify(p_section, p_articles[selected_index], &article_new) < 0)
865 sysadm 1.20 {
866 sysadm 1.26 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 sysadm 1.30 if ((ret = article_del(p_section, p_articles[selected_index])) < 0)
881 sysadm 1.26 {
882     log_error("article_del(aid=%d) error\n", p_articles[selected_index]->aid);
883 sysadm 1.20 }
884 sysadm 1.30 else if (ret > 0) // Article deleted
885     {
886 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
887 sysadm 1.30 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 sysadm 1.20 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 sysadm 1.41 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 sysadm 1.31 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 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
925 sysadm 1.31 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 sysadm 1.45 case SCAN_NEW_ARTICLE:
933 sysadm 1.46 ret = scan_unread_article_in_section(p_section, p_articles[selected_index], &p_article_locate);
934 sysadm 1.45 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 sysadm 1.46 ret = locate_article_in_section(p_section, p_article_locate, 0, 0,
946 sysadm 1.45 &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 sysadm 1.46 p_section->sid, p_article_locate->aid);
951 sysadm 1.45 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 sysadm 1.28 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 sysadm 1.37 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 sysadm 1.48 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 sysadm 1.1 default:
992     log_error("Unknown command %d\n", ret);
993     }
994     }
995    
996     return 0;
997     }
998 sysadm 1.37
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 sysadm 1.39 if (p_section->ex_menu_tm == 0) // N/A
1011     {
1012     moveto(2, 1);
1013     clrtoeol();
1014 sysadm 1.40 prints("该版块精华区未开放");
1015 sysadm 1.39 press_any_key();
1016     return 0;
1017     }
1018    
1019 sysadm 1.37 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 sysadm 1.39 log_error("get_menu_shm_readonly(sid=%d) error\n", p_section->sid);
1027 sysadm 1.37 return -3;
1028     }
1029    
1030     clearscr();
1031 sysadm 1.38 show_bottom("");
1032 sysadm 1.37
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 sysadm 1.38 show_bottom("");
1060 sysadm 1.37 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