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

Contents of /lbbs/src/section_list_display.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.83 - (show annotations)
Thu Dec 18 10:43:48 2025 UTC (2 months, 4 weeks ago) by sysadm
Branch: MAIN
Changes since 1.82: +2 -2 lines
Content type: text/x-csrc
Refine with log_debug()

1 /* SPDX-License-Identifier: GPL-3.0-or-later */
2 /*
3 * section_list_display
4 * - user interactive feature of section articles list
5 *
6 * Copyright (C) 2004-2025 Leaflet <leaflet@leafok.com>
7 */
8
9 #ifdef HAVE_CONFIG_H
10 #include "config.h"
11 #endif
12
13 #include "article_cache.h"
14 #include "article_favor.h"
15 #include "article_op.h"
16 #include "article_post.h"
17 #include "article_view_log.h"
18 #include "article_del.h"
19 #include "common.h"
20 #include "io.h"
21 #include "log.h"
22 #include "login.h"
23 #include "menu.h"
24 #include "menu_proc.h"
25 #include "section_list_display.h"
26 #include "section_list_loader.h"
27 #include "screen.h"
28 #include "str_process.h"
29 #include "user_info_display.h"
30 #include "user_list_display.h"
31 #include "user_priv.h"
32 #include <ctype.h>
33 #include <errno.h>
34 #include <string.h>
35 #include <time.h>
36 #include <sys/param.h>
37
38 enum _section_list_display_constant_t
39 {
40 TITLE_SEARCH_MAX_LEN = 60,
41 };
42
43 static int32_t section_aid_locations[BBS_max_section] = {0};
44 static int section_topic_view_mode = 0;
45 static int section_topic_view_tid = -1;
46
47 enum select_cmd_t
48 {
49 EXIT_SECTION = 0,
50 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 QUERY_USER,
59 SET_FAVOR_ARTICLE,
60 UNSET_FAVOR_ARTICLE,
61 FIRST_TOPIC_ARTICLE,
62 LAST_TOPIC_ARTICLE,
63 LAST_SECTION_ARTICLE,
64 SCAN_NEW_ARTICLE,
65 SCAN_ARTICLE_BACKWARD_BY_USER,
66 SCAN_ARTICLE_FORWARD_BY_USER,
67 SCAN_ARTICLE_BACKWARD_BY_TITLE,
68 SCAN_ARTICLE_FORWARD_BY_TITLE,
69 VIEW_EX_DIR,
70 SHOW_TOP10,
71 SEARCH_USER,
72 };
73
74 static int section_list_draw_items(int page_id, const ARTICLE *p_articles[], int article_count, int display_nickname, int ontop_start_offset)
75 {
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 size_t j;
84 char article_flag;
85 int is_viewed;
86 int is_favor;
87 time_t tm_now;
88
89 time(&tm_now);
90
91 clrline(4, 23);
92
93 for (i = 0; i < article_count; i++)
94 {
95 if (p_articles[i]->uid == BBS_priv.uid)
96 {
97 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 log_error("article_view_log_is_viewed(aid=%d) error\n", p_articles[i]->aid);
105 is_viewed = 0;
106 }
107 }
108
109 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 log_error("article_favor_check(aid=%d) error\n", p_articles[i]->aid);
115 is_favor = 0;
116 }
117 }
118 else
119 {
120 is_favor = 0;
121 }
122
123 if (p_articles[i]->excerption)
124 {
125 article_flag = (is_viewed ? 'm' : 'M');
126 }
127 else if (p_articles[i]->lock && is_viewed)
128 {
129 article_flag = 'x';
130 }
131 else
132 {
133 article_flag = (is_viewed ? ' ' : 'N');
134 }
135
136 localtime_r(&p_articles[i]->sub_dt, &tm_sub);
137 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 strncpy(title_f, (p_articles[i]->tid == 0 ? "● " : ""), sizeof(title_f) - 1);
147 title_f[sizeof(title_f) - 1] = '\0';
148 strncat(title_f, (p_articles[i]->transship ? "[转载]" : ""), sizeof(title_f) - 1 - strnlen(title_f, sizeof(title_f)));
149
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 len = split_line(title_f, 59 - (display_nickname ? BBS_nickname_max_len / 2 : BBS_username_max_len), &eol, &title_f_len, 1);
170 if (title_f[len] != '\0')
171 {
172 title_f[len] = '\0';
173 }
174
175 moveto(4 + i, 1);
176 if (i >= ontop_start_offset)
177 {
178 prints(" \033[1;33m[提示]\033[m%c%c %s%*s %s %s%s\033[m",
179 (is_favor ? '@' : ' '),
180 article_flag,
181 (display_nickname ? p_articles[i]->nickname : p_articles[i]->username),
182 (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 "",
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 prints(" %s%7d\033[m%c%c %s%*s %s %s%s\033[m",
196 (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 (is_favor ? '@' : ' '),
203 article_flag,
204 (display_nickname ? p_articles[i]->nickname : p_articles[i]->username),
205 (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 "",
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 }
217
218 return 0;
219 }
220
221 static int section_list_draw_screen(const char *sname, const char *stitle, const char *master_list, int display_nickname)
222 {
223 char str_section_master[LINE_BUFFER_LEN] = "诚征版主中";
224 char str_section_name[LINE_BUFFER_LEN];
225
226 if (master_list[0] != '\0')
227 {
228 snprintf(str_section_master, sizeof(str_section_master), "版主: %s", master_list);
229 }
230 snprintf(str_section_name, sizeof(str_section_name), "讨论区 [%s]", sname);
231
232 clearscr();
233 show_top(str_section_master, stitle, str_section_name);
234 moveto(2, 0);
235 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 moveto(3, 0);
240 if (display_nickname)
241 {
242 prints("\033[44;37m \033[1;37m 编 号 发布者昵称 日 期 文章标题 \033[m");
243 }
244 else
245 {
246 prints("\033[44;37m \033[1;37m 编 号 发 布 者 日 期 文章标题 \033[m");
247 }
248
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 time_t last_refresh_tm = time(NULL);
258
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 if (ch != KEY_NULL && ch != KEY_TIMEOUT)
271 {
272 BBS_last_access_tm = time(NULL);
273
274 // Refresh current action
275 if (user_online_update(NULL) < 0)
276 {
277 log_error("user_online_update(NULL) error\n");
278 }
279 }
280
281 switch (ch)
282 {
283 case KEY_NULL: // broken pipe
284 log_debug("KEY_NULL\n");
285 return EXIT_SECTION;
286 case KEY_TIMEOUT:
287 if (time(NULL) - BBS_last_access_tm >= BBS_max_user_idle_time)
288 {
289 log_debug("User input timeout\n");
290 return EXIT_SECTION;
291 }
292 continue;
293 case KEY_ESC:
294 case KEY_LEFT:
295 return EXIT_SECTION;
296 case 'n':
297 return CHANGE_NAME_DISPLAY;
298 case CR:
299 case 'r':
300 case KEY_RIGHT:
301 if (item_count > 0)
302 {
303 return VIEW_ARTICLE;
304 }
305 break;
306 case Ctrl('P'):
307 return POST_ARTICLE;
308 case 'E':
309 if (item_count > 0)
310 {
311 return EDIT_ARTICLE;
312 }
313 break;
314 case 'd':
315 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 case Ctrl('A'):
327 if (item_count > 0)
328 {
329 return QUERY_USER;
330 }
331 break;
332 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 case KEY_HOME:
345 *p_page_id = 0;
346 case 'P':
347 case KEY_PGUP:
348 *p_selected_index = 0;
349 case 'k':
350 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 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 }
370 else
371 {
372 (*p_selected_index)--;
373 }
374 break;
375 case '$':
376 case KEY_END:
377 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 if (total_page > 0)
382 {
383 *p_page_id = total_page - 1;
384 }
385 case 'N':
386 case KEY_PGDN:
387 if (item_count > 0)
388 {
389 *p_selected_index = item_count - 1;
390 }
391 case 'j':
392 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 else if (ch == KEY_DOWN || ch == 'j') // Rotate to the head of section list
401 {
402 *p_page_id = 0;
403 *p_selected_index = 0;
404 }
405 }
406 else
407 {
408 (*p_selected_index)++;
409 }
410 break;
411 case '=':
412 if (item_count > 0)
413 {
414 return FIRST_TOPIC_ARTICLE;
415 }
416 break;
417 case '\\':
418 if (item_count > 0)
419 {
420 return LAST_TOPIC_ARTICLE;
421 }
422 break;
423 case 'S':
424 if (item_count > 0)
425 {
426 return SCAN_NEW_ARTICLE;
427 }
428 break;
429 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 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 case 'u':
454 return SEARCH_USER;
455 case 'h':
456 return SHOW_HELP;
457 case 'x':
458 return VIEW_EX_DIR;
459 case 'H':
460 return SHOW_TOP10;
461 default:
462 break;
463 }
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 if (BBS_last_access_tm - last_refresh_tm >= BBS_section_list_load_interval)
488 {
489 return CHANGE_PAGE; // force section list refresh
490 }
491 }
492
493 return EXIT_SECTION;
494 }
495
496 static int display_article_key_handler(int *p_key, DISPLAY_CTX *p_ctx)
497 {
498 switch (*p_key)
499 {
500 case 'p':
501 case Ctrl('X'):
502 section_topic_view_mode = !section_topic_view_mode;
503 case 0: // Set msg
504 if (section_topic_view_mode)
505 {
506 snprintf(p_ctx->msg, sizeof(p_ctx->msg),
507 "| 返回[\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 }
511 else
512 {
513 snprintf(p_ctx->msg, sizeof(p_ctx->msg),
514 "| 返回[\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 }
518 *p_key = 0;
519 break;
520 case 'r': // Reply article
521 return 1;
522 case '=': // First topic article
523 return 1;
524 case '\\': // Last topic article
525 return 1;
526 case KEY_UP:
527 case KEY_PGUP:
528 case KEY_HOME:
529 if (p_ctx->reach_begin)
530 {
531 if (section_topic_view_mode)
532 {
533 *p_key = KEY_PGUP;
534 }
535 else
536 {
537 *p_key = KEY_UP;
538 }
539 return 1;
540 }
541 break;
542 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 case KEY_DOWN:
553 case KEY_PGDN:
554 case KEY_END:
555 if (p_ctx->reach_end)
556 {
557 if (section_topic_view_mode)
558 {
559 *p_key = KEY_PGDN;
560 }
561 else
562 {
563 *p_key = KEY_DOWN;
564 }
565 return 1;
566 }
567 break;
568 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 }
579
580 return 0;
581 }
582
583 int section_list_display(const char *sname, int32_t aid)
584 {
585 static int display_nickname = 0;
586
587 SECTION_LIST *p_section;
588 int64_t section_index;
589 int32_t aid_location;
590 char stitle[BBS_section_title_max_len + 1];
591 char master_list[(BBS_username_max_len + 1) * 3 + 1];
592 char page_info_str[LINE_BUFFER_LEN];
593 const ARTICLE *p_articles[BBS_article_limit_per_page];
594 int article_count;
595 int page_count;
596 int ontop_start_offset;
597 int page_id = 0;
598 int selected_index = 0;
599 ARTICLE_CACHE cache;
600 int ret;
601 int loop;
602 int direction;
603 ARTICLE article_new;
604 int page_id_cur;
605 const ARTICLE *p_article_locate;
606 USER_INFO user_info;
607 char user_intro[BBS_user_intro_max_len + 1];
608 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 char title[BBS_article_title_max_len + 1] = "\0";
614
615 p_section = section_list_find_by_name(sname);
616 if (p_section == NULL)
617 {
618 log_error("Section %s not found\n", sname);
619 return -1;
620 }
621
622 if (!checkpriv(&BBS_priv, p_section->sid, S_LIST))
623 {
624 log_error("Forbid access to unauthorized section, sid=%d, uid=%d\n",
625 p_section->sid, BBS_priv.uid);
626 return -1;
627 }
628
629 section_index = get_section_index(p_section);
630
631 if (get_section_info(p_section, NULL, stitle, master_list) < 0)
632 {
633 log_error("get_section_info(sid=%d) error\n", p_section->sid);
634 return -4;
635 }
636
637 if (aid == 0)
638 {
639 aid_location = section_aid_locations[section_index];
640 }
641 else
642 {
643 aid_location = aid;
644 }
645
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 log_error("article_block_find_by_aid(%d) error\n", aid_location);
653 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 log_error("locate_article_in_section(sid=%d, aid=%d, direction=0, step=0) error\n",
661 p_section->sid, p_article_locate->aid);
662 return -3;
663 }
664 }
665
666 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
667 {
668 log_error("section_list_draw_screen() error\n");
669 return -2;
670 }
671
672 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
673 if (ret < 0)
674 {
675 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
676 return -3;
677 }
678
679 section_topic_view_tid = -1;
680
681 if (article_count == 0) // empty section
682 {
683 selected_index = 0;
684 }
685 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
694 while (!SYS_server_exit)
695 {
696 ret = section_list_draw_items(page_id, p_articles, article_count, display_nickname, ontop_start_offset);
697 if (ret < 0)
698 {
699 log_error("section_list_draw_items(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
700 return -4;
701 }
702
703 snprintf(page_info_str, sizeof(page_info_str),
704 "\033[33m[第\033[36m%d\033[33m/\033[36m%d\033[33m页]",
705 page_id + 1, MAX(page_count, 1));
706
707 show_bottom(page_info_str);
708 iflush();
709
710 if (user_online_update(sname) < 0)
711 {
712 log_error("user_online_update(%s) error\n", sname);
713 }
714
715 ret = section_list_select(page_count, article_count, &page_id, &selected_index);
716
717 switch (ret)
718 {
719 case EXIT_SECTION:
720 // Update current aid location
721 if (selected_index < article_count && p_articles[selected_index] != NULL)
722 {
723 if (selected_index >= ontop_start_offset)
724 {
725 ret = last_article_in_section(p_section, &p_article_locate);
726 if (ret < 0)
727 {
728 log_error("last_article_in_section(sid=%d) error\n", p_section->sid);
729 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 }
745 return 0;
746 case CHANGE_PAGE:
747 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
748 if (ret < 0)
749 {
750 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
751 return -3;
752 }
753 if (article_count == 0) // empty section
754 {
755 selected_index = 0;
756 }
757 else if (selected_index >= article_count)
758 {
759 selected_index = article_count - 1;
760 }
761 break;
762 case VIEW_ARTICLE:
763 do
764 {
765 loop = 0;
766
767 if (article_cache_load(&cache, VAR_ARTICLE_CACHE_DIR, p_articles[selected_index]) < 0)
768 {
769 log_error("article_cache_load(aid=%d, cid=%d) error\n", p_articles[selected_index]->aid, p_articles[selected_index]->cid);
770 break;
771 }
772
773 if (user_online_update("VIEW_ARTICLE") < 0)
774 {
775 log_error("user_online_update(VIEW_ARTICLE) error\n");
776 }
777
778 ret = display_data(cache.p_data, cache.line_total, cache.line_offsets, 0,
779 display_article_key_handler, DATA_READ_HELP);
780
781 if (article_cache_unload(&cache) < 0)
782 {
783 log_error("article_cache_unload(aid=%d, cid=%d) error\n", p_articles[selected_index]->aid, p_articles[selected_index]->cid);
784 break;
785 }
786
787 // Update article_view_log
788 if (article_view_log_set_viewed(p_articles[selected_index]->aid, &BBS_article_view_log) < 0)
789 {
790 log_error("article_view_log_set_viewed(aid=%d) error\n", p_articles[selected_index]->aid);
791 }
792
793 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 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
804 if (ret < 0)
805 {
806 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
807 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 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
835 if (ret < 0)
836 {
837 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
838 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 ret = locate_article_in_section(p_section, p_articles[selected_index], direction, 1,
861 &page_id, &selected_index, &article_count);
862 if (ret < 0)
863 {
864 log_error("locate_article_in_section(sid=%d, aid=%d, direction=%d, step=1) error\n",
865 p_section->sid, p_articles[selected_index]->aid, direction);
866 return -3;
867 }
868 else if (ret > 0) // found
869 {
870 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
871 if (ret < 0)
872 {
873 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
874 return -3;
875 }
876 loop = 1;
877 }
878 break;
879 case 'r': // Reply article
880 if (user_online_update("REPLY_ARTICLE") < 0)
881 {
882 log_error("user_online_update(REPLY_ARTICLE) error\n");
883 }
884
885 if (article_reply(p_section, p_articles[selected_index], &article_new) < 0)
886 {
887 log_error("article_reply(aid=%d) error\n", p_articles[selected_index]->aid);
888 }
889 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 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
895 return -3;
896 }
897 }
898 loop = 1;
899 break;
900 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 log_error("locate_article_in_section(sid=%d, aid=%d, direction=%d, step=%d) error\n",
909 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 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
917 if (ret < 0)
918 {
919 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
920 return -3;
921 }
922 }
923 loop = 1;
924 }
925 break;
926 }
927 } while (loop);
928
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
932 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
933 {
934 log_error("section_list_draw_screen() error\n");
935 return -2;
936 }
937 break;
938 case CHANGE_NAME_DISPLAY:
939 display_nickname = !display_nickname;
940 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
941 {
942 log_error("section_list_draw_screen() error\n");
943 return -2;
944 }
945 break;
946 case POST_ARTICLE:
947 if (user_online_update("POST_ARTICLE") < 0)
948 {
949 log_error("user_online_update(POST_ARTICLE) error\n");
950 }
951
952 if ((ret = article_post(p_section, &article_new)) < 0)
953 {
954 log_error("article_post(sid=%d) error\n", p_section->sid);
955 }
956 else if (ret > 0) // New article posted
957 {
958 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
959 if (ret < 0)
960 {
961 log_error("query_section_articles(sid=%d, page_id=%d) error: %d\n", p_section->sid, page_id, ret);
962 return -3;
963 }
964 }
965 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
966 {
967 log_error("section_list_draw_screen() error\n");
968 return -2;
969 }
970 break;
971 case EDIT_ARTICLE:
972 if (!checkpriv(&BBS_priv, p_section->sid, S_POST) ||
973 p_articles[selected_index]->uid != BBS_priv.uid)
974 {
975 break; // No permission
976 }
977
978 if (user_online_update("EDIT_ARTICLE") < 0)
979 {
980 log_error("user_online_update() error\n");
981 }
982
983 if (article_modify(p_section, p_articles[selected_index], &article_new) < 0)
984 {
985 log_error("article_modify(aid=%d) error\n", p_articles[selected_index]->aid);
986 }
987 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 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
993 return -3;
994 }
995 }
996 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
997 {
998 log_error("section_list_draw_screen() error\n");
999 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 if ((ret = article_del(p_section, p_articles[selected_index])) < 0)
1009 {
1010 log_error("article_del(aid=%d) error\n", p_articles[selected_index]->aid);
1011 }
1012 else if (ret > 0) // Article deleted
1013 {
1014 do
1015 {
1016 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 }
1034 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1035 {
1036 log_error("section_list_draw_screen() error\n");
1037 return -2;
1038 }
1039 break;
1040 case QUERY_ARTICLE:
1041 if ((ret = display_article_meta(p_articles[selected_index]->aid)) < 0)
1042 {
1043 log_error("display_article_meta(aid=%d) error\n", p_articles[selected_index]->aid);
1044 }
1045 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1046 {
1047 log_error("section_list_draw_screen() error\n");
1048 return -2;
1049 }
1050 break;
1051 case QUERY_USER:
1052 if ((ret = query_user_info_by_uid(p_articles[selected_index]->uid, &user_info, user_intro, sizeof(user_intro))) < 0)
1053 {
1054 log_error("query_user_info_by_uid(uid=%d) error\n", p_articles[selected_index]->uid);
1055 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 log_error("user_info_display(uid=%d) error\n", p_articles[selected_index]->uid);
1066 }
1067
1068 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1069 {
1070 log_error("section_list_draw_screen() error\n");
1071 return -2;
1072 }
1073 break;
1074 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 log_error("article_favor_set(aid=%d, 1) error\n",
1082 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 log_error("article_favor_set(aid=%d, 0) error\n",
1093 p_articles[selected_index]->tid == 0 ? p_articles[selected_index]->aid : p_articles[selected_index]->tid);
1094 }
1095 break;
1096 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 log_error("locate_article_in_section(sid=%d, aid=%d, direction=%d, step=%d) error\n",
1105 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 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
1111 if (ret < 0)
1112 {
1113 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
1114 return -3;
1115 }
1116 }
1117 break;
1118 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 log_error("last_article_in_section(sid=%d) error\n", p_section->sid);
1124 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 log_error("locate_article_in_section(sid=%d, aid=%d, direction=0, step=0) error\n",
1135 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 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
1144 return -3;
1145 }
1146 }
1147 break;
1148 case SCAN_NEW_ARTICLE:
1149 ret = scan_unread_article_in_section(p_section, p_articles[selected_index], &p_article_locate);
1150 if (ret < 0)
1151 {
1152 log_error("scan_unread_article_in_section(sid=%d, aid=%d) error\n",
1153 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 ret = locate_article_in_section(p_section, p_article_locate, 0, 0,
1162 &page_id, &selected_index, &article_count);
1163 if (ret < 0)
1164 {
1165 log_error("locate_article_in_section(sid=%d, aid=%d, direction=0, step=0) error\n",
1166 p_section->sid, p_article_locate->aid);
1167 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 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
1175 return -3;
1176 }
1177 }
1178 break;
1179 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 (direction == 1 ? "↓搜寻作者: " : "↑搜寻作者: "),
1190 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 if (!(isalpha((int)username[i]) || (i > 0 && (isdigit((int)username[i]) || username[i] == '_'))))
1201 {
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 log_error("query_user_info_by_username(%s) error\n", username);
1218 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 log_error("scan_article_in_section_by_uid(sid=%d, aid=%d, direction=%d, uid=%d) error\n",
1228 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 log_error("scan_article_in_section_by_username(sid=%d, aid=%d, direction=%d, username=%s) error\n",
1243 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 log_error("locate_article_in_section(sid=%d, aid=%d, direction=0, step=0) error\n",
1258 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 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
1267 return -3;
1268 }
1269 }
1270 break;
1271 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 (direction == 1 ? "↓搜寻标题: " : "↑搜寻标题: "),
1279 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 log_error("scan_article_in_section_by_title(sid=%d, aid=%d, direction=%d, title=%s) error\n",
1291 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 log_error("locate_article_in_section(sid=%d, aid=%d, direction=0, step=0) error\n",
1305 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 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
1314 return -3;
1315 }
1316 }
1317 break;
1318 case SEARCH_USER:
1319 user_list_search();
1320 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1321 {
1322 log_error("section_list_draw_screen() error\n");
1323 return -2;
1324 }
1325 break;
1326 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 log_error("section_list_draw_screen() error\n");
1332 return -2;
1333 }
1334 break;
1335 case VIEW_EX_DIR:
1336 if (section_list_ex_dir_display(p_section) < 0)
1337 {
1338 log_error("section_list_ex_dir_display(sid=%d) error\n", p_section->sid);
1339 }
1340 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1341 {
1342 log_error("section_list_draw_screen() error\n");
1343 return -2;
1344 }
1345 break;
1346 case SHOW_TOP10:
1347 show_top10_menu(NULL);
1348 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1349 {
1350 log_error("section_list_draw_screen() error\n");
1351 return -2;
1352 }
1353 break;
1354 default:
1355 log_error("Unknown command %d\n", ret);
1356 }
1357 }
1358
1359 return 0;
1360 }
1361
1362 int section_list_ex_dir_display(SECTION_LIST *p_section)
1363 {
1364 MENU_SET ex_menu_set;
1365 int ch = 0;
1366 int loop;
1367
1368 if (p_section == NULL)
1369 {
1370 log_error("NULL pointer error\n");
1371 return -1;
1372 }
1373
1374 if (p_section->ex_menu_tm == 0) // N/A
1375 {
1376 moveto(2, 1);
1377 clrtoeol();
1378 prints("该版块精华区未开放");
1379 press_any_key();
1380 return 0;
1381 }
1382
1383 if (get_section_ex_menu_set(p_section, &ex_menu_set) < 0)
1384 {
1385 log_error("get_section_ex_menu_set(sid=%d) error\n", p_section->sid);
1386 return -3;
1387 }
1388 if (get_menu_shm_readonly(&ex_menu_set) < 0)
1389 {
1390 log_error("get_menu_shm_readonly(sid=%d) error\n", p_section->sid);
1391 return -3;
1392 }
1393
1394 clearscr();
1395 show_bottom("");
1396
1397 if (display_menu(&ex_menu_set) == 0)
1398 {
1399 for (loop = 1; !SYS_server_exit && loop;)
1400 {
1401 iflush();
1402 ch = igetch(100);
1403
1404 if (ch != KEY_NULL && ch != KEY_TIMEOUT)
1405 {
1406 BBS_last_access_tm = time(NULL);
1407
1408 // Refresh current action
1409 if (user_online_update(NULL) < 0)
1410 {
1411 log_error("user_online_update(NULL) error\n");
1412 }
1413 }
1414
1415 switch (ch)
1416 {
1417 case KEY_NULL: // broken pipe
1418 log_debug("KEY_NULL\n");
1419 loop = 0;
1420 break;
1421 case KEY_TIMEOUT:
1422 if (time(NULL) - BBS_last_access_tm >= BBS_max_user_idle_time)
1423 {
1424 log_debug("User input timeout\n");
1425 loop = 0;
1426 break;
1427 }
1428 continue;
1429 case CR:
1430 default:
1431 switch (menu_control(&ex_menu_set, ch))
1432 {
1433 case EXITMENU:
1434 loop = 0;
1435 break;
1436 case REDRAW:
1437 clearscr();
1438 show_bottom("");
1439 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
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 log_error("fopen(%s, wb) error: %d\n", filename, errno);
1467 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 log_error("fwrite(%s, sid) error\n", filename);
1475 ret = -2;
1476 break;
1477 }
1478
1479 if (fwrite(&(section_aid_locations[i]), sizeof(section_aid_locations[i]), 1, fp) != 1)
1480 {
1481 log_error("fwrite(%s, aid) error\n", filename);
1482 ret = -2;
1483 break;
1484 }
1485 }
1486
1487 if (fclose(fp) < 0)
1488 {
1489 log_error("fclose(%s) error: %d\n", filename, errno);
1490 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 log_error("fopen(%s, rb) error: %d\n", filename, errno);
1515 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 log_error("fread(%s, sid) error: %d\n", filename, ferror(fp));
1527 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 log_error("fread(%s, aid) error: %d\n", filename, ferror(fp));
1538 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 log_error("get_section_index(sid=%d) error\n", sid);
1552 ret = -3;
1553 break;
1554 }
1555 section_aid_locations[i] = aid;
1556 }
1557
1558 if (fclose(fp) < 0)
1559 {
1560 log_error("fclose(%s) error: %d\n", filename, errno);
1561 ret = -1;
1562 }
1563
1564 return ret;
1565 }

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