diff options
author | piaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2009-09-10 18:05:12 +0800 |
---|---|---|
committer | piaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2009-09-10 18:05:12 +0800 |
commit | 0a50f91422cc78e215c541d08dbf30fdeb91477c (patch) | |
tree | 9b09fa98181fe6ef345109eb0c279d3628889c09 /mbbsd | |
parent | 78a17f4498134b9db1fc95e7be14798422475475 (diff) | |
parent | f115309f094fb58ce49a14a24d58144aa13d3e5c (diff) | |
download | pttbbs-0a50f91422cc78e215c541d08dbf30fdeb91477c.tar pttbbs-0a50f91422cc78e215c541d08dbf30fdeb91477c.tar.gz pttbbs-0a50f91422cc78e215c541d08dbf30fdeb91477c.tar.bz2 pttbbs-0a50f91422cc78e215c541d08dbf30fdeb91477c.tar.lz pttbbs-0a50f91422cc78e215c541d08dbf30fdeb91477c.tar.xz pttbbs-0a50f91422cc78e215c541d08dbf30fdeb91477c.tar.zst pttbbs-0a50f91422cc78e215c541d08dbf30fdeb91477c.zip |
* make pwcu branch as trunk.
git-svn-id: http://opensvn.csie.org/pttbbs/trunk/pttbbs@4826 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
Diffstat (limited to 'mbbsd')
-rw-r--r-- | mbbsd/admin.c | 9 | ||||
-rw-r--r-- | mbbsd/angel.c | 10 | ||||
-rw-r--r-- | mbbsd/announce.c | 10 | ||||
-rw-r--r-- | mbbsd/assess.c | 215 | ||||
-rw-r--r-- | mbbsd/bbs.c | 104 | ||||
-rw-r--r-- | mbbsd/board.c | 5 | ||||
-rw-r--r-- | mbbsd/cache.c | 2 | ||||
-rw-r--r-- | mbbsd/cal.c | 7 | ||||
-rw-r--r-- | mbbsd/calendar.c | 38 | ||||
-rw-r--r-- | mbbsd/card.c | 22 | ||||
-rw-r--r-- | mbbsd/ch_go.c | 31 | ||||
-rw-r--r-- | mbbsd/ch_gomo.c | 31 | ||||
-rw-r--r-- | mbbsd/chat.c | 8 | ||||
-rw-r--r-- | mbbsd/chc.c | 37 | ||||
-rw-r--r-- | mbbsd/chess.c | 4 | ||||
-rw-r--r-- | mbbsd/edit.c | 2 | ||||
-rw-r--r-- | mbbsd/kaede.c | 2 | ||||
-rw-r--r-- | mbbsd/mail.c | 3 | ||||
-rw-r--r-- | mbbsd/mbbsd.c | 137 | ||||
-rw-r--r-- | mbbsd/menu.c | 2 | ||||
-rw-r--r-- | mbbsd/ordersong.c | 2 | ||||
-rw-r--r-- | mbbsd/passwd.c | 639 | ||||
-rw-r--r-- | mbbsd/pmore.c | 2 | ||||
-rw-r--r-- | mbbsd/read.c | 10 | ||||
-rw-r--r-- | mbbsd/register.c | 151 | ||||
-rw-r--r-- | mbbsd/talk.c | 76 | ||||
-rw-r--r-- | mbbsd/user.c | 278 | ||||
-rw-r--r-- | mbbsd/var.c | 5 | ||||
-rw-r--r-- | mbbsd/vote.c | 2 | ||||
-rw-r--r-- | mbbsd/xyz.c | 6 |
30 files changed, 972 insertions, 878 deletions
diff --git a/mbbsd/admin.c b/mbbsd/admin.c index 50face6b..011f81e7 100644 --- a/mbbsd/admin.c +++ b/mbbsd/admin.c @@ -43,7 +43,7 @@ m_user(void) if ((id = getuser(genbuf, &xuser))) { user_display(&xuser, 1); if( HasUserPerm(PERM_ACCOUNTS) ) - uinfo_query(&xuser, 1, id); + uinfo_query(xuser.userid, 1, id); else pressanykey(); } else { @@ -110,7 +110,7 @@ upgrade_passwd(userec_t *puser) memset(puser->chkpad2, 0, sizeof(puser->chkpad2)); puser->lastseen= 0; puser->version = PASSWD_VERSION; - return; + return ; } #endif } @@ -216,10 +216,13 @@ search_key_user(const char *passwdfile, int mode) // user_display does not have linefeed in tail. if (isCurrentPwd && HasUserPerm(PERM_ACCOUNTS)) - uinfo_query(&user, 1, unum); + uinfo_query(user.userid, 1, unum); else outs("\n"); + // XXX don't trust 'user' variable after here + // because uinfo_query may have changed it. + outs(ANSI_COLOR(44) " 空白鍵" \ ANSI_COLOR(37) ":搜尋下一個 " \ ANSI_COLOR(33)" Q" ANSI_COLOR(37)": 離開"); diff --git a/mbbsd/angel.c b/mbbsd/angel.c index 240e51a2..ab4f2bbc 100644 --- a/mbbsd/angel.c +++ b/mbbsd/angel.c @@ -14,9 +14,6 @@ angel_toggle_pause() return; currutmp->angelpause ++; currutmp->angelpause %= ANGELPAUSE_MODES; - - // maintain deprecated value - cuser.uflag2 &= ~UF2_ANGEL_OLDMASK; } void @@ -140,7 +137,7 @@ t_changeangel(){ Cdatelite(&now), cuser.userid, cuser.myangel); log_file(BBSHOME "/log/changeangel.log", LOG_CREAT, buf); - cuser.myangel[0] = 0; + pwcuSetMyAngel(""); outs("小天使更新完成,下次呼叫時會選出新的小天使"); } return XEASY; @@ -269,8 +266,7 @@ FindAngel(void){ (u->userlevel & PERM_ANGEL) && !angel_reject_me(u) && u->userid[0]){ - strlcpy(cuser.myangel, u->userid, sizeof(cuser.myangel)); - passwd_sync_update(usernum, &cuser); + pwcuSetMyAngel(u->userid); return 1; } }while(++trial < 5); @@ -394,7 +390,7 @@ TalkToAngel(){ memset(&xuser, 0, sizeof(xuser)); getuser(cuser.myangel, &xuser); // XXX if user doesn't exist if (!(xuser.userlevel & PERM_ANGEL)) - cuser.myangel[0] = 0; + pwcuSetMyAngel(""); } AngelPermChecked = 1; diff --git a/mbbsd/announce.c b/mbbsd/announce.c index 8663d392..0ec3f6ce 100644 --- a/mbbsd/announce.c +++ b/mbbsd/announce.c @@ -119,10 +119,6 @@ int copyqueue_toggle(CopyQueue *pcq) int i = copyqueue_locate(pcq); if(i >= 0) { -#if 0 - if (vans("已標記過此檔,要取消標記嗎 [y/N]: ") != 'y') - return 1; -#endif /* remove it */ used_copyqueue --; if(head_copyqueue > used_copyqueue) @@ -172,14 +168,8 @@ a_copyitem(const char *fpath, const char *title, const char *owner, int mode) //copyqueue_append(&cq); copyqueue_toggle(&cq); if (mode && flFirstAlert) { -#if 0 - move(b_lines-2, 0); clrtoeol(); - prints("目前已標記 %d 個檔案。[注意] 拷貝後才能刪除原文!", - copyqueue_querysize()); -#else vmsg("[注意] 提醒您複製/標記後要貼上(p)或附加(a)後才能刪除原文!"); flFirstAlert = 0; -#endif } } diff --git a/mbbsd/assess.c b/mbbsd/assess.c index 64bc7ad5..aa9abe71 100644 --- a/mbbsd/assess.c +++ b/mbbsd/assess.c @@ -26,219 +26,6 @@ int inc_##_attr(const char *userid, int num) \ return 0;\ } -modify_column(goodpost); /* inc_goodpost */ modify_column(badpost); /* inc_badpost */ -// how long is AID? see read.c... -#ifndef AIDC_LEN -#define AIDC_LEN (20) -#endif // AIDC_LEN - -// #define MAXGP (100) -#define MAXGP (UCHAR_MAX) - -int -u_fixgoodpost(void) -{ - char endinput = 0; - unsigned int newgp = 0; - int bid; - char bname[IDLEN+1]; - char xaidc[AIDC_LEN+1]; - - aidu_t gpaids[MAXGP+1]; - int gpbids[MAXGP+1]; - int cgps = 0; - - clear(); - vs_hdr("自動優文修正程式"); - - outs("開始修正優文之前,有些功\課要麻煩您先查好:\n\n" - "請先找到你所有的優文文章的看板與" AID_DISPLAYNAME "\n" - AID_DISPLAYNAME "的查詢方法是在該篇文章前面按下大寫 Q 。\n" - "查好後請把這些資料放在手邊,等下會請您輸入。\n" - "另外,若有多重登入請先關閉其它連線。\n" - "\n"); - outs("如果一切都準備好了,請按下 y 開始,或其它任意鍵跳出。\n\n"); - if (vans("優文的資料都查好了嗎?") != 'y') - { - vmsg("跳出修正程式。"); - return 0; - } - while (!endinput && newgp < MAXGP) - { - int y; - boardheader_t *bh = NULL; - - move(1, 0); clrtobot(); - outs("請依序輸入優文資訊,全部完成後按 ENTER 即可停止。\n"); - - move(b_lines-2, 0); clrtobot(); - prints("目前已確認優文數目: %d" ANSI_RESET "\n\n", newgp); - - if (!getdata(5, 0, "請輸入優文文章所在看板名稱: ", - bname, sizeof(bname), DOECHO)) - { - move(5, 0); - if (vans(ANSI_COLOR(1;33)"確定全部輸入完成了嗎? " - ANSI_RESET "[y/N]: ") != 'y') - continue; - endinput = 1; break; - } - move (6, 0); - outs("確認看板... "); - if (bname[0] == '\0' || !(bid = getbnum(bname))) - { - outs(ANSI_COLOR(1;31) "看板不存在!"); - vmsg("請重新輸入。"); - continue; - } - assert(0<=bid-1 && bid-1<MAX_BOARD); - bh = getbcache(bid); - strlcpy(bname, bh->brdname, sizeof(bname)); - prints("已找到看板 --> %s\n", bname); - y = vgety(); - - // loop AID query - while (newgp < MAXGP) - { - int n; - int fd; - char dirfile[PATHLEN]; - char *sp; - aidu_t aidu = 0; - fileheader_t fh; - - move(y, 0); clrtobot(); - move(b_lines-2, 0); clrtobot(); - prints("目前已確認優文數目: %d" ANSI_RESET "\n\n", newgp); - - if (getdata(y, 0, "請輸入" AID_DISPLAYNAME ": #", - xaidc, AIDC_LEN, DOECHO) == 0) - break; - - sp = xaidc; - while(*sp == ' ') sp ++; - if(*sp == '#') sp ++; - - if((aidu = aidc2aidu(sp)) <= 0) - { - outs(ANSI_COLOR(1;31) AID_DISPLAYNAME "格式不正確!"); - vmsg("請重新輸入。"); - continue; - } - - // check repeated input of same board+AID. - for (n = 0; n < cgps; n++) - { - if (gpaids[n] == aidu && gpbids[n] == bid) - { - vmsg("您已輸入過此優文了,請重新輸入。"); - aidu = 0; - break; - } - } - - if (aidu <= 0) - continue; - - // find aidu in board - n = -1; - // see read.c, search .bottom first. - if (n < 0) - { - outs("搜尋置底文章..."); - setbfile(dirfile, bname, FN_DIR ".bottom"); - n = search_aidu(dirfile, aidu); - } - if (n < 0) { - // search board - outs("未找到。\n搜尋看板文章.."); - setbfile(dirfile, bname, FN_DIR); - n = search_aidu(dirfile, aidu); - } - if (n < 0) - { - // search digest - outs("未找到。\n搜尋文摘.."); - setbfile(dirfile, currboard, fn_mandex); - n = search_aidu(dirfile, aidu); - } - if (n < 0) - { - // search failed... - outs("未找到\n" ANSI_COLOR(1;31) "找不到文章!"); - vmsg("請確認後重新輸入。"); - continue; - } - - // found something - fd = open(dirfile, O_RDONLY); - if (fd < 0) - { - outs(ANSI_COLOR(1;31) "系統錯誤。 請稍候再重試。\n"); - vmsg("若持續發生請至" BN_BUGREPORT "報告。"); - continue; - } - - lseek(fd, n*sizeof(fileheader_t), SEEK_SET); - memset(&fh, 0, sizeof(fh)); - read(fd, &fh, sizeof(fh)); - outs("\n開始核對資料...\n"); - n = 1; - // XXX 要接受大小寫不同嗎? (改 id) - // 常改 id 不是好事,要改就要承受無法回復的風險,完。 - if (strcmp(fh.owner, cuser.userid) != 0) - n = 0; - prints("作者: %s (%s)\n", fh.owner, n ? "正確" : - ANSI_COLOR(1;31) "錯誤" ANSI_RESET); - if (!(fh.filemode & FILE_MARKED)) - n = 0; - prints("M文: %s\n", (fh.filemode & FILE_MARKED) ? "正確" : - ANSI_COLOR(1;31) "錯誤" ANSI_RESET); - prints("推薦: %d\n", fh.recommend); - close(fd); - if (!n) - { - vmsg("輸入的文章並非優文,請重新輸入。"); - continue; - } - n = fh.recommend / 10; - prints("計算優文數值: %+d\n", n); - - if (n > 0) - { - // log new data - newgp += n; - gpaids[cgps] = aidu; - gpbids[cgps] = bid; - cgps ++; - } - - clrtobot(); - - - vmsg("優文已確認。若要輸入其它看板文章請在AID欄空白按 ENTER"); - } - vmsgf("%s 看板輸入完成。", bname); - } - if (newgp > MAXGP) - newgp = MAXGP; - if (newgp <= cuser.goodpost) - { - vmsg("確認優文數目未高於已有優文數,不調整。"); - } else { - log_filef("log/fixgoodpost.log", LOG_CREAT, - "%s %s 自動修正優文數: 由 %d 變為 %d\n", Cdate(&now), cuser.userid, - cuser.goodpost, newgp); - cuser.goodpost = newgp; - // update passwd file here? - passwd_force_update(ALERT_PWD_GOODPOST); - passwd_sync_update(usernum, &cuser); - vmsgf("更新優文數目為%d。", newgp); - } - - return 0; -} - -#endif +#endif // ASSESS diff --git a/mbbsd/bbs.c b/mbbsd/bbs.c index 2854e131..efac93c4 100644 --- a/mbbsd/bbs.c +++ b/mbbsd/bbs.c @@ -170,9 +170,7 @@ anticrosspost(void) cuser.userid, Cdatelite(&now)); post_violatelaw(cuser.userid, BBSMNAME "系統警察", "Cross-post", "罰單處份"); - cuser.userlevel |= PERM_VIOLATELAW; - cuser.timeviolatelaw = now; - cuser.vl_count++; + pwcuViolateLaw(); mail_id(cuser.userid, "Cross-Post罰單", "etc/crosspost.txt", BBSMNAME "警察部隊"); if ((now - cuser.firstlogin) / DAY_SECONDS < 14) @@ -243,17 +241,14 @@ save_violatelaw(void) } demoney(-1000 * cuser.vl_count); - cuser.userlevel &= (~PERM_VIOLATELAW); - // force overriding alerts - if(currutmp) - currutmp->alerts &= ~ALERT_PWD_PERM; - passwd_sync_update(usernum, &cuser); - sendalert(cuser.userid, ALERT_PWD_PERM); + pwcuSaveViolateLaw(); log_filef("log/violation", LOG_CREAT, "%s %s pay-violation: $%d complete.\n", Cdate(&now), cuser.userid, (int)cuser.vl_count*1000); - vmsg("罰單已付,請盡速重新登入。"); + vmsg("罰單已付,請重新登入。"); + u_exit("save_violate"); + exit(0); return 0; } @@ -346,6 +341,13 @@ CheckPostPerm(void) if (currmode & MODE_DIGEST) return 0; + // check if my own permission is changed. + if (ISNEWPERM(currutmp)) + { + currmode &= ~MODE_POSTCHECKED; + pwcuReload(); + } + if (currmode & MODE_POSTCHECKED) { /* checked? let's check if perm reloaded */ @@ -908,7 +910,8 @@ do_general(int garbage) int i, j; int defanony, ifuseanony; int money = 0; - char genbuf[PATHLEN], *owner; + char genbuf[PATHLEN]; + const char *owner; char ctype[8][5] = {"問題", "建議", "討論", "心得", "閒聊", "請益", "公告", "情報"}; boardheader_t *bp; @@ -1128,9 +1131,10 @@ do_general(int garbage) if (money > 0) { demoney(money); + pwcuIncNumPost(); addPost = 1; prints("這是您的第 %d 篇有效文章,獲得稿酬 %d 元", - ++cuser.numposts, money); + cuser.numposts, money); } else { // no money, no record. outs("本篇不列入記錄,敬請包涵。"); @@ -2351,14 +2355,6 @@ recommend_cancel(int ent, fileheader_t * fhdr, const char *direct) getdata(b_lines - 1, 0, "確定要推薦歸零[y/N]? ", yn, 5, LCECHO); if (yn[0] != 'y') return FULLUPDATE; -#ifdef ASSESS - // to save resource - if (fhdr->recommend > 9) - { - inc_goodpost(fhdr->owner, -1 * (fhdr->recommend / 10)); - sendalert(fhdr->owner, ALERT_PWD_GOODPOST); - } -#endif fhdr->recommend = 0; substitute_ref_record(direct, fhdr, ent); @@ -2445,9 +2441,6 @@ recommend(int ent, fileheader_t * fhdr, const char *direct) int isGuest = (strcmp(cuser.userid, STR_GUEST) == EQUSTR); int logIP = 0; int ymsg = b_lines -1; -#ifdef ASSESS - char oldrecom = fhdr->recommend; -#endif // ASSESS if (!fhdr || !fhdr->filename[0]) return DONOTHING; @@ -2726,7 +2719,7 @@ recommend(int ent, fileheader_t * fhdr, const char *direct) static int tolog = 0; if( tolog == 0 ) tolog = - (cuser.numlogins < 50 || (now - cuser.firstlogin) < DAY_SECONDS * 7) + (cuser.numlogindays < 50 || (now - cuser.firstlogin) < DAY_SECONDS * 7) ? 1 : 2; if( tolog == 1 ){ FILE *fp; @@ -2774,20 +2767,6 @@ recommend(int ent, fileheader_t * fhdr, const char *direct) } do_add_recommend(direct, fhdr, ent, buf, type); - -#ifdef ASSESS - /* 每 10 次推文 加一次 goodpost */ - // TODO 轉來的怎麼辦? - // when recommend reaches MAX_RECOMMENDS... - if (type == RECTYPE_GOOD && (fhdr->filemode & FILE_MARKED) && - (fhdr->recommend != oldrecom) && - fhdr->recommend % 10 == 0) - { - inc_goodpost(fhdr->owner, 1); - sendalert(fhdr->owner, ALERT_PWD_GOODPOST); - } -#endif - lastrecommend = now; lastrecommend_bid = currbid; strlcpy(lastrecommend_fname, fhdr->filename, sizeof(lastrecommend_fname)); @@ -2810,23 +2789,6 @@ mark_post(int ent, fileheader_t * fhdr, const char *direct) return DONOTHING; fhdr->filemode ^= FILE_MARKED; - -#ifdef ASSESS - if (fhdr->filemode & FILE_MARKED) - { - if (!(currbrdattr & BRD_BAD) && fhdr->recommend >= 10) - { - inc_goodpost(fhdr->owner, fhdr->recommend / 10); - sendalert(fhdr->owner, ALERT_PWD_GOODPOST); - } - } - else if (fhdr->recommend > 9) - { - inc_goodpost(fhdr->owner, -1 * (fhdr->recommend / 10)); - sendalert(fhdr->owner, ALERT_PWD_GOODPOST); - } -#endif - substitute_ref_record(direct, fhdr, ent); check_locked(fhdr); return PART_REDRAW; @@ -3072,7 +3034,7 @@ del_post(int ent, fileheader_t * fhdr, char *direct) xuser.timeviolatelaw = now; passwd_sync_update(tusernum, &xuser); } - sendalert(userid, ALERT_PWD_BADPOST); + sendalert(userid, ALERT_PWD_PERM); mail_id(userid, genbuf, newpath, cuser.userid); #ifdef BAD_POST_RECORD @@ -3130,15 +3092,15 @@ del_post(int ent, fileheader_t * fhdr, char *direct) if (tusernum) { userec_t xuser; - passwd_sync_query(tusernum, &xuser); - if (xuser.numposts) - xuser.numposts--; - passwd_sync_update(tusernum, &xuser); - sendalert_uid(tusernum, ALERT_PWD_POSTS); - - // TODO alert user? + assert(tusernum != usernum); + // TODO we're doing redundant i/o here... merge and refine someday + if (passwd_sync_query(tusernum, &xuser) == 0) { + if (xuser.numposts > 0) + xuser.numposts--; + passwd_sync_update(tusernum, &xuser); + } deumoney(tusernum, -fhdr->multi.money); - + sendalert_uid(tusernum, ALERT_PWD_PERM); #ifdef USE_COOLDOWN if (bp->brdattr & BRD_COOLDOWN) add_cooldowntime(tusernum, 15); @@ -3148,11 +3110,9 @@ del_post(int ent, fileheader_t * fhdr, char *direct) else { // owner case - if (cuser.numposts){ - cuser.numposts--; - sendalert(cuser.userid, ALERT_PWD_POSTS); - } + pwcuDecNumPost(); demoney(-fhdr->multi.money); + sendalert(cuser.userid, ALERT_PWD_PERM); vmsgf("您的文章減為 %d 篇,支付清潔費 %d 元", cuser.numposts, fhdr->multi.money); } @@ -3932,11 +3892,3 @@ Select(void) return do_select(); } -#ifdef HAVEMOBILE -void -mobile_message(const char *mobile, char *message) -{ - // this is for validation. - bsmtp(fpath, title, rcpt, "non-exist"); -} -#endif diff --git a/mbbsd/board.c b/mbbsd/board.c index a3101175..6bc7f6da 100644 --- a/mbbsd/board.c +++ b/mbbsd/board.c @@ -1343,7 +1343,8 @@ set_menu_BM(char *BM) { if (!HasUserPerm(PERM_NOCITIZEN) && (HasUserPerm(PERM_ALLBOARD) || is_uBM(BM, cuser.userid))) { currmode |= MODE_GROUPOP; - cuser.userlevel |= PERM_SYSSUBOP | PERM_BM; + // XXX 不是很確定是否該在這邊 save level? + pwcuBitEnableLevel(PERM_SYSSUBOP | PERM_BM); } } @@ -1599,7 +1600,7 @@ choose_board(int newflag) fav_sort_by_class(); } else - cuser.uflag ^= BRDSORT_FLAG; + pwcuToggleSortBoard(); brdnum = -1; break; diff --git a/mbbsd/cache.c b/mbbsd/cache.c index e56c162a..cac2135c 100644 --- a/mbbsd/cache.c +++ b/mbbsd/cache.c @@ -160,7 +160,7 @@ int is_BM_cache(int bid) /* bid starts from 1 */ { // auto enable BM permission if (!HasUserPerm(PERM_BM)) - cuser.userlevel |= PERM_BM; + pwcuBitEnableLevel(PERM_BM); return 1; } return 0; diff --git a/mbbsd/cal.c b/mbbsd/cal.c index 2e3b441a..c920aeb1 100644 --- a/mbbsd/cal.c +++ b/mbbsd/cal.c @@ -84,10 +84,7 @@ vice(int money, const char *item) static int inmailbox(int m) { - userec_t xuser; - passwd_sync_query(usernum, &xuser); - cuser.exmailbox = xuser.exmailbox + m; - passwd_sync_update(usernum, &cuser); + pwcuAddExMailBox(m); return cuser.exmailbox; } @@ -405,7 +402,7 @@ resolve_over18_user(const userec_t *u) void resolve_over18(void) { - over18 = resolve_over18_user(&cuser); + over18 = resolve_over18_user(cuser_ref); } int diff --git a/mbbsd/calendar.c b/mbbsd/calendar.c index dad8bc46..a8c63eb3 100644 --- a/mbbsd/calendar.c +++ b/mbbsd/calendar.c @@ -31,22 +31,44 @@ Days(int y, int m, int d) } /** - * return 1 if date is invalid + * return 1 if date and time is invalid */ -int ParseDate(const char *date, int *year, int *month, int *day) +int ParseDateTime(const char *date, int *year, int *month, int *day, + int *hour, int *min, int *sec) { - char *y, *m, *d; + char *y, *m, *d, *hh, *mm, *ss; char buf[128]; char *strtok_pos; strlcpy(buf, date, sizeof(buf)); y = strtok_r(buf, "/", &strtok_pos); if (!y) return 1; m = strtok_r(NULL, "/", &strtok_pos);if (!m) return 1; - d = strtok_r(NULL, "", &strtok_pos); if (!d) return 1; + d = strtok_r(NULL, " ", &strtok_pos); if (!d) return 1; + + if (hour) { + hh = strtok_r(NULL, ":", &strtok_pos); + if (!hh) return 1; + *hour = atoi(hh); + } + if (min ) { + mm = strtok_r(NULL, ":", &strtok_pos); + if (!mm) return 1; + *min = atoi(mm); + } + if (sec ) { + ss = strtok_r(NULL, "", &strtok_pos); + if (!ss) return 1; + *sec = atoi(ss); + } *year = atoi(y); *month = atoi(m); *day = atoi(d); + + if (hour && (*hour < 0 || *hour > 23)) return 1; + if (min && (*min < 0 || *min > 59)) return 1; + if (sec && (*sec < 0 || *sec > 59)) return 1; + if (*year < 1 || *month < 1 || *month > 12 || *day < 1 || *day > MonthDay(*month, is_leap_year(*year))) return 1; @@ -56,6 +78,14 @@ int ParseDate(const char *date, int *year, int *month, int *day) /** * return 1 if date is invalid */ +int ParseDate(const char *date, int *year, int *month, int *day) +{ + return ParseDateTime(date, year, month, day, NULL, NULL, NULL); +} + +/** + * return 1 if date is invalid + */ static int ParseEventDate(const char *date, event_t * t) { diff --git a/mbbsd/card.c b/mbbsd/card.c index 5735c4c6..48f29b98 100644 --- a/mbbsd/card.c +++ b/mbbsd/card.c @@ -441,28 +441,6 @@ game_log(int type, int money) if (money > 0) card_add_money(money); - // if the money is not real user money, no need to log anymore. -#if 0 - FILE *fp; - - switch (type) { - case JACK: - fp = fopen(BBSHOME "/etc/card/jack.log", "a"); - if (!fp) - return 0; - fprintf(fp, "%s win:%d\n", cuser.userid, money); - fclose(fp); - break; - case TEN_HALF: - fp = fopen(BBSHOME "/etc/card/tenhalf.log", "a"); - if (!fp) - return 0; - fprintf(fp, "%s win:%d\n", cuser.userid, money); - fclose(fp); - break; - } -#endif - return 0; } diff --git a/mbbsd/ch_go.c b/mbbsd/ch_go.c index 9c7256cd..308061b8 100644 --- a/mbbsd/ch_go.c +++ b/mbbsd/ch_go.c @@ -793,35 +793,14 @@ go_post_game(ChessInfo* info) } static void -go_usr_put(userec_t* userec, const ChessUser* user) -{ - userec->go_win = user->win; - userec->go_lose = user->lose; - userec->go_tie = user->tie; -} - -static void go_gameend(ChessInfo* info, ChessGameResult result) { if (info->mode == CHESS_MODE_VERSUS) { - ChessUser* const user1 = &info->user1; - /* ChessUser* const user2 = &info->user2; */ - - user1->lose--; - if (result == CHESS_RESULT_WIN) { - user1->win++; - currutmp->go_win++; - } else if (result == CHESS_RESULT_LOST) { - user1->lose++; - currutmp->go_lose++; - } else { - user1->tie++; - currutmp->go_tie++; - } - go_usr_put(&cuser, user1); + // lost was already initialized + if (result != CHESS_RESULT_LOST) + pwcuChessResult(SIG_GO, result); - passwd_sync_update(usernum, &cuser); } else if (info->mode == CHESS_MODE_REPLAY) { free(info->board); free(info->tag); @@ -936,9 +915,7 @@ gochess(int s, ChessGameMode mode) if (info->mode == CHESS_MODE_VERSUS) { /* Assume that info->user1 is me. */ info->user1.lose++; - passwd_sync_query(usernum, &cuser); - go_usr_put(&cuser, &info->user1); - passwd_sync_update(usernum, &cuser); + pwcuChessResult(SIG_GO, CHESS_RESULT_LOST); } if (mode == CHESS_MODE_WATCH) diff --git a/mbbsd/ch_gomo.c b/mbbsd/ch_gomo.c index b8a74cb6..fb1a4182 100644 --- a/mbbsd/ch_gomo.c +++ b/mbbsd/ch_gomo.c @@ -230,14 +230,6 @@ gomo_move_warn(int style, char buf[]) return NULL; } -static void -gomoku_usr_put(userec_t* userec, const ChessUser* user) -{ - userec->five_win = user->win; - userec->five_lose = user->lose; - userec->five_tie = user->tie; -} - static char* gomo_getstep(const gomo_step_t* step, char buf[]) { @@ -395,24 +387,11 @@ static void gomo_gameend(ChessInfo* info, ChessGameResult result) { if (info->mode == CHESS_MODE_VERSUS) { - ChessUser* const user1 = &info->user1; - /* ChessUser* const user2 = &info->user2; */ - - user1->lose--; - if (result == CHESS_RESULT_WIN) { - user1->win++; - currutmp->five_win++; - } else if (result == CHESS_RESULT_LOST) { - user1->lose++; - currutmp->five_lose++; - } else { - user1->tie++; - currutmp->five_tie++; - } - gomoku_usr_put(&cuser, user1); + // lost was already initialized + if (result != CHESS_RESULT_LOST) + pwcuChessResult(SIG_GOMO, result); - passwd_sync_update(usernum, &cuser); } else if (info->mode == CHESS_MODE_REPLAY) { free(info->board); free(info->tag); @@ -535,9 +514,7 @@ gomoku(int s, ChessGameMode mode) if (info->mode == CHESS_MODE_VERSUS) { /* Assume that info->user1 is me. */ info->user1.lose++; - passwd_sync_query(usernum, &cuser); - gomoku_usr_put(&cuser, &info->user1); - passwd_sync_update(usernum, &cuser); + pwcuChessResult(SIG_GOMO, CHESS_RESULT_LOST); } if (mode == CHESS_MODE_WATCH) diff --git a/mbbsd/chat.c b/mbbsd/chat.c index e6a78842..9ce7d6c3 100644 --- a/mbbsd/chat.c +++ b/mbbsd/chat.c @@ -204,13 +204,15 @@ chat_query(char *arg) char buf[ANSILINELEN], *ptr; FILE *fp; - snprintf(buf, sizeof(buf), "%s(%s) 共上站 %d 次,發表過 %d 篇文章", + snprintf(buf, sizeof(buf), + "%s(%s) " STR_LOGINDAYS " %d " STR_LOGINDAYS_QTY ",發表過 %d 篇文章", xuser.userid, xuser.nickname, - xuser.numlogins, xuser.numposts); + xuser.numlogindays, xuser.numposts); printchatline(buf); snprintf(buf, sizeof(buf), - "最近(%s)從[%s]上站", Cdate(&xuser.lastlogin), + "最近(%s)從[%s]上站", + Cdate(xuser.lastseen ? &xuser.lastseen : &xuser.lastlogin), (xuser.lasthost[0] ? xuser.lasthost : "(不詳)")); printchatline(buf); diff --git a/mbbsd/chc.c b/mbbsd/chc.c index b250a01e..6d4a2f4e 100644 --- a/mbbsd/chc.c +++ b/mbbsd/chc.c @@ -658,15 +658,6 @@ chc_ischeck(board_t board, int turn) */ static void -chcusr_put(userec_t* userec, const ChessUser* user) -{ - userec->chc_win = user->win; - userec->chc_lose = user->lose; - userec->chc_tie = user->tie; - userec->chess_elo_rating = user->rating; -} - -static void chc_init_user(const userinfo_t *uinfo, ChessUser *user) { strlcpy(user->userid, uinfo->userid, sizeof(user->userid)); @@ -848,9 +839,7 @@ chc(int s, ChessGameMode mode) /* Assume that info->user1 is me. */ info->user1.lose++; count_chess_elo_rating(&info->user1, &info->user2, 0.0); - passwd_sync_query(usernum, &cuser); - chcusr_put(&cuser, &info->user1); - passwd_sync_update(usernum, &cuser); + pwcuChessResult(SIG_CHC, CHESS_RESULT_LOST); } if (mode == CHESS_MODE_WATCH) @@ -876,36 +865,38 @@ chc_gameend(ChessInfo* info, ChessGameResult result) /* NOTE, 若紅方斷線則無 log */ time_t t = time(NULL); char buf[100]; + uint16_t lose1 = user1->lose, lose2 = user2->lose; + if (lose1 > 0) lose1--; + if (lose2 > 0) lose2--; sprintf(buf, "%s %s(%d,W%d/D%d/L%d) %s %s(%d,W%d/D%d/L%d)\n", ctime(&t), user1->userid, user1->rating, user1->win, - user1->tie, user1->lose - 1, + user1->tie, lose1, (result == CHESS_RESULT_TIE ? "和" : result == CHESS_RESULT_WIN ? "勝" : "負"), user2->userid, user2->rating, user2->win, - user2->tie, user2->lose - 1); + user2->tie, lose2); buf[24] = ' '; // replace '\n' log_file(BBSHOME "/log/chc.log", LOG_CREAT, buf); } + // lost was already initialized + if (result != CHESS_RESULT_LOST) + pwcuChessResult(SIG_CHC, result); + user1->rating = user1->orig_rating; - user1->lose--; + + // TODO update and save the elo rating if (result == CHESS_RESULT_WIN) { count_chess_elo_rating(user1, user2, 1.0); - user1->win++; - currutmp->chc_win++; } else if (result == CHESS_RESULT_LOST) { count_chess_elo_rating(user1, user2, 0.0); - user1->lose++; - currutmp->chc_lose++; } else { count_chess_elo_rating(user1, user2, 0.5); - user1->tie++; - currutmp->chc_tie++; } currutmp->chess_elo_rating = user1->rating; - chcusr_put(&cuser, user1); - passwd_sync_update(usernum, &cuser); + pwcuSetChessEloRating(user1->rating); + } else if (info->mode == CHESS_MODE_REPLAY) { free(info->board); free(info->tag); diff --git a/mbbsd/chess.c b/mbbsd/chess.c index 7c58b6a8..11cb2a6f 100644 --- a/mbbsd/chess.c +++ b/mbbsd/chess.c @@ -1441,7 +1441,7 @@ ChessPhotoInitial(ChessInfo* info) switch (line) { case 0: sprintf(genbuf, " <代號> %s", xuser.userid); break; case 1: sprintf(genbuf, " <暱稱> %.16s", xuser.nickname); break; - case 2: sprintf(genbuf, " <上站> %d", xuser.numlogins); break; + case 2: sprintf(genbuf, " <上站> %d", xuser.numlogindays); break; case 3: sprintf(genbuf, " <文章> %d", xuser.numposts); break; case 4: sprintf(genbuf, " <職位> %-4s %s", country, level); break; case 5: sprintf(genbuf, " <來源> %.16s", xuser.lasthost); break; @@ -1494,7 +1494,7 @@ ChessPhotoInitial(ChessInfo* info) switch (line - 9) { case 0: sprintf(PHOTO(line), "<代號> %-16.16s ", xuser.userid); break; case 1: sprintf(PHOTO(line), "<暱稱> %-16.16s ", xuser.nickname); break; - case 2: sprintf(PHOTO(line), "<上站> %-16d ", xuser.numlogins); break; + case 2: sprintf(PHOTO(line), "<上站> %-16d ", xuser.numlogindays); break; case 3: sprintf(PHOTO(line), "<文章> %-16d ", xuser.numposts); break; case 4: sprintf(PHOTO(line), "<職位> %-4s %-10s ", country, level); break; case 5: sprintf(PHOTO(line), "<來源> %-16.16s ", xuser.lasthost); break; diff --git a/mbbsd/edit.c b/mbbsd/edit.c index 78a3e83a..d262f90e 100644 --- a/mbbsd/edit.c +++ b/mbbsd/edit.c @@ -1741,7 +1741,7 @@ browse_sigs: ch = buf[0]; else ch = '1' + random() % (si.max+1); - cuser.signature = buf[0]; + pwcuSetSignature(buf[0]); if (ch != '0') { fpath[i] = ch; diff --git a/mbbsd/kaede.c b/mbbsd/kaede.c index 5a5545e5..628f51df 100644 --- a/mbbsd/kaede.c +++ b/mbbsd/kaede.c @@ -30,7 +30,7 @@ expand_esc_star(char *buf, const char *src, int szbuf) strlcpy(buf, cuser.nickname, szbuf); return 2; case 'l': // current user logins - snprintf(buf, szbuf, "%d", cuser.numlogins); + snprintf(buf, szbuf, "%d", cuser.numlogindays); return 2; case 'p': // current user posts snprintf(buf, szbuf, "%d", cuser.numposts); diff --git a/mbbsd/mail.c b/mbbsd/mail.c index f64f7269..96b2259f 100644 --- a/mbbsd/mail.c +++ b/mbbsd/mail.c @@ -1401,8 +1401,7 @@ mail_edit(int ent GCC_UNUSED, fileheader_t * fhdr, const char *direct) static int mail_nooutmail(int ent GCC_UNUSED, fileheader_t * fhdr GCC_UNUSED, const char *direct GCC_UNUSED) { - cuser.uflag2 ^= REJ_OUTTAMAIL; - passwd_sync_update(usernum, &cuser); + pwcuToggleOutMail(); return FULLUPDATE; } diff --git a/mbbsd/mbbsd.c b/mbbsd/mbbsd.c index 45ebce20..f10bec3d 100644 --- a/mbbsd/mbbsd.c +++ b/mbbsd/mbbsd.c @@ -190,15 +190,6 @@ log_usies(const char *mode, const char *mesg) } -static void -setflags(int mask, int value) -{ - if (value) - cuser.uflag |= mask; - else - cuser.uflag &= ~mask; -} - void u_exit(const char *mode) { @@ -210,27 +201,15 @@ u_exit(const char *mode) // verify if utmp is valid. only flush data if utmp is correct. assert(strncmp(currutmp->userid,cuser.userid, IDLEN)==0); - if(strncmp(currutmp->userid,cuser.userid, IDLEN)!=0) + if(strncmp(currutmp->userid, cuser.userid, IDLEN)!=0) return; auto_backup(); save_brdbuf(); brc_finalize(); - /* - cuser.goodpost = currutmp->goodpost; - cuser.badpost = currutmp->badpost; - */ - - // no need because in later passwd_sync_update will reload money from SHM. - // reload_money(); - setflags(PAGER_FLAG, currutmp->pager != PAGER_ON); - setflags(CLOAK_FLAG, currutmp->invisible); - - cuser.invisible = currutmp->invisible; - cuser.withme = currutmp->withme; - cuser.pager = currutmp->pager; - memcpy(cuser.mind, currutmp->mind, 4); + // XXX TOTO for guests, skip the save process? + pwcuExitSave(); setutmpbid(0); if (!SHM->GV2.e.shutdown) { @@ -239,11 +218,6 @@ u_exit(const char *mode) do_aloha("<<下站通知>> -- 我走囉!"); } - // 小於 60 秒不計 login 次數 - if (time(0) - login_start_time < 60 && cuser.numlogins > 0) - --cuser.numlogins; - - passwd_sync_update(usernum, &cuser); purge_utmp(currutmp); log_usies(mode, NULL); } @@ -368,7 +342,7 @@ signal_xcpu_handler(int sig) last_time_exceeded = login_start_time; assert(last_time_exceeded); // 不用 (time(0) - login_start_time) 來平均, 避免用好幾天之後突然狂吃 cpu 的狀況. - if (time(0) - last_time_exceeded < 86400) + if (time(0) - last_time_exceeded < DAY_SECONDS) give_more_time = false; last_time_exceeded = time(0); @@ -739,13 +713,7 @@ load_current_user(const char *uid) if (strcasecmp(uid, STR_GUEST) == 0) { if (initcuser(STR_GUEST)< 1) exit (0) ; - cuser.userlevel = 0; - cuser.uflag = PAGER_FLAG | BRDSORT_FLAG | MOVIE_FLAG; - cuser.uflag2= 0; // we don't need FAVNEW_FLAG or anything else. - -# ifdef GUEST_DEFAULT_DBCS_NOINTRESC - cuser.uflag |= DBCS_NOINTRESC; -# endif + pwcuInitGuestPerm(); // can we prevent mkuserdir() here? mkuserdir(cuser.userid); } else @@ -763,11 +731,7 @@ load_current_user(const char *uid) exit(0); #else /* 自動加上各個主要權限 */ // TODO only allow in local connection? - cuser.userlevel = PERM_BASIC | PERM_CHAT | PERM_PAGE | - PERM_POST | PERM_LOGINOK | PERM_MAILLIMIT | - PERM_CLOAK | PERM_SEECLOAK | PERM_XEMPT | - PERM_SYSOPHIDE | PERM_BM | PERM_ACCOUNTS | - PERM_CHATROOM | PERM_BOARD | PERM_SYSOP | PERM_BBSADM; + pwcuInitAdminPerm(); #endif } /* 早該有 home 了, 不知道為何有的帳號會沒有, 被砍掉了? */ @@ -811,7 +775,7 @@ login_query(char *ruid) sleep(3); exit(1); } - bzero(&cuser, sizeof(cuser)); + pwcuInitZero(); #ifdef DEBUG move(19, 0); @@ -1022,14 +986,15 @@ where(const char *from) static void check_BM(void) { - /* XXX: -_- */ - int i; + int i; - cuser.userlevel &= ~PERM_BM; + assert(HasUserPerm(PERM_BM)); for( i = 0 ; i < numboards ; ++i ) if( is_BM_cache(i + 1) ) /* XXXbid */ return; - //for (i = 0, bhdr = bcache; i < numboards && !is_BM(bhdr->BM); i++, bhdr++); + + // disable BM permission + pwcuBitDisableLevel(PERM_BM); } static void @@ -1067,10 +1032,10 @@ setup_utmp(int mode) uinfo.go_tie = cuser.go_tie; uinfo.invisible = cuser.invisible % 2; uinfo.pager = cuser.pager % PAGER_MODES; + uinfo.withme = cuser.withme & ~WITHME_ALLFLAG; if(cuser.withme & (cuser.withme<<1) & (WITHME_ALLFLAG<<1)) - cuser.withme = 0; /* unset all if contradict */ - uinfo.withme = cuser.withme & ~WITHME_ALLFLAG; + uinfo.withme = 0; getnewutmpent(&uinfo); @@ -1084,11 +1049,6 @@ setup_utmp(int mode) strip_nonebig5((unsigned char *)currutmp->nickname, sizeof(currutmp->nickname)); strip_nonebig5((unsigned char *)currutmp->mind, sizeof(currutmp->mind)); - // XXX 不用每 20 才檢查吧 - // XXX 這個 check 花不少時間,有點間隔比較好 - if ((cuser.userlevel & PERM_BM) && !(cuser.numlogins % 20)) - check_BM(); /* Ptt 自動取下離職板主權力 */ - // resolve fromhost #if defined(WHERE) @@ -1125,15 +1085,14 @@ setup_utmp(int mode) inline static void welcome_msg(void) { - prints(ANSI_RESET " 歡迎您第 " - ANSI_COLOR(1;33) "%d" ANSI_COLOR(0;37) " 度拜訪本站,上次您是從 " + prints(ANSI_RESET " 歡迎您再度拜訪本站,上次您是從 " ANSI_COLOR(1;33) "%s" ANSI_COLOR(0;37) " 連往本站," ANSI_CLRTOEND "\n" " 我記得那天是 " ANSI_COLOR(1;33) "%s" ANSI_COLOR(0;37) "。" ANSI_CLRTOEND "\n" ANSI_CLRTOEND "\n" , - cuser.numlogins, cuser.lasthost, Cdate(&(cuser.lastlogin))); + cuser.lasthost, Cdate(&(cuser.lastlogin))); pressanykey(); } @@ -1181,11 +1140,6 @@ inline static void birthday_make_a_wish(const struct tm *ptime, const struct tm } } -inline static void record_lasthost(const char *fromhost) -{ - strlcpy(cuser.lasthost, fromhost, sizeof(cuser.lasthost)); -} - inline static void check_mailbox_quota(void) { if (chkmailbox()) @@ -1194,31 +1148,7 @@ inline static void check_mailbox_quota(void) static void init_guest_info(void) { - int i; - char *nick[13] = { - "椰子", "貝殼", "內衣", "寶特瓶", "翻車魚", - "樹葉", "浮萍", "鞋子", "潛水艇", "魔王", - "鐵罐", "考卷", "大美女" - }; - char *name[13] = { - "大王椰子", "鸚鵡螺", "比基尼", "可口可樂", "仰泳的魚", - "憶", "高岡屋", "AIR Jordon", "紅色十月號", "批踢踢", - "SASAYA椰奶", "鴨蛋", "布魯克鱈魚香絲" - }; - char *addr[13] = { - "天堂樂園", "大海", "綠島小夜曲", "美國", "綠色珊瑚礁", - "遠方", "原本海", "NIKE", "蘇聯", "男八618室", - "愛之味", "天上", "藍色珊瑚礁" - }; - i = login_start_time % 13; - snprintf(cuser.nickname, sizeof(cuser.nickname), - "海邊漂來的%s", nick[(int)i]); - strlcpy(currutmp->nickname, cuser.nickname, - sizeof(currutmp->nickname)); - strlcpy(cuser.realname, name[(int)i], sizeof(cuser.realname)); - strlcpy(cuser.address, addr[(int)i], sizeof(cuser.address)); - memset(cuser.mind, 0, sizeof(cuser.mind)); - cuser.sex = i % 8; + pwcuInitGuestInfo(); currutmp->pager = PAGER_DISABLE; } @@ -1229,7 +1159,7 @@ inline static void foreign_warning(void){ mail_muser(cuser, "[出入境管理局]", "etc/foreign_expired_warn"); } else if (login_start_time - cuser.firstlogin > FOREIGN_REG_DAY * 24 * 3600){ - cuser.userlevel &= ~(PERM_LOGINOK | PERM_POST); + pwcuBitDisableLevel(PERM_LOGINOK | PERM_POST); vmsg("警告:請至出入境管理局申請永久居留"); } } @@ -1251,8 +1181,6 @@ user_login(void) /* 初始化 uinfo、flag、mode */ setup_utmp(LOGIN); - if (cuser.userlevel) - ++cuser.numlogins; /* log usies */ log_usies("ENTER", fromhost); @@ -1326,11 +1254,17 @@ user_login(void) append_log_recent_login(); check_bad_login(); check_mailbox_quota(); - check_birthday(); check_register(); - record_lasthost(fromhost); + pwcuLoginSave(); // is_first_login_of_today is only valid after pwcuLoginSave. restore_backup(); + // XXX 這個 check 花不少時間,有點間隔比較好 + if (HasUserPerm(PERM_BM) && + (cuser.numlogindays % 10 == 0) && // when using numlogindays, check with is_first_login_of_today + is_first_login_of_today ) + check_BM(); /* 自動取下離職板主權力 */ + + } else if (strcmp(cuser.userid, STR_GUEST) == 0) { /* guest */ init_guest_info(); @@ -1356,34 +1290,19 @@ user_login(void) /* If you wanna do incremental upgrade * (like, added a function/flag that wants user to confirm againe) * put it here. + * But you must use 'lasttime' because cuser.lastlogin + * is already changed. */ -#if defined(DBCSAWARE) && defined(DBCSAWARE_UPGRADE_STARTTIME) - // define the real time you upgraded in your pttbbs.conf - if(cuser.lastlogin < DBCSAWARE_UPGRADE_STARTTIME) - { - if (u_detectDBCSAwareEvilClient()) - cuser.uflag &= ~DBCSAWARE_FLAG; - else - cuser.uflag |= DBCSAWARE_FLAG; - } -#endif /* login time update */ - if(ptime.tm_yday!=lasttime.tm_yday) STATINC(STAT_TODAYLOGIN_MIN); - - - cuser.lastlogin = login_start_time; - } #if FOREIGN_REG_DAY > 0 foreign_warning(); #endif - passwd_sync_update(usernum, &cuser); - if(cuser.uflag2 & FAVNEW_FLAG) { fav_load(); if (get_fav_root() != NULL) { diff --git a/mbbsd/menu.c b/mbbsd/menu.c index c9212224..069107b1 100644 --- a/mbbsd/menu.c +++ b/mbbsd/menu.c @@ -602,7 +602,6 @@ u_mylogs() return 0; } -int u_fixgoodpost(void); // assess.c void Customize(); // user.c static int @@ -629,7 +628,6 @@ static const commands_t userlist[] = { {u_register, MENU_UNREGONLY, "RRegister 填寫《註冊申請單》"}, #ifdef ASSESS {u_cancelbadpost,PERM_LOGINOK, "BBye BadPost 申請刪除劣文"}, - {u_fixgoodpost, PERM_LOGINOK, "FFix GoodPost 修復優文"}, #endif // ASSESS {NULL, 0, NULL} }; diff --git a/mbbsd/ordersong.c b/mbbsd/ordersong.c index 8d41103d..477b85f1 100644 --- a/mbbsd/ordersong.c +++ b/mbbsd/ordersong.c @@ -147,7 +147,7 @@ do_order_song(void) log_filef("etc/osong.log", LOG_CREAT, "id: %-12s ◇ %s 點給 %s : \"%s\", 轉寄至 %s\n", cuser.userid, sender, receiver, say, address); if (append_record(OSONGPATH "/" FN_DIR, &mail, sizeof(mail)) != -1) { - cuser.lastsong = now; + pwcuSetLastSongTime(now); /* Jaky 超過 MAX_MOVIE 首歌就開始砍 */ // XXX 載入的順序會長得像是: // 3. ◆ <系統> 動態看板 SYSOP [01/23/08] diff --git a/mbbsd/passwd.c b/mbbsd/passwd.c index 405e5d7c..658e7dce 100644 --- a/mbbsd/passwd.c +++ b/mbbsd/passwd.c @@ -1,97 +1,620 @@ /* $Id$ */ +#define PWCU_IMPL #include "bbs.h" +#include "time.h" #ifdef _BBS_UTIL_C_ #error sorry, mbbsd/passwd.c does not support utility mode anymore. please use libcmbbs instead. #endif -static uint32_t latest_numposts; - -void -passwd_force_update(int flag) -{ - if(!currutmp || (currutmp->alerts & ALERT_PWD) == 0) - return; - currutmp->alerts &= ~flag; -} +#ifndef NO_CONST_CUSER + #undef cuser + #define cuser pwcuser +#endif int initcuser(const char *userid) { usernum = passwd_load_user(userid, &cuser); - latest_numposts = cuser.numposts; return usernum; } -// XXX I don't like the stupid synchronization here, -// but simply following previous work here... int passwd_sync_update(int num, userec_t * buf) { - int alerts; - if (num < 1 || num > MAX_USERS) return -1; // money update should be done before everything. buf->money = moneyof(num); + if (passwd_update(num, buf) != 0) + return -1; - if(usernum == num && currutmp && ((alerts = currutmp->alerts) & ALERT_PWD)) - { - userec_t u; - if (passwd_sync_query(num, &u) != 0) - return -1; + return 0; +} - if(alerts & ALERT_PWD_BADPOST) - cuser.badpost = buf->badpost = u.badpost; - if(alerts & ALERT_PWD_GOODPOST) - cuser.goodpost = buf->goodpost = u.goodpost; - if(alerts & ALERT_PWD_PERM) - cuser.userlevel = buf->userlevel = u.userlevel; - if(alerts & ALERT_PWD_JUSTIFY) - { - memcpy(buf->justify, u.justify, sizeof(u.justify)); - memcpy(cuser.justify, u.justify, sizeof(u.justify)); - memcpy(buf->email, u.email, sizeof(u.email)); - memcpy(cuser.email, u.email, sizeof(u.email)); - } - cuser.numposts += u.numposts - latest_numposts; - // XXX bad workaround - but.... let's use it until we've solved the sync issue - if ((int)cuser.numposts < 0) - cuser.numposts = 0; - currutmp->alerts &= ~ALERT_PWD; - - // ALERT_PWD_RELOAD: reload all! No need to write. - if (alerts & ALERT_PWD_RELOAD) - { - memcpy(&cuser, &u, sizeof(u)); - return 0; - } - } +int +passwd_sync_query(int num, userec_t * buf) +{ + if (passwd_query(num, buf) < 0) + return -1; - if (passwd_update(num, buf) != 0) + buf->money = moneyof(num); + return 0; +} + +// pwcu*: current user password helpers + +static int +pwcuInitCUser(userec_t *u) +{ + assert(usernum > 0 && usernum <= MAX_USERS); + if (passwd_query(usernum, u) != 0) + return -1; + assert(strncmp(u->userid, cuser.userid, IDLEN) == 0); + if (strncmp(u->userid, cuser.userid, IDLEN) != 0) + return -1; + return 0; +} + +static int +pwcuFinalCUser(userec_t *u) +{ + assert(usernum > 0 && usernum <= MAX_USERS); + assert(strcmp(u->userid, cuser.userid) == 0); + if (passwd_update(usernum, u) != 0) + return -1; + return 0; +} + +#define PWCU_START() userec_t u; if(pwcuInitCUser (&u) != 0) return -1 +#define PWCU_END() if (pwcuFinalCUser(&u) != 0) return -1; return 0 + +#define _ENABLE_BIT( var,mask) var |= (mask) +#define _DISABLE_BIT(var,mask) var &= ~(mask) +#define _SETBY_BIT(var,mask,val) if (val) { _ENABLE_BIT(var, (mask)); } else { _DISABLE_BIT(var, (mask)); } + +int pwcuBitEnableLevel (unsigned int mask) +{ + PWCU_START(); + _ENABLE_BIT( u.userlevel, mask); + _ENABLE_BIT(cuser.userlevel, mask); + PWCU_END(); +} + +int pwcuBitDisableLevel (unsigned int mask) +{ + PWCU_START(); + _DISABLE_BIT( u.userlevel, mask); + _DISABLE_BIT(cuser.userlevel, mask); + PWCU_END(); +} + +int +pwcuIncNumPost() +{ + PWCU_START(); + cuser.numposts = ++u.numposts; + PWCU_END(); +} + +int +pwcuDecNumPost() +{ + PWCU_START(); + if (u.numposts > 0) + u.numposts--; + cuser.numposts = u.numposts; + PWCU_END(); +} + +int +pwcuViolateLaw () +{ + PWCU_START(); + _ENABLE_BIT( u.userlevel, PERM_VIOLATELAW); + _ENABLE_BIT(cuser.userlevel, PERM_VIOLATELAW); + u.timeviolatelaw = now; + cuser.timeviolatelaw = u.timeviolatelaw; + u.vl_count++; + cuser.vl_count = u.vl_count; + PWCU_END(); +} + +int +pwcuSaveViolateLaw() +{ + PWCU_START(); + _DISABLE_BIT( u.userlevel, PERM_VIOLATELAW); + _DISABLE_BIT(cuser.userlevel, PERM_VIOLATELAW); + PWCU_END(); +} + +int +pwcuCancelBadpost() +{ + int day; + PWCU_START(); + + // check timebomb again + day = (now - u.timeremovebadpost ) / DAY_SECONDS; + if (day <= 180) + return -1; + if (u.badpost < 1) return -1; - if (currutmp && usernum > 0 && - latest_numposts != cuser.numposts) + cuser.badpost = --u.badpost; + cuser.timeremovebadpost = u.timeremovebadpost = now; + + PWCU_END(); +} + +int +pwcuAddExMailBox(int m) +{ + PWCU_START(); + u.exmailbox += m; + cuser.exmailbox = u.exmailbox; + PWCU_END(); +} + +int pwcuSetLastSongTime (time4_t clk) +{ + PWCU_START(); + u.lastsong = clk; + cuser.lastsong = clk; + PWCU_END(); +} + +int pwcuSetMyAngel (const char *angel_uid) +{ + PWCU_START(); + strlcpy( u.myangel, angel_uid, sizeof( u.myangel)); + strlcpy(cuser.myangel, angel_uid, sizeof(cuser.myangel)); + PWCU_END(); +} + +int pwcuSetNickname (const char *nickname) +{ + PWCU_START(); + strlcpy( u.nickname, nickname, sizeof( u.nickname)); + strlcpy(cuser.nickname, nickname, sizeof(cuser.nickname)); + PWCU_END(); +} + +int +pwcuToggleOutMail() +{ + PWCU_START(); + u.uflag2 ^= REJ_OUTTAMAIL; + _SETBY_BIT(cuser.uflag2, REJ_OUTTAMAIL, + u.uflag2 & REJ_OUTTAMAIL); + PWCU_END(); +} + +int +pwcuSetLoginView(unsigned int bits) +{ + PWCU_START(); + u.loginview = bits; + cuser.loginview = u.loginview; + PWCU_END(); +} + +int +pwcuRegCompleteJustify(const char *justify) +{ + PWCU_START(); + strlcpy( u.justify, justify, sizeof(u.justify)); + strlcpy(cuser.justify, justify, sizeof(cuser.justify)); + _ENABLE_BIT( u.userlevel, (PERM_POST | PERM_LOGINOK)); + _ENABLE_BIT(cuser.userlevel, (PERM_POST | PERM_LOGINOK)); + PWCU_END(); +} + +int +pwcuRegSetTemporaryJustify(const char *justify, const char *email) +{ + PWCU_START(); + strlcpy( u.email, email, sizeof(u.email)); + strlcpy(cuser.email, email, sizeof(cuser.email)); + strlcpy( u.justify, justify, sizeof(u.justify)); + strlcpy(cuser.justify, justify, sizeof(cuser.justify)); + _DISABLE_BIT( u.userlevel, (PERM_POST | PERM_LOGINOK)); + _DISABLE_BIT(cuser.userlevel, (PERM_POST | PERM_LOGINOK)); + PWCU_END(); +} + +int pwcuRegisterSetInfo (const char *rname, + const char *addr, + const char *career, + const char *phone, + const char *email, + int mobile, + uint8_t sex, + uint8_t year, + uint8_t month, + uint8_t day, + uint8_t is_foreign) +{ + PWCU_START(); + strlcpy(u.realname, rname, sizeof(u.realname)); + strlcpy(u.address, addr, sizeof(u.address)); + strlcpy(u.career, career, sizeof(u.career)); + strlcpy(u.phone, phone, sizeof(u.phone)); + strlcpy(u.email, email, sizeof(u.email)); + u.mobile = mobile; + u.sex = sex; + u.year = year; + u.month = month; + u.day = day; + _SETBY_BIT(u.uflag2, FOREIGN, is_foreign); + + // duplicate to cuser + + strlcpy(cuser.realname, rname, sizeof(cuser.realname)); + strlcpy(cuser.address, addr, sizeof(cuser.address)); + strlcpy(cuser.career, career, sizeof(cuser.career)); + strlcpy(cuser.phone, phone, sizeof(cuser.phone)); + strlcpy(cuser.email, email, sizeof(cuser.email)); + cuser.mobile = mobile; + cuser.sex = sex; + cuser.year = year; + cuser.month = month; + cuser.day = day; + _SETBY_BIT(cuser.uflag2, FOREIGN, is_foreign); + + PWCU_END(); +} + +#include "chess.h" +int +pwcuChessResult(int sigType, ChessGameResult r) +{ + uint16_t *utmp_win = NULL, *cuser_win = NULL, *u_win = NULL, + *utmp_lose= NULL, *cuser_lose= NULL, *u_lose= NULL, + *utmp_tie = NULL, *cuser_tie = NULL, *u_tie = NULL; + + PWCU_START(); + + // verify variable size + assert(sizeof(* utmp_win) == sizeof(currutmp->chc_win)); + assert(sizeof(*cuser_lose)== sizeof( cuser.five_lose)); + assert(sizeof(* u_tie) == sizeof( u.go_tie)); + + // determine variables + switch(sigType) { - sendalert_uid(usernum, ALERT_PWD_POSTS); - latest_numposts = cuser.numposts; + case SIG_CHC: + utmp_win = &(currutmp->chc_win); + utmp_lose = &(currutmp->chc_lose); + utmp_tie = &(currutmp->chc_tie); + cuser_win = &( cuser.chc_win); + cuser_lose= &( cuser.chc_lose); + cuser_tie = &( cuser.chc_tie); + u_win = &( u.chc_win); + u_lose = &( u.chc_lose); + u_tie = &( u.chc_tie); + break; + + case SIG_GO: + utmp_win = &(currutmp->go_win); + utmp_lose = &(currutmp->go_lose); + utmp_tie = &(currutmp->go_tie); + cuser_win = &( cuser.go_win); + cuser_lose= &( cuser.go_lose); + cuser_tie = &( cuser.go_tie); + u_win = &( u.go_win); + u_lose = &( u.go_lose); + u_tie = &( u.go_tie); + break; + + case SIG_GOMO: + utmp_win = &(currutmp->five_win); + utmp_lose = &(currutmp->five_lose); + utmp_tie = &(currutmp->five_tie); + cuser_win = &( cuser.five_win); + cuser_lose= &( cuser.five_lose); + cuser_tie = &( cuser.five_tie); + u_win = &( u.five_win); + u_lose = &( u.five_lose); + u_tie = &( u.five_tie); + break; + + default: + assert(!"unknown sigtype"); + break; } - return 0; + // perform action + switch(r) + { + case CHESS_RESULT_WIN: + *utmp_win = *cuser_win = + ++(*u_win); + // recover init lose + if (*u_lose > 0) + *utmp_lose = *cuser_lose = + --(*u_lose); + break; + + case CHESS_RESULT_TIE: + *utmp_tie = *cuser_tie = + ++*u_tie; + // recover init lose + if (*u_lose > 0) + *utmp_lose = *cuser_lose = + --(*u_lose); + break; + + case CHESS_RESULT_LOST: + *utmp_lose = *cuser_lose = + ++(*u_lose); + break; + + default: + assert(!"unknown result"); + return -1; + } + + PWCU_END(); +} + +int +pwcuSetChessEloRating(uint16_t elo_rating) +{ + PWCU_START(); + cuser.chess_elo_rating = u.chess_elo_rating = elo_rating; + PWCU_END(); } -// XXX I don't like the stupid synchronization here, -// but simply following previous work here... +int +pwcuSaveUserFlags() +{ + PWCU_START(); + u.uflag = cuser.uflag; + u.uflag2 = cuser.uflag2; + PWCU_END(); +} + +// non-important variables (only save on exit) + int -passwd_sync_query(int num, userec_t * buf) +pwcuSetSignature(unsigned char newsig) { - if (passwd_query(num, buf) < 0) - return -1; + // XXX you MUST save this variable in pwcuExitSave(); + cuser.signature = newsig; + return 0; +} + +int +pwcuSetWaterballMode(unsigned int bm) +{ + // XXX you MUST save this variable in pwcuExitSave(); + bm &= WATER_MASK; + cuser.uflag2 &= ~WATER_MASK; + cuser.uflag2 |= bm; + return 0; +} + +int +pwcuToggleSortBoard () +{ + // XXX you MUST save this variable in pwcuExitSave(); + cuser.uflag ^= BRDSORT_FLAG; + return 0; +} + +int +pwcuToggleFriendList() +{ + // XXX you MUST save this variable in pwcuExitSave(); + cuser.uflag ^= FRIEND_FLAG; + return 0; +} - if (buf == &cuser) - latest_numposts = cuser.numposts; +int +pwcuToggleUserFlag (unsigned int mask) +{ + // XXX you MUST save this variable in pwcuExitSave(); + cuser.uflag ^= mask; + return 0; +} +int +pwcuToggleUserFlag2 (unsigned int mask) +{ + // XXX you MUST save this variable in pwcuExitSave(); + cuser.uflag2 ^= mask; return 0; } + +// session save + +// XXX this is a little different - only invoked at login, +// which we should update/calculate every variables to log. +int pwcuLoginSave () +{ + // XXX because LoginSave was called very long after + // login_start_time, so we must reload passwd again + // here to prevent race condition. + // If you want to remove this reload, make sure + // pwcuLoginSave is called AFTER login_start_time + // was decided. + int regdays = 0, prev_regdays = 0; + int reftime = login_start_time; + time4_t baseref = 0; + struct tm baseref_tm = {0}; + + PWCU_START(); + + // new host from 'fromhost' + strlcpy( u.lasthost, fromhost, sizeof( u.lasthost)); + strlcpy(cuser.lasthost, fromhost, sizeof(cuser.lasthost)); + + // this must be valid. + assert(login_start_time > 0); + + // adjust base reference by rounding to beginning of each day (0:00am) + baseref = u.firstlogin; + if (localtime4_r(&baseref, &baseref_tm)) + { + baseref_tm.tm_sec = baseref_tm.tm_min = baseref_tm.tm_hour = 0; + baseref = mktime(&baseref_tm); + } + + // invalid session? + if (reftime < u.lastlogin) + reftime = u.lastlogin; + + regdays = ( reftime - baseref) / DAY_SECONDS; + prev_regdays = (u.lastlogin - baseref) / DAY_SECONDS; + // assert(regdays >= prev_regdays); + + if (u.numlogindays > prev_regdays) + u.numlogindays = prev_regdays; + + // calculate numlogindays (only increase one per each key) + if (regdays > prev_regdays) + { + ++u.numlogindays; + is_first_login_of_today = 1; + } + cuser.numlogindays = u.numlogindays; + + // update last login time + cuser.lastlogin = u.lastlogin = reftime; + + if (!PERM_HIDE(currutmp)) + cuser.lastseen = u.lastseen = reftime; + + PWCU_END(); +} + +// XXX this is a little different - only invoked at exist, +// so no need to sync back to cuser. +int +pwcuExitSave () +{ + int dirty = 0; + uint32_t uflag, uflag2, withme; + uint8_t invisible, pager; + int32_t money; + + PWCU_START(); + + // save variables for dirty check + uflag = u.uflag; + uflag2= u.uflag2; + withme= u.withme; + pager = u.pager; + invisible = u.invisible; + money = u.money; + + // uflag and uflag2: always trust cuser except REJ_OUTTAMAIL + _SETBY_BIT(cuser.uflag2, REJ_OUTTAMAIL, (u.uflag2 & REJ_OUTTAMAIL)); + u.uflag = cuser.uflag; + u.uflag2= cuser.uflag2; + + _DISABLE_BIT(u.uflag, (PAGER_FLAG | CLOAK_FLAG)); + if (currutmp->pager != PAGER_ON) + _ENABLE_BIT(u.uflag, PAGER_FLAG); + if (currutmp->invisible) + _ENABLE_BIT(u.uflag, CLOAK_FLAG); + + u.invisible = currutmp->invisible; + u.withme = currutmp->withme; + u.pager = currutmp->pager; + u.money = moneyof(usernum); + + // XXX 當初設計的人把 mind 設計成非 NULL terminated 的... + // assert(sizeof(u.mind) == sizeof(currutmp->mind)); + if (memcmp(u.mind, currutmp->mind, sizeof(u.mind)) != 0) + { + memcpy(u.mind,currutmp->mind, sizeof(u.mind)); + dirty = 1; + } + + // check dirty + if (!dirty && ( + uflag != u.uflag || + uflag2 != u.uflag2|| + withme != u.withme|| + pager != u.pager || + money != u.money || + invisible != u.invisible)) + { + dirty = 1; + } + +#ifdef DEBUG + log_filef("log/pwcu_exitsave.log", LOG_CREAT, + "%s exit %s at %s\n", u.userid, + dirty ? "DIRTY" : "CLEAN", + Cdatelite(&now)); +#endif + + // no need to save data. + if (!dirty) + return 0; + + PWCU_END(); +} + +int +pwcuReload () +{ + int r = passwd_sync_query(usernum, &cuser); + // XXX TODO verify cuser structure? + return r; +} + +// Initialization + +void pwcuInitZero () +{ + bzero(&cuser, sizeof(cuser)); +} + +int pwcuInitAdminPerm () +{ + PWCU_START(); + cuser.userlevel = PERM_BASIC | PERM_CHAT | PERM_PAGE | + PERM_POST | PERM_LOGINOK | PERM_MAILLIMIT | + PERM_CLOAK | PERM_SEECLOAK | PERM_XEMPT | + PERM_SYSOPHIDE | PERM_BM | PERM_ACCOUNTS | + PERM_CHATROOM | PERM_BOARD | PERM_SYSOP | PERM_BBSADM; + PWCU_END(); +} + +void pwcuInitGuestPerm () +{ + cuser.userlevel = 0; + cuser.uflag = PAGER_FLAG | BRDSORT_FLAG | MOVIE_FLAG; + cuser.uflag2= 0; // we don't need FAVNEW_FLAG or anything else. +# ifdef GUEST_DEFAULT_DBCS_NOINTRESC + _ENABLE_BIT(cuser.uflag, DBCS_NOINTRESC); +# endif +} + +#undef DIM +#define DIM(x) (sizeof(x)/sizeof(x[0])) + +void pwcuInitGuestInfo () +{ + int i; + char *nick[] = { + "椰子", "貝殼", "內衣", "寶特瓶", "翻車魚", + "樹葉", "浮萍", "鞋子", "潛水艇", "魔王", + "鐵罐", "考卷", "大美女" + }; + + i = random() % DIM(nick); + snprintf(cuser.nickname, sizeof(cuser.nickname), + "海邊漂來的%s", nick[i]); + strlcpy(currutmp->nickname, cuser.nickname, + sizeof(currutmp->nickname)); + strlcpy(cuser.realname, "guest", sizeof(cuser.realname)); + memset (cuser.mind, 0, sizeof(cuser.mind)); + cuser.sex = i % 8; +} diff --git a/mbbsd/pmore.c b/mbbsd/pmore.c index 1968f557..4304b55e 100644 --- a/mbbsd/pmore.c +++ b/mbbsd/pmore.c @@ -594,7 +594,7 @@ expand_esc_star(char *buf, const char *src, int szbuf) strlcpy(buf, cuser.userid, szbuf); return 2; case 'l': // current user logins - snprintf(buf, szbuf, "%d", cuser.numlogins); + snprintf(buf, szbuf, "%d", cuser.numlogindays); return 2; case 'p': // current user posts snprintf(buf, szbuf, "%d", cuser.numposts); diff --git a/mbbsd/read.c b/mbbsd/read.c index 4dca75c4..4616cd62 100644 --- a/mbbsd/read.c +++ b/mbbsd/read.c @@ -87,14 +87,6 @@ Tagger(time4_t chrono, int recno, int mode) return YEA; } -#if 0 -static void -EnumTagName(char *fname, int locus) /* unused */ -{ - snprintf(fname, sizeof(fname), "M.%d.A", (int)TagList[locus].chrono); -} -#endif - void EnumTagFhdr(fileheader_t * fhdr, char *direct, int locus) { @@ -985,7 +977,7 @@ i_read_key(const onekey_t * rcmdlist, keeploc_t * locmem, if ((id = getuser(headers[locmem->crs_ln - locmem->top_ln].owner, &muser))) { user_display(&muser, 1); if( HasUserPerm(PERM_ACCOUNTS) ) - uinfo_query(&muser, 1, id); + uinfo_query(muser.userid, 1, id); else pressanykey(); } diff --git a/mbbsd/register.c b/mbbsd/register.c index 495fdfcd..fcca3b6b 100644 --- a/mbbsd/register.c +++ b/mbbsd/register.c @@ -1,4 +1,5 @@ /* $Id$ */ +#define PWCU_IMPL #include "bbs.h" #define FN_REGISTER_LOG "register.log" // global registration history @@ -245,12 +246,6 @@ compute_user_value(const userec_t * urec, time4_t clock) return 30 - value; #endif -#if 0 - if (!urec->numlogins) /* 未 login 成功者,不保留 */ - return -1; - if (urec->numlogins <= 3) /* #login 少於三者,保留 20 天 */ - return 20 * 24 * 60 - value; -#endif /* 未完成註冊者,保留 15 天 */ /* 一般情況,保留 120 天 */ return (urec->userlevel & PERM_LOGINOK ? 120 : 15) * 24 * 60 - value; @@ -264,7 +259,7 @@ check_and_expire_account(int uid, const userec_t * urec, int expireRange) if ((val = compute_user_value(urec, now)) < 0) { snprintf(genbuf, sizeof(genbuf), "#%d %-12s %s %d %d %d", uid, urec->userid, Cdatelite(&(urec->lastlogin)), - urec->numlogins, urec->numposts, val); + urec->numlogindays, urec->numposts, val); // 若超過 expireRange 則砍人, // 不然就 return 0 @@ -514,12 +509,7 @@ email_justify(const userec_t *muser) snprintf(buf, sizeof(buf), " " BBSENAME " - [ %s ]", makeregcode(genbuf)); -#ifdef HAVEMOBILE - if (strcmp(muser->email, "m") == 0 || strcmp(muser->email, "M") == 0) - mobile_message(mobile, buf); - else -#endif - bsmtp("etc/registermail", buf, muser->email, "non-exist"); + bsmtp("etc/registermail", buf, muser->email, "non-exist"); move(20,0); clrtobot(); outs("我們即將寄出認證信 (您應該會在 10 分鐘內收到)\n" @@ -958,56 +948,6 @@ check_regmail(char *email) return allow; } -void -check_birthday(void) -{ - // check birthday - int changed = 0; - time_t t = (time_t)now; - struct tm tm; - - localtime_r(&t, &tm); - while ( cuser.year < 40 || // magic number 40: see user.c - cuser.year+3 > tm.tm_year) - { - char birthday[sizeof("mmmm/yy/dd ")]; - int y, m, d; - - clear(); - vs_hdr("輸入生日"); - move(2,0); - outs("本站為配合實行內容分級制度,請您輸入正確的生日資訊。"); - - getdata(5, 0, "生日 (西元年/月/日, 如 " DATE_SAMPLE "):", birthday, - sizeof(birthday), DOECHO); - - if (strcmp(birthday, DATE_SAMPLE) == 0) { - vmsg("不要複製範例! 請輸入你真實生日"); - continue; - } - if (ParseDate(birthday, &y, &m, &d)) { - vmsg("日期格式不正確"); - continue; - } else if (y < 1930) { - vmsg(MSG_ERR_TOO_OLD); - continue; - } else if (y+3 > tm.tm_year+1900) { - vmsg(MSG_ERR_TOO_YOUNG); - continue; - } - - cuser.year = (unsigned char)(y-1900); - cuser.month = (unsigned char)m; - cuser.day = (unsigned char)d; - changed = 1; - } - - if (changed) { - clear(); - resolve_over18(); - } -} - ///////////////////////////////////////////////////////////////////////////// // User Registration (Phase 2: Validation) ///////////////////////////////////////////////////////////////////////////// @@ -1115,7 +1055,7 @@ check_register(void) " 通告站長以獲得進階使用權力。\n\n"); outs(" 如果您之前曾使用 email 等認證方式通過註冊認證但又看到此訊息,\n" - " 代表您的認證由於資料不完整已被取消。\n"); + " 代表您的認證由於資料不完整已被取消 (常見於申請開新看板的板主)。\n"); u_register(); @@ -1152,8 +1092,7 @@ create_regform_request() file_append_record(FN_REQLIST, cuser.userid); // save justify information - snprintf(cuser.justify, sizeof(cuser.justify), - "<Manual>"); + pwcuRegSetTemporaryJustify("<Manual>", "x"); return 1; } @@ -1182,12 +1121,6 @@ toregister(char *email) "* 輸入後發生認證碼錯誤請重填一次 E-Mail *\n" "**********************************************************\n"); -#ifdef HAVEMOBILE - outs(" 3.若您有手機門號且想採取手機簡訊認證的方式 , 請輸入 m \n" - " 我們將會寄發含有認證碼的簡訊給您 \n" - " 收到後請到(U)ser => (R)egister 輸入認證碼, 即可通過認證\n"); -#endif - while (1) { email[0] = 0; getfield(15, "身分認證用", REGNOTES_ROOT "email", "E-Mail Address", email, 50); @@ -1195,24 +1128,6 @@ toregister(char *email) if (strcmp(email, "X") == 0) email[0] = 'x'; if (strcmp(email, "x") == 0) break; -#ifdef HAVEMOBILE - else if (strcmp(email, "m") == 0 || strcmp(email, "M") == 0) { - if (isvalidmobile(mobile)) { - char yn[3]; - getdata(16, 0, "請再次確認您輸入的手機號碼正確嘛? [y/N]", - yn, sizeof(yn), LCECHO); - if (yn[0] == 'y') - break; - } else { - move(15, 0); clrtobot(); - move(17, 0); - outs("指定的手機號碼不正確," - "若您無手機門號請選擇其他方式認證"); - pressanykey(); - } - - } -#endif else if (check_regmail(email)) { char yn[3]; #ifdef USE_EMAILDB @@ -1272,26 +1187,17 @@ toregister(char *email) return; } #endif - strlcpy(cuser.email, email, sizeof(cuser.email)); REGFORM2: if (strcasecmp(email, "x") == 0) { /* 手動認證 */ if (!create_regform_request()) - { vmsg("註冊申請單建立失敗。請至 " BN_BUGREPORT " 報告。"); - } } else { // register by mail or mobile - snprintf(cuser.justify, sizeof(cuser.justify), "<Email>"); -#ifdef HAVEMOBILE - if (phone != NULL && email[1] == 0 && tolower(email[0]) == 'm') - snprintf(cuser.justify, sizeof(cuser.justify), - "<Mobile>"); -#endif - email_justify(&cuser); + pwcuRegSetTemporaryJustify("<Email>", email); + email_justify(cuser_ref); } } - int u_register(void) { @@ -1301,9 +1207,7 @@ u_register(void) char inregcode[14], regcode[50]; char ans[3], *errcode; int i = 0; -#ifdef FOREIGN_REG int isForeign = (cuser.uflag2 & FOREIGN) ? 1 : 0; -#endif if (cuser.userlevel & PERM_LOGINOK) { outs("您的身份確認已經完成,不需填寫申請表"); @@ -1319,7 +1223,8 @@ u_register(void) move(3, 0); prints(" 您的註冊申請單尚在處理中(處理順位: %d),請耐心等候\n\n", i); outs(" * 如果您之前曾使用 email 等認證方式通過註冊認證但又看到此訊息,\n" - " 代表您的認證由於資料不完整已被取消。\n\n" + " 代表您的認證由於資料不完整已被取消 (由於建立新看板的流程中\n" + " 有驗證板主註冊資料的程序,若您最近有申請開新看板中則屬此項)\n\n" " * 如果您已收到註冊碼卻看到這個畫面,代表您在使用 Email 註冊後\n" " " ANSI_COLOR(1;31) "又另外申請了站長直接人工審核的註冊申請單。" ANSI_RESET "\n" @@ -1387,7 +1292,8 @@ u_register(void) // make it case insensitive. if (strcasecmp(inregcode, getregcode(regcode)) == 0) { - int unum; + int unum; + char justify[sizeof(cuser.justify)] = ""; delregcodefile(); if ((unum = searchuser(cuser.userid, NULL)) == 0) { vmsg("系統錯誤,查無此人!"); @@ -1399,15 +1305,16 @@ u_register(void) if(cuser.uflag2 & FOREIGN) mail_muser(cuser, "[出入境管理局]", "etc/foreign_welcome"); #endif - cuser.userlevel |= (PERM_LOGINOK | PERM_POST); + snprintf(justify, sizeof(justify), "<E-Mail>: %s", Cdate(&now)); + pwcuRegCompleteJustify(justify); outs("\n註冊成功\, 重新上站後將取得完整權限\n" "請按下任一鍵跳離後重新上站~ :)"); - snprintf(cuser.justify, sizeof(cuser.justify), - "<E-Mail>: %s", Cdate(&now)); pressanykey(); u_exit("registed"); exit(0); + // XXX shall never reach here. return QUIT; + } else if (strcasecmp(inregcode, "x") != 0) { if (regcode[0]) { @@ -1556,33 +1463,18 @@ u_register(void) if (ans[0] == 'y') break; } +#ifndef FOREIGN_REG + isForeign = 0; +#endif // copy values to cuser - strlcpy(cuser.realname, rname, sizeof(cuser.realname)); - strlcpy(cuser.address, addr, sizeof(cuser.address)); - strlcpy(cuser.email, email, sizeof(cuser.email)); - strlcpy(cuser.career, career, sizeof(cuser.career)); - strlcpy(cuser.phone, phone, sizeof(cuser.phone)); - - cuser.mobile = atoi(mobile); - cuser.sex = (sex_is[0] - '1') % 8; - cuser.month = mon; - cuser.day = day; - cuser.year = year; - -#ifdef FOREIGN_REG - if (isForeign) - cuser.uflag2 |= FOREIGN; - else - cuser.uflag2 &= ~FOREIGN; -#endif + pwcuRegisterSetInfo(rname, addr, career, phone, email, + atoi(mobile), (sex_is[0] - '1') % 8, + year, mon, day, isForeign); // if reach here, email is apparently 'x'. toregister(email); - // update cuser - passwd_sync_update(usernum, &cuser); - return FULLUPDATE; } @@ -1793,7 +1685,6 @@ regform_accept(const char *userid, const char *justify) // alert online users? if (search_ulist(unum)) { - sendalert(muser.userid, ALERT_PWD_PERM|ALERT_PWD_JUSTIFY); // force to reload perm kick_all(muser.userid); } diff --git a/mbbsd/talk.c b/mbbsd/talk.c index f1a884d7..e807cf64 100644 --- a/mbbsd/talk.c +++ b/mbbsd/talk.c @@ -436,6 +436,7 @@ my_query(const char *uident) { userec_t muser; int tuid, fri_stat = 0; + int is_self = 0; userinfo_t *uentp; const char *sex[8] = {MSG_BIG_BOY, MSG_BIG_GIRL, @@ -450,51 +451,57 @@ my_query(const char *uident) move(1, 0); setutmpmode(TQUERY); currutmp->destuid = tuid; - - // XXX some users keep complaining that query result (for numpost) - // is not synced... - // well, make them happy now. - if (tuid == usernum) - { - // XXX there're still users asking why money is not updated... - reload_money(); - memcpy(&muser, &cuser, sizeof(muser)); - } + reload_money(); if ((uentp = (userinfo_t *) search_ulist(tuid))) fri_stat = friend_stat(currutmp, uentp); + if (strcmp(muser.userid, cuser.userid) == 0) + is_self =1; + + // ------------------------------------------------------------ - prints("《ID暱稱》%s (%s)%*s《經濟狀況》%s", + prints( "《ID暱稱》%s (%s)%*s", muser.userid, muser.nickname, strlen(muser.userid) + strlen(muser.nickname) >= 25 ? 0 : - (int)(25 - strlen(muser.userid) - strlen(muser.nickname)), "", + (int)(25 - strlen(muser.userid) - strlen(muser.nickname)), ""); + + prints( "《經濟狀況》%s", money_level(muser.money)); - if (uentp && ((fri_stat & HFM && !uentp->invisible) || strcmp(muser.userid,cuser.userid) == 0)) + if (uentp && ((fri_stat & HFM && !uentp->invisible) || is_self)) prints(" ($%d)", muser.money); outc('\n'); - prints("《上站次數》%d次", muser.numlogins); + // ------------------------------------------------------------ + + prints("《" STR_LOGINDAYS "》%d " STR_LOGINDAYS_QTY, muser.numlogindays); #ifdef SHOW_LOGINOK if (!(muser.userlevel & PERM_LOGINOK)) outs(" (尚未通過認證)"); #endif - move(2, 40); + + move(vgety(), 40); + prints("《有效文章》%d 篇", muser.numposts); #ifdef ASSESS - prints("《有效文章篇數》%d篇 (優:%d/劣:%d)\n", muser.numposts, muser.goodpost, muser.badpost); -#else - prints("《有效文章篇數》%d篇\n", muser.numposts); + prints(" (劣:%d)", muser.badpost); #endif + outc('\n'); + + // ------------------------------------------------------------ prints(ANSI_COLOR(1;33) "《目前動態》%-28.28s" ANSI_RESET, (uentp && isvisible_stat(currutmp, uentp, fri_stat)) ? - modestring(uentp, 0) : "不在站上"); + modestring(uentp, 0) : "不在站上"); + + if ((uentp && ISNEWMAIL(uentp)) || load_mailalert(muser.userid)) + outs("《私人信箱》有新進信件還沒看\n"); + else + outs("《私人信箱》所有信件都看過了\n"); + + // ------------------------------------------------------------ - outs(((uentp && ISNEWMAIL(uentp)) || load_mailalert(muser.userid)) - ? "《私人信箱》有新進信件還沒看\n" : - "《私人信箱》所有信件都看過了\n"); prints("《上次上站》%-28.28s《上次故鄉》", - Cdate(&muser.lastlogin)); + Cdate(muser.lastseen ? &muser.lastseen : &muser.lastlogin)); // print out muser.lasthost #ifdef USE_MASKED_FROMHOST if(!HasUserPerm(PERM_SYSOP|PERM_ACCOUNTS)) @@ -503,12 +510,14 @@ my_query(const char *uident) outs(muser.lasthost[0] ? muser.lasthost : "(不詳)"); outs("\n"); - prints("《五子棋戰績》%3d 勝 %3d 敗 %3d 和 " - "《象棋戰績》%3d 勝 %3d 敗 %3d 和\n", + // ------------------------------------------------------------ + + prints("《 五子棋 》%5d 勝 %5d 敗 %5d 和 " + "《象棋戰績》%5d 勝 %5d 敗 %5d 和\n", muser.five_win, muser.five_lose, muser.five_tie, muser.chc_win, muser.chc_lose, muser.chc_tie); - if ((uentp && ((fri_stat & HFM) || strcmp(muser.userid,cuser.userid) == 0) && !uentp->invisible)) + if ((uentp && ((fri_stat & HFM) || is_self) && !uentp->invisible)) prints("《 性 別 》%-28.28s\n", sex[muser.sex % 8]); showplans_userec(&muser); @@ -2835,7 +2844,7 @@ userlist(void) if ((id = getuser(uentp->userid, &muser)) > 0) { user_display(&muser, 1); if( HasUserPerm(PERM_ACCOUNTS) ) - uinfo_query(&muser, 1, id); + uinfo_query(muser.userid, 1, id); else pressanykey(); } @@ -2914,7 +2923,7 @@ userlist(void) case 'f': if (HasUserPerm(PERM_LOGINOK)) { - cuser.uflag ^= FRIEND_FLAG; + pwcuToggleFriendList(); redrawall = redraw = 1; } break; @@ -2999,10 +3008,11 @@ userlist(void) if (HasUserPerm(PERM_LOGINOK)) { int tmp; char *wm[3] = {"一般", "進階", "未來"}; + + tmp = cuser.uflag2 & WATER_MASK; - cuser.uflag2 -= tmp; tmp = (tmp + 1) % 3; - cuser.uflag2 |= tmp; + pwcuSetWaterballMode(tmp); /* vmsg cannot support multi lines */ move(b_lines - 4, 0); clrtobot(); @@ -3035,7 +3045,7 @@ userlist(void) if (getdata_str(1, 0, "新的暱稱: ", tmp_nick, sizeof(tmp_nick), DOECHO, cuser.nickname) > 0) { - strlcpy(cuser.nickname, tmp_nick, sizeof(cuser.nickname)); + pwcuSetNickname(tmp_nick); strlcpy(currutmp->nickname, cuser.nickname, sizeof(currutmp->nickname)); } redrawall = redraw = 1; @@ -3300,8 +3310,8 @@ talkreply(void) strlcpy(currutmp->msgs[0].last_call_in, "呼叫、呼叫,聽到請回答 (Ctrl-R)", sizeof(currutmp->msgs[0].last_call_in)); currutmp->msgs[0].msgmode = MSGMODE_TALK; - prints("對方來自 [%s],共上站 %d 次,文章 %d 篇\n", - uip->from, xuser.numlogins, xuser.numposts); + prints("對方來自 [%s]," STR_LOGINDAYS " %d " STR_LOGINDAYS_QTY ",文章共 %d 篇\n", + uip->from, xuser.numlogindays, xuser.numposts); if (is_chess) ChessShowRequest(); diff --git a/mbbsd/user.c b/mbbsd/user.c index 04d1bac8..edfbc17f 100644 --- a/mbbsd/user.c +++ b/mbbsd/user.c @@ -1,4 +1,5 @@ /* $Id$ */ +#define PWCU_IMPL #include "bbs.h" static char * const sex[8] = { @@ -65,50 +66,58 @@ u_loginview(void) } if (pbits != cuser.loginview) { - cuser.loginview = pbits; - passwd_sync_update(usernum, &cuser); + pwcuSetLoginView(pbits); } return 0; } + int u_cancelbadpost(void) { - int day; - if(cuser.badpost==0) - {vmsg("你並沒有劣文."); return 0;} - - if(search_ulistn(usernum,2)) - {vmsg("請登出其他視窗, 否則不受理."); return 0;} + int day, prev = cuser.badpost; - passwd_sync_query(usernum, &cuser); - if (currutmp && (currutmp->alerts & ALERT_PWD)) - currutmp->alerts &= ~ALERT_PWD; + // early check. + if(cuser.badpost==0) { + vmsg("你並沒有劣文."); + return 0; + } + + // early check for race condition + if(search_ulistn(usernum,2)) { + vmsg("請登出其他視窗, 否則不受理."); + return 0; + } + // early check for time (must do again later) day = 180 - (now - cuser.timeremovebadpost ) / DAY_SECONDS; - if(day>0 && day<=180) - { - vmsgf("每 180 天才能申請一次, 還剩 %d 天.", day); - vmsg("您也可以注意站方是否有勞動服務方式刪除劣文."); - return 0; - } - - if( - vmsg("我願意尊守站方規定,組規,以及板規[y/N]?")!='y' || - vmsg("我願意尊重不歧視族群,不鬧板,尊重各板主權力[y/N]?")!='y' || - vmsg("我願意謹慎發表有意義言論,不謾罵攻擊,不跨板廣告[y/N]?")!='y' ) - - {vmsg("請您思考清楚後再來申請刪除."); return 0;} - - if(search_ulistn(usernum,2)) - {vmsg("請登出其他視窗, 否則不受理."); return 0;} - if(cuser.badpost) + if(day>0 && day<=180) { + vmsgf("每 180 天才能申請一次, 還剩 %d 天.", day); + return 0; + } + + // 無聊的 disclaimer... + if( vmsg("我願意尊守站方規定,組規,以及板規[y/N]?")!='y' || + vmsg("我願意尊重不歧視族群,不鬧板,尊重各板主權力[y/N]?")!='y' || + vmsg("我願意謹慎發表有意義言論,不謾罵攻擊,不跨板廣告[y/N]?")!='y' ) { - int prev = cuser.badpost--; - cuser.timeremovebadpost = now; - passwd_sync_update(usernum, &cuser); - log_filef("log/cancelbadpost.log", LOG_CREAT, - "%s %s 刪除一篇劣文 (%d -> %d 篇)\n", - Cdate(&now), cuser.userid, prev, cuser.badpost); + vmsg("請您思考清楚後再來申請刪除."); + return 0; } + + // check again for race condition + if(search_ulistn(usernum,2)) { + vmsg("請登出其他視窗, 否則不受理."); + return 0; + } + + if (pwcuCancelBadpost() != 0) { + vmsg("刪除失敗,請洽站務人員。"); + return 0; + } + + log_filef("log/cancelbadpost.log", LOG_CREAT, + "%s %s 刪除一篇劣文 (%d -> %d 篇)\n", + Cdate(&now), cuser.userid, prev, cuser.badpost); + vmsg("恭喜您已經成功\刪除一篇劣文."); return 0; } @@ -164,8 +173,12 @@ user_display(const userec_t * u, int adminmode) prints("\t\t認證資料: %s\n", u->justify); } - prints("\t\t上站文章: 上站 %d 次 / 文章 %d 篇\n", - u->numlogins, u->numposts); + // XXX enable STR_LOGINDAYS_QTY after removed old_numlogins. + prints("\t\t使用記錄: " STR_LOGINDAYS " %d " // STR_LOGINDAYS_QTY + ,u->numlogindays); + if (u->old_numlogins) + prints("(轉換新制前結算:%d)", u->old_numlogins); + prints(" / 文章 %d 篇\n", u->numposts); sethomedir(genbuf, u->userid); prints("\t\t私人信箱: %d 封 (購買信箱: %d 封)\n", @@ -196,8 +209,8 @@ user_display(const userec_t * u, int adminmode) // conditional fields #ifdef ASSESS - prints("\t\t優 劣 文: 優:%d / 劣:%d\n", - u->goodpost, u->badpost); + prints("\t\t劣文數目: %u (舊優文結算: %u)\n", + (unsigned int)u->badpost, (unsigned int)u->goodpost); #endif // ASSESS #ifdef CHESSCOUNTRY @@ -466,12 +479,12 @@ void Customize(void) key -= 'a'; dirty = 1; + if(key < ic) { - cuser.uflag ^= masks1[key]; + pwcuToggleUserFlag(masks1[key]); } else { - key -= ic; - cuser.uflag2 ^= masks2[key]; + pwcuToggleUserFlag2(masks2[key-ic]); } continue; } @@ -489,8 +502,7 @@ void Customize(void) { int currentset = cuser.uflag2 & WATER_MASK; currentset = (currentset + 1) % 3; - cuser.uflag2 &= ~WATER_MASK; - cuser.uflag2 |= currentset; + pwcuSetWaterballMode(currentset); vmsg("修正水球模式後請正常離線再重新上線"); dirty = 1; } @@ -527,7 +539,7 @@ void Customize(void) if(dirty) { - passwd_sync_update(usernum, &cuser); + pwcuSaveUserFlags(); outs("設定已儲存。\n"); } else { outs("結束設定。\n"); @@ -539,7 +551,7 @@ void Customize(void) void -uinfo_query(userec_t *u, int adminmode, int unum) +uinfo_query(const char *orig_uid, int adminmode, int unum) { userec_t x; int i = 0, fail; @@ -553,24 +565,35 @@ uinfo_query(userec_t *u, int adminmode, int unum) int money_changed; int tokill = 0; int changefrom = 0; + int xuid; fail = 0; mail_changed = money_changed = perm_changed = 0; + // verify unum + xuid = getuser(orig_uid, &x); + if (xuid == 0) { - // verify unum - int xuid = getuser(u->userid, &x); - if (xuid != unum) - { - move(b_lines-1, 0); clrtobot(); - prints(ANSI_COLOR(1;31) "錯誤資訊: unum=%d (lookup xuid=%d)" - ANSI_RESET "\n", unum, xuid); - vmsg("系統錯誤: 使用者資料號碼 (unum) 不合。請至 " BN_BUGREPORT "報告。"); - return; - } + vmsgf("找不到使用者 %s。", orig_uid); + return; + } + if (xuid != unum) + { + move(b_lines-1, 0); clrtobot(); + prints(ANSI_COLOR(1;31) "錯誤資訊: unum=%d (lookup xuid=%d)" + ANSI_RESET "\n", unum, xuid); + vmsg("系統錯誤: 使用者資料號碼 (unum) 不合。請至 " BN_BUGREPORT "報告。"); + return; + } + if (strcmp(orig_uid, x.userid) != 0) + { + move(b_lines-1, 0); clrtobot(); + prints(ANSI_COLOR(1;31) "錯誤資訊: userid=%s (lookup userid=%s)" + ANSI_RESET "\n", orig_uid, x.userid); + vmsg("系統錯誤: 使用者 ID 記錄不不合。請至 " BN_BUGREPORT "報告。"); + return; } - memcpy(&x, u, sizeof(userec_t)); ans = vans(adminmode ? "(1)改資料(2)密碼(3)權限(4)砍帳號(5)改ID(6)寵物(7)審判(M)信箱 [0]結束 " : "請選擇 (1)修改資料 (2)設定密碼 (M)修改信箱 (C) 個人化設定 ==> [0]結束 "); @@ -681,23 +704,19 @@ uinfo_query(userec_t *u, int adminmode, int unum) snprintf(buf, sizeof(buf), "%010d", x.mobile); getdata_buf(y++, 0, "手機號碼:", buf, 11, NUMECHO); x.mobile = atoi(buf); - snprintf(genbuf, sizeof(genbuf), "%d", (u->sex + 1) % 8); + snprintf(genbuf, sizeof(genbuf), "%d", (x.sex + 1) % 8); getdata_str(y++, 0, "性別 (1)葛格 (2)姐接 (3)底迪 (4)美眉 (5)薯叔 " "(6)阿姨 (7)植物 (8)礦物:", buf, 3, NUMECHO, genbuf); if (buf[0] >= '1' && buf[0] <= '8') x.sex = (buf[0] - '1') % 8; else - x.sex = u->sex % 8; + x.sex = x.sex % 8; while (1) { snprintf(genbuf, sizeof(genbuf), "%04i/%02i/%02i", - u->year + 1900, u->month, u->day); - if (getdata_str(y, 0, "生日 西元/月月/日日:", buf, 11, DOECHO, genbuf) == 0) { - x.month = u->month; - x.day = u->day; - x.year = u->year; - } else { + x.year + 1900, x.month, x.day); + if (getdata_str(y, 0, "生日 西元/月月/日日:", buf, 11, DOECHO, genbuf) != 0) { int y, m, d; if (ParseDate(buf, &y, &m, &d)) continue; @@ -744,7 +763,7 @@ uinfo_query(userec_t *u, int adminmode, int unum) int j, k; FILE* fp; for(j = 0; j < 2; ++j){ - sethomefile(genbuf, u->userid, chess_photo_name[j]); + sethomefile(genbuf, x.userid, chess_photo_name[j]); fp = fopen(genbuf, "r"); if(fp != NULL){ FILE* newfp; @@ -758,7 +777,7 @@ uinfo_query(userec_t *u, int adminmode, int unum) getdata_buf(y, 0, mybuf, genbuf + 11, 80 - 11, DOECHO); ++y; - sethomefile(mybuf, u->userid, chess_photo_name[j]); + sethomefile(mybuf, x.userid, chess_photo_name[j]); strcat(mybuf, ".new"); if((newfp = fopen(mybuf, "w")) != NULL){ rewind(fp); @@ -771,8 +790,8 @@ uinfo_query(userec_t *u, int adminmode, int unum) fclose(newfp); - sethomefile(genbuf, u->userid, chess_photo_name[j]); - sethomefile(mybuf, u->userid, chess_photo_name[j]); + sethomefile(genbuf, x.userid, chess_photo_name[j]); + sethomefile(mybuf, x.userid, chess_photo_name[j]); strcat(mybuf, ".new"); Rename(mybuf, genbuf); @@ -807,32 +826,69 @@ uinfo_query(userec_t *u, int adminmode, int unum) getdata_buf(y++, 0, "最近光臨機器:", x.lasthost, sizeof(x.lasthost), DOECHO); - snprintf(genbuf, sizeof(genbuf), "%d", x.numlogins); - if (getdata_str(y++, 0, "上線次數:", buf, 10, DOECHO, genbuf)) - if ((tmp = atoi(buf)) >= 0) - x.numlogins = tmp; - snprintf(genbuf, sizeof(genbuf), "%d", u->numposts); + while (1) { + struct tm t = {0}; + time4_t clk = x.lastlogin; + localtime4_r(&clk, &t); + snprintf(genbuf, sizeof(genbuf), "%04i/%02i/%02i %02i:%02i:%02i", + t.tm_year + 1900, t.tm_mon+1, t.tm_mday, + t.tm_hour, t.tm_min, t.tm_sec); + if (getdata_str(y, 0, "最近上線時間:", buf, 20, DOECHO, genbuf) != 0) { + int y, m, d, hh, mm, ss; + if (ParseDateTime(buf, &y, &m, &d, &hh, &mm, &ss)) + continue; + t.tm_year = y-1900; + t.tm_mon = m-1; + t.tm_mday = d; + t.tm_hour = hh; + t.tm_min = mm; + t.tm_sec = ss; + clk = mktime(&t); + if (!clk) + continue; + x.lastlogin= clk; + } + y++; + break; + } + + do { + int max_days = (x.lastlogin - x.firstlogin) / DAY_SECONDS; + snprintf(genbuf, sizeof(genbuf), "%d", x.numlogindays); + if (getdata_str(y++, 0, STR_LOGINDAYS, buf, 10, DOECHO, genbuf)) + if ((tmp = atoi(buf)) >= 0) + x.numlogindays = tmp; + if (x.numlogindays > max_days) + { + x.numlogindays = max_days; + vmsgf("根據此使用者最後上線時間,最大值為 %d.", max_days); + move(--y, 0); clrtobot(); + continue; + } + break; + } while (1); + + snprintf(genbuf, sizeof(genbuf), "%d", x.numposts); if (getdata_str(y++, 0, "文章數目:", buf, 10, DOECHO, genbuf)) if ((tmp = atoi(buf)) >= 0) x.numposts = tmp; #ifdef ASSESS - snprintf(genbuf, sizeof(genbuf), "%d", u->goodpost); - if (getdata_str(y++, 0, "優良文章數:", buf, 10, DOECHO, genbuf)) - if ((tmp = atoi(buf)) >= 0) - x.goodpost = tmp; - snprintf(genbuf, sizeof(genbuf), "%d", u->badpost); - if (getdata_str(y++, 0, "惡劣文章數:", buf, 10, DOECHO, genbuf)) + snprintf(genbuf, sizeof(genbuf), "%d", x.badpost); + if (getdata_str(y, 0, "惡劣文章數:", buf, 10, DOECHO, genbuf)) if ((tmp = atoi(buf)) >= 0) x.badpost = tmp; #endif // ASSESS + move(y-1, 0); clrtobot(); + prints("文章數目: %d (劣: %d)\n", + x.numposts, x.badpost); - snprintf(genbuf, sizeof(genbuf), "%d", u->vl_count); + snprintf(genbuf, sizeof(genbuf), "%d", x.vl_count); if (getdata_str(y++, 0, "違法記錄:", buf, 10, DOECHO, genbuf)) if ((tmp = atoi(buf)) >= 0) x.vl_count = tmp; snprintf(genbuf, sizeof(genbuf), - "%d/%d/%d", u->five_win, u->five_lose, u->five_tie); + "%d/%d/%d", x.five_win, x.five_lose, x.five_tie); if (getdata_str(y++, 0, "五子棋戰績 勝/敗/和:", buf, 16, DOECHO, genbuf)) while (1) { @@ -853,8 +909,8 @@ uinfo_query(userec_t *u, int adminmode, int unum) break; } snprintf(genbuf, sizeof(genbuf), - "%d/%d/%d", u->chc_win, u->chc_lose, u->chc_tie); - if (getdata_str(y++, 0, "象棋戰績 勝/敗/和:", buf, 16, DOECHO, + "%d/%d/%d", x.chc_win, x.chc_lose, x.chc_tie); + if (getdata_str(y++, 0, " 象棋 戰績 勝/敗/和:", buf, 16, DOECHO, genbuf)) while (1) { char *p; @@ -873,6 +929,33 @@ uinfo_query(userec_t *u, int adminmode, int unum) x.chc_tie = atoi(p); break; } + snprintf(genbuf, sizeof(genbuf), + "%d/%d/%d", x.go_win, x.go_lose, x.go_tie); + if (getdata_str(y++, 0, " 圍棋 戰績 勝/敗/和:", buf, 16, DOECHO, + genbuf)) + while (1) { + char *p; + char *strtok_pos; + p = strtok_r(buf, "/\r\n", &strtok_pos); + if (!p) + break; + x.go_win = atoi(p); + p = strtok_r(NULL, "/\r\n", &strtok_pos); + if (!p) + break; + x.go_lose = atoi(p); + p = strtok_r(NULL, "/\r\n", &strtok_pos); + if (!p) + break; + x.go_tie = atoi(p); + break; + } + y -= 3; // rollback games set to get more space + move(y++, 0); clrtobot(); + prints("棋類: (五子棋)%d/%d/%d (象棋)%d/%d/%d (圍棋)%d/%d/%d\n", + x.five_win, x.five_lose, x.five_tie, + x.chc_win, x.chc_lose, x.chc_tie, + x.go_win, x.go_lose, x.go_tie); #ifdef FOREIGN_REG if (getdata_str(y++, 0, "住在 1)台灣 2)其他:", buf, 2, DOECHO, x.uflag2 & FOREIGN ? "2" : "1")) if ((tmp = atoi(buf)) > 0){ @@ -903,7 +986,7 @@ uinfo_query(userec_t *u, int adminmode, int unum) y = 19; if (!adminmode) { if (!getdata(y++, 0, "請輸入原密碼:", buf, PASSLEN, NOECHO) || - !checkpasswd(u->passwd, buf)) { + !checkpasswd(x.passwd, buf)) { outs("\n\n您輸入的密碼不正確\n"); fail++; break; @@ -964,7 +1047,7 @@ uinfo_query(userec_t *u, int adminmode, int unum) } pre_confirmed = 1; - sprintf(title, "%s 的密碼重設通知 (by %s)",u->userid, cuser.userid); + sprintf(title, "%s 的密碼重設通知 (by %s)",x.userid, cuser.userid); unlink("etc/updatepwd.log"); if(! (fp = fopen("etc/updatepwd.log", "w"))) { @@ -976,11 +1059,11 @@ uinfo_query(userec_t *u, int adminmode, int unum) fprintf(fp, "%s 要求密碼重設:\n" "見證人為 %s, %s, %s", - u->userid, witness[0], witness[1], witness[2] ); + x.userid, witness[0], witness[1], witness[2] ); fclose(fp); post_file(BN_SECURITY, title, "etc/updatepwd.log", "[系統安全局]"); - mail_id(u->userid, title, "etc/updatepwd.log", cuser.userid); + mail_id(x.userid, title, "etc/updatepwd.log", cuser.userid); for(i=0; i<3; i++) { mail_id(witness[i], title, "etc/updatepwd.log", cuser.userid); @@ -1034,9 +1117,11 @@ uinfo_query(userec_t *u, int adminmode, int unum) strlcpy(x.userid, genbuf, sizeof(x.userid)); } break; + case '6': chicken_toggle_death(x.userid); break; + default: return; } @@ -1063,10 +1148,11 @@ uinfo_query(userec_t *u, int adminmode, int unum) mail_id(x.userid, "翅膀長出來了!", "etc/angel_notify", "[上帝]"); #endif } - if (strcmp(u->userid, x.userid)) { + + if (strcmp(orig_uid, x.userid)) { char src[STRLEN], dst[STRLEN]; - kick_all(u->userid); - sethomepath(src, u->userid); + kick_all(orig_uid); + sethomepath(src, orig_uid); sethomepath(dst, x.userid); Rename(src, dst); setuserid(unum, x.userid); @@ -1075,7 +1161,7 @@ uinfo_query(userec_t *u, int adminmode, int unum) // wait registration. x.userlevel &= ~(PERM_LOGINOK | PERM_POST); } - memcpy(u, &x, sizeof(x)); + if (tokill) { kick_all(x.userid); delete_allpost(x.userid); @@ -1109,10 +1195,7 @@ uinfo_query(userec_t *u, int adminmode, int unum) passwd_sync_update(unum, &x); if (adminmode) - { - sendalert(x.userid, ALERT_PWD_RELOAD); kick_all(x.userid); - } // resolve_over18 only works for cuser if (!adminmode) @@ -1124,8 +1207,9 @@ u_info(void) { move(2, 0); reload_money(); - user_display(&cuser, 0); - uinfo_query(&cuser, 0, usernum); + user_display(cuser_ref, 0); + uinfo_query (cuser.userid, 0, usernum); + pwcuReload(); strlcpy(currutmp->nickname, cuser.nickname, sizeof(currutmp->nickname)); return 0; } @@ -1407,7 +1491,7 @@ u_list_CB(void *data, int num, userec_t * uentp) prints("%-14s %-27.27s%5d %5d %s %s\n", uentp->userid, uentp->nickname, - uentp->numlogins, uentp->numposts, + uentp->numlogindays, uentp->numposts, HasUserPerm(PERM_SEEULEVELS) ? permstr : "", ptr); ctx->usercounter++; ctx->y++; diff --git a/mbbsd/var.c b/mbbsd/var.c index a9f52c73..eb178940 100644 --- a/mbbsd/var.c +++ b/mbbsd/var.c @@ -98,7 +98,7 @@ char margs[64] = "\0"; /* main argv list */ pid_t currpid; /* current process ID */ time4_t login_start_time; time4_t start_time; -userec_t cuser; /* current user structure */ +userec_t pwcuser; /* current user structure */ crosspost_t postrecord; /* anti cross post */ unsigned int currbrdattr; unsigned int currstat; @@ -371,9 +371,10 @@ char local_article; char fromhost[STRLEN] = "\0"; char fromhost_masked[32] = "\0"; // masked 'fromhost' char water_usies = 0; +char over18 = 0; +char is_first_login_of_today = 0; FILE *fp_writelog = NULL; water_t *water, *swater[6], *water_which; -char over18 = 0; /* chc_play.c */ diff --git a/mbbsd/vote.c b/mbbsd/vote.c index b3900bca..030c6704 100644 --- a/mbbsd/vote.c +++ b/mbbsd/vote.c @@ -789,7 +789,7 @@ user_vote_one(const vote_buffer_t *vbuf, const char *bname) fclose(lfp); // XXX if this is a private vote (limited), I think we don't need to check limits? if (cuser.firstlogin > closetime || cuser.numposts < limits_posts || - cuser.numlogins < limits_logins) { + cuser.numlogindays < limits_logins) { vmsg("你不夠資深喔!"); return FULLUPDATE; } diff --git a/mbbsd/xyz.c b/mbbsd/xyz.c index 8f1e7ed3..7f52a28d 100644 --- a/mbbsd/xyz.c +++ b/mbbsd/xyz.c @@ -273,17 +273,13 @@ Goodbye(void) else if (genbuf[0] == 'n') note(); } - clear(); - - show_80x24_screen("etc/Logout"); - { int diff = (now - login_start_time) / 60; snprintf(genbuf, sizeof(genbuf), "此次停留時間: %d 小時 %2d 分", diff / 60, diff % 60); } - if(!(cuser.userlevel & PERM_LOGINOK)) + if(!HasUserPerm(PERM_LOGINOK)) vmsg("尚未完成註冊。如要提昇權限請參考本站公佈欄辦理註冊"); else vmsg(genbuf); |