diff options
author | piaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2008-04-19 04:30:14 +0800 |
---|---|---|
committer | piaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2008-04-19 04:30:14 +0800 |
commit | da6a317fcaa76d01a43f80925f8d3137e193984c (patch) | |
tree | 59722cebfe6f33c8d002bc526f36191edfd477f6 | |
parent | a1f92612eb4f8e33612b498314c9c5ebd167a9b5 (diff) | |
download | pttbbs-da6a317fcaa76d01a43f80925f8d3137e193984c.tar pttbbs-da6a317fcaa76d01a43f80925f8d3137e193984c.tar.gz pttbbs-da6a317fcaa76d01a43f80925f8d3137e193984c.tar.bz2 pttbbs-da6a317fcaa76d01a43f80925f8d3137e193984c.tar.lz pttbbs-da6a317fcaa76d01a43f80925f8d3137e193984c.tar.xz pttbbs-da6a317fcaa76d01a43f80925f8d3137e193984c.tar.zst pttbbs-da6a317fcaa76d01a43f80925f8d3137e193984c.zip |
*** PASSWD CHANGE *** PLEASE READ UPDATING FOR DEFAILT INFORMATION.
YOU NEED TO SHUTDOWN BBS TO PREPARE THIS CHANGE.
- split justify to career and phone
- prevent padding in structers that wil be written to disk
git-svn-id: http://opensvn.csie.org/pttbbs/trunk/pttbbs@4194 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
-rw-r--r-- | UPDATING | 13 | ||||
-rw-r--r-- | include/pttstruct.h | 26 | ||||
-rw-r--r-- | mbbsd/admin.c | 51 | ||||
-rw-r--r-- | mbbsd/board.c | 5 | ||||
-rw-r--r-- | mbbsd/register.c | 127 | ||||
-rw-r--r-- | mbbsd/testsz.c | 21 | ||||
-rw-r--r-- | mbbsd/user.c | 68 | ||||
-rw-r--r-- | upgrade/Makefile | 2 | ||||
-rw-r--r-- | upgrade/r4194_passwd.c | 264 |
9 files changed, 424 insertions, 153 deletions
@@ -14,6 +14,19 @@ $Id$ https://opensvn.csie.org/traccgi/pttbbs/changeset/2273 ----------------------------------------------------------------------------- +r4194: [PASSWD/STRUCT] +*** PASSWD 調整: 此板把 r3968 的空間拿來放職業與電話了, + 請關站並執行 upgrade/r4194_passwd 昇級。 + +!!! 由此版起,我們把禁止 padding 的宣告加進會寫入 disk 的結構裡。 + 要注意的是如果你之前已經因為各種原因造成 padding 了, + 請自行寫轉換程式或是註解掉 pttstruct.h 內的 PACKSTRUCT + 各結構的參考大小都已標上。 + + mbbsd/testsz.c 現在可以方便你計算與比較各結構大小。 + 另外請注意如果你是在 64 bit 機器上使用卻又沒 #define TIMET64 + 很可能就會製造出一堆 padding。 + r4151: [REGISTER] 由於 PTT1/PTT2 轉換測試一切正常, 正式改用 Regform v2 的程式碼。 請比照 r4035 確定你已經把 register.new 給轉移好了。 diff --git a/include/pttstruct.h b/include/pttstruct.h index 0e73b556..88c8e10b 100644 --- a/include/pttstruct.h +++ b/include/pttstruct.h @@ -6,6 +6,9 @@ #define IDLEN 12 /* Length of bid/uid */ +// GCC pragma to prevent paddings +#define PACKSTRUCT __attribute__ ((packed)) + /* 競標資訊 */ #define SALE_COMMENTED 0x1 typedef struct bid_t { @@ -20,7 +23,7 @@ typedef struct bid_t { char flag; /* 屬性 (是否已評價) */ char pad[2]; int shipping; /* 運費 */ -} bid_t; +} PACKSTRUCT bid_t; /* 小雞的資料 */ typedef struct chicken_t { /* 128 bytes */ @@ -48,12 +51,12 @@ typedef struct chicken_t { /* 128 bytes */ int32_t mm_max; /* 滿法力 */ time4_t cbirth; /* 實際計算用的生日 */ int32_t pad[2]; /* 留著以後用 */ -} chicken_t; +} PACKSTRUCT chicken_t; #define PASSLEN 14 /* Length of encrypted passwd field */ #define REGLEN 38 /* Length of registration data */ -#define PASSWD_VERSION 2275 +#define PASSWD_VERSION 4194 typedef struct userec_t { uint32_t version; /* version number of this sturcture, we @@ -86,7 +89,16 @@ typedef struct userec_t { uint8_t invisible; /* 隱形狀態 */ char unused3[2]; uint32_t exmailbox; /* 購買信箱數 TODO short 就夠了 */ - chicken_t old_chicken; // mychicken; /* 寵物, r3968 後移出。 使用前請記得先 memset 此欄位。 */ + + // r3968 移出 chicken 128 byte + // chicken_t old_chicken; + char chkpad0[4]; /* 前面留空提高相容性(?) */ + char career[40]; + char phone[20]; + char chkpad1[52]; + time4_t chkpad2[3]; /* in case 有人忘了把 time4_t 調好... */ + // 以上應為 sizeof(chicken_t) 同等大小 + time4_t lastsong; /* 上次點歌時間 */ uint32_t loginview; /* 進站畫面 */ uint8_t channel; /* TODO unused */ @@ -118,7 +130,7 @@ typedef struct userec_t { time4_t timeremovebadpost; /* 上次刪除劣文時間 */ time4_t timeviolatelaw; /* 被開罰單時間 */ char pad[28]; -} userec_t; +} PACKSTRUCT userec_t; /* flags in userec_t.withme */ #define WITHME_ALLFLAG 0x55555555 @@ -173,7 +185,7 @@ typedef struct boardheader_t { /* 256 bytes */ char pad3[3]; time4_t SRexpire; /* SR Records expire time */ char pad4[40]; -} boardheader_t; +} PACKSTRUCT boardheader_t; // TODO BRD 快爆了,怎麼辦? 準備從 pad3 偷一個來當 attr2 吧... #define BRD_NOZAP 0x00000001 /* 不可zap */ @@ -249,7 +261,7 @@ typedef struct fileheader_t { /* 128 bytes */ /* XXX dirty, split into flag and money if money of each file is less than 16bit? */ unsigned char filemode; /* must be last field @ boards.c */ char pad3[3]; -} fileheader_t; +} PACKSTRUCT fileheader_t; #define FILE_LOCAL 0x01 /* local saved, non-mail */ #define FILE_READ 0x01 /* already read, mail only */ diff --git a/mbbsd/admin.c b/mbbsd/admin.c index 0a105e0d..e22ad368 100644 --- a/mbbsd/admin.c +++ b/mbbsd/admin.c @@ -89,6 +89,25 @@ static int retrieve_backup(userec_t *user) return -1; } +void +upgrade_passwd(userec_t *puser) +{ + if (puser->version == PASSWD_VERSION) + return; + if (!puser->userid[0]) + return; + if (puser->version == 2275) // chicken change + { + memset(puser->career, 0, sizeof(puser->career)); + memset(puser->phone, 0, sizeof(puser->phone)); + memset(puser->chkpad0, 0, sizeof(puser->chkpad0)); + memset(puser->chkpad1, 0, sizeof(puser->chkpad1)); + memset(puser->chkpad2, 0, sizeof(puser->chkpad2)); + puser->version = PASSWD_VERSION; + return; + } +} + static int search_key_user(const char *passwdfile, int mode) { @@ -109,32 +128,38 @@ search_key_user(const char *passwdfile, int mode) getdata(0, 0, "請輸入id :", key, sizeof(key), DOECHO); } else { // improved search - getdata(0, 0, "搜尋哪種欄位?" - "([0]全部 1.ID 2.姓名 3.暱稱 4.地址 5.email 6.IP 7.認證/電話) ", - key, 2, DOECHO); + vs_hdr("關鍵字搜尋"); + outs("搜尋欄位: [0]全部 1.ID 2.姓名 3.暱稱 4.地址 5.Mail 6.IP 7.職業 8.電話 9.認證\n"); + getdata(2, 0, "要搜尋哪種資料?", key, 2, NUMECHO); + if (isascii(key[0]) && isdigit(key[0])) keytype = key[0] - '0'; - if (keytype < 0 || keytype > 7) + if (keytype < 0 || keytype > 9) keytype = 0; - getdata(0, 0, "請輸入關鍵字: ", key, sizeof(key), DOECHO); + getdata(3, 0, "請輸入關鍵字: ", key, sizeof(key), DOECHO); } if(!key[0]) { fclose(fp1); return 0; } - while ((fread(&user, sizeof(user), 1, fp1)) > 0 && unum++ < MAX_USERS) { + vs_hdr(key); + + while ((fread(&user, sizeof(user), 1, fp1)) > 0 && unum++ <= MAX_USERS) { // skip empty records if (!user.userid[0]) continue; if (!(unum & 0xFF)) { - move(1, 0); + vs_hdr(key); prints("第 [%d] 筆資料\n", unum); refresh(); } + // XXX 這裡會取舊資料,要小心 PWD 的 upgrade + upgrade_passwd(&user); + keymatch = NULL; if (!mode) @@ -157,18 +182,24 @@ search_key_user(const char *passwdfile, int mode) DBCS_strcasestr(user.address, key)) keymatch = user.address; else if ((!keytype || keytype == 5) && - DBCS_strcasestr(user.email, key)) + strcasestr(user.email, key)) // not DBCS. keymatch = user.email; else if ((!keytype || keytype == 6) && - DBCS_strcasestr(user.lasthost, key)) + strcasestr(user.lasthost, key)) // not DBCS. keymatch = user.lasthost; else if ((!keytype || keytype == 7) && + DBCS_strcasestr(user.career, key)) + keymatch = user.career; + else if ((!keytype || keytype == 8) && + DBCS_strcasestr(user.phone, key)) + keymatch = user.phone; + else if ((!keytype || keytype == 9) && DBCS_strcasestr(user.justify, key)) keymatch = user.justify; } if(keymatch) { - move(1, 0); + vs_hdr(key); prints("第 [%d] 筆資料\n", unum); refresh(); diff --git a/mbbsd/board.c b/mbbsd/board.c index e999dc21..801d29c6 100644 --- a/mbbsd/board.c +++ b/mbbsd/board.c @@ -382,13 +382,10 @@ b_config(void) (bp->brdattr & BRD_IPLOGRECMD) ? ANSI_COLOR(1)"自動":"不會"); -// enable if we have it. -#ifdef EXP_ALIGNEDCMT prints( " " ANSI_COLOR(1;36) "a" ANSI_RESET " - 推文時 %s" ANSI_RESET " 開頭\n", (bp->brdattr & BRD_ALIGNEDCMT) ? - ANSI_COLOR(1)"對齊":"不對齊"); -#endif + ANSI_COLOR(1)"對齊":"不用對齊"); #ifdef USE_AUTOCPLOG prints( " " ANSI_COLOR(1;36) "x" ANSI_RESET diff --git a/mbbsd/register.c b/mbbsd/register.c index 899e78c8..7c21cd49 100644 --- a/mbbsd/register.c +++ b/mbbsd/register.c @@ -2,8 +2,6 @@ #include "bbs.h" #define FN_REGISTER_LOG "register.log" // global registration history -#define FN_JUSTIFY "justify" -#define FN_JUSTIFY_WAIT "justify.wait" #define FN_REJECT_NOTIFY "justify.reject" // Regform1 file name (deprecated) @@ -370,21 +368,6 @@ delregcodefile(void) // Justify Utilities //////////////////////////////////////////////////////////////////////////// -static void -justify_wait(char *userid, char *phone, char *career, - char *rname, char *addr, char *mobile) -{ - char buf[PATHLEN]; - sethomefile(buf, userid, FN_JUSTIFY_WAIT); - if (phone[0] != 0) { - FILE* fn = fopen(buf, "w"); - assert(fn); - fprintf(fn, "%s\n%s\ndummy\n%s\n%s\n%s\n", - phone, career, rname, addr, mobile); - fclose(fn); - } -} - static void email_justify(const userec_t *muser) { @@ -785,8 +768,7 @@ check_register(void) } int -create_regform_request( - const char *career, const char *phone) +create_regform_request() { FILE *fn; @@ -798,13 +780,11 @@ create_regform_request( return 0; // create request data - // fprintf(fn, "num: %d, %s", usernum, ctime4(&now)); fprintf(fn, "uid: %s\n", cuser.userid); fprintf(fn, "name: %s\n", cuser.realname); - fprintf(fn, "career: %s\n", career); + fprintf(fn, "career: %s\n", cuser.career); fprintf(fn, "addr: %s\n", cuser.address); - fprintf(fn, "phone: %s\n", phone); - // fprintf(fn, "mobile: %s\n", mobile); + fprintf(fn, "phone: %s\n", cuser.phone); fprintf(fn, "email: %s\n", "x"); // email is apparently 'x' here. fprintf(fn, "----\n"); fclose(fn); @@ -814,15 +794,13 @@ create_regform_request( // save justify information snprintf(cuser.justify, sizeof(cuser.justify), - "%s:%s:<Manual>", phone, career); + "<Manual>"); return 1; } static void -toregister(char *email, char *phone, char *career, char *mobile) +toregister(char *email) { - justify_wait(cuser.userid, phone, career, cuser.realname, cuser.address, mobile); - clear(); vs_hdr("認證設定"); if (cuser.userlevel & PERM_NOREGCODE){ @@ -920,18 +898,17 @@ toregister(char *email, char *phone, char *career, char *mobile) strlcpy(cuser.email, email, sizeof(cuser.email)); REGFORM2: if (strcasecmp(email, "x") == 0) { /* 手動認證 */ - if (!create_regform_request(career, phone)) + if (!create_regform_request()) { vmsg("註冊申請單建立失敗。請至 " BN_BUGREPORT " 報告。"); } } else { - // register by mail of phone - snprintf(cuser.justify, sizeof(cuser.justify), - "%s:%s:<Email>", phone, career); + // 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), - "%s:%s:<Mobile>", phone, career); + "<Mobile>"); #endif email_justify(&cuser); } @@ -949,8 +926,6 @@ u_register(void) unsigned char year, mon, day; char inregcode[14], regcode[50]; char ans[3], *errcode; - char genbuf[200]; - FILE *fn; int i = 0; if (cuser.userlevel & PERM_LOGINOK) { @@ -963,7 +938,7 @@ u_register(void) if (i > 0) { - clear(); + vs_hdr("註冊單尚在處理中"); move(3, 0); prints(" 您的註冊申請單尚在處理中(處理順位: %d),請耐心等候\n\n", i); outs(" 如果您已收到註冊碼卻看到這個畫面,那代表您在使用 Email 註冊後\n"); @@ -971,57 +946,29 @@ u_register(void) ANSI_RESET "\n\n"); outs(" 進入人工審核程序後 Email 註冊自動失效,有註冊碼也沒用,\n"); outs(" 要等到審核完成 (會多花很多時間,通常起碼數天) ,所以請耐心等候。\n\n"); - /* 下面是國王的 code 所需要的 message */ -#if 0 - outs(" 另外請注意,若站長審註冊單時您正在站上則會無法審核、自動跳過。\n"); - outs(" 所以等候審核時請勿掛站。若超過兩三天仍未被審到,通常就是這個原因。\n"); -#endif vmsg("您的註冊申請單尚在處理中"); return FULLUPDATE; } strlcpy(rname, cuser.realname, sizeof(rname)); - strlcpy(addr, cuser.address, sizeof(addr)); - strlcpy(email, cuser.email, sizeof(email)); + strlcpy(addr, cuser.address, sizeof(addr)); + strlcpy(email, cuser.email, sizeof(email)); + strlcpy(career,cuser.career, sizeof(career)); + strlcpy(phone, cuser.phone, sizeof(phone)); if (cuser.mobile) snprintf(mobile, sizeof(mobile), "0%09d", cuser.mobile); else mobile[0] = 0; + if (cuser.month == 0 && cuser.day == 0 && cuser.year == 0) birthday[0] = 0; else snprintf(birthday, sizeof(birthday), "%04i/%02i/%02i", 1900 + cuser.year, cuser.month, cuser.day); + sex_is[0] = (cuser.sex % 8) + '1'; sex_is[1] = 0; - career[0] = phone[0] = '\0'; - sethomefile(genbuf, cuser.userid, FN_JUSTIFY_WAIT); - if ((fn = fopen(genbuf, "r"))) { - fgets(genbuf, sizeof(genbuf), fn); - chomp(genbuf); - strlcpy(phone, genbuf, sizeof(phone)); - - fgets(genbuf, sizeof(genbuf), fn); - chomp(genbuf); - strlcpy(career, genbuf, sizeof(career)); - - fgets(genbuf, sizeof(genbuf), fn); // old version compatible - - fgets(genbuf, sizeof(genbuf), fn); - chomp(genbuf); - strlcpy(rname, genbuf, sizeof(rname)); - - fgets(genbuf, sizeof(genbuf), fn); - chomp(genbuf); - strlcpy(addr, genbuf, sizeof(addr)); - - fgets(genbuf, sizeof(genbuf), fn); - chomp(genbuf); - strlcpy(mobile, genbuf, sizeof(mobile)); - - fclose(fn); - } if (cuser.userlevel & PERM_NOREGCODE) { vmsg("您不被允許\使用認證碼認證。請填寫註冊申請單"); @@ -1036,7 +983,6 @@ u_register(void) strcmp(cuser.email, "x") != 0 && /* 上次手動認證失敗 */ strcmp(cuser.email, "X") != 0) { - clear(); vs_hdr("EMail認證"); move(2, 0); @@ -1077,12 +1023,8 @@ u_register(void) cuser.userlevel |= (PERM_LOGINOK | PERM_POST); outs("\n註冊成功\, 重新上站後將取得完整權限\n" "請按下任一鍵跳離後重新上站~ :)"); - sethomefile(genbuf, cuser.userid, FN_JUSTIFY_WAIT); - unlink(genbuf); snprintf(cuser.justify, sizeof(cuser.justify), - "%s:%s:email", phone, career); - sethomefile(genbuf, cuser.userid, FN_JUSTIFY); - log_file(genbuf, LOG_CREAT, cuser.justify); + "<E-Mail>: %s", Cdate(&now)); pressanykey(); u_exit("registed"); exit(0); @@ -1096,11 +1038,11 @@ u_register(void) else { vmsg("認證碼已過期,請重新註冊。"); - toregister(email, phone, career, mobile); + toregister(email); return FULLUPDATE; } } else { - toregister(email, phone, career, mobile); + toregister(email); return FULLUPDATE; } } @@ -1210,26 +1152,27 @@ u_register(void) } // 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.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 (fore[0]) cuser.uflag2 |= FOREIGN; else cuser.uflag2 &= ~FOREIGN; #endif - trim(career); - trim(addr); - trim(phone); // if reach here, email is apparently 'x'. - toregister(email, phone, career, mobile); + toregister(email); // update cuser passwd_update(usernum, &cuser); @@ -1430,12 +1373,8 @@ regform_accept(const char *userid, const char *justify) strlcpy(muser.email, "x", sizeof(muser.email)); // handle files - sethomefile(buf, muser.userid, FN_JUSTIFY_WAIT); - unlink(buf); sethomefile(buf, muser.userid, FN_REJECT_NOTIFY); unlink(buf); - sethomefile(buf, muser.userid, FN_JUSTIFY); - log_filef(buf, LOG_CREAT, "%s\n", muser.justify); // update password file passwd_update(unum, &muser); @@ -1475,8 +1414,6 @@ regform_reject(const char *userid, const char *reason, const RegformEntry *pre) muser.userlevel &= ~(PERM_LOGINOK | PERM_POST); // handle files - sethomefile(buf, muser.userid, FN_JUSTIFY_WAIT); - unlink(buf); // update password file passwd_update(unum, &muser); @@ -1699,17 +1636,15 @@ regfrm_accept(RegformEntry *pre, int priority) sethomefile(fn, pre->userid, FN_REGFORM); // build justify string - removespace(pre->phone); - removespace(pre->career); snprintf(justify, sizeof(justify), - "%s:%s:%s", pre->phone, pre->career, cuser.userid); + "[%s] %s", cuser.userid, Cdate(&now)); // call handler regform_accept(pre->userid, justify); // append current form to history. sethomefile(fnlog, pre->userid, FN_REGFORM_LOG); - snprintf(buf, sizeof(buf), "Date: %s", Cdate(&now)); + snprintf(buf, sizeof(buf), "Date: %s\n", Cdate(&now)); file_append_line(fnlog, buf); AppendTail(fn, fnlog, 0); // global history @@ -2311,10 +2246,10 @@ regform2_validate_page(int dryrun) for (i = 0; i < cforms; i++) { - char justify[REGLEN]; + char justify[REGLEN+1]; if (ans[i] == 'y') snprintf(justify, sizeof(justify), // build justify string - "%s:%s:%s", forms[i].phone, forms[i].career, cuser.userid); + "%s %s", cuser.userid, Cdate(&now)); prints("%2d. %-12s - %c %s\n", i+1, forms[i].userid, ans[i], ans[i] == 'n' ? rejects[i] : diff --git a/mbbsd/testsz.c b/mbbsd/testsz.c new file mode 100644 index 00000000..99d4ad22 --- /dev/null +++ b/mbbsd/testsz.c @@ -0,0 +1,21 @@ +#include <stdio.h> +#include <sys/types.h> +#include "bbs.h" + +int main() +{ + printf("sizeof(size_t) = %lu\n", sizeof(size_t)); + printf("sizeof(off_t) = %lu\n", sizeof(off_t)); + printf("sizeof(int) = %lu\n", sizeof(int)); + printf("sizeof(long) = %lu\n", sizeof(long)); + printf("sizeof(time_t) = %lu\n", sizeof(time_t)); + printf("sizeof(time4_t) = %lu %s\n", sizeof(time4_t), sizeof(time4_t) == 4 ? "" : "ERROR!!!!!"); + printf("sizeof(userec_t) = %lu\n", sizeof(userec_t)); + printf("sizeof(fileheader_t) = %lu\n", sizeof(fileheader_t)); + printf("sizeof(boardheader_t) = %lu\n", sizeof(boardheader_t)); + printf("sizeof(chicken_t) = %lu\n", sizeof(chicken_t)); + printf("sizeof(userinfo_t) = %lu\n", sizeof(userinfo_t)); + printf("sizeof(msgque_t) = %lu\n", sizeof(msgque_t)); + printf("sizeof(SHM_t) = %lu\n", sizeof(SHM_t)); + return 0; +} diff --git a/mbbsd/user.c b/mbbsd/user.c index 44985776..18f5576d 100644 --- a/mbbsd/user.c +++ b/mbbsd/user.c @@ -124,60 +124,58 @@ user_display(const userec_t * u, int adminmode) " " ANSI_COLOR(30;41) "┴┬┴┬┴┬" ANSI_RESET " " ANSI_COLOR(1;30;45) " 使 用 者" " 資 料 " " " ANSI_RESET " " ANSI_COLOR(30;41) "┴┬┴┬┴┬" ANSI_RESET "\n"); - prints(" 代號暱稱: %s(%s)\n" - " 真實姓名: %s" -#if FOREIGN_REG_DAY > 0 - " %s%s" -#elif defined(FOREIGN_REG) - " %s" -#endif - "\n" - " 居住住址: %s\n" - " 電子信箱: %s\n" - " 性 別: %s\n" - " 銀行帳戶: %d 銀兩\n", - u->userid, u->nickname, u->realname, + prints("\t\t代號暱稱: %s(%s)\n", u->userid, u->nickname); + prints("\t\t真實姓名: %s", u->realname); #if FOREIGN_REG_DAY > 0 + prints(" %s%s", u->uflag2 & FOREIGN ? "(外籍: " : "", u->uflag2 & FOREIGN ? (u->uflag2 & LIVERIGHT) ? "永久居留)" : "未取得居留權)" - : "", + : ""); #elif defined(FOREIGN_REG) - u->uflag2 & FOREIGN ? "(外籍)" : "", + prints(" %s" u->uflag2 & FOREIGN ? "(外籍)" : ""); #endif - u->address, u->email, - sex[u->sex % 8], u->money); - - sethomedir(genbuf, u->userid); - prints(" 私人信箱: %d 封 (購買信箱: %d 封)\n" - " 手機號碼: %010d\n" - " 生 日: %04i/%02i/%02i (%s滿18歲)\n", - get_num_records(genbuf, sizeof(fileheader_t)), - u->exmailbox, u->mobile, + outs("\n"); // end of realname + prints("\t\t職業學歷: %s\n", u->career); + prints("\t\t居住地址: %s\n", u->address); + prints("\t\t電話手機: %s", u->phone); + if (u->mobile) + prints(" / %010d", u->mobile); + outs("\n"); + + prints("\t\t電子信箱: %s\n", u->email); + prints("\t\t銀行帳戶: %d 銀兩\n", u->money); + prints("\t\t性 別: %s\n", sex[u->sex%8]); + prints("\t\t生 日: %04i/%02i/%02i (%s滿18歲)\n", u->year + 1900, u->month, u->day, - resolve_over18_user(u) ? "已" : "未" - ); + resolve_over18_user(u) ? "已" : "未"); - prints(" 註冊日期: (已滿%d天) %s", + prints("\t\t註冊日期: (已滿%d天) %s", (int)((now - u->firstlogin)/86400), ctime4(&u->firstlogin)); - prints(" 上次上站: %s (%s)\n", u->lasthost, Cdate(&u->lastlogin)); + prints("\t\t上次上站: %s (%s)\n", + u->lasthost, Cdate(&u->lastlogin)); if (adminmode) { strcpy(genbuf, "bTCPRp#@XWBA#VSM0123456789ABCDEF"); for (diff = 0; diff < 32; diff++) if (!(u->userlevel & (1 << diff))) genbuf[diff] = '-'; - prints(" 帳號權限: %s\n", genbuf); - prints(" 認證資料: %s\n", u->justify); + prints("\t\t帳號權限: %s\n", genbuf); + prints("\t\t認證資料: %s\n", u->justify); } - prints(" 上站文章: %d 次 / %d 篇\n", + prints("\t\t上站文章: %d 次 / %d 篇\n", u->numlogins, u->numposts); + sethomedir(genbuf, u->userid); + prints("\t\t私人信箱: %d 封 (購買信箱: %d 封)\n", + get_num_records(genbuf, sizeof(fileheader_t)), + u->exmailbox); + if (!adminmode) { diff = (now - login_start_time) / 60; - prints(" 停留期間: %d 小時 %2d 分\n", + prints("\t\t停留期間: %d 小時 %2d 分\n", diff / 60, diff % 60); } @@ -186,7 +184,7 @@ user_display(const userec_t * u, int adminmode) int i; boardheader_t *bhdr; - outs(" 擔任板主: "); + outs("\t\t擔任板主: "); for (i = 0, bhdr = bcache; i < numboards; i++, bhdr++) { if (is_uBM(bhdr->BM, u->userid)) { @@ -199,7 +197,7 @@ user_display(const userec_t * u, int adminmode) // conditional fields #ifdef ASSESS - prints(" 優 劣 文: 優:%d / 劣:%d\n", + prints("\t\t優 劣 文: 優:%d / 劣:%d\n", u->goodpost, u->badpost); #endif // ASSESS @@ -223,7 +221,7 @@ user_display(const userec_t * u, int adminmode) #ifdef PLAY_ANGEL if (adminmode) - prints(" 小 天 使: %s\n", + prints("\t\t小 天 使: %s\n", u->myangel[0] ? u->myangel : "無"); #endif diff --git a/upgrade/Makefile b/upgrade/Makefile index 51633d9f..833881b1 100644 --- a/upgrade/Makefile +++ b/upgrade/Makefile @@ -8,7 +8,7 @@ CFLAGS+= -DPTTBBS_UTIL BBSBASE= $(SRCROOT)/include/var.h -#UTIL_OBJS= \ +UTIL_OBJS= \ util_cache.o util_record.o util_passwd.o util_var.o \ util_stuff.o diff --git a/upgrade/r4194_passwd.c b/upgrade/r4194_passwd.c new file mode 100644 index 00000000..3e6c97c4 --- /dev/null +++ b/upgrade/r4194_passwd.c @@ -0,0 +1,264 @@ +#include "bbs.h" + +int trans = 0; +int partial = 0; +int justified = 0; +int regformed = 0; + +char * const str_space = " \t\n\r"; + + +//////////////////////////////////////////////////////////////////////////// +// Regform Utilities +//////////////////////////////////////////////////////////////////////////// +#define FN_REGFORM "regform" +#define FN_REQLIST "reg.wait" + +// TODO define and use structure instead, even in reg request file. +typedef struct { + char userid[IDLEN+1]; + char name [20]; + char career[40]; + char addr [50]; + char phone [20]; +} RegformEntry; + +// regform format utilities +int +load_regform_entry(RegformEntry *pre, FILE *fp) +{ + char buf[STRLEN]; + char *v; + + memset(pre, 0, sizeof(RegformEntry)); + while (fgets(buf, sizeof(buf), fp)) + { + if (buf[0] == '-') + break; + buf[sizeof(buf)-1] = 0; + v = strchr(buf, ':'); + if (v == NULL) + continue; + *v++ = 0; + if (*v == ' ') v++; + chomp(v); + + if (strcmp(buf, "uid") == 0) + strlcpy(pre->userid, v, sizeof(pre->userid)); + else if (strcmp(buf, "name") == 0) + strlcpy(pre->name, v, sizeof(pre->name)); + else if (strcmp(buf, "career") == 0) + strlcpy(pre->career, v, sizeof(pre->career)); + else if (strcmp(buf, "addr") == 0) + strlcpy(pre->addr, v, sizeof(pre->addr)); + else if (strcmp(buf, "phone") == 0) + strlcpy(pre->phone, v, sizeof(pre->phone)); + } + return pre->userid[0] ? 1 : 0; +} + +int +regfrm_load(const char *userid, RegformEntry *pre) +{ + FILE *fp = NULL; + char fn[PATHLEN]; + int ret = 0; + sethomefile(fn, userid, FN_REGFORM); + if (!dashf(fn)) + return 0; + + fp = fopen(fn, "rt"); + if (!fp) + return 0; + ret = load_regform_entry(pre, fp); + fclose(fp); + return ret; +} + +// working queue +FILE * +regq_init_pull() +{ + FILE *fp = tmpfile(), *src =NULL; + char buf[STRLEN]; + if (!fp) return NULL; + src = fopen(FN_REQLIST, "rt"); + if (!src) { fclose(fp); return NULL; } + while (fgets(buf, sizeof(buf), src)) + fputs(buf, fp); + fclose(src); + rewind(fp); + return fp; +} + +int +regq_pull(FILE *fp, char *uid) +{ + char buf[STRLEN]; + size_t idlen = 0; + uid[0] = 0; + if (fgets(buf, sizeof(buf), fp) == NULL) + return 0; + idlen = strcspn(buf, str_space); + if (idlen < 1) return 0; + if (idlen > IDLEN) idlen = IDLEN; + strlcpy(uid, buf, idlen+1); + return 1; +} + +int +regq_end_pull(FILE *fp) +{ + // no need to unlink because fp is a tmpfile. + if (!fp) return 0; + fclose(fp); + return 1; +} + +void transform(userec_t *new, userec_t *old, int i) +{ + char fn[1024]; + char *s, *s2; + memcpy(new, old, sizeof(userec_t)); + + // already converted? + if (old->version == PASSWD_VERSION || !old->userid[0]) + return; + + if (old->version != 2275 && old->userid[0]) + { + fprintf(stderr, "invalid record at %d: %s\n", i, old->userid); + if (i == 1) + memset(new, 0, sizeof(userec_t)); + return; + } + + // update version info + new->version = PASSWD_VERSION; + // zero out + memset(new->career, 0, sizeof(new->career)); + memset(new->phone, 0, sizeof(new->phone)); + memset(new->chkpad0, 0, sizeof(new->chkpad0)); + memset(new->chkpad1, 0, sizeof(new->chkpad1)); + memset(new->chkpad2, 0, sizeof(new->chkpad2)); + + // quick skip + if (!old->justify[0] || !old->userid[0]) + return; + + printf("%s ", old->userid); + printf("%s -> ", old->justify); + + s = old->justify; + + // process only if justify is truncated. + while (strlen(old->justify) == sizeof(old->justify) -1) + { + RegformEntry re; + + // try regform first. + if (regfrm_load(old->userid, &re)) { + // trust the form. + strlcpy(new->career, re.career, sizeof(new->career)); + strlcpy(new->phone, re.phone, sizeof(new->phone)); + // justify will be updated someday... throw it + printf("<regq> [%s][%s][%s]\n", new->career, new->phone, new->justify); + regformed ++; + trans++; + return; + } + + // try to build from ~/justify, if exists. + sethomefile(fn, old->userid, "justify"); + if (dashf(fn)) { + FILE *fp = fopen(fn, "rt"); + fn[0] = 0; + fgets(fn, sizeof(fn), fp); + fclose(fp); + chomp(fn); + + if (strlen(fn) > strlen(s)) + { + char *xs; + int quotes = 3; + s = fn; + // some justifies have multiple entries without \n... + xs = s + strlen(s); + while (quotes > 0 && xs > s) + if (*--xs == ':') + quotes--; + if (xs > s) + s = xs+1; + + justified ++; + } + } + + break; + } + + // build career/phone + s2 = strchr(s, ':'); + if (s2) { + *s2++ = 0; + while (*s && !isdigit(*s) && *s != '(') s++; + strlcpy(new->phone, s, sizeof(new->phone)); + strlcpy(new->justify, s2, sizeof(new->justify)); + s = s2; + s2 = strchr(s, ':'); + if (s2) + { + *s2++ = 0; + } + else if (new->userlevel & PERM_LOGINOK) + { + // skip non-loginOK users + partial ++; + printf(" <partial> "); + } + strlcpy(new->career, s, sizeof(new->career)); + if (s2) + strlcpy(new->justify, s2, sizeof(new->justify)); + else + strlcpy(new->justify, "", sizeof(new->justify)); + } + printf("[%s][%s][%s]\n", new->career, new->phone, new->justify); + + trans++; +} + +int main(void) +{ + int fd, fdw; + userec_t new; + userec_t old; + int i = 0; + + printf("sizeof(userec_t)=%lu\n", 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); + + // TODO use FN_REQLIST to process other forms + printf("total %d records translated (%d partial, %d justified, %d regformed).\n", + trans, partial, justified, regformed); + return 0; +} |