summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpiaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2009-09-10 18:05:12 +0800
committerpiaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2009-09-10 18:05:12 +0800
commit0a50f91422cc78e215c541d08dbf30fdeb91477c (patch)
tree9b09fa98181fe6ef345109eb0c279d3628889c09
parent78a17f4498134b9db1fc95e7be14798422475475 (diff)
parentf115309f094fb58ce49a14a24d58144aa13d3e5c (diff)
downloadpttbbs-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
-rw-r--r--UPDATING8
-rw-r--r--common/bbs/cache.c3
-rw-r--r--common/bbs/passwd.c3
-rw-r--r--include/common.h3
-rw-r--r--include/proto.h63
-rw-r--r--include/pttstruct.h29
-rw-r--r--mbbsd/admin.c9
-rw-r--r--mbbsd/angel.c10
-rw-r--r--mbbsd/announce.c10
-rw-r--r--mbbsd/assess.c215
-rw-r--r--mbbsd/bbs.c104
-rw-r--r--mbbsd/board.c5
-rw-r--r--mbbsd/cache.c2
-rw-r--r--mbbsd/cal.c7
-rw-r--r--mbbsd/calendar.c38
-rw-r--r--mbbsd/card.c22
-rw-r--r--mbbsd/ch_go.c31
-rw-r--r--mbbsd/ch_gomo.c31
-rw-r--r--mbbsd/chat.c8
-rw-r--r--mbbsd/chc.c37
-rw-r--r--mbbsd/chess.c4
-rw-r--r--mbbsd/edit.c2
-rw-r--r--mbbsd/kaede.c2
-rw-r--r--mbbsd/mail.c3
-rw-r--r--mbbsd/mbbsd.c137
-rw-r--r--mbbsd/menu.c2
-rw-r--r--mbbsd/ordersong.c2
-rw-r--r--mbbsd/passwd.c639
-rw-r--r--mbbsd/pmore.c2
-rw-r--r--mbbsd/read.c10
-rw-r--r--mbbsd/register.c151
-rw-r--r--mbbsd/talk.c76
-rw-r--r--mbbsd/user.c278
-rw-r--r--mbbsd/var.c5
-rw-r--r--mbbsd/vote.c2
-rw-r--r--mbbsd/xyz.c6
-rw-r--r--upgrade/Makefile3
-rw-r--r--upgrade/r4825_pwcu.c77
-rw-r--r--util/birth.c6
-rw-r--r--util/reaper.c2
-rw-r--r--util/xchatd.c2
41 files changed, 1141 insertions, 908 deletions
diff --git a/UPDATING b/UPDATING
index 6a772ee4..5fb8b61d 100644
--- a/UPDATING
+++ b/UPDATING
@@ -18,8 +18,16 @@ https://opensvn.csie.org/traccgi/pttbbs/changeset/2273
make r3968_chicken
make r4035_regnew
make r4194_passwd
+ make r4825_pwcu
-----------------------------------------------------------------------------
+r4825: [numlogindays, lastseen]
+numlogins 的算法有調整,並且改名為 numlogindays;
+lastlogin 也多了一個叫 lastseen (別人 talk->query 到的值)
+lastlogin 只要登入就一定會更新,lastseen 則否。
+另,這個 r4825 的 upgrade 是 optional 的,不跑也不 ok,
+只是看你要不要一併調整 numlogin 的值。
+
r4483: [mbbsd command option]
從這版開始, mbbsd 的 command line 參數改變. 使用 getopt 處理參數.
譬如原本
diff --git a/common/bbs/cache.c b/common/bbs/cache.c
index 1166a85b..a23326bd 100644
--- a/common/bbs/cache.c
+++ b/common/bbs/cache.c
@@ -27,7 +27,10 @@
// these cannot be used!
#define currutmp YOU_FAILED
#define usernum YOU_FAILED
+#undef cuser
+#undef cuser_ref
#define cuser YOU_FAILED
+#define cuser_ref YOU_FAILED
#define abort_bbs YOU_FAILED
#define log_usies YOU_FAILED
diff --git a/common/bbs/passwd.c b/common/bbs/passwd.c
index 3e55d4d2..71d995d9 100644
--- a/common/bbs/passwd.c
+++ b/common/bbs/passwd.c
@@ -23,7 +23,10 @@
// these cannot be used!
#define currutmp YOU_FAILED
#define usernum YOU_FAILED
+#undef cuser
+#undef cuser_ref
#define cuser YOU_FAILED
+#define cuser_ref YOU_FAILED
#define abort_bbs YOU_FAILED
#define log_usies YOU_FAILED
diff --git a/include/common.h b/include/common.h
index f9377875..d5400070 100644
--- a/include/common.h
+++ b/include/common.h
@@ -115,6 +115,9 @@
#define STR_POST1 "看板:"
#define STR_POST2 "站內:"
+#define STR_LOGINDAYS "登入次數"
+#define STR_LOGINDAYS_QTY "次"
+
/* AIDS */
#define AID_DISPLAYNAME "文章代碼(AID)"
/* end of AIDS */
diff --git a/include/proto.h b/include/proto.h
index d49c8ae4..ea232c78 100644
--- a/include/proto.h
+++ b/include/proto.h
@@ -53,11 +53,7 @@ void BlogMain(int);
#endif
/* assess */
-int inc_goodpost(const char *, int num);
int inc_badpost(const char *, int num);
-int inc_goodsale(const char *, int num);
-int inc_badsale(const char *, int num);
-//void set_assess(int uid, unsigned char num, int type);
/* bbs */
void delete_allpost(const char *userid);
@@ -130,7 +126,7 @@ const char * postperm_msg(const char *bname);
int give_tax(int money);
const char* money_level(int money);
int vice(int money, const char* item);
-#define reload_money() cuser.money=moneyof(usernum)
+#define reload_money() // cuser.money=moneyof(usernum)
int lockutmpmode(int unmode, int state);
int unlockutmpmode(void);
int x_file(void);
@@ -458,7 +454,6 @@ int setupnewuser(const userec_t *user);
int regform_estimate_queuesize();
void new_register(void);
void check_register(void);
-void check_birthday(void);
int check_regmail(char *email); // check and prompt for invalid reason; will str_lower() mail domain.
void delregcodefile(void);
@@ -612,7 +607,7 @@ int kill_user(int num, const char *userid);
int u_editcalendar(void);
void user_display(const userec_t *u, int real);
int isvalidemail(char *email);
-void uinfo_query(userec_t *u, int real, int unum);
+void uinfo_query(const char *uid, int real, int unum);
int showsignature(char *fname, int *j, SigInfo *psi);
int u_cancelbadpost();
void kick_all(const char *user);
@@ -692,15 +687,61 @@ void passwd_force_update(int flag);
int passwd_sync_update (int num, userec_t * buf);
int passwd_sync_query (int num, userec_t * buf);
-// int passwd_add_my_numpost(int diff); // temporary hack before new account system ready.
-
// current user help utilities
+int pwcuBitEnableLevel (unsigned int mask);
+int pwcuBitDisableLevel (unsigned int mask);
+int pwcuIncNumPost ();
+int pwcuDecNumPost ();
+int pwcuSetGoodPost (unsigned int newgp);
+int pwcuViolateLaw ();
+int pwcuSaveViolateLaw ();
+int pwcuCancelBadpost ();
+int pwcuAddExMailBox (int m);
+int pwcuToggleOutMail ();
+int pwcuSetLoginView (unsigned int bits);
+int pwcuSetLastSongTime (time4_t clk);
+int pwcuSetMyAngel (const char *angel_uid);
+int pwcuSetNickname (const char *nickname);
+int pwcuChessResult (int sigType, ChessGameResult);
+int pwcuSetChessEloRating(uint16_t elo_rating);
+int pwcuSaveUserFlags ();
+int pwcuRegCompleteJustify (const char *justify);
+int pwcuRegSetTemporaryJustify(const char *justify, const char *email);
+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);
+
+// non-important based variables (only save on exit)
int pwcuSetSignature (unsigned char newsig);
-int pwcuBitSetLevel (unsigned int mask);
-int pwcuBitUnsetLevel (unsigned int mask);
+int pwcuSetWaterballMode(unsigned int bm);
+int pwcuToggleSortBoard ();
+int pwcuToggleFriendList();
+int pwcuToggleUserFlag (unsigned int mask); // not saved until pwcuSaveUserFlags
+int pwcuToggleUserFlag2 (unsigned int mask); // not saved until pwcuSaveUserFlags
+
+// session management
+int pwcuLoginSave ();
+int pwcuExitSave ();
+int pwcuReload ();
+
+// initialization
+void pwcuInitZero ();
+void pwcuInitGuestPerm ();
+void pwcuInitGuestInfo ();
+int pwcuInitAdminPerm ();
/* calendar */
int calendar(void);
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);
#endif
diff --git a/include/pttstruct.h b/include/pttstruct.h
index 2c3591c4..4a8b76a9 100644
--- a/include/pttstruct.h
+++ b/include/pttstruct.h
@@ -63,10 +63,10 @@ typedef struct userec_t {
uint32_t uflag; /* 習慣1 , see uflags.h */
uint32_t uflag2; /* 習慣2 , see uflags.h */
uint32_t userlevel; /* 權限 */
- uint32_t numlogins; /* 上站次數 */
+ uint32_t numlogindays; /* 上線資歷 (每日最多+1的登入次數) */
uint32_t numposts; /* 文章篇數 */
time4_t firstlogin; /* 註冊時間 */
- time4_t lastlogin; /* 最近上站時間 */
+ time4_t lastlogin; /* 最近上站時間(包含隱身) */
char lasthost[IPV4LEN+1];/* 上次上站來源 */
int32_t money; /* Ptt幣 */
@@ -95,8 +95,10 @@ typedef struct userec_t {
char career[40]; /* 學歷職業 */
char phone[20]; /* 電話 */
- char chkpad1[52];
- time4_t chkpad2[3]; /* in case 有人忘了把 time4_t 調好... */
+ uint32_t old_numlogins; /* 轉換前的 numlogins, 備份檢視用 */
+ char chkpad1[48];
+ time4_t lastseen; /* 最近上站時間(隱身不計) */
+ time4_t chkpad2[2]; /* in case 有人忘了把 time4_t 調好... */
// 以上應為 sizeof(chicken_t) 同等大小
time4_t lastsong; /* 上次點歌時間 */
@@ -137,6 +139,15 @@ typedef struct userec_t {
char pad_tail[28];
} PACKSTRUCT userec_t;
+#ifndef NO_CONST_CUSER
+// const userec_t cuser;
+# define cuser_ref ((const userec_t*)&pwcuser)
+# define cuser (*cuser_ref)
+#else
+# define cuser_ref (&cuser)
+# define cuser pwcuser
+#endif
+
/* flags in userec_t.withme */
#define WITHME_ALLFLAG 0x55555555
#define WITHME_TALK 0x00000001
@@ -304,14 +315,8 @@ typedef struct msgque_t {
#define ALERT_NEW_MAIL (0x01)
#define ISNEWMAIL(utmp) (utmp->alerts & ALERT_NEW_MAIL)
-#define ALERT_PWD_PERM (0x02)
-#define ALERT_PWD_BADPOST (0x04)
-#define ALERT_PWD_GOODPOST (0x08)
-#define ALERT_PWD_JUSTIFY (0x10)
-// #define ALERT_PWD_LOGINS (0x20)
-#define ALERT_PWD_POSTS (0x40)
-#define ALERT_PWD_RELOAD (0x80) // reload entire pwd
-#define ALERT_PWD (ALERT_PWD_PERM|ALERT_PWD_BADPOST|ALERT_PWD_GOODPOST|ALERT_PWD_JUSTIFY|ALERT_PWD_POSTS|ALERT_PWD_RELOAD)
+#define ALERT_PWD_PERM (0x02)
+#define ISNEWPERM(utmp) (utmp->alerts & ALERT_PWD_PERM)
// userinfo_t.angelpause values
#define ANGELPAUSE_NONE (0) // reject none (accept all)
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);
diff --git a/upgrade/Makefile b/upgrade/Makefile
index 833881b1..373ba4ac 100644
--- a/upgrade/Makefile
+++ b/upgrade/Makefile
@@ -9,8 +9,7 @@ CFLAGS+= -DPTTBBS_UTIL
BBSBASE= $(SRCROOT)/include/var.h
UTIL_OBJS= \
- util_cache.o util_record.o util_passwd.o util_var.o \
- util_stuff.o
+ util_var.o
LDLIBS+= $(SRCROOT)/common/sys/libcmsys.a \
$(SRCROOT)/common/bbs/libcmbbs.a
diff --git a/upgrade/r4825_pwcu.c b/upgrade/r4825_pwcu.c
new file mode 100644
index 00000000..32c5d3ce
--- /dev/null
+++ b/upgrade/r4825_pwcu.c
@@ -0,0 +1,77 @@
+#define _UTIL_C_
+#include "bbs.h"
+#include <time.h>
+
+int accs = 0;
+
+int transform(userec_t *new, userec_t *old, int i)
+{
+ int mind = 1, maxd = 1;
+ userec_t *u = new;
+
+ memcpy(new, old, sizeof(userec_t));
+
+ if (!u->userid[0])
+ return 0;
+
+ accs ++;
+
+ // save old login number
+ u->old_numlogins = u->numlogindays;
+
+ // adjust new 'lastseen'
+ u->lastseen = u->lastlogin;
+
+ // check validate firstlogin
+ // if (u->firstlogin < SITE_CREATION_DATE)
+ // u->firstlogin = SITE_CREATION_DATE;
+
+ // calculate max logindays
+ maxd = (u->lastlogin - u->firstlogin) / DAY_SECONDS;
+ if (maxd < mind)
+ maxd = mind;
+ if (u->numlogindays > maxd)
+ u->numlogindays = maxd;
+
+ printf("%-13s: numlogin: %d -> %d\n",
+ u->userid, u->old_numlogins, u->numlogindays);
+
+ // force convert!
+ // passwd_update(n+1, u);
+
+ return 0;
+}
+
+int main(void)
+{
+ int fd, fdw;
+ userec_t new;
+ userec_t old;
+ int i = 0;
+
+ printf("sizeof(userec_t)=%u\n", (unsigned int)sizeof(userec_t));
+ printf("You're going to convert your .PASSWDS\n");
+ printf("The new file will be named .PASSWDS.trans.tmp\n");
+
+ if (chdir(BBSHOME) < 0) {
+ perror("chdir");
+ exit(-1);
+ }
+
+ if ((fd = open(FN_PASSWD, O_RDONLY)) < 0 ||
+ (fdw = open(FN_PASSWD".trans.tmp", O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0 ) {
+ perror("open");
+ exit(-1);
+ }
+
+ while (read(fd, &old, sizeof(old)) > 0) {
+ transform(&new, &old, ++i);
+ write(fdw, &new, sizeof(new));
+ }
+
+ close(fd);
+ close(fdw);
+
+ printf("total %d records converted.\n", accs);
+ return 0;
+}
diff --git a/util/birth.c b/util/birth.c
index 436c37a6..bac1bad3 100644
--- a/util/birth.c
+++ b/util/birth.c
@@ -12,7 +12,7 @@ int bad_user_id(const char *userid) {
int j;
if (strlen(user.userid) < 2 || !isalpha(user.userid[0]))
return 1;
- if (user.numlogins == 0 || user.numlogins > 15000)
+ if (user.numlogindays == 0 || user.numlogindays > 15000)
return 1;
if (user.numposts > 15000)
return 1;
@@ -66,13 +66,13 @@ int main(argc, argv)
Link(path, genbuf);
sprintf(genbuf, BBSHOME "/home/%c/%s/.DIR", user.userid[0], user.userid);
append_record(genbuf, &mymail, sizeof(mymail));
- if ((user.numlogins + user.numposts) < 20)
+ if ((user.numlogindays + user.numposts) < 20)
continue;
fprintf(fp1,
" [%2d/%-2d] %-14s %-24s login:%-5d post:%-5d\n",
ptime->tm_mon + 1, ptime->tm_mday, user.userid,
- user.nickname, user.numlogins, user.numposts);
+ user.nickname, user.numlogindays, user.numposts);
}
}
fclose(fp1);
diff --git a/util/reaper.c b/util/reaper.c
index d89f6e56..70bd3814 100644
--- a/util/reaper.c
+++ b/util/reaper.c
@@ -136,7 +136,7 @@ int check_last_login(void *data, int n, userec_t *u) {
{
// invalid record
printf("使用者 %-*s (登入%3d 次, %s%s, %s [%04X])\n 最後登入日期異常 [%04X]: %s",
- IDLEN, u->userid, u->numlogins,
+ IDLEN, u->userid, u->numlogindays,
(u->userlevel & PERM_LOGINOK) ? "已過認證" : "未過認證",
(u->userlevel & PERM_SYSOP) ? "[SYSOP]" : "",
buf,
diff --git a/util/xchatd.c b/util/xchatd.c
index e0c82201..912d0d7a 100644
--- a/util/xchatd.c
+++ b/util/xchatd.c
@@ -151,7 +151,7 @@ static char msg_not_here[] = "◆ [%s] 不在這間聊天室";
#define FUZZY_USER ((ChatUser *) -1)
-
+#undef cuser
typedef struct userec_t ACCT;
/* ----------------------------------------------------- */