summaryrefslogtreecommitdiffstats
path: root/mbbsd/passwd.c
diff options
context:
space:
mode:
Diffstat (limited to 'mbbsd/passwd.c')
-rw-r--r--mbbsd/passwd.c639
1 files changed, 581 insertions, 58 deletions
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;
+}