/[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.84 - (hide annotations)
Fri Dec 19 06:16:27 2025 UTC (2 months, 4 weeks ago) by sysadm
Branch: MAIN
Changes since 1.83: +85 -85 lines
Content type: text/x-csrc
Append \n to the end of logging message by log_...()
Remove ending \n from each logging message

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

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