精華區beta SetupBBS 關於我們 聯絡資訊
/*-------------------------------------------------------*/ /* user.c ( NTHU CS MapleBBS Ver 2.36 ) */ /*-------------------------------------------------------*/ /* author : opus.bbs@bbs.cs.nthu.edu.tw */ /* target : user configurable setting routines */ /* create : 95/03/29 */ /* update : 95/12/15 */ /*-------------------------------------------------------*/ #include "bbs.h" extern int numboards; extern boardheader *bcache; extern void resolve_boards(); char *sex[8] = { MSG_BIG_BOY, MSG_BIG_GIRL, MSG_LITTLE_BOY, MSG_LITTLE_GIRL, MSG_MAN, MSG_WOMAN, MSG_PLANT, MSG_MIME }; void user_display(u, real) userec *u; { int diff; char genbuf[200]; clrtobot(); prints( "代號 :%s\n" "暱稱 :%s\n" "真實姓名 :%s\n" "居住住址 :%s\n" "電子郵件信箱:%s\n" "性別 :%s\n" "銀行帳戶 :%ld 銀兩\n" "生日 :%02i/%02i/%02i\n", u->userid, u->username, u->realname, u->address, u->email, sex[u->sex], u->money, u->month, u->day, u->year); prints(/*"終端機形態 :%s\n"*/ "註冊日期 :%s", /*u->termtype,*/ ctime(&u->firstlogin)); prints("最近光臨日期:%s", ctime(&u->lastlogin)); if (real) prints("最近光臨機器:%s\n", u->lasthost); prints("上站次數 :%d 次\n", u->numlogins); prints("文章數目 :%d 篇\n", u->numposts); sethomedir(genbuf, u->userid); prints("私人信箱 :%d 封\n", get_num_records(genbuf, sizeof(fileheader))); if (real) { strcpy(genbuf, "bTCPRp#@XWBA#VS"); for (diff = 0; diff < 15; diff++) if (!(u->userlevel & (1 << diff))) genbuf[diff] = '-'; prints("認證資料 :%s\n使用者權限 :%s\n", u->justify, genbuf); } else { diff = (time(0) - login_start_time) / 60; prints("停留期間 :%d 小時 %2d 分\n", diff / 60, diff % 60); } /* Thor: 想看看這個 user 是那些版的版主 */ if (u->userlevel >= PERM_BM) { int i, len, ch; boardheader *bhdr; char *list; resolve_boards(); len = strlen(u->userid); outs("擔任板主 :"); for (i = 0, bhdr = bcache; i < numboards; i++, bhdr++) { list = bhdr->BM; ch = list[0]; if ((ch > ' ') && (ch < 128)) { do { if (!ci_strncmp(list, u->userid, len)) { ch = list[len]; if ((ch == 0) || (ch == '/')) { outs(bhdr->brdname); outc(' '); break; } } while (ch = *list++) if (ch == '/') break; } while (ch); } } outc('\n'); } outs((u->userlevel & PERM_LOGINOK) ? "\n您的註冊程序已經完成,歡迎加入本站" : "\n如果要提昇權限,請參考本站公佈欄辦理註冊"); #ifdef NEWUSER_LIMIT if ((u->lastlogin - u->firstlogin < 3 * 86400) && !HAS_PERM(PERM_POST)) outs("\n新手上路,三天後開放權限"); #endif } void uinfo_query(u, real, unum) userec *u; { userec x; register int i, fail, mail_changed; char ans[4], buf[STRLEN]; char genbuf[200]; int flag=0,temp; char *genpasswd(); fail = mail_changed = 0; memcpy(&x, u, sizeof(userec)); getdata(b_lines - 1, 0, real ? "(1)修改資料 (2)設定密碼 (3)設定權限 (4)清除帳號 (5)改ID [0]結束 " : "請選擇 (1)修改資料 (2)設定密碼 ==> [0]結束 ", ans, 3, DOECHO); if (ans[0] > '2' && !real) { ans[0] = '0'; } if (ans[0] == '1' || ans[0] == '3') { clear(); i = 2; move(i++, 0); outs(msg_uid); outs(x.userid); } switch (ans[0]) { case '1': move(0, 0); outs("請逐項修改。"); getdata_buf(i++, 0," 暱 稱 :",x.username, 24, DOECHO); getdata_buf(i++, 0,"真實姓名:",x.realname, 20, DOECHO); getdata_buf(i++, 0,"居住地址:",x.address, 50, DOECHO); getdata_str(i++, 0,"電子信箱:",buf, 50, DOECHO,x.email); if ( strcmp(buf,x.email) && strchr(buf, '@')) { strcpy(x.email,buf); mail_changed = 1 - real; } sprintf(genbuf, "%i", u->sex + 1); getdata_str(i++, 0, "性別 (1)葛格 (2)姐接 (3)底迪 (4)美眉 (5)薯叔 (6)阿姨 (7)植物 (8)礦物:", buf, 3, DOECHO,genbuf); if (buf[0] >= '1' && buf[0] <= '8') x.sex = buf[0] - '1'; else x.sex = u->sex; while (1) { int len; sprintf(genbuf, "%02i/%02i/%02i", u->month, u->day, u->year); len = getdata_str(i, 0, "生日 月月/日日/西元:", buf, 9, DOECHO,genbuf); if (len && len != 8) continue; if (!len) { x.month = u->month; x.day = u->day; x.year = u->year; } else if (len == 8) { x.month = (buf[0] - '0') * 10 + (buf[1] - '0'); x.day = (buf[3] - '0') * 10 + (buf[4] - '0'); x.year = (buf[6] - '0') * 10 + (buf[7] - '0'); } else continue; if (!real && (x.month > 12 || x.month < 1 || x.day > 31 || x.day < 1 || x.year > 90 || x.year < 40)) continue; i++; break; } if (real) { unsigned long int l; sprintf(genbuf, "%ld", x.money); if (getdata_str(i++, 0,"銀行帳戶:", buf, 10, DOECHO,genbuf)) if ((l = atol(buf)) >= 0) x.money = l; getdata_buf(i++, 0,"認證資料:", x.justify, 44, DOECHO); getdata_buf(i++, 0,"最近光臨機器:", x.lasthost, 16, DOECHO); sprintf(genbuf, "%d", x.numlogins); if (getdata_str(i++, 0,"上線次數:", buf, 10, DOECHO,genbuf)) if ((fail = atoi(buf)) >= 0) x.numlogins = fail; sprintf(genbuf,"%d", u->numposts); if (getdata_str(i++, 0, "文章數目:", buf, 10, DOECHO,genbuf)) if ((fail = atoi(buf)) >= 0) x.numposts = fail; fail = 0; } break; case '2': i = 19; if (!real) { if (!getdata(i++, 0, "請輸入原密碼:", buf, PASSLEN, NOECHO) || !checkpasswd(u->passwd, buf)) { outs("\n\n您輸入的密碼不正確\n"); fail++; break; } } if (!getdata(i++, 0, "請設定新密碼:", buf, PASSLEN, NOECHO)) { outs("\n\n密碼設定取消, 繼續使用舊密碼\n"); fail++; break; } strncpy(genbuf, buf, PASSLEN); getdata(i++, 0, "請檢查新密碼:", buf, PASSLEN, NOECHO); if (strncmp(buf, genbuf, PASSLEN)) { outs("\n\n新密碼確認失敗, 無法設定新密碼\n"); fail++; break; } buf[8] = '\0'; strncpy(x.passwd, genpasswd(buf), PASSLEN); break; case '3': i = setperms(x.userlevel); if (i == x.userlevel) fail++; else { flag=1; temp=x.userlevel; x.userlevel = i; } break; case '4': i = QUIT; break; case '5': if (getdata_str(b_lines - 3, 0, "新的使用者代號:", genbuf, IDLEN + 1, DOECHO,x.userid)) { if (searchuser(genbuf)) { outs("錯誤! 已經有同樣 ID 的使用者"); fail++; } else { strcpy(x.userid, genbuf); } } break; default: return; } if (fail) { pressanykey(); return; } getdata(b_lines - 1, 0, msg_sure_ny, ans, 3, LCECHO); if (*ans == 'y') { if (flag) Security(temp,i,cuser.userid,x.userid); if (strcmp(u->userid, x.userid)) { char src[STRLEN], dst[STRLEN]; sethomepath(src, u->userid); sethomepath(dst, x.userid); Rename(src, dst); setuserid(unum, x.userid); } memcpy(u, &x, sizeof(x)); if (mail_changed) { #ifdef EMAIL_JUSTIFY x.userlevel &= ~PERM_LOGINOK; mail_justify(); #endif } if (i == QUIT) { char src[STRLEN], dst[STRLEN]; sprintf(src, "home/%s", x.userid); sprintf(dst, "tmp/%s", x.userid); if (Rename(src, dst)) { sprintf(genbuf, "/bin/rm -fr %s", src); system(genbuf); } /* woju */ log_usies("KILL", x.userid); x.userid[0] = '\0'; setuserid(unum, x.userid); } else log_usies("SetUser", x.userid); substitute_record(fn_passwd, &x, sizeof(x), unum); } } int u_info() { move(2, 0); user_display(&cuser, 0); uinfo_query(&cuser, 0, usernum); strcpy(currutmp->realname, cuser.realname); strcpy(currutmp->username, cuser.username); return 0; } int u_ansi() { showansi ^= 1; cuser.uflag ^= COLOR_FLAG; outs(reset_color); return 0; } int u_cloak() { outs((currutmp->invisible ^= 1) ? MSG_CLOAKED : MSG_UNCLOAK); return XEASY; } int u_switchproverb() { /* char *state[4]={"用功\型","安逸型","自定型","SHUTUP"}; */ char buf[100]; cuser.proverb =(cuser.proverb +1) %4; setuserfile(buf,fn_proverb); if( cuser.proverb==2 && dashd(buf)) { FILE *fp=fopen(buf,"a"); fprintf(fp,"座右銘狀態為[自定型]要記得設座右銘的內容唷!!"); fclose(fp); } substitute_record(fn_passwd, &cuser, sizeof(cuser), usernum); /* move(22,2); clrtoeol(); sprintf(buf,"座右銘(半點callin) 已切換成 [%s] " ,state[cuser.proverb]); outs(buf); pressanykey(); */ return 0; } int u_editproverb() { char buf[100]; setutmpmode(PROVERB); setuserfile(buf,fn_proverb); move(1,0); clrtobot(); outs("\n\n 請一行一行依序鍵入想系統提醒你的內容," "\n 儲存後記得把狀態設為 [自定型] 才有作用" "\n 座右銘最多100條"); pressanykey(); vedit(buf,NA); return 0; } /* Ptt拿掉 int u_lock() { char genbuf[PASSLEN]; log_usies("LOCK ", "screen"); do { getdata(b_lines - 1, 0, "▲ 請輸入密碼,以解除螢幕鎖定:", genbuf, PASSLEN, NOECHO); } while (!checkpasswd(cuser.passwd, genbuf)); return FULLUPDATE; } */ #ifdef HAVE_SUICIDE int u_kill() { char genbuf[200]; getdata(b_lines - 1, 0, "▲ 如果確定要清除您的帳號,請輸入密碼:", genbuf, PASSLEN, NOECHO); if (*genbuf == '\0' || !checkpasswd(cuser.passwd, genbuf)) { outmsg("您輸入的密碼不正確,帳號未清除。"); igetch(); return FULLUPDATE; } #ifdef HAVE_REPORT report("suicide"); #endif sprintf(genbuf, "#%d %s:%s %d %d", usernum, cuser.realname, cuser.username, cuser.numlogins, cuser.numposts); log_usies("SUCI ", genbuf); sprintf(genbuf, "%s %s", fromhost, Cdate(&(cuser.firstlogin))); log_usies("SUCI ", genbuf); sethomepath(genbuf, cuser.userid); if (Rename(genbuf, "tmp")) { /* woju */ sprintf(genbuf, "(cd home; tar cvf SUCI_%s.tar %s); /bin/rm -fr home/%s", cuser.userid, cuser.userid, cuser.userid); system(genbuf); } cuser.userid[0] = '\0'; substitute_record(fn_passwd, &cuser, sizeof(cuser), usernum); setuserid(usernum, cuser.userid); purge_utmp(currutmp); clear(); outs("親愛的朋友,青山長在,綠水長流,咱們後會有期吧!"); pressanykey(); sleep(1); reset_tty(); exit(0); } #endif void showplans(uid) char *uid; { FILE *planfile; int i; char genbuf[200]; sethomefile(genbuf, uid, fn_plans); if (planfile = fopen(genbuf, "r")) { prints("%s 的名片:\n", uid); i = 0; while (i++ < MAXQUERYLINES && fgets(genbuf, 256, planfile)) { strip_ansi(genbuf,genbuf,1); outs(Ptt_prints(genbuf)); } fclose(planfile); } else prints("%s 目前沒有名片", uid); } int showsignature(fname) char *fname; { FILE *fp; char buf[256]; int i, j; char ch; clear(); move(2, 0); setuserfile(fname, "sig.0"); j = strlen(fname) - 1; for (ch = '1'; ch <= '9'; ch++) { fname[j] = ch; if (fp = fopen(fname, "r")) { prints("【 簽名檔.%c 】\n", ch); for (i = 0; i++ < MAXSIGLINES && fgets(buf, 256, fp); outs(buf)); fclose(fp); } } return j; } int u_editsig() { int aborted; char ans[4]; int j; char genbuf[200]; j = showsignature(genbuf); getdata(0, 0, "簽名檔 (E)編輯 (D)刪除 (Q)取消?[Q] ", ans, 4, LCECHO); aborted = 0; if (ans[0] == 'd') aborted = 1; if (ans[0] == 'e') aborted = 2; if (aborted) { if (!getdata(1, 0, "請選擇簽名檔(1-9)?[1] ", ans, 4, DOECHO)) ans[0] = '1'; if (ans[0] >= '1' && ans[0] <= '9') { genbuf[j] = ans[0]; if (aborted == 1) { unlink(genbuf); outs(msg_del_ok); } else { setutmpmode(EDITSIG); aborted = vedit(genbuf, NA); if (aborted != -1) outs("簽名檔更新完畢"); } } pressanykey(); } return 0; } int u_editplan() { char genbuf[200]; getdata(b_lines - 1, 0, "名片 (D)刪除 (E)編輯 [Q]取消?[Q] ", genbuf, 3, LCECHO); if (genbuf[0] == 'e') { int aborted; setutmpmode(EDITPLAN); setuserfile(genbuf, fn_plans); aborted = vedit(genbuf, NA); if (aborted != -1) outs("名片更新完畢"); pressanykey(); return 0; } else if (genbuf[0] == 'd') { setuserfile(genbuf, fn_plans); unlink(genbuf); outmsg("名片刪除完畢"); } return 0; } /* --------------------------------------------- */ /* 使用者填寫註冊表格 */ /* --------------------------------------------- */ static void getfield(line, info, desc, buf, len) int line, len; char *info, *desc, *buf; { char prompt[STRLEN]; char genbuf[200]; sprintf(genbuf, "原先設定:%-30.30s (%s)", buf, info); move(line, 2); outs(genbuf); sprintf(prompt, "%s:", desc); if (getdata(line + 1, 2, prompt, genbuf, len, DOECHO)) strcpy(buf, genbuf); move(line, 2); prints("%s:%s", desc, buf); clrtoeol(); } int u_register() { char rname[20], addr[50]; char phone[20], career[40], email[50],birthday[9],sex_is[2],year,mon,day; char ans[3], *ptr; FILE *fn; time_t now; char genbuf[200]; if (cuser.userlevel & PERM_LOGINOK) { outs("您的身份確認已經完成,不需填寫申請表"); return XEASY; } if (fn = fopen(fn_register, "r")) { while (fgets(genbuf, STRLEN, fn)) { if (ptr = strchr(genbuf, '\n')) *ptr = '\0'; if (strncmp(genbuf, "uid: ", 5) == 0 && strcmp(genbuf + 5, cuser.userid) == 0) { fclose(fn); outs("您的註冊申請單尚在處理中,請耐心等候"); return XEASY; } } fclose(fn); } getdata(b_lines - 1, 0, "您確定要填寫註冊單嗎(Y/N)?[N] ", ans, 3, LCECHO); if (ans[0] != 'y') return FULLUPDATE; move(2, 0); clrtobot(); strcpy(rname, cuser.realname); strcpy(addr, cuser.address); strcpy(email, cuser.email); sprintf(birthday, "%02i/%02i/%02i", cuser.month, cuser.day, cuser.year); sex_is[0]=cuser.sex+'1';sex_is[1]=0; career[0] = phone[0] = '\0'; while (1) { clear(); move(3, 0); prints("%s(%s) 您好,請據實填寫以下的資料:", cuser.userid, cuser.username); getfield(6, "請用中文", "真實姓名", rname, 20); getfield(8, "學校系級或單位職稱", "服務單位", career, 40); getfield(10, "包括寢室或門牌號碼", "目前住址", addr, 50); getfield(12, "包括長途撥號區域碼", "連絡電話", phone, 20); while (1) { int len; getfield(14, "月月/日日/西元 如:09/27/76","生日",birthday,9); len = strlen(birthday); if(!len) { sprintf(birthday, "%02i/%02i/%02i", cuser.month, cuser.day, cuser.year); mon=cuser.month; day=cuser.day; year=cuser.year; } else if (len==8) { mon = (birthday[0] - '0') * 10 + (birthday[1] - '0'); day = (birthday[3] - '0') * 10 + (birthday[4] - '0'); year = (birthday[6] - '0') * 10 + (birthday[7] - '0'); } else continue; if (mon > 12 || mon < 1 || day > 31 || day < 1 || year > 90 || year < 40) continue; break; } getfield(16, "1.葛格 2.姐接 ","性別",sex_is,2); getfield(18, "身分認證用", "E-Mail Address", email, 50); getdata(b_lines - 1, 0, "以上資料是否正確(Y/N)?(Q)取消註冊 [N] ", ans, 3, LCECHO); if (ans[0] == 'q') return 0; if (ans[0] == 'y') break; } strcpy(cuser.realname, rname); strcpy(cuser.address, addr); strcpy(cuser.email, email); cuser.sex= sex_is[0]-'1'; cuser.month=mon;cuser.day=day;cuser.year=year; if (fn = fopen(fn_register, "a")) { now = time(NULL); trim(career); trim(addr); trim(phone); fprintf(fn, "num: %d, %s", usernum, ctime(&now)); fprintf(fn, "uid: %s\n", cuser.userid); fprintf(fn, "name: %s\n", rname); fprintf(fn, "career: %s\n", career); fprintf(fn, "addr: %s\n", addr); fprintf(fn, "phone: %s\n", phone); fprintf(fn, "email: %s\n", email); fprintf(fn, "----\n"); fclose(fn); } clear(); move(9,3); prints("最後Post一篇自我介紹文章給大家吧,告訴所有老骨頭我來啦^$。\ \n\n\n\n"); pressanykey(); brc_initial("WhoAmI"); set_board(); do_post(); return 0; } /* --------------------------------------------- */ /* 列出所有註冊使用者 */ /* --------------------------------------------- */ extern struct UCACHE *uidshm; int usercounter, totalusers, showrealname; ushort u_list_special; extern int bad_user_id(char userid[]); static int u_list_CB(uentp) userec *uentp; { static int i; char permstr[8], *ptr; register int level; if (uentp == NULL) { move(2, 0); clrtoeol(); prints(" 使用者代號 %-25s 上站 文章 %s 最近光臨日期 \n", showrealname ? /*#if defined(REALINFO) && defined(ACTS_REALNAMES)*/ "真實姓名" : /*#else*/ "綽號暱稱" /*#endif*/ ,HAS_PERM(PERM_SEEULEVELS) ? "等級" : ""); i = 3; return 0; } if (bad_user_id(uentp->userid)) /* Ptt */ return 0; if (uentp->userlevel < u_list_special) return 0; if (i == b_lines) { prints(" 已顯示 %d/%d 人(%d%%) (Space) 看下一頁 (Q) 離開 ", usercounter, totalusers, usercounter * 100 / totalusers); i = igetch(); if (i == 'q' || i == 'Q') return QUIT; i = 3; } if (i == 3) { move(3, 0); clrtobot(); } level = uentp->userlevel; strcpy(permstr, "----"); if (level & PERM_SYSOP) permstr[0] = 'S'; else if (level & PERM_ACCOUNTS) permstr[0] = 'A'; else if (level & PERM_DENYPOST) permstr[0] = 'p'; if (level & (PERM_BOARD)) permstr[1] = 'B'; else if (level & (PERM_BM)) permstr[1] = 'b'; if (level & (PERM_XEMPT)) permstr[2] = 'X'; else if (level & (PERM_LOGINOK)) permstr[2] = 'R'; if (level & (PERM_CLOAK | PERM_SEECLOAK)) permstr[3] = 'C'; ptr = (char *) Cdate(&uentp->lastlogin); ptr[18] = '\0'; prints("%-14s %-27.27s%5d %5d %s %s\n", uentp->userid, showrealname ? /*#if defined(REALINFO) && defined(ACTS_REALNAMES)*/ uentp->realname : /*#else*/ uentp->username /*#endif*/ ,uentp->numlogins, uentp->numposts, HAS_PERM(PERM_SEEULEVELS) ? permstr : "", ptr); usercounter++; i++; return 0; } int u_list() { char genbuf[3]; setutmpmode(LAUSERS); showrealname = u_list_special = usercounter = 0; totalusers = uidshm->number; if (HAS_PERM(PERM_SEEULEVELS)) { getdata(b_lines - 1, 0, "觀看 [1]特殊等級 (2)全部?", genbuf, 3, DOECHO); if (genbuf[0] != '2') u_list_special = 32; } if (HAS_PERM(PERM_CHATROOM) || HAS_PERM(PERM_SYSOP)) { getdata(b_lines - 1, 0, "顯示 [1]真實姓名 (2)暱稱?", genbuf, 3, DOECHO); if (genbuf[0] != '2') showrealname = 1; } u_list_CB(NULL); if (apply_record(fn_passwd, u_list_CB, sizeof(userec)) == -1) { outs(msg_nobody); return XEASY; } move(b_lines, 0); clrtoeol(); prints(" 已顯示 %d/%d 的使用者(系統容量無上限) (請按任意鍵繼續) ", usercounter, totalusers); egetch(); return 0; }