/[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.85 - (hide annotations)
Thu Dec 25 14:37:08 2025 UTC (2 months, 3 weeks ago) by sysadm
Branch: MAIN
Changes since 1.84: +18 -0 lines
Content type: text/x-csrc
Add feature: Set/Unset excerption article

1 sysadm 1.69 /* SPDX-License-Identifier: GPL-3.0-or-later */
2     /*
3     * section_list_display
4     * - user interactive feature of section articles list
5     *
6 sysadm 1.70 * Copyright (C) 2004-2025 Leaflet <leaflet@leafok.com>
7 sysadm 1.69 */
8 sysadm 1.1
9 sysadm 1.75 #ifdef HAVE_CONFIG_H
10     #include "config.h"
11     #endif
12    
13 sysadm 1.9 #include "article_cache.h"
14 sysadm 1.53 #include "article_favor.h"
15 sysadm 1.41 #include "article_op.h"
16 sysadm 1.20 #include "article_post.h"
17 sysadm 1.34 #include "article_view_log.h"
18 sysadm 1.26 #include "article_del.h"
19 sysadm 1.1 #include "common.h"
20     #include "io.h"
21 sysadm 1.34 #include "log.h"
22     #include "login.h"
23 sysadm 1.37 #include "menu.h"
24 sysadm 1.48 #include "menu_proc.h"
25 sysadm 1.34 #include "section_list_display.h"
26     #include "section_list_loader.h"
27 sysadm 1.1 #include "screen.h"
28 sysadm 1.34 #include "str_process.h"
29 sysadm 1.57 #include "user_info_display.h"
30 sysadm 1.63 #include "user_list_display.h"
31 sysadm 1.18 #include "user_priv.h"
32 sysadm 1.65 #include <ctype.h>
33 sysadm 1.59 #include <errno.h>
34 sysadm 1.29 #include <string.h>
35 sysadm 1.1 #include <time.h>
36 sysadm 1.6 #include <sys/param.h>
37 sysadm 1.1
38 sysadm 1.72 enum _section_list_display_constant_t
39     {
40     TITLE_SEARCH_MAX_LEN = 60,
41     };
42 sysadm 1.66
43 sysadm 1.59 static int32_t section_aid_locations[BBS_max_section] = {0};
44 sysadm 1.11 static int section_topic_view_mode = 0;
45 sysadm 1.13 static int section_topic_view_tid = -1;
46 sysadm 1.11
47 sysadm 1.1 enum select_cmd_t
48     {
49     EXIT_SECTION = 0,
50 sysadm 1.41 VIEW_ARTICLE,
51     CHANGE_PAGE,
52     SHOW_HELP,
53     CHANGE_NAME_DISPLAY,
54     POST_ARTICLE,
55     EDIT_ARTICLE,
56     DELETE_ARTICLE,
57     QUERY_ARTICLE,
58 sysadm 1.57 QUERY_USER,
59 sysadm 1.53 SET_FAVOR_ARTICLE,
60     UNSET_FAVOR_ARTICLE,
61 sysadm 1.85 SET_EXCERPTION_ARTICLE,
62 sysadm 1.41 FIRST_TOPIC_ARTICLE,
63     LAST_TOPIC_ARTICLE,
64 sysadm 1.68 LAST_SECTION_ARTICLE,
65 sysadm 1.45 SCAN_NEW_ARTICLE,
66 sysadm 1.64 SCAN_ARTICLE_BACKWARD_BY_USER,
67     SCAN_ARTICLE_FORWARD_BY_USER,
68 sysadm 1.66 SCAN_ARTICLE_BACKWARD_BY_TITLE,
69     SCAN_ARTICLE_FORWARD_BY_TITLE,
70 sysadm 1.41 VIEW_EX_DIR,
71 sysadm 1.48 SHOW_TOP10,
72 sysadm 1.63 SEARCH_USER,
73 sysadm 1.1 };
74    
75 sysadm 1.80 static int section_list_draw_items(int page_id, const ARTICLE *p_articles[], int article_count, int display_nickname, int ontop_start_offset)
76 sysadm 1.1 {
77     char str_time[LINE_BUFFER_LEN];
78     struct tm tm_sub;
79     char title_f[BBS_article_title_max_len + 1];
80     int title_f_len;
81     int eol;
82     int len;
83     int i;
84 sysadm 1.42 size_t j;
85 sysadm 1.3 char article_flag;
86 sysadm 1.17 int is_viewed;
87 sysadm 1.53 int is_favor;
88 sysadm 1.3 time_t tm_now;
89    
90     time(&tm_now);
91 sysadm 1.1
92     clrline(4, 23);
93    
94     for (i = 0; i < article_count; i++)
95     {
96 sysadm 1.18 if (p_articles[i]->uid == BBS_priv.uid)
97 sysadm 1.17 {
98 sysadm 1.18 is_viewed = 1;
99     }
100     else
101     {
102     is_viewed = article_view_log_is_viewed(p_articles[i]->aid, &BBS_article_view_log);
103     if (is_viewed < 0)
104     {
105 sysadm 1.84 log_error("article_view_log_is_viewed(aid=%d) error", p_articles[i]->aid);
106 sysadm 1.18 is_viewed = 0;
107     }
108 sysadm 1.17 }
109    
110 sysadm 1.53 if (p_articles[i]->tid == 0)
111     {
112     is_favor = article_favor_check(p_articles[i]->aid, &BBS_article_favor);
113     if (is_favor < 0)
114     {
115 sysadm 1.84 log_error("article_favor_check(aid=%d) error", p_articles[i]->aid);
116 sysadm 1.53 is_favor = 0;
117     }
118     }
119     else
120     {
121     is_favor = 0;
122     }
123    
124 sysadm 1.3 if (p_articles[i]->excerption)
125     {
126 sysadm 1.17 article_flag = (is_viewed ? 'm' : 'M');
127 sysadm 1.3 }
128 sysadm 1.17 else if (p_articles[i]->lock && is_viewed)
129 sysadm 1.3 {
130     article_flag = 'x';
131     }
132 sysadm 1.35 else
133     {
134     article_flag = (is_viewed ? ' ' : 'N');
135     }
136 sysadm 1.3
137 sysadm 1.1 localtime_r(&p_articles[i]->sub_dt, &tm_sub);
138 sysadm 1.3 if (tm_now - p_articles[i]->sub_dt < 3600 * 24 * 365)
139     {
140     strftime(str_time, sizeof(str_time), "%b %e ", &tm_sub);
141     }
142     else
143     {
144     strftime(str_time, sizeof(str_time), "%m/%Y", &tm_sub);
145     }
146    
147 sysadm 1.40 strncpy(title_f, (p_articles[i]->tid == 0 ? "● " : ""), sizeof(title_f) - 1);
148 sysadm 1.1 title_f[sizeof(title_f) - 1] = '\0';
149 sysadm 1.40 strncat(title_f, (p_articles[i]->transship ? "[转载]" : ""), sizeof(title_f) - 1 - strnlen(title_f, sizeof(title_f)));
150 sysadm 1.42
151     // Rewrite title with "Re: Re: " prefix into "Re: ... "
152     j = 0;
153     if (p_articles[i]->tid != 0)
154     {
155     while (strncmp(p_articles[i]->title + j, "Re: ", strlen("Re: ")) == 0)
156     {
157     j += strlen("Re: ");
158     }
159     if (j >= strlen("Re: Re: "))
160     {
161     strncat(title_f, "Re: ... ", sizeof(title_f) - 1 - strnlen(title_f, sizeof(title_f)));
162     }
163     else
164     {
165     j = 0;
166     }
167     }
168     strncat(title_f, p_articles[i]->title + j, sizeof(title_f) - 1 - strnlen(title_f, sizeof(title_f)));
169    
170 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);
171 sysadm 1.1 if (title_f[len] != '\0')
172     {
173     title_f[len] = '\0';
174     }
175    
176     moveto(4 + i, 1);
177 sysadm 1.36 if (i >= ontop_start_offset)
178     {
179 sysadm 1.53 prints(" \033[1;33m[提示]\033[m%c%c %s%*s %s %s%s\033[m",
180     (is_favor ? '@' : ' '),
181 sysadm 1.36 article_flag,
182     (display_nickname ? p_articles[i]->nickname : p_articles[i]->username),
183 sysadm 1.43 (display_nickname ? BBS_nickname_max_len / 2 - str_length(p_articles[i]->nickname, 1)
184     : BBS_username_max_len - str_length(p_articles[i]->username, 1)),
185 sysadm 1.36 "",
186     str_time,
187     (p_articles[i]->aid == section_topic_view_tid
188     ? "\033[1;33m"
189     : (p_articles[i]->tid == section_topic_view_tid
190     ? "\033[1;36m"
191     : "")),
192     title_f);
193     }
194     else
195     {
196 sysadm 1.53 prints(" %s%7d\033[m%c%c %s%*s %s %s%s\033[m",
197 sysadm 1.36 (p_articles[i]->aid == section_topic_view_tid
198     ? "\033[1;33m"
199     : (p_articles[i]->tid == section_topic_view_tid
200     ? "\033[1;36m"
201     : "")),
202     p_articles[i]->aid,
203 sysadm 1.53 (is_favor ? '@' : ' '),
204 sysadm 1.36 article_flag,
205     (display_nickname ? p_articles[i]->nickname : p_articles[i]->username),
206 sysadm 1.43 (display_nickname ? BBS_nickname_max_len / 2 - str_length(p_articles[i]->nickname, 1)
207     : BBS_username_max_len - str_length(p_articles[i]->username, 1)),
208 sysadm 1.36 "",
209     str_time,
210     (p_articles[i]->aid == section_topic_view_tid
211     ? "\033[1;33m"
212     : (p_articles[i]->tid == section_topic_view_tid
213     ? "\033[1;36m"
214     : "")),
215     title_f);
216     }
217 sysadm 1.1 }
218    
219     return 0;
220     }
221    
222 sysadm 1.5 static int section_list_draw_screen(const char *sname, const char *stitle, const char *master_list, int display_nickname)
223 sysadm 1.1 {
224 sysadm 1.40 char str_section_master[LINE_BUFFER_LEN] = "诚征版主中";
225 sysadm 1.1 char str_section_name[LINE_BUFFER_LEN];
226    
227 sysadm 1.5 if (master_list[0] != '\0')
228 sysadm 1.1 {
229 sysadm 1.74 snprintf(str_section_master, sizeof(str_section_master), "版主: %s", master_list);
230 sysadm 1.1 }
231 sysadm 1.40 snprintf(str_section_name, sizeof(str_section_name), "讨论区 [%s]", sname);
232 sysadm 1.1
233     clearscr();
234 sysadm 1.5 show_top(str_section_master, stitle, str_section_name);
235 sysadm 1.1 moveto(2, 0);
236 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] "
237     "阅读[\033[1;32m→\033[0;37m,\033[1;32mENTER\033[0;37m] 发表[\033[1;32mCtrl-P\033[0;37m] "
238     "%s[\033[1;32mn\033[0;37m] 精华区[\033[1;32mx\033[0;37m] 帮助[\033[1;32mh\033[0;37m]\033[m",
239     (display_nickname ? "用户名" : "昵称"));
240 sysadm 1.1 moveto(3, 0);
241 sysadm 1.4 if (display_nickname)
242     {
243 sysadm 1.40 prints("\033[44;37m \033[1;37m 编 号 发布者昵称 日 期 文章标题 \033[m");
244 sysadm 1.4 }
245     else
246     {
247 sysadm 1.40 prints("\033[44;37m \033[1;37m 编 号 发 布 者 日 期 文章标题 \033[m");
248 sysadm 1.4 }
249 sysadm 1.1
250     return 0;
251     }
252    
253     static enum select_cmd_t section_list_select(int total_page, int item_count, int *p_page_id, int *p_selected_index)
254     {
255     int old_page_id = *p_page_id;
256     int old_selected_index = *p_selected_index;
257     int ch;
258 sysadm 1.30 time_t last_refresh_tm = time(NULL);
259 sysadm 1.1
260     if (item_count > 0 && *p_selected_index >= 0)
261     {
262     moveto(4 + *p_selected_index, 1);
263     outc('>');
264     iflush();
265     }
266    
267     while (!SYS_server_exit)
268     {
269     ch = igetch(100);
270    
271 sysadm 1.54 if (ch != KEY_NULL && ch != KEY_TIMEOUT)
272     {
273     BBS_last_access_tm = time(NULL);
274 sysadm 1.79
275     // Refresh current action
276     if (user_online_update(NULL) < 0)
277     {
278 sysadm 1.84 log_error("user_online_update(NULL) error");
279 sysadm 1.79 }
280 sysadm 1.54 }
281    
282 sysadm 1.1 switch (ch)
283     {
284 sysadm 1.57 case KEY_NULL: // broken pipe
285 sysadm 1.84 log_debug("KEY_NULL");
286 sysadm 1.54 return EXIT_SECTION;
287 sysadm 1.1 case KEY_TIMEOUT:
288 sysadm 1.71 if (time(NULL) - BBS_last_access_tm >= BBS_max_user_idle_time)
289 sysadm 1.1 {
290 sysadm 1.84 log_debug("User input timeout");
291 sysadm 1.54 return EXIT_SECTION;
292 sysadm 1.1 }
293     continue;
294 sysadm 1.54 case KEY_ESC:
295     case KEY_LEFT:
296     return EXIT_SECTION;
297 sysadm 1.4 case 'n':
298     return CHANGE_NAME_DISPLAY;
299 sysadm 1.1 case CR:
300 sysadm 1.28 case 'r':
301 sysadm 1.1 case KEY_RIGHT:
302     if (item_count > 0)
303     {
304     return VIEW_ARTICLE;
305     }
306     break;
307 sysadm 1.20 case Ctrl('P'):
308     return POST_ARTICLE;
309     case 'E':
310 sysadm 1.41 if (item_count > 0)
311     {
312     return EDIT_ARTICLE;
313     }
314     break;
315 sysadm 1.26 case 'd':
316 sysadm 1.41 if (item_count > 0)
317     {
318     return DELETE_ARTICLE;
319     }
320     break;
321     case Ctrl('Q'):
322     if (item_count > 0)
323     {
324     return QUERY_ARTICLE;
325     }
326     break;
327 sysadm 1.57 case Ctrl('A'):
328     if (item_count > 0)
329     {
330     return QUERY_USER;
331     }
332     break;
333 sysadm 1.53 case 'F':
334     if (item_count > 0)
335     {
336     return SET_FAVOR_ARTICLE;
337     }
338     break;
339     case '-':
340     if (item_count > 0)
341     {
342     return UNSET_FAVOR_ARTICLE;
343     }
344     break;
345 sysadm 1.85 case 'm':
346     if (item_count > 0)
347     {
348     return SET_EXCERPTION_ARTICLE;
349     }
350     break;
351 sysadm 1.1 case KEY_HOME:
352     *p_page_id = 0;
353 sysadm 1.28 case 'P':
354 sysadm 1.1 case KEY_PGUP:
355     *p_selected_index = 0;
356 sysadm 1.28 case 'k':
357 sysadm 1.1 case KEY_UP:
358     if (*p_selected_index <= 0)
359     {
360     if (*p_page_id > 0)
361     {
362     (*p_page_id)--;
363     *p_selected_index = BBS_article_limit_per_page - 1;
364     }
365 sysadm 1.44 else if (ch == KEY_UP || ch == 'k') // Rotate to the tail of section list
366     {
367     if (total_page > 0)
368     {
369     *p_page_id = total_page - 1;
370     }
371     if (item_count > 0)
372     {
373     *p_selected_index = item_count - 1;
374     }
375     }
376 sysadm 1.1 }
377     else
378     {
379     (*p_selected_index)--;
380     }
381     break;
382 sysadm 1.28 case '$':
383 sysadm 1.1 case KEY_END:
384 sysadm 1.68 if (*p_page_id + 1 == total_page && *p_selected_index + 1 == item_count) // Press END at end of list
385     {
386     return LAST_SECTION_ARTICLE;
387     }
388 sysadm 1.1 if (total_page > 0)
389     {
390     *p_page_id = total_page - 1;
391     }
392 sysadm 1.28 case 'N':
393 sysadm 1.1 case KEY_PGDN:
394     if (item_count > 0)
395     {
396     *p_selected_index = item_count - 1;
397     }
398 sysadm 1.28 case 'j':
399 sysadm 1.1 case KEY_DOWN:
400     if (*p_selected_index + 1 >= item_count) // next page
401     {
402     if (*p_page_id + 1 < total_page)
403     {
404     (*p_page_id)++;
405     *p_selected_index = 0;
406     }
407 sysadm 1.44 else if (ch == KEY_DOWN || ch == 'j') // Rotate to the head of section list
408 sysadm 1.25 {
409 sysadm 1.44 *p_page_id = 0;
410     *p_selected_index = 0;
411 sysadm 1.25 }
412 sysadm 1.1 }
413     else
414     {
415     (*p_selected_index)++;
416     }
417     break;
418 sysadm 1.31 case '=':
419 sysadm 1.41 if (item_count > 0)
420     {
421     return FIRST_TOPIC_ARTICLE;
422     }
423     break;
424 sysadm 1.31 case '\\':
425 sysadm 1.41 if (item_count > 0)
426     {
427     return LAST_TOPIC_ARTICLE;
428     }
429     break;
430 sysadm 1.45 case 'S':
431     if (item_count > 0)
432     {
433     return SCAN_NEW_ARTICLE;
434     }
435     break;
436 sysadm 1.64 case 'A':
437     if (item_count > 0)
438     {
439     return SCAN_ARTICLE_BACKWARD_BY_USER;
440     }
441     break;
442     case 'a':
443     if (item_count > 0)
444     {
445     return SCAN_ARTICLE_FORWARD_BY_USER;
446     }
447     break;
448 sysadm 1.66 case '?':
449     if (item_count > 0)
450     {
451     return SCAN_ARTICLE_BACKWARD_BY_TITLE;
452     }
453     break;
454     case '/':
455     if (item_count > 0)
456     {
457     return SCAN_ARTICLE_FORWARD_BY_TITLE;
458     }
459     break;
460 sysadm 1.63 case 'u':
461     return SEARCH_USER;
462 sysadm 1.28 case 'h':
463     return SHOW_HELP;
464 sysadm 1.37 case 'x':
465     return VIEW_EX_DIR;
466 sysadm 1.49 case 'H':
467 sysadm 1.48 return SHOW_TOP10;
468 sysadm 1.1 default:
469 sysadm 1.56 break;
470 sysadm 1.1 }
471    
472     if (old_page_id != *p_page_id)
473     {
474     return CHANGE_PAGE;
475     }
476    
477     if (item_count > 0 && old_selected_index != *p_selected_index)
478     {
479     if (old_selected_index >= 0)
480     {
481     moveto(4 + old_selected_index, 1);
482     outc(' ');
483     }
484     if (*p_selected_index >= 0)
485     {
486     moveto(4 + *p_selected_index, 1);
487     outc('>');
488     }
489     iflush();
490    
491     old_selected_index = *p_selected_index;
492     }
493    
494 sysadm 1.30 if (BBS_last_access_tm - last_refresh_tm >= BBS_section_list_load_interval)
495     {
496     return CHANGE_PAGE; // force section list refresh
497     }
498 sysadm 1.1 }
499    
500     return EXIT_SECTION;
501     }
502    
503 sysadm 1.11 static int display_article_key_handler(int *p_key, DISPLAY_CTX *p_ctx)
504 sysadm 1.10 {
505 sysadm 1.11 switch (*p_key)
506 sysadm 1.10 {
507 sysadm 1.11 case 'p':
508 sysadm 1.28 case Ctrl('X'):
509 sysadm 1.11 section_topic_view_mode = !section_topic_view_mode;
510 sysadm 1.10 case 0: // Set msg
511 sysadm 1.11 if (section_topic_view_mode)
512 sysadm 1.10 {
513 sysadm 1.11 snprintf(p_ctx->msg, sizeof(p_ctx->msg),
514 sysadm 1.40 "| 返回[\033[32m←\033[33m,\033[32mESC\033[33m] "
515     "同主题阅读[\033[32m↑\033[33m/\033[32m↓\033[33m] "
516     "切换[\033[32mp\033[33m] 回复[\033[32mr\033[33m] 帮助[\033[32mh\033[33m] |");
517 sysadm 1.10 }
518     else
519     {
520 sysadm 1.11 snprintf(p_ctx->msg, sizeof(p_ctx->msg),
521 sysadm 1.40 "| 返回[\033[32m←\033[33m,\033[32mESC\033[33m] "
522     "移动[\033[32m↑\033[33m/\033[32m↓\033[33m/\033[32mPgUp\033[33m/\033[32mPgDn\033[33m] "
523     "切换[\033[32mp\033[33m] 回复[\033[32mr\033[33m] 帮助[\033[32mh\033[33m] |");
524 sysadm 1.10 }
525 sysadm 1.11 *p_key = 0;
526 sysadm 1.10 break;
527 sysadm 1.20 case 'r': // Reply article
528     return 1;
529 sysadm 1.31 case '=': // First topic article
530     return 1;
531     case '\\': // Last topic article
532     return 1;
533 sysadm 1.12 case KEY_UP:
534 sysadm 1.16 case KEY_PGUP:
535     case KEY_HOME:
536 sysadm 1.12 if (p_ctx->reach_begin)
537     {
538     if (section_topic_view_mode)
539     {
540     *p_key = KEY_PGUP;
541     }
542 sysadm 1.16 else
543     {
544     *p_key = KEY_UP;
545     }
546 sysadm 1.12 return 1;
547     }
548     break;
549 sysadm 1.28 case 'k':
550     if (section_topic_view_mode)
551     {
552     *p_key = KEY_PGUP;
553     }
554     else
555     {
556     *p_key = KEY_UP;
557     }
558     return 1;
559 sysadm 1.12 case KEY_DOWN:
560 sysadm 1.16 case KEY_PGDN:
561     case KEY_END:
562 sysadm 1.12 if (p_ctx->reach_end)
563     {
564     if (section_topic_view_mode)
565     {
566     *p_key = KEY_PGDN;
567     }
568 sysadm 1.16 else
569     {
570     *p_key = KEY_DOWN;
571     }
572 sysadm 1.12 return 1;
573     }
574     break;
575 sysadm 1.28 case 'j':
576     if (section_topic_view_mode)
577     {
578     *p_key = KEY_PGDN;
579     }
580     else
581     {
582     *p_key = KEY_DOWN;
583     }
584     return 1;
585 sysadm 1.10 }
586    
587     return 0;
588     }
589    
590 sysadm 1.46 int section_list_display(const char *sname, int32_t aid)
591 sysadm 1.1 {
592 sysadm 1.4 static int display_nickname = 0;
593    
594 sysadm 1.1 SECTION_LIST *p_section;
595 sysadm 1.46 int64_t section_index;
596     int32_t aid_location;
597 sysadm 1.5 char stitle[BBS_section_title_max_len + 1];
598     char master_list[(BBS_username_max_len + 1) * 3 + 1];
599 sysadm 1.6 char page_info_str[LINE_BUFFER_LEN];
600 sysadm 1.80 const ARTICLE *p_articles[BBS_article_limit_per_page];
601 sysadm 1.1 int article_count;
602 sysadm 1.6 int page_count;
603 sysadm 1.36 int ontop_start_offset;
604 sysadm 1.1 int page_id = 0;
605     int selected_index = 0;
606 sysadm 1.10 ARTICLE_CACHE cache;
607 sysadm 1.1 int ret;
608 sysadm 1.12 int loop;
609     int direction;
610 sysadm 1.24 ARTICLE article_new;
611 sysadm 1.31 int page_id_cur;
612 sysadm 1.46 const ARTICLE *p_article_locate;
613 sysadm 1.57 USER_INFO user_info;
614 sysadm 1.66 char user_intro[BBS_user_intro_max_len + 1];
615 sysadm 1.64 char username[BBS_username_max_len + 1];
616     char username_list[1][BBS_username_max_len + 1];
617     int32_t uid;
618     int i;
619     int ok;
620 sysadm 1.66 char title[BBS_article_title_max_len + 1] = "\0";
621 sysadm 1.1
622 sysadm 1.50 p_section = section_list_find_by_name(sname);
623 sysadm 1.1 if (p_section == NULL)
624     {
625 sysadm 1.84 log_error("Section %s not found", sname);
626 sysadm 1.1 return -1;
627     }
628    
629 sysadm 1.52 if (!checkpriv(&BBS_priv, p_section->sid, S_LIST))
630     {
631 sysadm 1.84 log_error("Forbid access to unauthorized section, sid=%d, uid=%d",
632 sysadm 1.52 p_section->sid, BBS_priv.uid);
633     return -1;
634     }
635    
636 sysadm 1.50 section_index = get_section_index(p_section);
637    
638 sysadm 1.58 if (get_section_info(p_section, NULL, stitle, master_list) < 0)
639 sysadm 1.5 {
640 sysadm 1.84 log_error("get_section_info(sid=%d) error", p_section->sid);
641 sysadm 1.58 return -4;
642 sysadm 1.5 }
643    
644 sysadm 1.46 if (aid == 0)
645     {
646     aid_location = section_aid_locations[section_index];
647     }
648     else
649     {
650     aid_location = aid;
651 sysadm 1.51 }
652 sysadm 1.46
653     // Locate at article with aid_locate
654     if (aid_location > 0)
655     {
656     p_article_locate = article_block_find_by_aid(aid_location);
657     if (p_article_locate == NULL)
658     {
659 sysadm 1.84 log_error("article_block_find_by_aid(%d) error", aid_location);
660 sysadm 1.46 return -3;
661     }
662    
663     ret = locate_article_in_section(p_section, p_article_locate, 0, 0,
664     &page_id, &selected_index, &article_count);
665     if (ret < 0)
666     {
667 sysadm 1.84 log_error("locate_article_in_section(sid=%d, aid=%d, direction=0, step=0) error",
668 sysadm 1.46 p_section->sid, p_article_locate->aid);
669     return -3;
670     }
671     }
672    
673 sysadm 1.5 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
674 sysadm 1.1 {
675 sysadm 1.84 log_error("section_list_draw_screen() error");
676 sysadm 1.1 return -2;
677     }
678    
679 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
680 sysadm 1.5 if (ret < 0)
681 sysadm 1.1 {
682 sysadm 1.84 log_error("query_section_articles(sid=%d, page_id=%d) error", p_section->sid, page_id);
683 sysadm 1.5 return -3;
684 sysadm 1.1 }
685 sysadm 1.5
686 sysadm 1.46 section_topic_view_tid = -1;
687    
688 sysadm 1.5 if (article_count == 0) // empty section
689 sysadm 1.1 {
690     selected_index = 0;
691     }
692 sysadm 1.46 else if (aid > 0)
693     {
694     // Update current topic
695     section_topic_view_tid = (p_articles[selected_index]->tid == 0 ? p_articles[selected_index]->aid : p_articles[selected_index]->tid);
696    
697     // Update current aid location
698     section_aid_locations[section_index] = p_articles[selected_index]->aid;
699     }
700 sysadm 1.1
701     while (!SYS_server_exit)
702     {
703 sysadm 1.36 ret = section_list_draw_items(page_id, p_articles, article_count, display_nickname, ontop_start_offset);
704 sysadm 1.1 if (ret < 0)
705     {
706 sysadm 1.84 log_error("section_list_draw_items(sid=%d, page_id=%d) error", p_section->sid, page_id);
707 sysadm 1.1 return -4;
708     }
709 sysadm 1.6
710 sysadm 1.7 snprintf(page_info_str, sizeof(page_info_str),
711 sysadm 1.40 "\033[33m[第\033[36m%d\033[33m/\033[36m%d\033[33m页]",
712 sysadm 1.7 page_id + 1, MAX(page_count, 1));
713 sysadm 1.8
714 sysadm 1.6 show_bottom(page_info_str);
715 sysadm 1.1 iflush();
716    
717 sysadm 1.33 if (user_online_update(sname) < 0)
718     {
719 sysadm 1.84 log_error("user_online_update(%s) error", sname);
720 sysadm 1.33 }
721    
722 sysadm 1.6 ret = section_list_select(page_count, article_count, &page_id, &selected_index);
723 sysadm 1.60
724 sysadm 1.1 switch (ret)
725     {
726     case EXIT_SECTION:
727 sysadm 1.62 // Update current aid location
728 sysadm 1.77 if (selected_index < article_count && p_articles[selected_index] != NULL)
729 sysadm 1.62 {
730 sysadm 1.68 if (selected_index >= ontop_start_offset)
731     {
732     ret = last_article_in_section(p_section, &p_article_locate);
733     if (ret < 0)
734     {
735 sysadm 1.84 log_error("last_article_in_section(sid=%d) error", p_section->sid);
736 sysadm 1.68 return -3;
737     }
738     else if (ret == 0)
739     {
740     section_aid_locations[section_index] = 0;
741     }
742     else // ret > 0
743     {
744     section_aid_locations[section_index] = p_article_locate->aid;
745     }
746     }
747     else
748     {
749     section_aid_locations[section_index] = (p_articles[selected_index]->visible ? p_articles[selected_index]->aid : 0);
750     }
751 sysadm 1.62 }
752 sysadm 1.1 return 0;
753     case CHANGE_PAGE:
754 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
755 sysadm 1.5 if (ret < 0)
756 sysadm 1.1 {
757 sysadm 1.84 log_error("query_section_articles(sid=%d, page_id=%d) error", p_section->sid, page_id);
758 sysadm 1.5 return -3;
759 sysadm 1.1 }
760 sysadm 1.5 if (article_count == 0) // empty section
761 sysadm 1.1 {
762     selected_index = 0;
763     }
764 sysadm 1.5 else if (selected_index >= article_count)
765 sysadm 1.1 {
766     selected_index = article_count - 1;
767     }
768     break;
769     case VIEW_ARTICLE:
770 sysadm 1.12 do
771 sysadm 1.9 {
772 sysadm 1.12 loop = 0;
773 sysadm 1.9
774 sysadm 1.12 if (article_cache_load(&cache, VAR_ARTICLE_CACHE_DIR, p_articles[selected_index]) < 0)
775     {
776 sysadm 1.84 log_error("article_cache_load(aid=%d, cid=%d) error", p_articles[selected_index]->aid, p_articles[selected_index]->cid);
777 sysadm 1.12 break;
778     }
779    
780 sysadm 1.33 if (user_online_update("VIEW_ARTICLE") < 0)
781     {
782 sysadm 1.84 log_error("user_online_update(VIEW_ARTICLE) error");
783 sysadm 1.33 }
784    
785 sysadm 1.19 ret = display_data(cache.p_data, cache.line_total, cache.line_offsets, 0,
786 sysadm 1.12 display_article_key_handler, DATA_READ_HELP);
787    
788     if (article_cache_unload(&cache) < 0)
789     {
790 sysadm 1.84 log_error("article_cache_unload(aid=%d, cid=%d) error", p_articles[selected_index]->aid, p_articles[selected_index]->cid);
791 sysadm 1.12 break;
792     }
793    
794 sysadm 1.17 // Update article_view_log
795     if (article_view_log_set_viewed(p_articles[selected_index]->aid, &BBS_article_view_log) < 0)
796     {
797 sysadm 1.84 log_error("article_view_log_set_viewed(aid=%d) error", p_articles[selected_index]->aid);
798 sysadm 1.17 }
799    
800 sysadm 1.12 switch (ret)
801     {
802     case KEY_UP:
803     if (selected_index <= 0)
804     {
805     if (page_id > 0)
806     {
807     page_id--;
808     selected_index = BBS_article_limit_per_page - 1;
809    
810 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
811 sysadm 1.12 if (ret < 0)
812     {
813 sysadm 1.84 log_error("query_section_articles(sid=%d, page_id=%d) error", p_section->sid, page_id);
814 sysadm 1.12 return -3;
815     }
816    
817     if (article_count != BBS_article_limit_per_page) // page is not full
818     {
819     selected_index = MAX(0, article_count - 1);
820     }
821     else
822     {
823     loop = 1;
824     }
825     }
826     }
827     else
828     {
829     selected_index--;
830     loop = 1;
831     }
832     break;
833     case KEY_DOWN:
834     if (selected_index + 1 >= article_count) // next page
835     {
836     if (page_id + 1 < page_count)
837     {
838     page_id++;
839     selected_index = 0;
840    
841 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
842 sysadm 1.12 if (ret < 0)
843     {
844 sysadm 1.84 log_error("query_section_articles(sid=%d, page_id=%d) error", p_section->sid, page_id);
845 sysadm 1.12 return -3;
846     }
847    
848     if (article_count == 0) // empty page
849     {
850     selected_index = 0;
851     }
852     else
853     {
854     loop = 1;
855     }
856     }
857     }
858     else
859     {
860     selected_index++;
861     loop = 1;
862     }
863     break;
864     case KEY_PGUP:
865     case KEY_PGDN:
866     direction = (ret == KEY_PGUP ? -1 : 1);
867 sysadm 1.31 ret = locate_article_in_section(p_section, p_articles[selected_index], direction, 1,
868     &page_id, &selected_index, &article_count);
869 sysadm 1.12 if (ret < 0)
870     {
871 sysadm 1.84 log_error("locate_article_in_section(sid=%d, aid=%d, direction=%d, step=1) error",
872 sysadm 1.12 p_section->sid, p_articles[selected_index]->aid, direction);
873     return -3;
874     }
875 sysadm 1.31 else if (ret > 0) // found
876 sysadm 1.12 {
877 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
878 sysadm 1.12 if (ret < 0)
879     {
880 sysadm 1.84 log_error("query_section_articles(sid=%d, page_id=%d) error", p_section->sid, page_id);
881 sysadm 1.12 return -3;
882     }
883     loop = 1;
884     }
885     break;
886 sysadm 1.20 case 'r': // Reply article
887 sysadm 1.33 if (user_online_update("REPLY_ARTICLE") < 0)
888     {
889 sysadm 1.84 log_error("user_online_update(REPLY_ARTICLE) error");
890 sysadm 1.33 }
891    
892 sysadm 1.24 if (article_reply(p_section, p_articles[selected_index], &article_new) < 0)
893 sysadm 1.20 {
894 sysadm 1.84 log_error("article_reply(aid=%d) error", p_articles[selected_index]->aid);
895 sysadm 1.20 }
896 sysadm 1.67 else if (ret > 0) // Article replied
897     {
898     ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
899     if (ret < 0)
900     {
901 sysadm 1.84 log_error("query_section_articles(sid=%d, page_id=%d) error", p_section->sid, page_id);
902 sysadm 1.67 return -3;
903     }
904     }
905 sysadm 1.20 loop = 1;
906     break;
907 sysadm 1.31 case '=': // First topic article
908     case '\\': // Last topic article
909     page_id_cur = page_id;
910     direction = (ret == '=' ? -1 : 1);
911     ret = locate_article_in_section(p_section, p_articles[selected_index], direction, BBS_article_limit_per_section,
912     &page_id, &selected_index, &article_count);
913     if (ret < 0)
914     {
915 sysadm 1.84 log_error("locate_article_in_section(sid=%d, aid=%d, direction=%d, step=%d) error",
916 sysadm 1.31 p_section->sid, p_articles[selected_index]->aid, direction, BBS_article_limit_per_section);
917     return -3;
918     }
919     else if (ret > 0) // found
920     {
921     if (page_id != page_id_cur) // page changed
922     {
923 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
924 sysadm 1.31 if (ret < 0)
925     {
926 sysadm 1.84 log_error("query_section_articles(sid=%d, page_id=%d) error", p_section->sid, page_id);
927 sysadm 1.31 return -3;
928     }
929     }
930     loop = 1;
931     }
932     break;
933 sysadm 1.12 }
934     } while (loop);
935 sysadm 1.13
936     // Update current topic
937     section_topic_view_tid = (p_articles[selected_index]->tid == 0 ? p_articles[selected_index]->aid : p_articles[selected_index]->tid);
938 sysadm 1.46
939 sysadm 1.35 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
940     {
941 sysadm 1.84 log_error("section_list_draw_screen() error");
942 sysadm 1.35 return -2;
943     }
944     break;
945 sysadm 1.4 case CHANGE_NAME_DISPLAY:
946     display_nickname = !display_nickname;
947 sysadm 1.5 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
948 sysadm 1.1 {
949 sysadm 1.84 log_error("section_list_draw_screen() error");
950 sysadm 1.1 return -2;
951     }
952     break;
953 sysadm 1.20 case POST_ARTICLE:
954 sysadm 1.33 if (user_online_update("POST_ARTICLE") < 0)
955     {
956 sysadm 1.84 log_error("user_online_update(POST_ARTICLE) error");
957 sysadm 1.33 }
958    
959 sysadm 1.30 if ((ret = article_post(p_section, &article_new)) < 0)
960 sysadm 1.20 {
961 sysadm 1.84 log_error("article_post(sid=%d) error", p_section->sid);
962 sysadm 1.20 }
963 sysadm 1.24 else if (ret > 0) // New article posted
964     {
965 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
966 sysadm 1.24 if (ret < 0)
967     {
968 sysadm 1.84 log_error("query_section_articles(sid=%d, page_id=%d) error: %d", p_section->sid, page_id, ret);
969 sysadm 1.24 return -3;
970     }
971     }
972 sysadm 1.20 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
973     {
974 sysadm 1.84 log_error("section_list_draw_screen() error");
975 sysadm 1.20 return -2;
976     }
977     break;
978     case EDIT_ARTICLE:
979 sysadm 1.26 if (!checkpriv(&BBS_priv, p_section->sid, S_POST) ||
980     p_articles[selected_index]->uid != BBS_priv.uid)
981 sysadm 1.20 {
982 sysadm 1.26 break; // No permission
983 sysadm 1.20 }
984 sysadm 1.33
985     if (user_online_update("EDIT_ARTICLE") < 0)
986     {
987 sysadm 1.84 log_error("user_online_update() error");
988 sysadm 1.33 }
989    
990 sysadm 1.24 if (article_modify(p_section, p_articles[selected_index], &article_new) < 0)
991 sysadm 1.20 {
992 sysadm 1.84 log_error("article_modify(aid=%d) error", p_articles[selected_index]->aid);
993 sysadm 1.26 }
994 sysadm 1.67 else if (ret > 0) // Article modified
995     {
996     ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
997     if (ret < 0)
998     {
999 sysadm 1.84 log_error("query_section_articles(sid=%d, page_id=%d) error", p_section->sid, page_id);
1000 sysadm 1.67 return -3;
1001     }
1002     }
1003 sysadm 1.26 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1004     {
1005 sysadm 1.84 log_error("section_list_draw_screen() error");
1006 sysadm 1.26 return -2;
1007     }
1008     break;
1009     case DELETE_ARTICLE:
1010     if (!checkpriv(&BBS_priv, p_section->sid, S_POST) ||
1011     (!checkpriv(&BBS_priv, p_section->sid, S_MAN_S) && p_articles[selected_index]->uid != BBS_priv.uid))
1012     {
1013     break; // No permission
1014     }
1015 sysadm 1.30 if ((ret = article_del(p_section, p_articles[selected_index])) < 0)
1016 sysadm 1.26 {
1017 sysadm 1.84 log_error("article_del(aid=%d) error", p_articles[selected_index]->aid);
1018 sysadm 1.20 }
1019 sysadm 1.30 else if (ret > 0) // Article deleted
1020     {
1021 sysadm 1.67 do
1022 sysadm 1.30 {
1023 sysadm 1.67 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
1024     if (ret >= 0 && selected_index > article_count - 1)
1025     {
1026     selected_index = article_count - 1;
1027     break;
1028     }
1029     else if (ret < 0 && page_id > 0)
1030     {
1031     page_id--;
1032     selected_index = BBS_article_limit_per_page - 1;
1033     }
1034     else if (ret < 0 && page_id <= 0)
1035     {
1036     selected_index = 0;
1037     break;
1038     }
1039     } while (ret < 0);
1040 sysadm 1.30 }
1041 sysadm 1.20 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1042     {
1043 sysadm 1.84 log_error("section_list_draw_screen() error");
1044 sysadm 1.20 return -2;
1045     }
1046     break;
1047 sysadm 1.41 case QUERY_ARTICLE:
1048     if ((ret = display_article_meta(p_articles[selected_index]->aid)) < 0)
1049     {
1050 sysadm 1.84 log_error("display_article_meta(aid=%d) error", p_articles[selected_index]->aid);
1051 sysadm 1.41 }
1052     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1053     {
1054 sysadm 1.84 log_error("section_list_draw_screen() error");
1055 sysadm 1.41 return -2;
1056     }
1057     break;
1058 sysadm 1.57 case QUERY_USER:
1059 sysadm 1.61 if ((ret = query_user_info_by_uid(p_articles[selected_index]->uid, &user_info, user_intro, sizeof(user_intro))) < 0)
1060 sysadm 1.57 {
1061 sysadm 1.84 log_error("query_user_info_by_uid(uid=%d) error", p_articles[selected_index]->uid);
1062 sysadm 1.57 return -2;
1063     }
1064     else if (ret == 0)
1065     {
1066     clearscr();
1067     prints("该用户已升天");
1068     press_any_key();
1069     }
1070     else if (user_info_display(&user_info) < 0) // && ret > 0
1071     {
1072 sysadm 1.84 log_error("user_info_display(uid=%d) error", p_articles[selected_index]->uid);
1073 sysadm 1.57 }
1074    
1075     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1076     {
1077 sysadm 1.84 log_error("section_list_draw_screen() error");
1078 sysadm 1.57 return -2;
1079     }
1080     break;
1081 sysadm 1.53 case SET_FAVOR_ARTICLE:
1082     ret = article_favor_set(p_articles[selected_index]->tid == 0
1083     ? p_articles[selected_index]->aid
1084     : p_articles[selected_index]->tid,
1085     &BBS_article_favor, 1);
1086     if (ret < 0)
1087     {
1088 sysadm 1.84 log_error("article_favor_set(aid=%d, 1) error",
1089 sysadm 1.53 p_articles[selected_index]->tid == 0 ? p_articles[selected_index]->aid : p_articles[selected_index]->tid);
1090     }
1091     break;
1092     case UNSET_FAVOR_ARTICLE:
1093     ret = article_favor_set(p_articles[selected_index]->tid == 0
1094     ? p_articles[selected_index]->aid
1095     : p_articles[selected_index]->tid,
1096     &BBS_article_favor, 0);
1097     if (ret < 0)
1098     {
1099 sysadm 1.84 log_error("article_favor_set(aid=%d, 0) error",
1100 sysadm 1.53 p_articles[selected_index]->tid == 0 ? p_articles[selected_index]->aid : p_articles[selected_index]->tid);
1101     }
1102     break;
1103 sysadm 1.85 case SET_EXCERPTION_ARTICLE:
1104     if (checkpriv(&BBS_priv, p_section->sid, S_POST | S_MAN_S))
1105     {
1106     ret = article_excerption_set(p_section, p_articles[selected_index]->aid, (p_articles[selected_index]->excerption ? 0 : 1));
1107     if (ret < 0)
1108     {
1109     log_error("article_excerption_set(sid=%d, aid=%d, set=%d) error\n",
1110     p_section->sid, p_articles[selected_index]->aid, (p_articles[selected_index]->excerption ? 0 : 1));
1111     }
1112     }
1113     break;
1114 sysadm 1.31 case FIRST_TOPIC_ARTICLE:
1115     case LAST_TOPIC_ARTICLE:
1116     page_id_cur = page_id;
1117     direction = (ret == FIRST_TOPIC_ARTICLE ? -1 : 1);
1118     ret = locate_article_in_section(p_section, p_articles[selected_index], direction, BBS_article_limit_per_section,
1119     &page_id, &selected_index, &article_count);
1120     if (ret < 0)
1121     {
1122 sysadm 1.84 log_error("locate_article_in_section(sid=%d, aid=%d, direction=%d, step=%d) error",
1123 sysadm 1.31 p_section->sid, p_articles[selected_index]->aid, direction, BBS_article_limit_per_section);
1124     return -3;
1125     }
1126     else if (ret > 0 && page_id != page_id_cur) // found and page changed
1127     {
1128 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
1129 sysadm 1.31 if (ret < 0)
1130     {
1131 sysadm 1.84 log_error("query_section_articles(sid=%d, page_id=%d) error", p_section->sid, page_id);
1132 sysadm 1.31 return -3;
1133     }
1134     }
1135     break;
1136 sysadm 1.68 case LAST_SECTION_ARTICLE:
1137     page_id_cur = page_id;
1138     ret = last_article_in_section(p_section, &p_article_locate);
1139     if (ret < 0)
1140     {
1141 sysadm 1.84 log_error("last_article_in_section(sid=%d) error", p_section->sid);
1142 sysadm 1.68 return -3;
1143     }
1144     else if (ret == 0)
1145     {
1146     break;
1147     }
1148     ret = locate_article_in_section(p_section, p_article_locate, 0, 0,
1149     &page_id, &selected_index, &article_count);
1150     if (ret < 0)
1151     {
1152 sysadm 1.84 log_error("locate_article_in_section(sid=%d, aid=%d, direction=0, step=0) error",
1153 sysadm 1.68 p_section->sid, p_article_locate->aid);
1154     return -3;
1155     }
1156     else if (ret > 0 && page_id != page_id_cur) // found and page changed
1157     {
1158     ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
1159     if (ret < 0)
1160     {
1161 sysadm 1.84 log_error("query_section_articles(sid=%d, page_id=%d) error", p_section->sid, page_id);
1162 sysadm 1.68 return -3;
1163     }
1164     }
1165     break;
1166 sysadm 1.45 case SCAN_NEW_ARTICLE:
1167 sysadm 1.46 ret = scan_unread_article_in_section(p_section, p_articles[selected_index], &p_article_locate);
1168 sysadm 1.45 if (ret < 0)
1169     {
1170 sysadm 1.84 log_error("scan_unread_article_in_section(sid=%d, aid=%d) error",
1171 sysadm 1.45 p_section->sid, p_articles[selected_index]->aid);
1172     return -3;
1173     }
1174     else if (ret == 0) // not found
1175     {
1176     break;
1177     }
1178     page_id_cur = page_id;
1179 sysadm 1.46 ret = locate_article_in_section(p_section, p_article_locate, 0, 0,
1180 sysadm 1.45 &page_id, &selected_index, &article_count);
1181     if (ret < 0)
1182     {
1183 sysadm 1.84 log_error("locate_article_in_section(sid=%d, aid=%d, direction=0, step=0) error",
1184 sysadm 1.46 p_section->sid, p_article_locate->aid);
1185 sysadm 1.45 return -3;
1186     }
1187     else if (ret > 0 && page_id != page_id_cur) // found and page changed
1188     {
1189     ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
1190     if (ret < 0)
1191     {
1192 sysadm 1.84 log_error("query_section_articles(sid=%d, page_id=%d) error", p_section->sid, page_id);
1193 sysadm 1.45 return -3;
1194     }
1195     }
1196     break;
1197 sysadm 1.64 case SCAN_ARTICLE_BACKWARD_BY_USER:
1198     case SCAN_ARTICLE_FORWARD_BY_USER:
1199     direction = (ret == SCAN_ARTICLE_FORWARD_BY_USER ? 1 : -1);
1200     strncpy(username, p_articles[selected_index]->username, sizeof(username) - 1);
1201     username[sizeof(username) - 1] = '\0';
1202     uid = 0;
1203    
1204     moveto(SCREEN_ROWS, 1);
1205     clrtoeol();
1206     get_data(SCREEN_ROWS, 1,
1207 sysadm 1.73 (direction == 1 ? "↓搜寻作者: " : "↑搜寻作者: "),
1208 sysadm 1.64 username, sizeof(username), BBS_username_max_len);
1209    
1210     if (username[0] == '\0')
1211     {
1212     break;
1213     }
1214    
1215     // Verify format
1216     for (i = 0, ok = 1; ok && username[i] != '\0'; i++)
1217     {
1218 sysadm 1.76 if (!(isalpha((int)username[i]) || (i > 0 && (isdigit((int)username[i]) || username[i] == '_'))))
1219 sysadm 1.64 {
1220     ok = 0;
1221     }
1222     }
1223     if (ok && i > BBS_username_max_len)
1224     {
1225     ok = 0;
1226     }
1227     if (!ok)
1228     {
1229     break;
1230     }
1231    
1232     ret = query_user_info_by_username(username, 1, &uid, username_list);
1233     if (ret < 0)
1234     {
1235 sysadm 1.84 log_error("query_user_info_by_username(%s) error", username);
1236 sysadm 1.64 break;
1237     }
1238    
1239     if (uid > 0)
1240     {
1241     ret = scan_article_in_section_by_uid(p_section, p_articles[selected_index],
1242     direction, uid, &p_article_locate);
1243     if (ret < 0)
1244     {
1245 sysadm 1.84 log_error("scan_article_in_section_by_uid(sid=%d, aid=%d, direction=%d, uid=%d) error",
1246 sysadm 1.64 p_section->sid, p_articles[selected_index]->aid, direction, uid);
1247     return -3;
1248     }
1249     else if (ret == 0) // not found
1250     {
1251     break;
1252     }
1253     }
1254     else // uid == 0
1255     {
1256     ret = scan_article_in_section_by_username(p_section, p_articles[selected_index],
1257     direction, username, &p_article_locate);
1258     if (ret < 0)
1259     {
1260 sysadm 1.84 log_error("scan_article_in_section_by_username(sid=%d, aid=%d, direction=%d, username=%s) error",
1261 sysadm 1.64 p_section->sid, p_articles[selected_index]->aid, direction, username);
1262     return -3;
1263     }
1264     else if (ret == 0) // not found
1265     {
1266     break;
1267     }
1268     }
1269    
1270     page_id_cur = page_id;
1271     ret = locate_article_in_section(p_section, p_article_locate, 0, 0,
1272     &page_id, &selected_index, &article_count);
1273     if (ret < 0)
1274     {
1275 sysadm 1.84 log_error("locate_article_in_section(sid=%d, aid=%d, direction=0, step=0) error",
1276 sysadm 1.64 p_section->sid, p_article_locate->aid);
1277     return -3;
1278     }
1279     else if (ret > 0 && page_id != page_id_cur) // found and page changed
1280     {
1281     ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
1282     if (ret < 0)
1283     {
1284 sysadm 1.84 log_error("query_section_articles(sid=%d, page_id=%d) error", p_section->sid, page_id);
1285 sysadm 1.64 return -3;
1286     }
1287     }
1288     break;
1289 sysadm 1.66 case SCAN_ARTICLE_BACKWARD_BY_TITLE:
1290     case SCAN_ARTICLE_FORWARD_BY_TITLE:
1291     direction = (ret == SCAN_ARTICLE_FORWARD_BY_TITLE ? 1 : -1);
1292    
1293     moveto(SCREEN_ROWS, 1);
1294     clrtoeol();
1295     get_data(SCREEN_ROWS, 1,
1296 sysadm 1.73 (direction == 1 ? "↓搜寻标题: " : "↑搜寻标题: "),
1297 sysadm 1.66 title, sizeof(title), TITLE_SEARCH_MAX_LEN);
1298    
1299     if (title[0] == '\0')
1300     {
1301     break;
1302     }
1303    
1304     ret = scan_article_in_section_by_title(p_section, p_articles[selected_index],
1305     direction, title, &p_article_locate);
1306     if (ret < 0)
1307     {
1308 sysadm 1.84 log_error("scan_article_in_section_by_title(sid=%d, aid=%d, direction=%d, title=%s) error",
1309 sysadm 1.66 p_section->sid, p_articles[selected_index]->aid, direction, title);
1310     return -3;
1311     }
1312     else if (ret == 0) // not found
1313     {
1314     break;
1315     }
1316    
1317     page_id_cur = page_id;
1318     ret = locate_article_in_section(p_section, p_article_locate, 0, 0,
1319     &page_id, &selected_index, &article_count);
1320     if (ret < 0)
1321     {
1322 sysadm 1.84 log_error("locate_article_in_section(sid=%d, aid=%d, direction=0, step=0) error",
1323 sysadm 1.66 p_section->sid, p_article_locate->aid);
1324     return -3;
1325     }
1326     else if (ret > 0 && page_id != page_id_cur) // found and page changed
1327     {
1328     ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
1329     if (ret < 0)
1330     {
1331 sysadm 1.84 log_error("query_section_articles(sid=%d, page_id=%d) error", p_section->sid, page_id);
1332 sysadm 1.66 return -3;
1333     }
1334     }
1335     break;
1336 sysadm 1.63 case SEARCH_USER:
1337     user_list_search();
1338     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1339     {
1340 sysadm 1.84 log_error("section_list_draw_screen() error");
1341 sysadm 1.63 return -2;
1342     }
1343     break;
1344 sysadm 1.28 case SHOW_HELP:
1345     // Display help information
1346     display_file(DATA_READ_HELP, 1);
1347     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1348     {
1349 sysadm 1.84 log_error("section_list_draw_screen() error");
1350 sysadm 1.28 return -2;
1351     }
1352     break;
1353 sysadm 1.37 case VIEW_EX_DIR:
1354     if (section_list_ex_dir_display(p_section) < 0)
1355     {
1356 sysadm 1.84 log_error("section_list_ex_dir_display(sid=%d) error", p_section->sid);
1357 sysadm 1.37 }
1358     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1359     {
1360 sysadm 1.84 log_error("section_list_draw_screen() error");
1361 sysadm 1.37 return -2;
1362     }
1363     break;
1364 sysadm 1.48 case SHOW_TOP10:
1365     show_top10_menu(NULL);
1366     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1367     {
1368 sysadm 1.84 log_error("section_list_draw_screen() error");
1369 sysadm 1.48 return -2;
1370     }
1371     break;
1372 sysadm 1.1 default:
1373 sysadm 1.84 log_error("Unknown command %d", ret);
1374 sysadm 1.1 }
1375     }
1376    
1377     return 0;
1378     }
1379 sysadm 1.37
1380     int section_list_ex_dir_display(SECTION_LIST *p_section)
1381     {
1382     MENU_SET ex_menu_set;
1383     int ch = 0;
1384 sysadm 1.78 int loop;
1385 sysadm 1.37
1386     if (p_section == NULL)
1387     {
1388 sysadm 1.84 log_error("NULL pointer error");
1389 sysadm 1.37 return -1;
1390     }
1391    
1392 sysadm 1.39 if (p_section->ex_menu_tm == 0) // N/A
1393     {
1394     moveto(2, 1);
1395     clrtoeol();
1396 sysadm 1.40 prints("该版块精华区未开放");
1397 sysadm 1.39 press_any_key();
1398     return 0;
1399     }
1400    
1401 sysadm 1.37 if (get_section_ex_menu_set(p_section, &ex_menu_set) < 0)
1402     {
1403 sysadm 1.84 log_error("get_section_ex_menu_set(sid=%d) error", p_section->sid);
1404 sysadm 1.37 return -3;
1405     }
1406     if (get_menu_shm_readonly(&ex_menu_set) < 0)
1407     {
1408 sysadm 1.84 log_error("get_menu_shm_readonly(sid=%d) error", p_section->sid);
1409 sysadm 1.37 return -3;
1410     }
1411    
1412     clearscr();
1413 sysadm 1.38 show_bottom("");
1414 sysadm 1.37
1415     if (display_menu(&ex_menu_set) == 0)
1416     {
1417 sysadm 1.78 for (loop = 1; !SYS_server_exit && loop;)
1418 sysadm 1.37 {
1419     iflush();
1420     ch = igetch(100);
1421 sysadm 1.54
1422     if (ch != KEY_NULL && ch != KEY_TIMEOUT)
1423     {
1424     BBS_last_access_tm = time(NULL);
1425 sysadm 1.79
1426     // Refresh current action
1427     if (user_online_update(NULL) < 0)
1428     {
1429 sysadm 1.84 log_error("user_online_update(NULL) error");
1430 sysadm 1.79 }
1431 sysadm 1.54 }
1432    
1433 sysadm 1.37 switch (ch)
1434     {
1435     case KEY_NULL: // broken pipe
1436 sysadm 1.84 log_debug("KEY_NULL");
1437 sysadm 1.78 loop = 0;
1438     break;
1439 sysadm 1.37 case KEY_TIMEOUT:
1440 sysadm 1.71 if (time(NULL) - BBS_last_access_tm >= BBS_max_user_idle_time)
1441 sysadm 1.37 {
1442 sysadm 1.84 log_debug("User input timeout");
1443 sysadm 1.78 loop = 0;
1444     break;
1445 sysadm 1.37 }
1446     continue;
1447     case CR:
1448     default:
1449     switch (menu_control(&ex_menu_set, ch))
1450     {
1451     case EXITMENU:
1452 sysadm 1.78 loop = 0;
1453 sysadm 1.37 break;
1454     case REDRAW:
1455     clearscr();
1456 sysadm 1.38 show_bottom("");
1457 sysadm 1.37 display_menu(&ex_menu_set);
1458     break;
1459     case NOREDRAW:
1460     case UNKNOWN_CMD:
1461     default:
1462     break;
1463     }
1464     }
1465     }
1466     }
1467    
1468     detach_menu_shm(&ex_menu_set);
1469    
1470     return 0;
1471     }
1472 sysadm 1.59
1473     int section_aid_locations_save(int uid)
1474     {
1475     char filename[FILE_PATH_LEN];
1476     FILE *fp;
1477     int i;
1478     int ret = 0;
1479    
1480     snprintf(filename, sizeof(filename), "%s/%d", VAR_SECTION_AID_LOC_DIR, uid);
1481    
1482     if ((fp = fopen(filename, "wb")) == NULL)
1483     {
1484 sysadm 1.84 log_error("fopen(%s, wb) error: %d", filename, errno);
1485 sysadm 1.59 return -1;
1486     }
1487    
1488     for (i = 0; i < p_section_list_pool->section_count; i++)
1489     {
1490     if (fwrite(&(p_section_list_pool->sections[i].sid), sizeof(p_section_list_pool->sections[i].sid), 1, fp) != 1)
1491     {
1492 sysadm 1.84 log_error("fwrite(%s, sid) error", filename);
1493 sysadm 1.59 ret = -2;
1494     break;
1495     }
1496    
1497     if (fwrite(&(section_aid_locations[i]), sizeof(section_aid_locations[i]), 1, fp) != 1)
1498     {
1499 sysadm 1.84 log_error("fwrite(%s, aid) error", filename);
1500 sysadm 1.59 ret = -2;
1501     break;
1502     }
1503     }
1504    
1505     if (fclose(fp) < 0)
1506     {
1507 sysadm 1.84 log_error("fclose(%s) error: %d", filename, errno);
1508 sysadm 1.59 ret = -1;
1509     }
1510    
1511     return ret;
1512     }
1513    
1514     int section_aid_locations_load(int uid)
1515     {
1516     char filename[FILE_PATH_LEN];
1517     FILE *fp;
1518     int i;
1519     int32_t sid;
1520     int32_t aid;
1521     SECTION_LIST *p_section;
1522     int ret = 0;
1523    
1524     snprintf(filename, sizeof(filename), "%s/%d", VAR_SECTION_AID_LOC_DIR, uid);
1525    
1526     if ((fp = fopen(filename, "rb")) == NULL)
1527     {
1528     if (errno == ENOENT) // file not exist
1529     {
1530     return 0;
1531     }
1532 sysadm 1.84 log_error("fopen(%s, rb) error: %d", filename, errno);
1533 sysadm 1.59 return -1;
1534     }
1535    
1536     while (!feof(fp))
1537     {
1538     if (fread(&sid, sizeof(sid), 1, fp) != 1)
1539     {
1540     if (ferror(fp) == 0)
1541     {
1542     break;
1543     }
1544 sysadm 1.84 log_error("fread(%s, sid) error: %d", filename, ferror(fp));
1545 sysadm 1.59 ret = -2;
1546     break;
1547     }
1548    
1549     if (fread(&aid, sizeof(aid), 1, fp) != 1)
1550     {
1551     if (ferror(fp) == 0)
1552     {
1553     break;
1554     }
1555 sysadm 1.84 log_error("fread(%s, aid) error: %d", filename, ferror(fp));
1556 sysadm 1.59 ret = -2;
1557     break;
1558     }
1559    
1560     p_section = section_list_find_by_sid(sid);
1561     if (p_section == NULL)
1562     {
1563     continue; // skip section no longer exist
1564     }
1565    
1566     i = get_section_index(p_section);
1567     if (i < 0)
1568     {
1569 sysadm 1.84 log_error("get_section_index(sid=%d) error", sid);
1570 sysadm 1.59 ret = -3;
1571     break;
1572     }
1573     section_aid_locations[i] = aid;
1574     }
1575    
1576     if (fclose(fp) < 0)
1577     {
1578 sysadm 1.84 log_error("fclose(%s) error: %d", filename, errno);
1579 sysadm 1.59 ret = -1;
1580     }
1581    
1582     return ret;
1583     }

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