diff options
author | piaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2010-10-24 00:06:14 +0800 |
---|---|---|
committer | piaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2010-10-24 00:06:14 +0800 |
commit | 8456e939e055be247bca74fd53594baa72098d2e (patch) | |
tree | 46936e612d780230ebd63522f5a08c82764d3428 | |
parent | 50bab622bc5c6a3407ac03b6ec1fc5daa54d5b48 (diff) | |
download | pttbbs-8456e939e055be247bca74fd53594baa72098d2e.tar pttbbs-8456e939e055be247bca74fd53594baa72098d2e.tar.gz pttbbs-8456e939e055be247bca74fd53594baa72098d2e.tar.bz2 pttbbs-8456e939e055be247bca74fd53594baa72098d2e.tar.lz pttbbs-8456e939e055be247bca74fd53594baa72098d2e.tar.xz pttbbs-8456e939e055be247bca74fd53594baa72098d2e.tar.zst pttbbs-8456e939e055be247bca74fd53594baa72098d2e.zip |
new ban system
git-svn-id: http://opensvn.csie.org/pttbbs/trunk@5149 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
-rw-r--r-- | pttbbs/include/common.h | 4 | ||||
-rw-r--r-- | pttbbs/include/proto.h | 7 | ||||
-rw-r--r-- | pttbbs/mbbsd/Makefile | 2 | ||||
-rw-r--r-- | pttbbs/mbbsd/acl.c | 258 | ||||
-rw-r--r-- | pttbbs/mbbsd/bbs.c | 9 | ||||
-rw-r--r-- | pttbbs/mbbsd/board.c | 6 | ||||
-rw-r--r-- | pttbbs/mbbsd/cache.c | 35 |
7 files changed, 309 insertions, 12 deletions
diff --git a/pttbbs/include/common.h b/pttbbs/include/common.h index 9cbd7465..baead6ee 100644 --- a/pttbbs/include/common.h +++ b/pttbbs/include/common.h @@ -21,7 +21,9 @@ #define FN_MONEY "etc/money" #define FN_OVERRIDES "overrides" #define FN_REJECT "reject" -#define FN_WATER "water" +#define FN_WATER "water" // 舊水桶 +#define FN_BANNED "banned" // 新水桶 +#define FN_BANNED_HISTORY "banned.history" // 新水桶之歷史記錄 #define FN_CANVOTE "can_vote" #define FN_VISABLE "visable" // 不知道是誰拼錯的,將錯就錯吧... #define FN_USIES "usies" /* BBS log */ diff --git a/pttbbs/include/proto.h b/pttbbs/include/proto.h index 8bca64ee..43d46661 100644 --- a/pttbbs/include/proto.h +++ b/pttbbs/include/proto.h @@ -51,6 +51,12 @@ int a_menu(const char *maintitle, const char *path, int lastlevel, int lastbid, void a_copyitem(const char* fpath, const char* title, const char* owner, int mode); int Announce(void); +/* acl */ +time4_t is_user_banned_by_board(const char *user, const char *board); +time4_t is_banned_by_board(const char *board); +int ban_user_for_board(const char *user, const char *board, time4_t expire, const char *reason); +int edit_banned_list_for_board(const char *board); + /* assess */ int inc_badpost(const char *, int num); int bad_comment(const char *fn); @@ -118,6 +124,7 @@ char*getuserid(int num); int getuser(const char *userid, userec_t *xuser); int searchnewuser(int mode); int count_logins(int uid, int show); +void invalid_board_permission_cache(const char *board); int is_BM_cache(int); int apply_boards(int (*func)(boardheader_t *)); int haspostperm(const char *bname); diff --git a/pttbbs/mbbsd/Makefile b/pttbbs/mbbsd/Makefile index a77dee71..31f0d71a 100644 --- a/pttbbs/mbbsd/Makefile +++ b/pttbbs/mbbsd/Makefile @@ -9,7 +9,7 @@ SRCROOT= .. PROG= mbbsd COREOBJS = bbs.o announce.o read.o board.o brc.o mail.o record.o fav.o -ACCOBJS = user.o register.o passwd.o emaildb.o +ACCOBJS = user.o acl.o register.o passwd.o emaildb.o NETOBJS = mbbsd.o io.o term.o telnet.o TALKOBJS = friend.o talk.o ccw.o UTILOBJS = stuff.o kaede.o convert.o name.o syspost.o cache.o cal.o diff --git a/pttbbs/mbbsd/acl.c b/pttbbs/mbbsd/acl.c new file mode 100644 index 00000000..0eed630c --- /dev/null +++ b/pttbbs/mbbsd/acl.c @@ -0,0 +1,258 @@ +/* $Id$ */ +#include "bbs.h" + +// Access Control List +// Holder of all access / permission related stuff +// +// Author: Hung-Te Lin (piaip) + +/////////////////////////////////////////////////////////////////////////// +// New ban system (store in user home) + +#define BANNED_OBJECT_TYPE_USER 'u' +#define BANNED_OBJECT_TYPE_BORAD 'b' + +static void +banned_make_tag_filename(const char *who, const char *object, char object_type, + size_t szbuf, char *buf, int create_folder) { + char prefix[3] = { object_type, '_', 0 }; + + if (!who) + setuserfile(buf, FN_BANNED "/"); + else + sethomefile(buf, who, FN_BANNED "/"); + if (create_folder && !dashd(buf)) { + mkdir(buf, 0755); + } + strlcat(buf, prefix, szbuf); + strlcat(buf, object, szbuf); +} + +static int +banned_get_info(const char *filename, + time4_t *pexpire, size_t szreason, char *reason) { + FILE *fp = fopen(filename, "rt"); + int ts = 0; + char buf[STRLEN]; + + if(!fp) + return 0; + + // banned file format: + // EXPIRE_TIME + // REASON + fgets(buf, sizeof(buf), fp); + if (pexpire) { + sscanf(buf, "%u", &ts); + *pexpire = (time4_t) ts; + } + fgets(buf, sizeof(buf), fp); + if (szreason && reason) { + chomp(buf); + strlcpy(reason, buf, szreason); + } + fclose(fp); + return 1; +} + +static int +banned_set_info(const char *filename, time4_t expire, const char *reason) { + FILE *fp = fopen(filename, "wt"); + if (!fp) + return 0; + if (!reason) + reason = ""; + + fprintf(fp, "%u\n%s\n", (unsigned)expire, reason); + fclose(fp); + return 1; +} + +// return if 'who (NULL=self)' is banned by 'object' +static time4_t +is_banned_by(const char *who, const char *object, char object_type) { + char tag_fn[PATHLEN]; + time4_t expire = 0; + + banned_make_tag_filename(who, object, object_type, sizeof(tag_fn),tag_fn,0); + if (!dashf(tag_fn)) + return 0; + + // check expire + if (banned_get_info(tag_fn, &expire, 0, NULL) && now > expire) { + unlink(tag_fn); + return 0; + } + return expire; +} + +// add 'who (NULL=self)' to the ban list of 'object' +static int +ban_user_as(const char *who, const char *object, char object_type, + time_t expire, const char *reason) { + char tag_fn[PATHLEN]; + + banned_make_tag_filename(who, object, object_type, sizeof(tag_fn),tag_fn,1); + return banned_set_info(tag_fn, expire, reason); +} + +time4_t +is_user_banned_by_board(const char *user, const char *board) { + return is_banned_by(user, board, BANNED_OBJECT_TYPE_BORAD); +} + +time4_t +is_banned_by_board(const char *board) { + return is_user_banned_by_board(cuser.userid, board); +} + +int +ban_user_for_board(const char *user, const char *board, + time4_t expire, const char *reason) { + return ban_user_as(user, board, BANNED_OBJECT_TYPE_BORAD, expire, reason); +} + +int +unban_user_for_board(const char *user, const char *board) { + char tag_fn[PATHLEN]; + + banned_make_tag_filename(user, board, BANNED_OBJECT_TYPE_BORAD, + sizeof(tag_fn), tag_fn, 0); + return unlink(tag_fn) == 0; +} + +int +edit_banned_list_for_board(const char *board) { + // TODO generalize this. + int result; + char uid[IDLEN+1], ans[3]; + char history_log[PATHLEN]; + char reason[STRLEN]; + char datebuf[STRLEN]; + time4_t expire = now; + + if (!board || !*board || getbnum(board) < 1) + return 0; + + setbfile(history_log, board, FN_BANNED_HISTORY); + + while (1) { + clear(); + vs_hdr2f(" 設定看板水桶 \t 看板: %s", board); + getdata(1, 0, "要 (A)增加 (D)提前清除 (L)列出水桶歷史 (Q)結束? [Q] ", + ans, sizeof(ans), LCECHO); + if (*ans == 'q' || !*ans) + break; + + switch (*ans) { + case 'a': + move(1, 0); + usercomplete(msg_uid, uid); + if (!*uid || !searchuser(uid, uid)) + continue; + if (is_user_banned_by_board(uid, board)) { + vmsg("使用者已在水桶中。"); + continue; + } + move(1, 0); clrtobot(); + prints("將使用者 %s 加入看板 %s 的水桶。", uid, board); + syncnow(); + move(4, 0); + outs("目前接受的格式是 [數字][單位]。 單位有: 年(y), 月(m), 天(d)\n"); + outs("範例: 3m (三個月), 180d (180天), 10y (10年)\n"); + outs("注意不可混合輸入(ex: 沒有三個半月這種東西,要換算成天數\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; + } + expire = now + val * DAY_SECONDS; + move(4, 0); clrtobot(); + prints("水桶期限將設定為 %d 天後: %s", + val, Cdatelite(&expire)); + } + + assert(sizeof(reason) >= TTLEN); + // maybe race condition here, but fine. + getdata(5, 0, "請輸入理由(空白可取消): ", reason, TTLEN,DOECHO); + if (!*reason) { + vmsg("未輸入理由,無法受理。"); + continue; + } + + sprintf(datebuf, "%s", Cdatelite(&expire)); + move(1, 0); clrtobot(); + prints("\n使用者 %s 即將加入水桶 (解除時間: %s)\n" + "理由: %s\n", uid, datebuf, reason); + + // last chance + getdata(5, 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, + "%s %s%s 將 %s 加入水桶 (解除時間: %s),理由: %s\n", + Cdatelite(&now), + result ? "" : "(未成功\)", + cuser.userid, uid, datebuf, reason); + vmsg(result ? "已將使用者加入水桶" : "失敗,請向站長報告"); + invalid_board_permission_cache(board); + break; + + case 'd': + move(1, 0); + usercomplete(msg_uid, uid); + if (!*uid || !searchuser(uid, uid)) + continue; + if (!is_user_banned_by_board(uid, board)) { + vmsg("使用者未被水桶。"); + continue; + } + move(1, 0); clrtobot(); + prints("提前解除使用者 %s 於看板 %s 的水桶。", uid, board); + assert(sizeof(reason) >= TTLEN); + getdata(2, 0, "請輸入理由(空白可取消解除): ",reason,TTLEN,DOECHO); + if (!*reason) { + vmsg("未輸入理由,無法受理。"); + continue; + } + unban_user_for_board(uid, board); + log_filef(history_log, LOG_CREAT, + "%s %s 解除 %s 的水桶,理由: %s\n", + Cdatelite(&now), cuser.userid, uid, reason); + vmsg("使用者水桶已解除。"); + invalid_board_permission_cache(board); + break; + + case 'l': + if (more(history_log, YEA) == -1) + vmsg("目前尚無水桶記錄。"); + break; + + default: + break; + } + } + return 0; +} diff --git a/pttbbs/mbbsd/bbs.c b/pttbbs/mbbsd/bbs.c index d468237a..af045bcb 100644 --- a/pttbbs/mbbsd/bbs.c +++ b/pttbbs/mbbsd/bbs.c @@ -130,7 +130,8 @@ add_to_post_history( int fd = 0, last_index = 0; setdirpath(hist_file, direct, FN_EDITHISTORY "/"); - mkdir(hist_file, 0755); + if (!dashd(hist_file)) + mkdir(hist_file, 0755); strlcat(hist_file, basename, sizeof(hist_file)); if ((fd = open(hist_file, O_RDWR|O_CREAT, 0644)) >= 0) { @@ -3573,10 +3574,8 @@ view_post_history(int ent, const fileheader_t * fhdr, const char *direct) strlcat(hist_file, fhdr->filename, sizeof(hist_file)); } - // TODO check if hist_file is a valid file (directoy gives fake result) - - fd = open(hist_file, O_RDONLY); - if (fd < 0) { + if (!dashf(hist_file) || + (fd = open(hist_file, O_RDONLY)) < 0) { vmsg(err_no_history); return FULLUPDATE; } diff --git a/pttbbs/mbbsd/board.c b/pttbbs/mbbsd/board.c index f53fc35a..ccf51f22 100644 --- a/pttbbs/mbbsd/board.c +++ b/pttbbs/mbbsd/board.c @@ -541,7 +541,7 @@ b_config(void) if (!isBM) outs(" (需板主權限)"); outs(aRst); move_ansi(ipostres++, COLPOSTRES); - prints("%sw%s)水桶名單 %sv%s)可見會員名單 ", + prints("%sw%s)設定水桶 %sv%s)可見會員名單 ", aHot, aRst, aHot, aRst); move_ansi(ipostres++, COLPOSTRES); prints("%sm%s)舉辦投票 %so%s)投票名單 ", @@ -740,7 +740,11 @@ b_config(void) case 'w': clear(); +#ifdef USE_NEW_BAN_SYSTEM + edit_banned_list_for_board(currboard); +#else friend_edit(BOARD_WATER); +#endif clear(); break; diff --git a/pttbbs/mbbsd/cache.c b/pttbbs/mbbsd/cache.c index f4b80fe4..bf10e577 100644 --- a/pttbbs/mbbsd/cache.c +++ b/pttbbs/mbbsd/cache.c @@ -125,6 +125,18 @@ getutmpmode(void) * section - board */ +void +invalid_board_permission_cache(const char *board) { + boardheader_t *bp = NULL; + int bid = getbnum(board); + + assert(0<=bid-1 && bid-1<MAX_BOARD); + bp = getbcache(bid); + bp->perm_reload = now; + substitute_record(fn_board, bp, sizeof(boardheader_t), bid); +} + + /* HasBoardPerm() in board.c... */ int apply_boards(int (*func) (boardheader_t *)) @@ -176,7 +188,6 @@ const char * postperm_msg(const char *bname) { register int i; - char buf[PATHLEN]; boardheader_t *bp = NULL; if (!(i = getbnum(bname))) @@ -189,9 +200,25 @@ postperm_msg(const char *bname) if (HasUserPerm(PERM_SYSOP)) return NULL; - setbfile(buf, bname, fn_water); - if (file_exist_record(buf, cuser.userid)) - return "使用者水桶中"; +#ifdef USE_NEW_BAN_SYSTEM + { + // static is bad, but this is faster... + static char ban_msg[STRLEN]; + time4_t expire = is_banned_by_board(bname); + if (expire > now) { + sprintf(ban_msg, "使用者水桶中(尚有%d天)", + ((expire - now) / DAY_SECONDS) +1); + return ban_msg; + } + } +#else + { + char buf[PATHLEN]; + setbfile(buf, bname, fn_water); + if (file_exist_record(buf, cuser.userid)) + return "使用者水桶中"; + } +#endif if (!strcasecmp(bname, DEFAULT_BOARD)) return NULL; |