summaryrefslogtreecommitdiffstats
path: root/pttbbs/mbbsd/bbs.c
diff options
context:
space:
mode:
Diffstat (limited to 'pttbbs/mbbsd/bbs.c')
-rw-r--r--pttbbs/mbbsd/bbs.c369
1 files changed, 311 insertions, 58 deletions
diff --git a/pttbbs/mbbsd/bbs.c b/pttbbs/mbbsd/bbs.c
index bb7d7f9a..756b8055 100644
--- a/pttbbs/mbbsd/bbs.c
+++ b/pttbbs/mbbsd/bbs.c
@@ -100,7 +100,6 @@ save_violatelaw()
*/
static time_t board_note_time;
-static char *brd_title;
void
set_board()
@@ -113,12 +112,10 @@ set_board()
u_exit("access control violation!");
}
board_note_time = bp->bupdate;
- brd_title = bp->BM;
- if (brd_title[0] <= ' ')
- brd_title = "徵求中";
- snprintf(currBM, sizeof(currBM), "板主:%s", brd_title);
- brd_title = ((bp->bvote != 2 && bp->bvote) ? "本看板進行投票中" :
- bp->title + 7);
+ if(bp->BM[0] <= ' ')
+ strcpy(currBM, "徵求中");
+ else
+ snprintf(currBM, sizeof(currBM), "板主:%s", bp->BM);
currmode = (currmode & (MODE_DIRTY | MODE_MENU)) | MODE_STARTED;
if (HAS_PERM(PERM_ALLBOARD) || is_BM_cache(currbid))
@@ -130,9 +127,18 @@ set_board()
static void
readtitle()
{
+ boardheader_t *bp;
+ char *brd_title;
+
+ bp = getbcache(currbid);
+ if(bp->bvote != 2 && bp->bvote)
+ brd_title = "本看板進行投票中";
+ else
+ brd_title = bp->title + 7;
+
showtitle(currBM, brd_title);
outs("[←]離開 [→]閱\讀 [^P]發表文章 [b]備忘錄 [d]刪除 [z]精華區 "
- "[TAB]文摘 [h]elp\n\033[7m 編號 日 期 作 者 文 章 標 題"
+ "[TAB]文摘 [h]elp\n\033[7m 編號 日 期 作 者 文 章 標 題"
" \033[m");
}
@@ -140,12 +146,9 @@ static void
readdoent(int num, fileheader_t * ent)
{
int type;
- char *mark, *title, color, special = 0, isonline = 0;
+ char *mark, *title, color, special = 0, isonline = 0, recom[5];
userinfo_t *uentp;
- if (ent->recommend > 9 || ent->recommend < 0)
- ent->recommend = 0;
-//Ptt:暫時
- type = brc_unread(ent->filename, brc_num, brc_list) ? '+' : ' ';
+ type = brc_unread(ent->filename, brc_num, brc_list) ? '+' : ' ';
if ((currmode & MODE_BOARD) && (ent->filemode & FILE_DIGEST))
type = (type == ' ') ? '*' : '#';
@@ -160,13 +163,15 @@ readdoent(int num, fileheader_t * ent)
type = 's';
}
title = subject(mark = ent->title);
- if (title == mark)
+ if (ent->filemode & FILE_BID)
+ color = '1', mark = "$";
+ else if (title == mark)
color = '1', mark = "□";
else
color = '3', mark = "R:";
- if (title[47])
- strlcpy(title + 44, " …", sizeof(title) - 44); /* 把多餘的 string 砍掉 */
+ if (title[45])
+ strlcpy(title + 42, " …", sizeof(title) - 42); /* 把多餘的 string 砍掉 */
if (!strncmp(title, "[公告]", 6))
special = 1;
@@ -180,14 +185,21 @@ readdoent(int num, fileheader_t * ent)
(uentp = search_ulist(uid)) && isvisible(currutmp, uentp))
isonline = 1;
#endif
+ if(ent->recommend>99)
+ strcpy(recom,"1m爆");
+ else if(ent->recommend>9)
+ sprintf(recom,"3m%2d",ent->recommend);
+ else if(ent->recommend>0)
+ sprintf(recom,"2m%2d",ent->recommend);
+ else strcpy(recom,"0m ");
prints(
#ifdef COLORDATE
- "%6d %c\033[1;32m%c\033[%dm%-6s\033[m\033[%dm%-13.12s",
+ "%6d %c\033[1;3%4.4s\033[%dm%-6s\033[m\033[%dm%-13.12s",
#else
- "%6d %c\033[1;32m%c\033[m%-6s\033[%dm%-13.12s",
+ "%6d %c\033[1;3%4.4s\033[m%-6s\033[%dm%-13.12s",
#endif
- num, type, ent->recommend ? ent->recommend + '0' : ' ',
+ num, type, recom,
#ifdef COLORDATE
(ent->date[3] + ent->date[4]) % 7 + 31,
#endif
@@ -440,10 +452,65 @@ do_allpost(fileheader_t *postfile, const char *fpath, const char *owner)
setbtotal(getbnum(ALLPOST));
}
}
+static void
+setupbidinfo(bid_t *bidinfo)
+{
+ char buf[256];
+ bidinfo->enddate = gettime(20, now+86400,"結束標案於");
+ do
+ getdata_str(21,0,"底價:",buf, 8, LCECHO, "1");
+ while((bidinfo->high=atoi(buf))<=0);
+ do
+ getdata_str(21,20, "每標至少增加多少:",buf, 5, LCECHO, "1");
+ while((bidinfo->increment=atoi(buf))<=0);
+ getdata(21,44, "直接購買價(可不設):",buf, 5, LCECHO);
+ bidinfo->buyitnow=atoi(buf);
+
+ getdata_str(22,0,
+ "付款方式: 1.Ptt幣 2.郵局或銀行轉帳 3.支票或電匯 4.郵局貨到付款 [1]:",
+ buf, 3, LCECHO,"1");
+ bidinfo->payby=(buf[0]-'1');
+ if(bidinfo->payby<0 ||bidinfo->payby>3)bidinfo->payby=0;
+ getdata_str(23,0, "運費(0:免運費或文中說明)[0]:", buf, 6, LCECHO, "0");
+ bidinfo->shipping = atoi(buf);
+ if(bidinfo->shipping<0) bidinfo->shipping=0;
+}
+static void
+print_bidinfo(FILE *io, bid_t bidinfo)
+{
+ char *payby[4]={ "Ptt幣","郵局或銀行轉帳","支票或電匯","郵局貨到付款"};
+ if(io)
+ {
+ if(!bidinfo.userid[0])
+ fprintf(io,"起標價: %-20d\n",bidinfo.high);
+ else
+ fprintf(io, "目前最高價:%-20d出價者:%-16s\n",bidinfo.high, bidinfo.userid);
+ fprintf(io, "付款方式: %-20s結束於:%-16s\n",payby[bidinfo.payby%4],Cdate(& bidinfo.enddate));
+ if(bidinfo.buyitnow)
+ fprintf(io, "直接購買價:%-20d",bidinfo.buyitnow);
+ if(bidinfo.shipping)
+ fprintf(io, "運費:%d", bidinfo.shipping);
+ fprintf(io, "\n");
+ }
+ else
+ {
+ if(!bidinfo.userid[0])
+ prints("起標價: %-20d\n",bidinfo.high);
+ else
+ prints("目前最高價:%-20d出價者:%-16s\n",bidinfo.high, bidinfo.userid);
+ prints("付款方式: %-20s結束於:%-16s\n",payby[bidinfo.payby%4],Cdate(& bidinfo.enddate));
+ if(bidinfo.buyitnow)
+ prints("直接購買價:%-20d",bidinfo.buyitnow);
+ if(bidinfo.shipping)
+ prints("運費:%d", bidinfo.shipping);
+ prints("\n");
+ }
+}
static int
-do_general()
+do_general(int isbid)
{
+ bid_t bidinfo;
fileheader_t postfile;
char fpath[80], buf[80];
int aborted, defanony, ifuseanony;
@@ -483,27 +550,46 @@ do_general()
#endif
#endif
- setbfile(genbuf, currboard, FN_POST_NOTE);
+ if(!isbid)
+ setbfile(genbuf, currboard, FN_POST_NOTE);
+ else
+ setbfile(genbuf, currboard, FN_POST_BID);
if (more(genbuf, NA) == -1)
- more("etc/" FN_POST_NOTE, NA);
-
+ {
+ if(!isbid)
+ more("etc/" FN_POST_NOTE, NA);
+ else
+ more("etc/" FN_POST_BID, NA);
+ }
move(19, 0);
- prints("發表文章於【\033[33m %s\033[m 】 \033[32m%s\033[m 看板\n\n",
+ prints("%s於【\033[33m %s\033[m 】 \033[32m%s\033[m 看板\n",
+ isbid?"公開招標":"發表文章",
currboard, bp->title + 7);
-
+ if(isbid)
+ {
+ memset(&bidinfo,0,sizeof(bidinfo));
+ setupbidinfo(&bidinfo);
+ postfile.money=bidinfo.high;
+ move(20,0);
+ clrtobot();
+ }
if (quote_file[0])
do_reply_title(20, currtitle);
else {
- getdata(21, 0,
- "種類:1.問題 2.建議 3.討論 4.心得 5.閒聊 6.公告 7.情報 (1-7或不選)",
+ if(!isbid)
+ {
+ getdata(21, 0,
+ "種類:1.問題 2.建議 3.討論 4.心得 5.閒聊 6.公告 7.情報 (1-7或不選)",
save_title, 3, LCECHO);
- local_article = save_title[0] - '1';
- if (local_article >= 0 && local_article <= 6)
+
+ local_article = save_title[0] - '1';
+ if (local_article >= 0 && local_article <= 6)
snprintf(save_title, sizeof(save_title),
"[%s] ", ctype[local_article]);
- else
+ else
save_title[0] = '\0';
+ }
getdata_buf(22, 0, "標題:", save_title, TTLEN, DOECHO);
strip_ansi(save_title, save_title, 0);
}
@@ -523,7 +609,16 @@ do_general()
/* build filename */
setbpath(fpath, currboard);
stampfile(fpath, &postfile);
-
+ if(isbid)
+ {
+ aborted = (int)fopen(fpath, "w");
+ if(aborted)
+ {
+ print_bidinfo((FILE*)aborted, bidinfo);
+ fclose((FILE*)aborted);
+ }
+ }
+
aborted = vedit(fpath, YEA, &islocal);
if (aborted == -1) {
unlink(fpath);
@@ -550,13 +645,20 @@ do_general()
#endif
/* 錢 */
aborted = (aborted > MAX_POST_MONEY * 2) ? MAX_POST_MONEY : aborted / 2;
- postfile.money = aborted;
+ if(!isbid)
+ postfile.money = aborted;
strlcpy(postfile.owner, owner, sizeof(postfile.owner));
strlcpy(postfile.title, save_title, sizeof(postfile.title));
if (islocal) /* local save */
- postfile.filemode = FILE_LOCAL;
+ postfile.filemode |= FILE_LOCAL;
setbdir(buf, currboard);
+ if(isbid)
+ {
+ sprintf(genbuf, "%s.bid", fpath);
+ append_record(genbuf,(void*) &bidinfo, sizeof(bidinfo));
+ postfile.filemode |= FILE_BID ;
+ }
if (append_record(buf, &postfile, sizeof(postfile)) != -1) {
setbtotal(currbid);
@@ -576,9 +678,14 @@ do_general()
aborted = (aborted > MAX_POST_MONEY) ? MAX_POST_MONEY : aborted;
#endif
if (strcmp(currboard, "Test") && !ifuseanony) {
- prints("這是您的第 %d 篇文章。 稿酬 %d 銀。",
- ++cuser.numposts, aborted);
- demoney(aborted);
+ prints("這是您的第 %d 篇文章。",++cuser.numposts);
+ if(!(postfile.filemode&FILE_BID))
+ {
+ prints(" 稿酬 %d 銀。",aborted);
+ demoney(aborted);
+ }
+ else
+ prints("招標文章沒有稿酬。");
passwd_update(usernum, &cuser); /* post 數 */
} else
outs("測試信件不列入紀錄,敬請包涵。");
@@ -605,7 +712,7 @@ do_general()
strlcpy(postfile.owner, cuser.userid, sizeof(postfile.owner));
strlcpy(postfile.title, save_title, sizeof(postfile.title));
- postfile.filemode = FILE_BOTH; /* both-reply flag */
+ postfile.filemode |= FILE_BOTH; /* both-reply flag */
sethomedir(genbuf, quote_user);
if (append_record(genbuf, &postfile, sizeof(postfile)) == -1)
msg = err_uid;
@@ -628,7 +735,18 @@ do_post()
if (bp->brdattr & BRD_VOTEBOARD)
return do_voteboard();
else if (!(bp->brdattr & BRD_GROUPBOARD))
- return do_general();
+ return do_general(0);
+ touchdircache(currbid);
+ return 0;
+}
+
+int
+do_post_openbid()
+{
+ boardheader_t *bp;
+ bp = getbcache(currbid);
+ if (!(bp->brdattr & BRD_VOTEBOARD))
+ return do_general(1);
touchdircache(currbid);
return 0;
}
@@ -1137,7 +1255,7 @@ hold_gamble(int ent, fileheader_t * fhdr, char *direct)
} while (i < 10 || i > 10000);
fprintf(fp, "%d\n", i);
if (!getdata(3, 0, "設定自動封盤時間?(Y/n)", yn, 3, LCECHO) || yn[0] != 'n') {
- bp->endgamble = gettime(4, now);
+ bp->endgamble = gettime(4, now, "封盤於");
substitute_record(fn_board, bp, sizeof(boardheader_t), currbid);
}
move(6, 0);
@@ -1252,6 +1370,138 @@ recommend_cancel(int ent, fileheader_t * fhdr, char *direct)
touchdircache(currbid);
return FULLUPDATE;
}
+static int
+do_add_recommend(char * direct,fileheader_t * fhdr, int ent, char*buf)
+{
+ char path[256];
+ lock_substitute_record(direct, fhdr, sizeof(*fhdr), ent, LOCK_EX);
+ setdirpath(path, direct, fhdr->filename);
+ log_file(path, buf);
+ if (!(fhdr->recommend < 100))
+ lock_substitute_record(direct, fhdr, sizeof(*fhdr), ent, LOCK_UN);
+ else{
+ fhdr->recommend++;
+ passwd_update(usernum, &cuser);
+ lock_substitute_record(direct, fhdr, sizeof(*fhdr), ent, LOCK_UN);
+ substitute_check(fhdr);
+ touchdircache(currbid);
+ }
+ return 0;
+}
+static int
+do_bid(int ent, fileheader_t * fhdr, boardheader_t *bp, char *direct, struct tm *ptime)
+{
+ char genbuf[200], fpath[256],say[30];
+ bid_t bidinfo;
+ int i, next;
+
+ setdirpath(fpath, direct, fhdr->filename);
+ strcat(fpath,".bid");
+ get_record(fpath, &bidinfo, sizeof(bidinfo), 1);
+
+ move(18,0); clrtobot();
+ prints("競標主題: %s\n", fhdr->title);
+ print_bidinfo(0, bidinfo);
+ if(now>bidinfo.enddate || bidinfo.high==bidinfo.buyitnow)
+ {
+ prints("此競標已經結束,");
+ if( bidinfo.userid[0])
+ {
+ /*if(!payby && bidinfo.usermax!=-1)
+ {以Ptt幣自動扣款
+ }*/
+ prints("恭喜 %s 以 %d 得標!", bidinfo.userid, bidinfo.high);
+ }
+ else prints("無人得標!");
+ pressanykey();
+ return FULLUPDATE;
+ }
+ if(bidinfo.userid[0])
+ {
+ prints("下次出價至少要:%d", bidinfo.high + bidinfo.increment);
+ if(bidinfo.buyitnow)
+ prints(" (超過 %d 等於直接購買)",bidinfo.buyitnow);
+ next=bidinfo.high + bidinfo.increment;
+ }
+ else
+ {
+ prints("起標價: %d", bidinfo.high);
+ next=bidinfo.high;
+ }
+ if(!strcmp(cuser.userid,bidinfo.userid))
+ {
+ prints("你是最高得標者!");
+ pressanykey();
+ return FULLUPDATE;
+ }
+ if (strcmp(cuser.userid, fhdr->owner) == 0){
+ vmsg("警告! 本人不能出價!");
+ return FULLUPDATE;
+ }
+ getdata_str(23,0,"是否要下標? (y/N)", genbuf, 3, LCECHO,"n");
+ if(genbuf[0]!='y') return FULLUPDATE;
+
+ getdata(23, 0, "您的最高下標金額(0:取消):", genbuf, 7, LCECHO);
+
+ i=atoi(genbuf);
+
+ get_record(fpath, &bidinfo, sizeof(bidinfo), 1);
+ if(!bidinfo.userid[0])
+ next=bidinfo.high;
+ else
+ next=bidinfo.high + bidinfo.increment;
+
+ if(i< next || (bidinfo.payby==0 && cuser.money<i ));
+ {
+ outmsg("取消下標或標金不足");
+ pressanykey();
+ }
+
+ getdata(23,0,"下標感言:",say,12,DOECHO);
+ snprintf(genbuf, sizeof(genbuf),
+ "\033[1;31m→ \033[33m%s\033[m\033[33m:%s\033[m%*s金額:%-15d標%15s %02d/%02d\n",
+ cuser.userid,say,
+ 31 - strlen(cuser.userid) - strlen(say), " ",
+ next, fromhost,
+ ptime->tm_mon + 1, ptime->tm_mday);
+ do_add_recommend(direct, fhdr, ent, genbuf);
+ if(next>bidinfo.usermax)
+ {
+ bidinfo.usermax=i;
+ bidinfo.high=next;
+ strcpy(bidinfo.userid,cuser.userid);
+ }
+ else if(next<bidinfo.usermax && i>bidinfo.usermax)
+ {
+ bidinfo.high=bidinfo.usermax+bidinfo.increment;
+ bidinfo.usermax=i;
+ strcpy(bidinfo.userid,cuser.userid);
+
+ snprintf(genbuf, sizeof(genbuf),
+"\033[1;31m→ \033[33m自動競標%s勝出\033[m\033[33m\033[m%*s金額:%-15d標 %02d/%02d\n",
+ cuser.userid,
+ 20 - strlen(cuser.userid) , " ",
+ bidinfo.high,
+ ptime->tm_mon + 1, ptime->tm_mday);
+ do_add_recommend(direct, fhdr, ent, genbuf);
+ }
+ else
+ {
+ if(i+bidinfo.increment<bidinfo.usermax)
+ bidinfo.high=i+bidinfo.increment;
+ else
+ bidinfo.high=bidinfo.usermax; /*這邊怪怪的*/
+ snprintf(genbuf, sizeof(genbuf),
+"\033[1;31m→ \033[33m自動競標%s勝出\033[m\033[33m\033[m%*s金額:%-15d標 %02d/%02d\n",
+ bidinfo.userid,
+ 20 - strlen(bidinfo.userid) , " ",
+ bidinfo.high,
+ ptime->tm_mon + 1, ptime->tm_mday);
+ do_add_recommend(direct, fhdr, ent, genbuf);
+ }
+ substitute_record(fpath, &bidinfo, sizeof(bidinfo), 1);
+ return FULLUPDATE;
+}
static int
recommend(int ent, fileheader_t * fhdr, char *direct)
@@ -1263,18 +1513,19 @@ recommend(int ent, fileheader_t * fhdr, char *direct)
bp = getbcache(currbid);
if( bp->brdattr & BRD_NORECOMMEND ){
- vmsg("抱歉, 本板禁止推薦");
+ vmsg("抱歉, 本板禁止推薦或競標");
return FULLUPDATE;
}
if (!(currmode & MODE_POST) || bp->brdattr & BRD_VOTEBOARD) {
- vmsg("您因權限不足無法推薦!");
+ vmsg("您因權限不足!");
return FULLUPDATE;
}
+ if( fhdr->filemode & FILE_BID)
+ return do_bid(ent, fhdr, bp, direct, ptime);
+
setdirpath(path, direct, fhdr->filename);
- if (fhdr->recommend > 9 || fhdr->recommend < 0)
- /* 暫時性的 code 原來舊有值取消 */
- fhdr->recommend = 0;
+
if (fhdr->recommend == 0 && strcmp(cuser.userid, fhdr->owner) == 0){
vmsg("警告! 本人不能推薦第一次!");
@@ -1290,6 +1541,7 @@ recommend(int ent, fileheader_t * fhdr, char *direct)
}
#endif
+
if (!getdata(b_lines - 2, 0, "推薦語:", path, 40, DOECHO) ||
path == NULL ||
!getdata(b_lines - 1, 0, "確定要推薦, 請仔細考慮(Y/N)?[n] ",
@@ -1302,18 +1554,7 @@ recommend(int ent, fileheader_t * fhdr, char *direct)
cuser.userid, path,
51 - strlen(cuser.userid) - strlen(path), " ", fromhost,
ptime->tm_mon + 1, ptime->tm_mday);
- lock_substitute_record(direct, fhdr, sizeof(*fhdr), ent, LOCK_EX);
- setdirpath(path, direct, fhdr->filename);
- log_file(path, buf);
- if (!(fhdr->recommend < 9))
- lock_substitute_record(direct, fhdr, sizeof(*fhdr), ent, LOCK_UN);
- else{
- fhdr->recommend++;
- passwd_update(usernum, &cuser);
- lock_substitute_record(direct, fhdr, sizeof(*fhdr), ent, LOCK_UN);
- substitute_check(fhdr);
- touchdircache(currbid);
- }
+ do_add_recommend(direct, fhdr, ent, buf);
lastrecommend = now;
return FULLUPDATE;
}
@@ -1660,7 +1901,8 @@ b_note_edit_bname(int bid)
} else {
if (!getdata(2, 0, "設定有效期限天?(n/Y)", buf, 3, LCECHO)
|| buf[0] != 'n')
- fh->bupdate = gettime(3, fh->bupdate ? fh->bupdate : now);
+ fh->bupdate = gettime(3, fh->bupdate ? fh->bupdate : now,
+ "有效日期至");
else
fh->bupdate = 0;
substitute_record(fn_board, fh, sizeof(boardheader_t), bid);
@@ -1703,7 +1945,6 @@ static int
b_post_note()
{
char buf[200], yn[3];
-
if (currmode & MODE_BOARD) {
setbfile(buf, currboard, FN_POST_NOTE);
if (more(buf, NA) == -1)
@@ -1713,6 +1954,17 @@ b_post_note()
vedit(buf, NA, NULL);
else
unlink(buf);
+
+
+ setbfile(buf, currboard, FN_POST_BID);
+ if (more(buf, NA) == -1)
+ more("etc/" FN_POST_BID, NA);
+ getdata(b_lines - 2, 0, "是否要用自訂競標文章注意事項?", yn, sizeof(yn), LCECHO);
+ if (yn[0] == 'y')
+ vedit(buf, NA, NULL);
+ else
+ unlink(buf);
+
return FULLUPDATE;
}
return 0;
@@ -2067,6 +2319,7 @@ struct onekey_t read_comms[] = {
{'y', reply_post},
{'z', b_man},
{Ctrl('P'), do_post},
+ {Ctrl('O'), do_post_openbid},
{Ctrl('W'), whereami},
{'\0', NULL}
};