diff options
-rw-r--r-- | pttbbs/mbbsd/acl.c | 417 | ||||
-rw-r--r-- | pttbbs/mbbsd/bbs.c | 2 | ||||
-rw-r--r-- | pttbbs/mbbsd/board.c | 37 |
3 files changed, 297 insertions, 159 deletions
diff --git a/pttbbs/mbbsd/acl.c b/pttbbs/mbbsd/acl.c index c794bca4..96aec664 100644 --- a/pttbbs/mbbsd/acl.c +++ b/pttbbs/mbbsd/acl.c @@ -134,22 +134,207 @@ unban_user_for_board(const char *user, const char *board) { return unlink(tag_fn) == 0; } -int -edit_banned_list_for_board(const char *board) { - // TODO generalize this. +static time4_t +ui_print_user_banned_status_for_board(const char *uid, const char *board) { + char reason[STRLEN]; + time4_t expire = expire = get_user_banned_status_by_board( + uid, board, sizeof(reason), reason); + + if (expire > now) { + prints("使用者 %s 禁言中,解除時間尚有 %d 天: %s\n理由:%s", + uid, (expire-now)/DAY_SECONDS+1, + Cdatelite(&expire), reason); + } else { + prints("使用者 %s 目前不在禁言名單中。\n", + uid); + expire = 0; + } + return expire; +} + +static int +ui_ban_user_for_board(const char *uid, const char *board) { + time4_t expire = now; + int y, x; int result; int do_notify = 0; - char uid[IDLEN+1], ans[3]; + char ans[3]; char history_log[PATHLEN]; char reason[STRLEN]; char datebuf[STRLEN]; + + setbfile(history_log, board, FN_BANNED_HISTORY); + + getyx(&y, &x); + if ((expire = is_user_banned_by_board(uid, board))) { + vmsgf("使用者之前已被禁言,尚有 %d 天;詳情可用(S)或(L)查看", + (expire - now) / DAY_SECONDS+1); + return -1; + } + prints("將使用者 %s 加入看板 %s 的禁言名單。", uid, board); + move(y+3, 0); + syncnow(); + outs("目前接受的格式是 [數字][單位]。 " + "單位有: 年(y), 月(m), 天(d)\n" + "範例: 3m (三個月), 120d (120天), 10y (10年)\n" + "注意不可混合輸入(例:沒有三個半月這種東西,請換算成天數)\n" + ); + getdata(y+1, 0, "請以數字跟單位(預設為天)輸入期限: ", + datebuf, 8, DOECHO); + trim(datebuf); + if (!*datebuf) { + vmsg("未輸入期限,放棄。"); + return -1; + } else { + int val = atoi(datebuf); + switch(tolower(datebuf[strlen(datebuf)-1])) { + case 'y': + val *= 365; + break; + case 'm': + val *= 30; + break; + case 'd': + default: + break; + } + if (val < 1) { + vmsg("日期格式輸入錯誤或是小於一天無法處理。"); + return -1; + } + if (now + val * DAY_SECONDS < now) { + vmsg("日期過大或無法處理,請重新輸入。"); + return -1; + } + expire = now + val * DAY_SECONDS; + move(y+3, 0); clrtobot(); + // sprintf(datebuf, "%s", Cdatelite(&expire)); + sprintf(datebuf, "%d 天", val); + prints("期限將設定為 %s之後: %s\n", + datebuf, Cdatelite(&expire)); + if (val > KEEP_DAYS_REGGED) { + mvprints(y+6, 0, ANSI_COLOR(1;31) + "注意: 超過 %d 天的設定有可能因為對方一直" + "未上站而導致帳號過期被重新註冊,\n" + " 此時同名的新帳號由於不一定是同一人所以" + "不會被禁言(水桶)。\n" ANSI_RESET, + KEEP_DAYS_REGGED); + } + } + + assert(sizeof(reason) >= BAKUMAN_REASON_LEN); + // maybe race condition here, but fine. + getdata(y+4, 0, "請輸入理由(空白可取消新增): ", + reason, BAKUMAN_REASON_LEN, DOECHO); + if (!*reason) { + vmsg("未輸入理由,取消此次設定"); + return -1; + } + + clrtobot(); + getdata(y+6, 0, "要寄信通知使用者嗎? (會附上前面輸入的理由) [Y/n]: ", + ans, sizeof(ans), LCECHO); + if (ans[0] == 'n') + do_notify = 0; + else + do_notify = 1; + + move(y, 0); clrtobot(); + prints("\n使用者 %s 即將加入禁言名單 (期限: %s)\n" + "理由: %s\n" + "%s寄信通知使用者" ANSI_RESET "\n", + uid, datebuf, reason, + do_notify ? ANSI_COLOR(1;32) "會" : ANSI_COLOR(1;31) "不會"); + + // last chance + getdata(y+5, 0, "確認以上資料全部正確嗎? [y/N]: ", + ans, sizeof(ans), LCECHO); + if (ans[0] != 'y') { + vmsg("請重新輸入"); + return -1; + } + + result = ban_user_for_board(uid, board, expire, reason); + log_filef(history_log, LOG_CREAT, + ANSI_COLOR(1) "%s %s" ANSI_COLOR(33) "%s" ANSI_RESET + " 限制 " ANSI_COLOR(1;31) "%s" ANSI_RESET + " 發言,期限為 %s\n 理由: %s\n", + Cdatelite(&now), + result ? "" : + ANSI_COLOR(0;31)"[系統錯誤] "ANSI_COLOR(1), + cuser.userid, uid, datebuf, reason); + vmsg(result ? "已將使用者加入禁言名單" : "失敗,請向站長報告"); + if (result && do_notify) { + char xtitle[STRLEN]; + char xmsg[STRLEN*5]; + + snprintf(xtitle, sizeof(xtitle), "%s 看板禁言通知(水桶)", board); + snprintf(xmsg, sizeof(xmsg), + "%s 看板已暫時禁止您發表意見 (放入水桶名單)。\n" + "原因: %s\n" + "其它資訊請洽該看板板規與公告。\n", board, reason); + mail_log2id_text(uid, xtitle, xmsg, "[系統通知]", 1); + sendalert(uid, ALERT_NEW_MAIL); + } + invalid_board_permission_cache(board); + return 0; +} + +static int +ui_unban_user_for_board(const char *uid, const char *board) { + time4_t expire = now; + int y, x; + char ans[3]; + char history_log[PATHLEN]; + char reason[STRLEN]; + + setbfile(history_log, board, FN_BANNED_HISTORY); + + getyx(&y, &x); + if (!(expire = is_user_banned_by_board(uid, board))) { + vmsg("使用者未在禁言名單。"); + return -1; + } + move(y, 0); clrtobot(); + prints("提前解除使用者 %s 於看板 %s 的禁言限制 (尚有 %d 天)。", + uid, board, (expire-now)/DAY_SECONDS+1); + assert(sizeof(reason) >= BAKUMAN_REASON_LEN); + getdata(y+1, 0, "請輸入理由(空白可取消解除): ", + reason, BAKUMAN_REASON_LEN, DOECHO); + if (!*reason) { + vmsg("未輸入理由,取消此次設定"); + return -1; + } + + // last chance + getdata(y+4, 0, "確認以上資料全部正確嗎? [y/N]: ", + ans, sizeof(ans), LCECHO); + if (ans[0] != 'y') { + vmsg("請重新輸入"); + return -1; + } + + unban_user_for_board(uid, board); + log_filef(history_log, LOG_CREAT, + ANSI_COLOR(1) "%s " ANSI_COLOR(33) "%s" ANSI_RESET + " 解除 " ANSI_COLOR(1;32) "%s" ANSI_RESET + " 的禁言限制 (距原期限尚有 %d 天)\n 理由: %s\n", + Cdatelite(&now), cuser.userid, uid, + (expire - now) / DAY_SECONDS+1, reason); + vmsg("使用者的禁言限制已解除,最晚至該使用者重新上站後生效"); + invalid_board_permission_cache(board); + return 0; +} + +int +edit_banned_list_for_board(const char *board) { + // TODO generalize this. time4_t expire = now; + char uid[IDLEN+1], ans[3]; if (!board || !*board || getbnum(board) < 1) return 0; - setbfile(history_log, board, FN_BANNED_HISTORY); - while (1) { clear(); vs_hdr2f(" Bakuman 權限設定系統 \t" @@ -211,16 +396,7 @@ ANSI_COLOR(1) " - 想查看某使用者為何被水桶可用(S)或是(L)再用 / 搜尋\n" if (!*uid || !searchuser(uid, uid)) continue; move(1, 0); clrtobot(); - expire = get_user_banned_status_by_board( - uid, board, sizeof(reason), reason); - if (expire > now) { - prints("使用者 %s 禁言中,解除時間尚有 %d 天: %s\n理由:%s", - uid, (expire-now)/DAY_SECONDS+1, - Cdatelite(&expire), reason); - } else { - prints("使用者 %s 目前不在禁言名單中。\n", - uid); - } + ui_print_user_banned_status_for_board(uid, board); pressanykey(); break; @@ -229,117 +405,9 @@ ANSI_COLOR(1) " - 想查看某使用者為何被水桶可用(S)或是(L)再用 / 搜尋\n" usercomplete(msg_uid, uid); if (!*uid || !searchuser(uid, uid)) continue; - if ((expire = is_user_banned_by_board(uid, board))) { - vmsgf("使用者之前已被禁言,尚有 %d 天;詳情可用(S)或(L)查看", - (expire - now) / DAY_SECONDS+1); - continue; - } move(1, 0); clrtobot(); - prints("將使用者 %s 加入看板 %s 的禁言名單。", uid, board); - syncnow(); - move(4, 0); - outs("目前接受的格式是 [數字][單位]。 " - "單位有: 年(y), 月(m), 天(d)\n" - "範例: 3m (三個月), 120d (120天), 10y (10年)\n" - "注意不可混合輸入(例:沒有三個半月這種東西,請換算成天數)\n" - ); - getdata(2, 0, "請以數字跟單位(預設為天)輸入期限: ", - datebuf, 8, DOECHO); - trim(datebuf); - if (!*datebuf) { - vmsg("未輸入期限,放棄。"); - continue; - } else { - int val = atoi(datebuf); - switch(tolower(datebuf[strlen(datebuf)-1])) { - case 'y': - val *= 365; - break; - case 'm': - val *= 30; - break; - case 'd': - default: - break; - } - if (val < 1) { - vmsg("日期格式輸入錯誤或是小於一天無法處理。"); - continue; - } - if (now + val * DAY_SECONDS < now) { - vmsg("日期過大或無法處理,請重新輸入。"); - continue; - } - expire = now + val * DAY_SECONDS; - move(4, 0); clrtobot(); - // sprintf(datebuf, "%s", Cdatelite(&expire)); - sprintf(datebuf, "%d 天", val); - prints("期限將設定為 %s之後: %s\n", - datebuf, Cdatelite(&expire)); - if (val > KEEP_DAYS_REGGED) { - mvprints(7, 0, ANSI_COLOR(1;31) - "注意: 超過 %d 天的設定有可能因為對方一直" - "未上站而導致帳號過期被重新註冊,\n" - " 此時同名的新帳號由於不一定是同一人所以" - "不會被禁言(水桶)。\n" ANSI_RESET, - KEEP_DAYS_REGGED); - } - } - - assert(sizeof(reason) >= BAKUMAN_REASON_LEN); - // maybe race condition here, but fine. - getdata(5, 0, "請輸入理由(空白可取消新增): ", - reason, BAKUMAN_REASON_LEN, DOECHO); - if (!*reason) { - vmsg("未輸入理由,取消此次設定"); + if (ui_ban_user_for_board(uid, board) < 0) continue; - } - - getdata(7, 0, "要寄信通知使用者嗎? (會附上前面輸入的理由) [Y/n]: ", - ans, sizeof(ans), LCECHO); - if (ans[0] == 'n') - do_notify = 0; - else - do_notify = 1; - - move(1, 0); clrtobot(); - prints("\n使用者 %s 即將加入禁言名單 (期限: %s)\n" - "理由: %s\n" - "%s寄信通知使用者" ANSI_RESET "\n", - uid, datebuf, reason, - do_notify ? ANSI_COLOR(1;32) "會" : ANSI_COLOR(1;31) "不會"); - - // last chance - getdata(6, 0, "確認以上資料全部正確嗎? [y/N]: ", - ans, sizeof(ans), LCECHO); - if (ans[0] != 'y') { - vmsg("請重新輸入"); - continue; - } - - result = ban_user_for_board(uid, board, expire, reason); - log_filef(history_log, LOG_CREAT, - ANSI_COLOR(1) "%s %s" ANSI_COLOR(33) "%s" ANSI_RESET - " 限制 " ANSI_COLOR(1;31) "%s" ANSI_RESET - " 發言,期限為 %s\n 理由: %s\n", - Cdatelite(&now), - result ? "" : - ANSI_COLOR(0;31)"[系統錯誤] "ANSI_COLOR(1), - cuser.userid, uid, datebuf, reason); - vmsg(result ? "已將使用者加入禁言名單" : "失敗,請向站長報告"); - if (result && do_notify) { - char xtitle[STRLEN]; - char xmsg[STRLEN*5]; - - snprintf(xtitle, sizeof(xtitle), "%s 看板禁言通知(水桶)", board); - snprintf(xmsg, sizeof(xmsg), - "%s 看板已暫時禁止您發表意見 (放入水桶名單)。\n" - "原因: %s\n" - "其它資訊請洽該看板板規與公告。\n", board, reason); - mail_log2id_text(uid, xtitle, xmsg, "[系統通知]", 1); - sendalert(uid, ALERT_NEW_MAIL); - } - invalid_board_permission_cache(board); break; case 'd': @@ -347,43 +415,18 @@ ANSI_COLOR(1) " - 想查看某使用者為何被水桶可用(S)或是(L)再用 / 搜尋\n" usercomplete(msg_uid, uid); if (!*uid || !searchuser(uid, uid)) continue; - if (!(expire = is_user_banned_by_board(uid, board))) { - vmsg("使用者未在禁言名單。"); - continue; - } - move(1, 0); clrtobot(); - prints("提前解除使用者 %s 於看板 %s 的禁言限制 (尚有 %d 天)。", - uid, board, (expire-now)/DAY_SECONDS+1); - assert(sizeof(reason) >= BAKUMAN_REASON_LEN); - getdata(2, 0, "請輸入理由(空白可取消解除): ", - reason, BAKUMAN_REASON_LEN, DOECHO); - if (!*reason) { - vmsg("未輸入理由,取消此次設定"); - continue; - } - - // last chance - getdata(5, 0, "確認以上資料全部正確嗎? [y/N]: ", - ans, sizeof(ans), LCECHO); - if (ans[0] != 'y') { - vmsg("請重新輸入"); + move(1, 0); + if (ui_unban_user_for_board(uid, board) < 0) continue; - } - - unban_user_for_board(uid, board); - log_filef(history_log, LOG_CREAT, - ANSI_COLOR(1) "%s " ANSI_COLOR(33) "%s" ANSI_RESET - " 解除 " ANSI_COLOR(1;32) "%s" ANSI_RESET - " 的禁言限制 (距原期限尚有 %d 天)\n 理由: %s\n", - Cdatelite(&now), cuser.userid, uid, - (expire - now) / DAY_SECONDS+1, reason); - vmsg("使用者的禁言限制已解除,最晚至該使用者重新上站後生效"); - invalid_board_permission_cache(board); break; case 'l': - if (more(history_log, YEA) == -1) - vmsg("目前尚無設定記錄。"); + do { + char history_log[PATHLEN]; + setbfile(history_log, board, FN_BANNED_HISTORY); + if (more(history_log, YEA) == -1) + vmsg("目前尚無設定記錄。"); + } while (0); break; #ifdef SHOW_OLD_BAN @@ -407,3 +450,61 @@ ANSI_COLOR(1) " - 想查看某使用者為何被水桶可用(S)或是(L)再用 / 搜尋\n" } return 0; } + +int +edit_user_acl_for_board(const char *uid, const char *board) { + time4_t expire; + int finished = 0; + +#define LNACLEDIT (10) + + int ytitle = b_lines - LNACLEDIT; + grayout(0, ytitle-2, GRAYOUT_DARK); + + while (!finished) { + move(ytitle-1, 0); clrtobot(); + outs("\n" ANSI_REVERSE); + vbarf(" 設定使用者 %s 於看板《%s》之權限", uid, board); + + move(ytitle+2, 0); + expire = ui_print_user_banned_status_for_board(uid, board); + + move(ytitle+5, 0); + prints(" " ANSI_COLOR(1;36) "%s" ANSI_RESET " - %s\n", + expire ? "u" : "w", + expire ? "提前解除" : "加入禁言名單"); + + switch (vans("請選擇欲進行之操作, 其它鍵結束: ")) { + case 'w': + if (expire) { + finished = 1; + break; + } + move(ytitle-1, 0); clrtobot(); + outs("\n" ANSI_REVERSE); + vbarf(" 禁言使用者"); + move(ytitle+2, 0); + if (ui_ban_user_for_board(uid, board) < 0) + continue; + break; + + case 'u': + if (!expire) { + finished = 1; + break; + } + move(ytitle-1, 0); clrtobot(); + outs("\n" ANSI_REVERSE); + vbarf(" 提前解除禁言"); + move(ytitle+2, 0); + if (ui_unban_user_for_board(uid, board) < 0) + continue; + break; + + default: + finished = 1; + break; + } + } + return 0; +} diff --git a/pttbbs/mbbsd/bbs.c b/pttbbs/mbbsd/bbs.c index 92d24dcf..a11e3b83 100644 --- a/pttbbs/mbbsd/bbs.c +++ b/pttbbs/mbbsd/bbs.c @@ -4324,7 +4324,7 @@ const onekey_t read_comms[] = { #endif { 1, b_mark_read_unread }, // 'v' { 1, b_call_in }, // 'w' - { 1, old_cross_post }, // 'x' + { 1, b_quick_acl }, // 'x' { 1, reply_post }, // 'y' { 0, b_man }, // 'z' 122 { 0, NULL }, // '{' 123 diff --git a/pttbbs/mbbsd/board.c b/pttbbs/mbbsd/board.c index 1d551f05..ad1e2ace 100644 --- a/pttbbs/mbbsd/board.c +++ b/pttbbs/mbbsd/board.c @@ -785,6 +785,43 @@ b_config(void) return FULLUPDATE; } +int +b_quick_acl(int ent, fileheader_t *fhdr, const char *direct) +{ + const boardheader_t *bp = getbcache(currbid); + if (!bp) + return FULLUPDATE; + + if (!(currmode & MODE_BOARD) && !HasUserPerm(PERM_SYSOP)) + return FULLUPDATE; + + char uid[IDLEN+2]; + strncpy(uid, fhdr->owner, sizeof(uid)); +#ifdef STR_SAFEDEL_TITLE + if (fhdr->filename[0] == '.' && + strncmp(fhdr->title, STR_SAFEDEL_TITLE, + strlen(STR_SAFEDEL_TITLE)) == 0) { + char *ps = &fhdr->title[strlen(STR_SAFEDEL_TITLE)]; + if (ps[0] == ' ' && ps[1] == '[') { + ps += 2; + char *pe = strchr(ps, ']'); + if (pe) { + strncpy(uid, ps, pe - ps); + uid[pe - ps] = '\0'; + } + } + } +#endif + if (!uid[0] || !is_validuserid(uid) || !searchuser(uid, uid)) { + vmsg("該使用者帳號不存在"); + return FULLUPDATE; + } + + edit_user_acl_for_board(uid, bp->brdname); + + return FULLUPDATE; +} + static int check_newpost(boardstat_t * ptr) { /* Ptt 改 */ |