/* $Id$ */
#include "bbs.h"
#define VOTEBOARD "NewBoard"
// user
int CheckVoteRestriction(int bid)
{
if ((currmode & MODE_BOARD) || HasUserPerm(PERM_SYSOP))
return 1;
// check first-login
if (cuser.firstlogin > (now - (time4_t)bcache[bid - 1].vote_limit_regtime * MONTH_SECONDS))
return 0;
#ifdef USE_LOGIN_LIMITS
if (cuser.numlogindays / 10 < (unsigned int)bcache[bid - 1].vote_limit_logins)
return 0;
#endif
if (cuser.numposts / 10 < (unsigned int)bcache[bid - 1].vote_limit_posts)
return 0;
if (cuser.badpost > (255 - (unsigned int)bcache[bid - 1].vote_limit_badpost))
return 0;
return 1;
}
// article
int CheckVoteRestrictionFile(const fileheader_t * fhdr)
{
if ((currmode & MODE_BOARD) || HasUserPerm(PERM_SYSOP))
return 1;
// check first-login
if (cuser.firstlogin > (now - (time4_t)fhdr->multi.vote_limits.regtime * MONTH_SECONDS))
return 0;
#ifdef USE_LOGIN_LIMITS
if (cuser.numlogindays / 10 < (unsigned int)fhdr->multi.vote_limits.logins)
return 0;
#endif
if (cuser.numposts / 10 < (unsigned int)fhdr->multi.vote_limits.posts)
return 0;
if (cuser.badpost > (255 - (unsigned int)fhdr->multi.vote_limits.badpost))
return 0;
return 1;
}
void
do_voteboardreply(const fileheader_t * fhdr)
{
char genbuf[256];
char reason[36]="";
char fpath[80];
char oldfpath[80];
char opnion[10];
char *ptr;
FILE *fo,*fi;
fileheader_t votefile;
int yes=0, no=0, len;
int fd;
unsigned long endtime=0;
clear();
if (!CheckPostPerm()||HasUserPerm(PERM_NOCITIZEN)) {
vmsg("對不起,您目前無法在此發表文章!");
return;
}
if (!CheckVoteRestrictionFile(fhdr))
{
vmsg("你不夠資深喔! (可按 i 查看限制)");
return;
}
setbpath(fpath, currboard);
stampfile(fpath, &votefile);
setbpath(oldfpath, currboard);
strcat(oldfpath, "/");
strcat(oldfpath, fhdr->filename);
fi = fopen(oldfpath, "r");
assert(fi);
while (fgets(genbuf, sizeof(genbuf), fi)) {
char *space;
if (yes>=0)
{
if (!strncmp(genbuf, "----------",10))
{yes=-1; continue;}
else
yes++;
}
if (yes>3) outs(genbuf);
if (!strncmp(genbuf, "連署結束時間", 12)) {
ptr = strchr(genbuf, '(');
assert(ptr);
sscanf(ptr + 1, "%lu", &endtime);
if (endtime < (unsigned long)now) {
vmsg("連署時間已過");
fclose(fi);
return;
}
}
if(yes>=0) continue;
space = strpbrk(genbuf+4, " \n");
if(space) *space='\0';
if (!strncasecmp(genbuf + 4, cuser.userid, IDLEN)) {
move(5, 10);
outs("您已經連署過本篇了");
getdata(17, 0, "要修改您之前的連署嗎?(Y/N) [N]", opnion, 3, LCECHO);
if (opnion[0] != 'y') {
fclose(fi);
return;
}
strlcpy(reason, genbuf + 19, 34);
break;
}
}
fclose(fi);
do {
if (!getdata(19, 0, "請問您 (Y)支持 (N)反對 這個議題:", opnion, 3, LCECHO)) {
return;
}
} while (opnion[0] != 'y' && opnion[0] != 'n');
sprintf(genbuf, "請問您與這個議題的關係或%s理由為何:",
opnion[0] == 'y' ? "支持" : "反對");
if (!getdata_buf(20, 0, genbuf, reason, 35, DOECHO)) {
return;
}
if ((fd = open(oldfpath, O_RDONLY)) == -1)
return;
if(flock(fd, LOCK_EX)==-1 )
{close(fd); return;}
if(!(fi = fopen(oldfpath, "r")))
{flock(fd, LOCK_UN); close(fd); return;}
if(!(fo = fopen(fpath, "w")))
{
flock(fd, LOCK_UN);
close(fd);
fclose(fi);
return;
}
while (fgets(genbuf, sizeof(genbuf), fi)) {
if (!strncmp("----------", genbuf, 10))
break;
fputs(genbuf, fo);
}
if (!endtime) {
now += 14 * 24 * 60 * 60;
fprintf(fo, "連署結束時間: (%d)%s\n\n", now, Cdate(&now));
now -= 14 * 24 * 60 * 60;
}
fputs(genbuf, fo);
len = strlen(cuser.userid);
for(yes=0; fgets(genbuf, sizeof(genbuf), fi);) {
if (!strncmp("----------", genbuf, 10))
break;
if (strlen(genbuf)<30 || (genbuf[4+len]==' ' && !strncasecmp(genbuf + 4, cuser.userid, len)))
continue;
fprintf(fo, "%3d.%s", ++yes, genbuf + 4);
}
if (opnion[0] == 'y')
fprintf(fo, "%3d.%-15s%-34s 來源:%s\n", ++yes, cuser.userid, reason, cuser.lasthost);
fputs(genbuf, fo);
for(no=0; fgets(genbuf, sizeof(genbuf), fi);) {
if (!strncmp("----------", genbuf, 10))
break;
if (strlen(genbuf)<30 || (genbuf[4+len]==' ' && !strncasecmp(genbuf + 4, cuser.userid, len)))
continue;
fprintf(fo, "%3d.%s", ++no, genbuf + 4);
}
if (opnion[0] == 'n')
fprintf(fo, "%3d.%-15s%-34s 來源:%s\n", ++no, cuser.userid, reason, cuser.lasthost);
fprintf(fo, "----------總計----------\n");
fprintf(fo, "支持人數:%-9d反對人數:%-9d\n", yes, no);
fprintf(fo, "\n--\n※ 發信站 :" BBSNAME "(" MYHOSTNAME
") \n◆ From: 連署文章\n");
flock(fd, LOCK_UN);
close(fd);
fclose(fi);
fclose(fo);
unlink(oldfpath);
rename(fpath, oldfpath);
}
int
do_voteboard(int type)
{
fileheader_t votefile;
char topic[100];
char title[STRLEN];
char genbuf[2048];
char fpath[PATHLEN];
FILE *fp;
int temp;
if (!CheckPostPerm()) {
vmsg("對不起,您目前無法在此發表文章!");
return FULLUPDATE;
}
if (!CheckVoteRestriction(currbid))
{
vmsg("你不夠資深喔! (可按 i 查看限制)");
return FULLUPDATE;
}
vs_hdr(BBSNAME "連署系統");
outs("您正在使用" BBSNAME "的連署系統,請小心回答下列問題才能開始連署\n");
outs("任意提出連署案者,將被列入不受歡迎使用者喔\n\n");
outs("(1)活動連署 (2)記名公投 ");
if(type==0)
outs("(3)申請新板 (4)廢除舊板 (5)連署板主 \n(6)罷免板主 (7)連署小組長 (8)罷免小組長 (9)申請新群組\n");
do {
getdata(6, 0, "請輸入連署類別 [0:取消]:", topic, 3, DOECHO);
temp = atoi(topic);
} while (temp < 0 || temp > 9 || (type && temp>2));
switch (temp) {
case 0:
return FULLUPDATE;
case 1:
if (!getdata(7, 0, "請輸入活動主題:", topic, 30, DOECHO))
return FULLUPDATE;
snprintf(title, sizeof(title), "%s %s", "[活動連署]", topic);
snprintf(genbuf, sizeof(genbuf),
"%s\n\n%s%s\n", "活動連署", "活動主題: ", topic);
strcat(genbuf, "\n活動內容: \n");
break;
case 2:
if (!getdata(7, 0, "請輸入公投主題:", topic, 30, DOECHO))
return FULLUPDATE;
snprintf(title, sizeof(title), "%s %s", "[記名公投]", topic);
snprintf(genbuf, sizeof(genbuf),
"%s\n\n%s%s\n", "記名公投", "公投主題: ", topic);
strcat(genbuf, "\n公投原因: \n");
break;
case 3:
do {
if (!getdata(7, 0, "請輸入看板英文名稱:", topic, IDLEN + 1, DOECHO))
return FULLUPDATE;
else if (!is_valid_brdname(topic))
outs("不是正確的看板名稱");
else if (getbnum(topic) > 0)
outs("本名稱已經存在");
else
break;
} while (temp > 0);
snprintf(title, sizeof(title), "[申請新板] %s", topic);
snprintf(genbuf, sizeof(genbuf),
"%s\n\n%s%s\n%s", "申請新板", "英文名稱: ", topic, "中文名稱: ");
if (!getdata(8, 0, "請輸入看板中文名稱:", topic, BTLEN + 1, DOECHO))
return FULLUPDATE;
strcat(genbuf, topic);
strcat(genbuf, "\n看板類別: ");
if (!getdata(9, 0, "請輸入看板類別:", topic, 20, DOECHO))
return FULLUPDATE;
strcat(genbuf, topic);
strcat(genbuf, "\n板主名單: ");
getdata(10, 0, "請輸入板主名單:", topic, IDLEN * 3 + 3, DOECHO);
strcat(genbuf, topic);
strcat(genbuf, "\n申請原因: \n");
break;
case 4:
move(1,0); clrtobot();
generalnamecomplete("請輸入看板英文名稱:",
topic, IDLEN+1,
SHM->Bnumber,
&completeboard_compar,
&completeboard_permission,
&completeboard_getname);
if (!getbnum(topic))
{
vmsg("無此看版。");
return FULLUPDATE;
}
snprintf(title, sizeof(title), "[廢除舊板] %s", topic);
snprintf(genbuf, sizeof(genbuf),
"%s\n\n%s%s\n", "廢除舊板", "英文名稱: ", topic);
strcat(genbuf, "\n廢除原因: \n");
break;
case 5:
move(1,0); clrtobot();
generalnamecomplete("請輸入看板英文名稱:",
topic, IDLEN+1,
SHM->Bnumber,
&completeboard_compar,
&completeboard_permission,
&completeboard_getname);
if (!getbnum(topic))
{
vmsg("無此看版。");
return FULLUPDATE;
}
snprintf(title, sizeof(title), "[連署板主] %s", topic);
snprintf(genbuf, sizeof(genbuf), "%s\n\n%s%s\n%s%s", "連署板主", "英文名稱: ", topic, "申請 ID : ", cuser.userid);
strcat(genbuf, "\n申請政見: \n");
break;
case 6:
move(1,0); clrtobot();
generalnamecomplete("請輸入看板英文名稱:",
topic, IDLEN+1,
SHM->Bnumber,
&completeboard_compar,
&completeboard_permission,
&completeboard_getname);
if (!getbnum(topic))
{
vmsg("無此看版。");
return FULLUPDATE;
}
snprintf(title, sizeof(title), "[罷免板主] %s", topic);
snprintf(genbuf, sizeof(genbuf),
"%s\n\n%s%s\n%s", "罷免板主", "英文名稱: ",
topic, "板主 ID : ");
temp=getbnum(topic);
assert(0<=temp-1 && temp-1<MAX_BOARD);
do {
if (!getdata(7, 0, "請輸入板主ID:", topic, IDLEN + 1, DOECHO))
return FULLUPDATE;
}while (!userid_is_BM(topic, bcache[temp - 1].BM));
strcat(genbuf, topic);
strcat(genbuf, "\n罷免原因: \n");
break;
case 7:
if (!getdata(7, 0, "請輸入小組中英文名稱:", topic, 30, DOECHO))
return FULLUPDATE;
snprintf(title, sizeof(title), "[連署小組長] %s", topic);
snprintf(genbuf, sizeof(genbuf),
"%s\n\n%s%s\n%s%s", "連署小組長", "小組名稱: ",
topic, "申請 ID : ", cuser.userid);
strcat(genbuf, "\n申請政見: \n");
break;
case 8:
if (!getdata(7, 0, "請輸入小組中英文名稱:", topic, 30, DOECHO))
return FULLUPDATE;
snprintf(title, sizeof(title), "[罷免小組長] %s", topic);
snprintf(genbuf, sizeof(genbuf), "%s\n\n%s%s\n%s",
"罷免小組長", "小組名稱: ", topic, "小組長 ID : ");
if (!getdata(8, 0, "請輸入小組長ID:", topic, IDLEN + 1, DOECHO))
return FULLUPDATE;
strcat(genbuf, topic);
strcat(genbuf, "\n罷免原因: \n");
break;
case 9:
if (!getdata(7, 0, "請輸入群組中英文名稱:", topic, 30, DOECHO))
return FULLUPDATE;
snprintf(title, sizeof(title), "[申請新群組] %s", topic);
snprintf(genbuf, sizeof(genbuf), "%s\n\n%s%s\n%s%s",
"申請群組", "群組名稱: ", topic, "申請 ID : ", cuser.userid);
strcat(genbuf, "\n申請政見: \n");
break;
default:
return FULLUPDATE;
}
outs("請輸入簡介或政見(至多五行),要清楚填寫");
for (temp = 12; temp < 17; temp++) {
if (!getdata(temp, 0, ":", topic, 60, DOECHO))
break;
strcat(genbuf, topic);
strcat(genbuf, "\n");
}
if (temp == 11)
return FULLUPDATE;
strcat(genbuf, "連署結束時間: ");
now += 14 * 24 * 60 * 60;
snprintf(topic, sizeof(topic), "(%d)", now);
strcat(genbuf, topic);
strcat(genbuf, Cdate(&now));
strcat(genbuf, "\n\n");
now -= 14 * 24 * 60 * 60;
strcat(genbuf, "----------支持----------\n");
strcat(genbuf, "----------反對----------\n");
outs("開始連署嘍");
setbpath(fpath, currboard);
stampfile(fpath, &votefile);
if (!(fp = fopen(fpath, "w"))) {
outs("開檔失敗,請稍候重來一次");
return FULLUPDATE;
}
fprintf(fp, "%s%s %s%s\n%s%s\n%s%s\n", "作者: ", cuser.userid,
"看板: ", currboard,
"標題: ", title,
"時間: ", ctime4(&now));
fprintf(fp, ANSI_COLOR(1;33) "若想加入連署請按 y 回應" ANSI_RESET "\n\n");
fprintf(fp, "%s\n", genbuf);
fclose(fp);
strlcpy(votefile.owner, cuser.userid, sizeof(votefile.owner));
strlcpy(votefile.title, title, sizeof(votefile.title));
votefile.filemode |= FILE_VOTE;
/* use lower 16 bits of 'money' to store limits */
/* lower 8 bits are posts, higher 8 bits are logins */
votefile.multi.vote_limits.regtime = bcache[currbid - 1].vote_limit_regtime;
#ifdef USE_LOGIN_LIMITS
votefile.multi.vote_limits.logins = bcache[currbid - 1].vote_limit_logins;
#endif
votefile.multi.vote_limits.posts = bcache[currbid - 1].vote_limit_posts;
votefile.multi.vote_limits.badpost = bcache[currbid - 1].vote_limit_badpost;
setbdir(genbuf, currboard);
if (append_record(genbuf, &votefile, sizeof(votefile)) != -1)
setbtotal(currbid);
do_voteboardreply(&votefile);
return FULLUPDATE;
}