summaryrefslogblamecommitdiffstats
path: root/mbbsd/passwd.c
blob: 75a013fb1d6e3e5f3a5c1c9f4a45596453979a2a (plain) (tree)
1
2
3
4
5
6
7
8
9
          
                 
                
                 
 

                                                                                                

      
                      


                      
 






                                               
   
                                           
 
                                   
                  
 

                                                     
                                     
                  
 


                                   

             
 
   
                                          
 
                                   
                  
 
                              



                                   



                                       
 



                                                
                                           
                  



                                                                                   


                                                         

             





                                                 



                                                                                   
                                            



                  






                                                                                                                                  
 
                                             

                                                                                                           

                                           

                 

                                       


               
                                           

                 

                                        




















                                   



                  

                                                  










                                            

                                                   


               





                   



                                                  

                                                     
                                     

                      

                  





                                                        








                                  










                                               
                                                             






                                                             
                                                              



                                                              



                   


                                             











                                   














































                                                                  
                                                












                                                            
                                                    



               
















                                                                
     






































                                               
     
 







































                                                             

 
    
                                           

                 


                                   


               
    
                      
 

                                                 
                                          

 

                      
 

                                                 
                                         
 
 

                                              


            
    
                                          
 
                                                         





                                      

             
 

                                      
 
                                                         




                                  

             
 
               
 



                                                           







                                                       


                               
                                                 
                 

                               
                                                              
                                                              
 


                                 
                                                                          





                                                                       
 



                              

                                                         

                                       


                                        
 

                                                              
     
                         

                                    
                                        

                             
                                            
 
                             
                                              
 




                                                          

                  
 









                                                                      
 

                                                                
 




                                                                                             
 



                                                                                            
 
            
                                                                            



                                                                               
     
            
                                                                            
                                                                               
      
             

 


                  
                                       

                                               


             














                                   

                 




                                 













                                                              
                             
                            
                
                                                                    
                                    
                                                
       
      

 


                                       


                          
                    



                                                   

                             
                                                    
                                     

                                               

                                                             

                      
/* $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

#ifndef NO_CONST_CUSER
 #undef  cuser
 #define cuser pwcuser
#endif

int 
initcuser(const char *userid)
{
    usernum = passwd_load_user(userid, &cuser);
    return usernum;
}

int
passwd_sync_update(int num, userec_t * buf)
{
    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 (num == usernum)
    cuser.money = moneyof(num);

    return 0;
}

int
passwd_sync_query(int num, userec_t * buf)
{
    if (passwd_query(num, buf) < 0)
    return -1;

    buf->money = moneyof(num);

    if (num == usernum)
    cuser.money = moneyof(num);

    return 0;
}

// pwcu*: current user password helpers

static int
pwcuInitCUser(userec_t *u)
{
    assert(usernum > 0 && usernum <= MAX_USERS);
    if (passwd_sync_query(usernum, u) != 0)
    return -1;
#ifdef DEBUG
    log_filef("log/pwcu_exitsave.log", LOG_CREAT, "%s InitCUser  invoked at %s\n", 
        cuser.userid, Cdatelite(&now));
#endif
    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);
#ifdef DEBUG
    log_filef("log/pwcu_exitsave.log", LOG_CREAT, "%s FinalCUser invoked at %s\n", 
        cuser.userid, Cdatelite(&now));
#endif
    if (passwd_sync_update(usernum, u) != 0)
    return -1;
    return 0;
}

#ifdef   DISABLE_AGGRESSIVE_PWCU_CACHE
# define PWCU_START()   userec_t u; if(pwcuInitCUser (&u) != 0) return -1
# define PWCU_END() if (pwcuFinalCUser(&u) != 0) return -1; return 0
#else
# define PWCU_START()   userec_t u, u_orig; do { if(pwcuInitCUser (&u) != 0) return -1; memcpy(&u_orig, &u, sizeof(u)); } while(0)
# define PWCU_END() do { if (memcmp(&u_orig, &u, sizeof(u)) != 0 && pwcuFinalCUser(&u) != 0) return -1; return 0; } while(0)
#endif

#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();

    // no matter what, reload the timebomb
    cuser.badpost = u.badpost;
    cuser.timeremovebadpost = u.timeremovebadpost;

    // check timebomb again
    day = (now - u.timeremovebadpost ) / DAY_SECONDS;
    if (day < BADPOST_CLEAR_DURATION)
    return -1;
    if (u.badpost < 1)
    return -1;

    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.uflag     ^=  UF_REJ_OUTTAMAIL;
    _SETBY_BIT(cuser.uflag, UF_REJ_OUTTAMAIL,
        u.uflag & UF_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.uflag, UF_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.uflag, UF_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)
    {
    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;
    }

    // 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();
}

int 
pwcuToggleUserFlag  (unsigned int mask)
{
    PWCU_START();
    u.uflag ^= mask;
    _SETBY_BIT(cuser.uflag,  mask,
               u.uflag & mask);
    PWCU_END();
}

int 
pwcuToggleSortBoard ()
{
    // XXX if this is executed too often,
    // put it into 'non-important variable list'.
    return pwcuToggleUserFlag(UF_BRDSORT);
}

int 
pwcuToggleFriendList()
{
    // XXX if this is executed too often,
    // put it into 'non-important variable list'.
    return pwcuToggleUserFlag(UF_FRIEND);
}

// non-important variables (only save on exit)

static char 
pwcu_dirty;

int 
pwcuSetPagerUIType  (unsigned int  uitype)
{
    // XXX you MUST save this variable in pwcuExitSave();
    uitype %= PAGER_UI_TYPES;
    if (cuser.pager_ui_type != uitype)
    {
    pwcu_dirty = 1;
    cuser.pager_ui_type = uitype;
    }
    return 0;
}

int
pwcuSetSignature(unsigned char newsig)
{
    // XXX you MUST save this variable in pwcuExitSave();
    if (cuser.signature != newsig)
    {
    pwcu_dirty = 1;
    cuser.signature = newsig;
    }
    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};

    // XXX one more read here... can we avoid it?
    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);

    // plus one for initial day
    if (u.numlogindays > prev_regdays+1)
    u.numlogindays = prev_regdays+1;

    // 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    ()
{
    // determine dirty
    if (pwcu_dirty  ||
    cuser.withme    != currutmp->withme ||
    cuser.pager != currutmp->pager  ||
    cuser.invisible != currutmp->invisible ||
    (memcmp(cuser.mind,currutmp->mind, sizeof(cuser.mind)) != 0) )
    {
    // maybe dirty, let's work harder.
    PWCU_START();
    pwcu_dirty = 1;

    // XXX we may work harder to determine if this is a real
    // dirty cache, however maybe it's not that important.

    // configure new utmp values
    u.withme    = currutmp->withme;
    u.pager     = currutmp->pager;
    u.invisible = currutmp->invisible;
    memcpy(u.mind, currutmp->mind, sizeof(u.mind)); // XXX u.mind is NOT NULL-terminated.

    // configure those changed by 'not important variables' API
    u.signature = cuser.signature;
    u.pager_ui_type = cuser.pager_ui_type;
    // u.money      = moneyof(usernum); // should be already updated by deumoney

#ifdef DEBUG
    log_filef("log/pwcu_exitsave.log", LOG_CREAT, "%s exit %s at %s\n", 
        cuser.userid, pwcu_dirty ? "DIRTY" : "CLEAN", Cdatelite(&now));
#endif
    PWCU_END();
    // XXX return 0 here (PWCU_END), following code is not executed.
    }
#ifdef DEBUG
    log_filef("log/pwcu_exitsave.log", LOG_CREAT, "%s exit %s at %s\n", 
        cuser.userid, pwcu_dirty ? "DIRTY" : "CLEAN", Cdatelite(&now));
#endif
    return 0;
}

int 
pwcuReload  ()
{
    // XXX TODO verify cuser structure?
    int r = passwd_sync_query(usernum, &cuser);
    pwcu_dirty = 0;
    return r;
}

int
pwcuReloadMoney ()
{
    cuser.money=moneyof(usernum);
    return 0;
}

int
pwcuDeMoney (int money)
{
    deumoney(usernum, money);
    cuser.money = moneyof(usernum);
    return 0;
}

// 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 = UF_BRDSORT;
    cuser.pager = PAGER_OFF;
#ifdef DBCSAWARE
    _ENABLE_BIT(cuser.uflag, (UF_DBCS_AWARE | UF_DBCS_DROP_REPEAT));
# ifdef GUEST_DEFAULT_DBCS_NOINTRESC
    _ENABLE_BIT(cuser.uflag, UF_DBCS_NOINTRESC);
# endif
#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;
}