/* $Id: bbs.c,v 1.47 2002/06/02 01:55:21 in2 Exp $ */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <time.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include "config.h" #include "pttstruct.h" #include "perm.h" #include "modes.h" #include "common.h" #include "proto.h" extern struct bcache_t *brdshm; extern userinfo_t *currutmp; extern userec_t cuser; extern void touchdircache(int bid); extern int TagNum; extern time_t now; extern char fromhost[]; static void mail_by_link(char* owner, char* title, char* path) { char genbuf[200]; fileheader_t mymail; sprintf(genbuf,BBSHOME"/home/%c/%s", cuser.userid[0], cuser.userid); stampfile(genbuf, &mymail); strcpy(mymail.owner, owner); sprintf(mymail.title, title); unlink(genbuf); Link(path, genbuf); sprintf(genbuf,BBSHOME"/home/%c/%s/.DIR",cuser.userid[0],cuser.userid); append_record(genbuf, &mymail, sizeof(mymail)); } extern int usernum; void anticrosspost() { char buf[200]; sprintf(buf, "\033[1;33;46m%s \033[37;45mcross post �峹 \033[37m %s\033[m", cuser.userid, ctime(&now)); log_file("etc/illegal_money", buf); post_violatelaw(cuser.userid, "Ptt�t��ĵ��", "Cross-post", "�@��B��"); cuser.userlevel |= PERM_VIOLATELAW; cuser.vl_count ++; mail_by_link("Pttĵ���", "Cross-Post�@��", BBSHOME "/etc/crosspost.txt"); passwd_update(usernum, &cuser); exit(0); } /* Heat CharlieL*/ int save_violatelaw() { char buf[128], ok[3]; setutmpmode(VIOLATELAW); clear(); stand_title("ú�@�椤��"); if(!(cuser.userlevel & PERM_VIOLATELAW)) { mprints(22, 0, "\033[1;31m�A�L���? �A�S�S���Q�}�@��~~\033[m"); pressanykey(); return 0; } reload_money(); if(cuser.money < (int)cuser.vl_count*1000) { sprintf(buf, "\033[1;31m�o�O�A�� %d ���H�ϥ����k�W" "����ú�X %d $Ptt ,�A�u�� %d ��, ��������!!\033[m", (int)cuser.vl_count, (int)cuser.vl_count * 1000, cuser.money); mprints(22, 0, buf); pressanykey(); return 0; } move(5,0); prints("\033[1;37m�A���D��? �]���A���H�k " "�w�g�y���ܦh�H�����K\033[m\n"); prints("\033[1;37m�A�O�_�T�w�H�ᤣ�|�A�ǤF�H\033[m\n"); if(!getdata(10,0,"�T�w�ܡH[y/n]:", ok, sizeof(ok), LCECHO) || ok[0] == 'n' || ok[0] == 'N') { mprints(22,0,"\033[1;31m���A�Q�q�F�A�ӧa!! " "�ڬ۫H�A���|�������諸~~~\033[m"); pressanykey(); return 0; } sprintf(buf, "�o�O�A�� %d ���H�k ����ú�X %d $Ptt", cuser.vl_count, cuser.vl_count*1000); mprints(11,0,buf); if(!getdata(10, 0, "�n�I��[y/n]:", ok, sizeof(ok), LCECHO) || ok[0] == 'N' || ok[0] == 'n') { mprints(22,0, "\033[1;31m �� �s���� �A�ӧa!!!\033[m"); pressanykey(); return 0; } demoney(-1000*cuser.vl_count); cuser.userlevel &= (~PERM_VIOLATELAW); passwd_update(usernum, &cuser); return 0; } /* void make_blist() { CreateNameList(); apply_boards(g_board_names); } */ extern int currbid; extern char currBM[]; extern int currmode; extern char currboard[]; static time_t board_note_time; static char *brd_title; void set_board() { boardheader_t *bp; bp = getbcache(currbid); board_note_time = bp->bupdate; brd_title = bp->BM; if(brd_title[0] <= ' ') brd_title = "�x�D��"; sprintf(currBM, "�O�D�G%s", brd_title); brd_title = ((bp->bvote != 2 && bp->bvote) ? "���ݪO�i��벼��" : bp->title + 7); currmode = (currmode & (MODE_DIRTY | MODE_MENU)) | MODE_STARTED ; if (HAS_PERM(PERM_ALLBOARD) || is_BM(bp->BM)) currmode = currmode | MODE_BOARD | MODE_POST; else if(haspostperm(currboard)) currmode |= MODE_POST; } static void readtitle() { showtitle(currBM, brd_title); outs("[��]���} [��]�\\Ū [^P]�o���峹 [b]�Ƨѿ� [d]�R�� [z]��ذ� " "[TAB]��K [h]elp\n\033[7m �s�� �� �� �@ �� �� �� �� �D" " \033[m"); } extern int brc_num; extern int brc_list[]; extern char currtitle[TTLEN + 1]; extern int Tagger(); static void readdoent(int num, fileheader_t *ent) { int type,uid; char *mark, *title, color, special=0, isonline=0; userinfo_t *uentp; if(ent->recommend>9 || ent->recommend <0 ) ent->recommend=0; //Ptt:�Ȯ� type = brc_unread(ent->filename,brc_num,brc_list) ? '+' : ' '; if((currmode & MODE_BOARD) && (ent->filemode & FILE_DIGEST)) type = (type == ' ') ? '*' : '#'; else if(currmode & MODE_BOARD || HAS_PERM(PERM_LOGINOK)) { if(ent->filemode & FILE_MARKED) type = (type == ' ') ? 'm' : 'M'; else if (TagNum && !Tagger(atoi(ent->filename + 2), 0, TAG_NIN)) type = 'D'; else if (ent->filemode & FILE_SOLVED) type = 's'; } title = subject(mark = ent->title); if(title == mark) color = '1', mark = "��"; else color = '3', mark = "R:"; if(title[47]) strcpy(title + 44, " �K"); /* ��h�l�� string �屼 */ if(!strncmp(title,"[���i]",6)) special=1; if(!strchr(ent->owner, '.') && (uid=searchuser(ent->owner)) && (uentp = search_ulist(uid)) && isvisible(currutmp, uentp) ) isonline=1; if(strncmp(currtitle, title, TTLEN)) prints("%6d %c\033[1;32m%c\033[m%-6s\033[%dm%-13.12s\033[m%s " "\033[1m%.*s\033[m%s\n", num, type, ent->recommend?ent->recommend+'0':' ', ent->date, isonline, ent->owner, mark, special?6:0, title, special?title+6:title); else prints("%6d %c\033[1;32m%c\033[m%-6s\033[%dm%-13.12s\033[1;3%cm%s " "%s\033[m\n", num, type, ent->recommend?ent->recommend+'0':' ', ent->date, isonline, ent->owner, color, mark, title); } extern char currfile[]; int cmpfilename(fileheader_t *fhdr) { return (!strcmp(fhdr->filename, currfile)); } extern unsigned char currfmode; int cmpfmode(fileheader_t *fhdr) { return (fhdr->filemode & currfmode); } extern char currowner[]; int cmpfowner(fileheader_t *fhdr) { return !strcasecmp(fhdr->owner, currowner); } extern char *err_bid; extern userinfo_t *currutmp; int whereami(int ent, fileheader_t *fhdr, char *direct) { boardheader_t *bh, *p[32], *root; int i,j; if(!currutmp->brc_id) return 0; move(1,0); clrtobot(); bh=getbcache(currutmp->brc_id); root=getbcache(1); p[0]=bh; for(i=0;i<31 && p[i]->parent!=root && p[i]->parent;i++) p[i+1]=p[i]->parent; j=i; prints("�ڦb��?\n%-40.40s %.13s\n", p[j]->title+7, p[j]->BM); for(j--;j>=0;j--) prints("%*s %-13.13s %-37.37s %.13s\n", (i-j)*2, "", p[j]->brdname, p[j]->title, p[j]->BM); pressanykey(); return FULLUPDATE; } static int substitute_check(fileheader_t *fhdr) { fileheader_t hdr; char genbuf[100]; int num=0; /* rocker.011018: �걵�Ҧ���reference�W�i�IJv */ if ((currmode & MODE_SELECT) && (fhdr->money & FHR_REFERENCE)) { num = fhdr->money & ~FHR_REFERENCE; setbdir(genbuf, currboard); get_record(genbuf, &hdr, sizeof (hdr), num); /* �A�o�̭ncheck�@�U��Ӫ�dir�̭��O���O���Q�H�ʹL... */ if (strcmp (hdr.filename, fhdr->filename)) num = getindex(genbuf, fhdr->filename, sizeof(fileheader_t)); substitute_record(genbuf, fhdr, sizeof(*fhdr), num); } return num; } static int do_select(int ent, fileheader_t *fhdr, char *direct) { char bname[20]; char bpath[60]; boardheader_t *bh; struct stat st; int i; move(0, 0); clrtoeol(); generalnamecomplete(MSG_SELECT_BOARD, bname, sizeof(bname), brdshm->number, completeboard_compar, completeboard_permission, completeboard_getname); if(bname[0]=='\0' || !(i = getbnum(bname))) return FULLUPDATE; bh = getbcache(i); if(!Ben_Perm(bh)) return FULLUPDATE; strcpy(bname, bh->brdname); currbid=i; setbpath(bpath, bname); if((*bname == '\0') || (stat(bpath, &st) == -1)) { move(2, 0); clrtoeol(); outs(err_bid); return FULLUPDATE; } setutmpbid(currbid); brc_initial(bname); set_board(); setbdir(direct, currboard); move(1, 0); clrtoeol(); return NEWDIRECT; } /* ----------------------------------------------------- */ /* ��} innbbsd ��X�H��B�s�u��H���B�z�{�� */ /* ----------------------------------------------------- */ void outgo_post(fileheader_t *fh, char *board) { FILE *foo; if((foo = fopen("innd/out.bntp", "a"))) { fprintf(foo, "%s\t%s\t%s\t%s\t%s\n", board, fh->filename, cuser.userid, cuser.username, fh->title); fclose(foo); } } extern char *str_author1; extern char *str_author2; static void cancelpost(fileheader_t *fh, int by_BM) { FILE *fin, *fout; char *ptr, *brd; fileheader_t postfile; char genbuf[200]; char nick[STRLEN], fn1[STRLEN], fn2[STRLEN]; setbfile(fn1, currboard, fh->filename); if((fin = fopen(fn1, "r"))) { brd = by_BM ? "deleted" : "junk"; setbpath(fn2, brd); stampfile(fn2, &postfile); memcpy(postfile.owner, fh->owner, IDLEN + TTLEN + 10); nick[0] = '\0'; while(fgets(genbuf, sizeof(genbuf), fin)) { if (!strncmp(genbuf, str_author1, LEN_AUTHOR1) || !strncmp(genbuf, str_author2, LEN_AUTHOR2)) { if((ptr = strrchr(genbuf, ')'))) *ptr = '\0'; if((ptr = (char *)strchr(genbuf, '('))) strcpy(nick, ptr + 1); break; } } if((fout = fopen("innd/cancel.bntp", "a"))) { fprintf(fout, "%s\t%s\t%s\t%s\t%s\n", currboard, fh->filename, cuser.userid, nick, fh->title); fclose(fout); } fclose(fin); Rename(fn1, fn2); setbdir(genbuf, brd); append_record(genbuf, &postfile, sizeof(postfile)); } } extern char *str_reply; extern char save_title[]; /* ----------------------------------------------------- */ /* �o���B�^���B�s��B����峹 */ /* ----------------------------------------------------- */ void do_reply_title(int row, char *title) { char genbuf[200]; char genbuf2[4]; if(strncasecmp(title, str_reply, 4)) sprintf(save_title, "Re: %s", title); else strcpy(save_title, title); save_title[TTLEN - 1] = '\0'; sprintf(genbuf, "�ĥέ���D�m%.60s�n��?[Y] ", save_title); getdata(row, 0, genbuf, genbuf2, 4, LCECHO); if(genbuf2[0] == 'n' || genbuf2[0] == 'N') getdata(++row, 0, "���D�G", save_title, TTLEN, DOECHO); } static void do_unanonymous_post(char* fpath) { fileheader_t mhdr; char title[128]; char genbuf[200]; setbpath(genbuf, "UnAnonymous"); if(dashd(genbuf)) { stampfile(genbuf, &mhdr); unlink(genbuf); Link(fpath, genbuf); strcpy(mhdr.owner, cuser.userid); strcpy(mhdr.title, save_title); mhdr.filemode = 0; setbdir(title, "UnAnonymous"); append_record(title, &mhdr, sizeof(mhdr)); } } extern char quote_file[]; extern char quote_user[]; extern int curredit; extern unsigned int currbrdattr; extern char currdirect[]; extern char *err_uid; #ifdef NO_WATER_POST static time_t last_post_time = 0; static time_t water_counts = 0; #endif int local_article; char real_name[IDLEN + 1]; static int do_general() { fileheader_t postfile; char fpath[80], buf[80]; int aborted, defanony, ifuseanony; char genbuf[200],*owner, *ctype[]={"���D","��ij","�Q��","�߱o","����","���i","����"}; boardheader_t *bp; int islocal; ifuseanony = 0; bp = getbcache(currbid); clear(); if(!(currmode & MODE_POST)) { move(5, 10); outs("�藍�_�A�z�ثe�L�k�b���o���峹�I"); pressanykey(); return FULLUPDATE; } #ifdef NO_WATER_POST /* �T�������̦h�o�����g�峹 */ if(currutmp->lastact - last_post_time < 60 * 3) { if(water_counts >= 5) { move(5, 10); outs("�藍�_�A�z���峹�Ӥ��o�A�ݷ|�Apost�a�I�p���Z:�i��'X'���ˤ峹"); pressanykey(); return FULLUPDATE; } } else { last_post_time = currutmp->lastact; water_counts = 0; } #endif setbfile(genbuf, currboard, FN_POST_NOTE ); if(more(genbuf,NA) == -1) more("etc/"FN_POST_NOTE , NA); move(19,0); prints("�o���峹��i\033[33m %s\033[m �j \033[32m%s\033[m �ݪO\n\n", currboard, bp->title + 7); if(quote_file[0]) do_reply_title(20, currtitle); else { getdata(21, 0, "�����G1.���D 2.��ij 3.�Q�� 4.�߱o 5.���� 6.���i 7.���� (1-7�Τ���)", save_title,3,LCECHO); local_article = save_title[0]-'1'; if(local_article>=0 && local_article<=6) sprintf(save_title,"[%s] ",ctype[local_article]); else save_title[0]='\0'; getdata_buf(22, 0, "���D�G", save_title, TTLEN, DOECHO); strip_ansi(save_title,save_title,0); } if(save_title[0] == '\0') return FULLUPDATE; curredit &= ~EDIT_MAIL; curredit &= ~EDIT_ITEM; setutmpmode(POSTING); /* ����� Internet �v���̡A�u��b�����o���峹 */ if(HAS_PERM(PERM_INTERNET)) local_article = 0; else local_article = 1; /* build filename */ setbpath(fpath, currboard); stampfile(fpath, &postfile); aborted = vedit(fpath, YEA, &islocal); if(aborted == -1) { unlink(fpath); pressanykey(); return FULLUPDATE; } water_counts++; /* po���\ */ /* set owner to Anonymous , for Anonymous board */ #ifdef HAVE_ANONYMOUS /* Ptt and Jaky */ defanony=currbrdattr & BRD_DEFAULTANONYMOUS; if((currbrdattr & BRD_ANONYMOUS) && ((strcmp(real_name,"r") && defanony) || (real_name[0] && !defanony)) ) { strcat(real_name,"."); owner = real_name; ifuseanony=1; } else owner = cuser.userid; #else owner = cuser.userid; #endif /* �� */ aborted = (aborted > MAX_POST_MONEY * 2) ? MAX_POST_MONEY : aborted / 2; postfile.money = aborted; strcpy(postfile.owner, owner); strcpy(postfile.title, save_title); if(islocal) /* local save */ postfile.filemode = FILE_LOCAL; setbdir(buf, currboard); if(append_record(buf, &postfile, sizeof(postfile)) != -1) { setbtotal(currbid); if(currmode & MODE_SELECT) append_record(currdirect,&postfile,sizeof(postfile)); if(!islocal && !(bp->brdattr & BRD_NOTRAN)) outgo_post(&postfile, currboard); brc_addlist(postfile.filename); if(!(currbrdattr & BRD_HIDE) && (!bp->level || (currbrdattr & BRD_POSTMASK))) { setbpath(genbuf, ALLPOST); stampfile(genbuf, &postfile); unlink(genbuf); /* jochang: boards may spread across many disk */ /* link doesn't work across device, Link doesn't work if we have same-time-across-device posts, we try symlink now */ { /* we need absolute path for symlink */ char abspath[256]=BBSHOME"/"; strcat(abspath,fpath); symlink(abspath,genbuf); } strcpy(postfile.owner, owner); strcpy(postfile.title, save_title); postfile.filemode = FILE_LOCAL; setbdir(genbuf, ALLPOST); if(append_record(genbuf, &postfile, sizeof(postfile)) != -1) { setbtotal(getbnum(ALLPOST)); } } outs("���Q�K�X�G�i�A"); #ifdef MAX_POST_MONEY aborted = (aborted > MAX_POST_MONEY) ? MAX_POST_MONEY : aborted; #endif if(strcmp(currboard, "Test") && !ifuseanony) { prints("�o�O�z���� %d �g�峹�C �Z�S %d �ȡC", ++cuser.numposts, aborted ); demoney(aborted); passwd_update(usernum, &cuser); /* post �� */ } else outs("���իH�C�J�����A�q�Х]�[�C"); /* �^�����@�̫H�c */ if(curredit & EDIT_BOTH) { char *str, *msg = "�^���ܧ@�̫H�c"; if((str = strchr(quote_user, '.'))) { if( #ifndef USE_BSMTP bbs_sendmail(fpath, save_title, str + 1) #else bsmtp(fpath, save_title, str + 1 ,0) #endif < 0) msg = "�@�̵L�k���H"; } else { sethomepath(genbuf, quote_user); stampfile(genbuf, &postfile); unlink(genbuf); Link(fpath, genbuf); strcpy(postfile.owner, cuser.userid); strcpy(postfile.title, save_title); postfile.filemode = FILE_BOTH;/* both-reply flag */ sethomedir(genbuf, quote_user); if(append_record(genbuf, &postfile, sizeof(postfile)) == -1) msg = err_uid; } outs(msg); curredit ^= EDIT_BOTH; } if(currbrdattr & BRD_ANONYMOUS) do_unanonymous_post(fpath); } pressanykey(); return FULLUPDATE; } int do_post() { boardheader_t *bp; bp = getbcache(currbid); if(bp->brdattr & BRD_VOTEBOARD) return do_voteboard(); else if(!(bp->brdattr & BRD_GROUPBOARD)) return do_general(); touchdircache(currbid); return 0; } extern int b_lines; extern int curredit; static void do_generalboardreply(fileheader_t *fhdr){ char genbuf[200]; getdata(b_lines - 1, 0, "�� �^���� (F)�ݪO (M)�@�̫H�c (B)�G�̬ҬO (Q)�����H[F] ", genbuf, 3, LCECHO); switch(genbuf[0]) { case 'm': mail_reply(0, fhdr, 0); case 'q': break; case 'b': curredit = EDIT_BOTH; default: strcpy(currtitle, fhdr->title); strcpy(quote_user, fhdr->owner); do_post(); } *quote_file = 0; } int getindex(char *fpath, char *fname, int size) { int fd, now=0; fileheader_t fhdr; if((fd = open(fpath, O_RDONLY, 0)) != -1) { while((read(fd, &fhdr, size) == size)) { now++; if(!strcmp(fhdr.filename,fname)) { close(fd); return now; } } close(fd); } return 0; } int invalid_brdname(char *brd) { register char ch; ch = *brd++; if(not_alnum(ch)) return 1; while((ch = *brd++)) { if(not_alnum(ch) && ch != '_' && ch != '-' && ch != '.') return 1; } return 0; } static int b_call_in(int ent, fileheader_t *fhdr, char *direct) { userinfo_t *u = search_ulist(searchuser(fhdr->owner)); if( u ){ int fri_stat; fri_stat = friend_stat(currutmp, u); if( isvisible_stat(currutmp, u, fri_stat) && call_in(u, fri_stat) ) return FULLUPDATE; } return DONOTHING; } static void do_reply(fileheader_t *fhdr) { boardheader_t *bp; bp = getbcache(currbid); if (bp->brdattr & BRD_VOTEBOARD) do_voteboardreply(fhdr); else do_generalboardreply(fhdr); } static int reply_post(int ent, fileheader_t *fhdr, char *direct) { if(!(currmode & MODE_POST)) return DONOTHING; setdirpath(quote_file, direct, fhdr->filename); do_reply(fhdr); *quote_file = 0; return FULLUPDATE; } static int edit_post(int ent, fileheader_t *fhdr, char *direct) { char fpath[80], fpath0[80]; char genbuf[200]; fileheader_t postfile; boardheader_t *bp; bp = getbcache(currbid); if (!HAS_PERM(PERM_SYSOP) && (bp->brdattr & BRD_VOTEBOARD)) return DONOTHING; if ((!HAS_PERM(PERM_SYSOP)) && strcmp(fhdr->owner, cuser.userid)) return DONOTHING; setutmpmode(REEDIT); setdirpath(genbuf, direct, fhdr->filename); local_article = fhdr->filemode & FILE_LOCAL; strcpy(save_title, fhdr->title); /* rocker.011018: �o�̬O���O���ˬd�@�U�ק�峹�᪺money�M�즳�����? */ if(vedit(genbuf, 0, NULL) != -1) { setbpath(fpath, currboard); stampfile(fpath, &postfile); unlink(fpath); setbfile(fpath0, currboard, fhdr->filename); Rename(fpath0, fpath); /* rocker.011018: fix �걵�Ҧ���峹��峹�N������bug */ if ((currmode & MODE_SELECT) && (fhdr->money & FHR_REFERENCE)) { fileheader_t hdr; int num; num = fhdr->money & ~FHR_REFERENCE; setbdir(fpath0, currboard); get_record(fpath0, &hdr, sizeof (hdr), num); /* �A�o�̭ncheck�@�U��Ӫ�dir�̭��O���O���Q�H�ʹL... */ if (!strcmp (hdr.filename, fhdr->filename)) { strcpy(hdr.filename, postfile.filename); strcpy(hdr.title, save_title); substitute_record(fpath0, &hdr, sizeof(hdr), num); } } strcpy(fhdr->filename, postfile.filename); strcpy(fhdr->title, save_title); brc_addlist(postfile.filename); substitute_record(direct, fhdr, sizeof(*fhdr), ent); /* rocker.011018: ���K��s�@�Ucache */ touchdircache(currbid); } return FULLUPDATE; } extern crosspost_t postrecord; #define UPDATE_USEREC (currmode |= MODE_DIRTY) static int cross_post(int ent, fileheader_t *fhdr, char *direct) { char xboard[20], fname[80], xfpath[80], xtitle[80], inputbuf[10]; fileheader_t xfile; FILE *xptr; int author = 0; char genbuf[200]; char genbuf2[4]; boardheader_t *bp; move(2, 0); clrtoeol(); move(3, 0); clrtoeol(); move(1, 0); bp = getbcache(currbid); if (bp && (bp->brdattr & BRD_VOTEBOARD)) return FULLUPDATE; generalnamecomplete("������峹��ݪO�G", xboard, sizeof(xboard), brdshm->number, completeboard_compar, completeboard_permission, completeboard_getname); if(*xboard == '\0' || !haspostperm(xboard)) return FULLUPDATE; if((ent = str_checksum(fhdr->title)) != 0 && ent == postrecord.checksum[0]) { /* �ˬd cross post ���� */ if(postrecord.times++ > MAX_CROSSNUM) anticrosspost(); } else { postrecord.times = 0; postrecord.checksum[0] = ent; } ent = 1; if(HAS_PERM(PERM_SYSOP) || !strcmp(fhdr->owner, cuser.userid)) { getdata(2, 0, "(1)������ (2)������榡�H[1] ", genbuf, 3, DOECHO); if(genbuf[0] != '2') { ent = 0; getdata(2, 0, "�O�d��@�̦W�ٶ�?[Y] ", inputbuf, 3, DOECHO); if (inputbuf[0] != 'n' && inputbuf[0] != 'N') author = 1; } } if(ent) sprintf(xtitle, "[���]%.66s", fhdr->title); else strcpy(xtitle, fhdr->title); sprintf(genbuf, "�ĥέ���D�m%.60s�n��?[Y] ", xtitle); getdata(2, 0, genbuf, genbuf2, 4, LCECHO); if(genbuf2[0] == 'n' || genbuf2[0] == 'N') { if(getdata_str(2, 0, "���D�G", genbuf, TTLEN, DOECHO,xtitle)) strcpy(xtitle, genbuf); } getdata(2, 0, "(S)�s�� (L)���� (Q)�����H[Q] ", genbuf, 3, LCECHO); if(genbuf[0] == 'l' || genbuf[0] == 's') { int currmode0 = currmode; currmode = 0; setbpath(xfpath, xboard); stampfile(xfpath, &xfile); if(author) strcpy(xfile.owner, fhdr->owner); else strcpy(xfile.owner, cuser.userid); strcpy(xfile.title, xtitle); if(genbuf[0] == 'l') { xfile.filemode = FILE_LOCAL; } setbfile(fname, currboard, fhdr->filename); // if(ent) { xptr = fopen(xfpath, "w"); strcpy(save_title, xfile.title); strcpy(xfpath, currboard); strcpy(currboard, xboard); write_header(xptr); strcpy(currboard, xfpath); fprintf(xptr, "�� [��������� %s �ݪO]\n\n", currboard); b_suckinfile(xptr, fname); addsignature(xptr,0); fclose(xptr); /* Cross fs�����D } else { unlink(xfpath); link(fname, xfpath); } */ setbdir(fname, xboard); append_record(fname, &xfile, sizeof(xfile)); bp = getbcache(getbnum(xboard)); if(!xfile.filemode && !(bp->brdattr && BRD_NOTRAN)) outgo_post(&xfile, xboard); setbtotal(getbnum(xboard)); cuser.numposts++; UPDATE_USEREC; outs("�峹�������"); pressanykey(); currmode = currmode0; } return FULLUPDATE; } static int read_post(int ent, fileheader_t *fhdr, char *direct) { char genbuf[200]; int more_result; if(fhdr->owner[0] == '-') return DONOTHING; setdirpath(genbuf, direct, fhdr->filename); if((more_result = more(genbuf, YEA)) == -1) return DONOTHING; brc_addlist(fhdr->filename); strncpy(currtitle, subject(fhdr->title), TTLEN); strncpy(currowner, subject(fhdr->owner), IDLEN + 2); switch (more_result) { case 1: return READ_PREV; case 2: return RELATE_PREV; case 3: return READ_NEXT; case 4: return RELATE_NEXT; case 5: return RELATE_FIRST; case 6: return FULLUPDATE; case 7: case 8: if((currmode & MODE_POST)) { strcpy(quote_file, genbuf); do_reply(fhdr); *quote_file = 0; } return FULLUPDATE; case 9: return 'A'; case 10: return 'a'; case 11: return '/'; case 12: return '?'; } outmsg("\033[34;46m �\\Ū�峹 \033[31;47m (R/Y)\033[30m�^�H \033[31m" "(=[]<>)\033[30m�����D�D \033[31m(����)\033[30m�W�U�� \033[31m(��)" "\033[30m���} \033[m"); switch(egetch()) { case 'q': case 'Q': case KEY_LEFT: break; case ' ': case KEY_RIGHT: case KEY_DOWN: case KEY_PGDN: case 'n': case Ctrl('N'): return READ_NEXT; case KEY_UP: case 'p': case Ctrl('P'): case KEY_PGUP: return READ_PREV; case '=': return RELATE_FIRST; case ']': case 't': return RELATE_NEXT; case '[': return RELATE_PREV; case '.': case '>': return THREAD_NEXT; case ',': case '<': return THREAD_PREV; case Ctrl('C'): cal(); return FULLUPDATE; break; case Ctrl('I'): t_idle(); return FULLUPDATE; case 'y': case 'r': case 'R': case 'Y': if((currmode & MODE_POST)) { strcpy(quote_file, genbuf); do_reply(fhdr); *quote_file = 0; } } return FULLUPDATE; } /* ----------------------------------------------------- */ /* �Ķ���ذ� */ /* ----------------------------------------------------- */ static int b_man() { char buf[64]; setapath(buf, currboard); if( (currmode & MODE_BOARD) || HAS_PERM(PERM_SYSOP) ){ char genbuf[128]; int fd; sprintf(genbuf, "%s/.rebuild", buf); if( (fd = open(genbuf, O_CREAT, 0640)) > 0 ) close(fd); } return a_menu(currboard, buf, HAS_PERM(PERM_ALLBOARD) ? 2 : (currmode & MODE_BOARD ? 1 : 0)); } #ifndef NO_GAMBLE static int join_gamble(int ent, fileheader_t *fhdr, char *direct) { ticket(currbid); return FULLUPDATE; } static int hold_gamble(int ent, fileheader_t *fhdr, char *direct) { char fn_ticket[128],fn_ticket_end[128],genbuf[128], msg[256]="",yn[10]=""; int i; FILE *fp=NULL; if(!(currmode & MODE_BOARD)) return 0; setbfile(fn_ticket, currboard, FN_TICKET); setbfile(fn_ticket_end, currboard, FN_TICKET_END); if(dashf(fn_ticket)) { getdata(b_lines - 1, 0, "�w�g���|���L, " "�O�_�n [����U�`]?(N/y)�G", yn, 3, LCECHO); if(yn[0]!='y') return FULLUPDATE; rename(fn_ticket, fn_ticket_end); return FULLUPDATE; } if(dashf(fn_ticket_end)) { getdata(b_lines - 1, 0, "�w�g���|���L, " "�O�_�n [�}��]?(N/y)�G", yn, 3, LCECHO); if(yn[0]!='y') return FULLUPDATE; openticket(currbid); return FULLUPDATE; } getdata(b_lines - 2, 0, "�n�|���L (N/y):", yn, 3, LCECHO); if(yn[0]!='y') return FULLUPDATE; getdata(b_lines - 1, 0, "�䤰��? �п�J�D�D (��J��s�褺�e):", msg, 20, DOECHO); if(msg[0]==0 || vedit(fn_ticket_end, NA, NULL)<0) return FULLUPDATE; clear(); showtitle("�|���L",BBSNAME); setbfile(genbuf, currboard, FN_TICKET_ITEMS); // sprintf(genbuf, "%s/"FN_TICKET_ITEMS, direct); if(!(fp=fopen(genbuf,"w"))) return FULLUPDATE; do { getdata(2, 0, "��J�m������ (����:10-10000):",yn,6, LCECHO); i=atoi(yn); } while( i<10 || i>10000); fprintf(fp,"%d\n",i); move(3,0); sprintf(genbuf,"�Ш� %s �� ��'f'�ѻP���!\n\n�@�i %d Ptt��, �o�O%s�����\n", currboard, i, i<100 ? "�p�䦡" : i<500 ? "������": i<1000 ?"�Q�گ�" : i<5000 ?"�I����" : "�ɮa����"); strcat(msg, genbuf); prints("�Ш̦���J�m���W��, �ݴ���2~8��. (�����K��, ��J������enter)\n"); for(i=0; i<8; i++) { sprintf(yn, " %d)",i+1); getdata(6+i, 0, yn, genbuf, 9, DOECHO); if(!genbuf[0] && i>1) break; fprintf(fp,"%s\n",genbuf); } fclose(fp); move(8+i,0); prints("��L�]�w����"); sprintf(genbuf,"[���i] %s �� �}�l���!", currboard); post_msg(currboard, genbuf, msg, cuser.userid); post_msg("Record", genbuf+7, msg, "[�������l]"); /* Tim ����CS, �H�K���b����user���Ƥw�g�g�i�� */ rename(fn_ticket_end, fn_ticket); // �]�w���~���ɦW��L�� return FULLUPDATE; } #endif static int cite_post(int ent, fileheader_t *fhdr, char *direct) { char fpath[256]; char title[TTLEN + 1]; setbfile(fpath, currboard, fhdr->filename); strcpy(title, "�� "); strncpy(title+3, fhdr->title, TTLEN-3); title[TTLEN] = '\0'; a_copyitem(fpath, title, 0, 1); b_man(); return FULLUPDATE; } int edit_title(int ent, fileheader_t *fhdr, char *direct) { char genbuf[200]; fileheader_t tmpfhdr = *fhdr; int dirty = 0; if(currmode & MODE_BOARD || !strcmp(cuser.userid,fhdr->owner)) { if(getdata(b_lines - 1, 0, "���D�G", genbuf, TTLEN, DOECHO)) { strcpy(tmpfhdr.title, genbuf); dirty++; } } if(HAS_PERM(PERM_SYSOP)) { if(getdata(b_lines - 1, 0, "�@�̡G", genbuf, IDLEN + 2, DOECHO)) { strcpy(tmpfhdr.owner, genbuf); dirty++; } if(getdata(b_lines - 1, 0, "����G", genbuf, 6, DOECHO)) { sprintf(tmpfhdr.date, "%.5s", genbuf); dirty++; } } if(currmode & MODE_BOARD || !strcmp(cuser.userid,fhdr->owner)) { getdata(b_lines-1, 0, "�T�w(Y/N)?[n] ", genbuf, 3, DOECHO); if((genbuf[0] == 'y' || genbuf[0] == 'Y') && dirty) { *fhdr = tmpfhdr; substitute_record(direct, fhdr, sizeof(*fhdr), ent); /* rocker.011018: �o�����ӧ令��reference���覡���o��Ӫ��ɮ� */ substitute_check(fhdr); touchdircache(currbid); } return FULLUPDATE; } return DONOTHING; } extern unsigned int currstat; static int solve_post(int ent, fileheader_t * fhdr, char *direct){ if (HAS_PERM(PERM_SYSOP)) { fhdr->filemode ^= FILE_SOLVED; substitute_record(direct, fhdr, sizeof(*fhdr), ent); touchdircache(currbid); return PART_REDRAW; } return DONOTHING; } static int recommend_cancel(int ent, fileheader_t *fhdr, char *direct) { char yn[5]; if (!(currmode & MODE_BOARD)) return DONOTHING; getdata(b_lines-1, 0, "�T�w�n�����k�s(Y/N)?[n] ", yn, 5, LCECHO); if(yn[0]!='y') return FULLUPDATE; fhdr->recommend=0; substitute_record(direct, fhdr, sizeof(*fhdr), ent); substitute_check(fhdr); touchdircache(currbid); return FULLUPDATE; } static int recommend(int ent, fileheader_t *fhdr, char *direct) { struct tm *ptime=localtime(&now); extern userec_t xuser; char buf[200],path[200], yn[5]; boardheader_t *bp; bp = getbcache(currbid); if(!(currmode & MODE_POST) || !strcmp(fhdr->owner,cuser.userid) || bp->brdattr & BRD_VOTEBOARD) { move(b_lines-1,0); prints("�z�]�v�������L�k���� �� ������˦ۤv���峹!"); pressanykey(); return FULLUPDATE; } if(fhdr->recommend>9 || fhdr->recommend<0 )// �Ȯɩʪ�code ����¦��Ȩ��� fhdr->recommend=0; if (!(currmode & MODE_BOARD) && getuser(cuser.userid) && now - xuser.recommend < 60 ) { move(b_lines-1,0); prints("���W�����ˮɶ��Ӫ��o, �Цh���I�ɶ��J�Ӿ\\Ū�峹!"); pressanykey(); return FULLUPDATE; } if(!getdata(b_lines-2, 0, "���˻y:",path,40,DOECHO) || !getdata(b_lines-1, 0, "�T�w�n����, �ХJ�ӦҼ{(Y/N)?[n] ", yn, 5,LCECHO) || yn[0]!='y') return FULLUPDATE; sprintf(buf, "\033[1;31m�� \033[33m%s\033[m\033[33m:%s\033[m%*s���˦�:%s %02d/%02d\n", cuser.userid, path, 45-strlen(cuser.userid)-strlen(path), " ",fromhost, ptime->tm_mon+1,ptime->tm_mday) ; setdirpath(path, direct, fhdr->filename); log_file(path, buf); if(fhdr->recommend<9) { fhdr->recommend++; cuser.recommend=now; passwd_update(usernum, &cuser); substitute_record(direct, fhdr, sizeof(*fhdr), ent); substitute_check(fhdr); touchdircache(currbid); } return FULLUPDATE; } static int mark_post(int ent, fileheader_t *fhdr, char *direct) { if(!(currmode & MODE_BOARD)) return DONOTHING; fhdr->filemode ^= FILE_MARKED; substitute_record(direct, fhdr, sizeof(*fhdr), ent); substitute_check(fhdr); touchdircache(currbid); return PART_REDRAW; } extern char *msg_sure_ny; int del_range(int ent, fileheader_t *fhdr, char *direct) { char num1[8], num2[8]; int inum1, inum2; /* rocker.011018: �걵�Ҧ��U�٬O�����\�R������n */ if(currmode & MODE_SELECT) { outmsg("�Х��^�쥿�`�Ҧ���A�i��R��..."); refresh(); /*safe_sleep(1);*/ return FULLUPDATE; } if((currstat != READING) || (currmode & MODE_BOARD)) { getdata(1, 0, "[�]�w�R���d��] �_�I�G", num1, 5, DOECHO); inum1 = atoi(num1); if(inum1 <= 0) { outmsg("�_�I���~"); refresh(); /*safe_sleep(1);*/ return FULLUPDATE; } getdata(1, 28, "���I�G", num2, 5, DOECHO); inum2 = atoi(num2); if(inum2 < inum1) { outmsg("���I���~"); refresh(); /*safe_sleep(1);*/ return FULLUPDATE; } getdata(1, 48, msg_sure_ny, num1, 3, LCECHO); if(*num1 == 'y') { outmsg("�B�z��,�еy��..."); refresh(); if(currmode & MODE_SELECT) { int fd,size = sizeof(fileheader_t); char genbuf[100]; fileheader_t rsfh; int i = inum1,now; if(currstat == RMAIL) sethomedir(genbuf, cuser.userid); else setbdir(genbuf,currboard); if((fd = (open(direct, O_RDONLY, 0))) != -1) { if(lseek(fd, (off_t)(size * (inum1 - 1)), SEEK_SET) != -1) { while(read(fd,&rsfh,size) == size) { if(i > inum2) break; now = getindex(genbuf, rsfh.filename, size); strcpy(currfile, rsfh.filename); delete_file(genbuf, sizeof(fileheader_t), now, cmpfilename); i++; } } close(fd); } } delete_range(direct, inum1, inum2); fixkeep(direct, inum1); if(currmode & MODE_BOARD) setbtotal(currbid); return DIRCHANGED; } return FULLUPDATE; } return DONOTHING; } extern char *msg_del_ny; extern char *msg_del_ok; static int del_post(int ent, fileheader_t *fhdr, char *direct) { char genbuf[100]; int not_owned; boardheader_t *bp; bp = getbcache(currbid); if((fhdr->filemode & FILE_MARKED) || (fhdr->filemode & FILE_DIGEST) || (fhdr->owner[0] == '-')) return DONOTHING; not_owned = strcmp(fhdr->owner, cuser.userid); if((!(currmode & MODE_BOARD) && not_owned) || ((bp->brdattr & BRD_VOTEBOARD) && !HAS_PERM(PERM_SYSOP)) || !strcmp(cuser.userid, STR_GUEST)) return DONOTHING; getdata(1, 0, msg_del_ny, genbuf, 3, LCECHO); if(genbuf[0] == 'y' || genbuf[0] == 'Y') { strcpy(currfile, fhdr->filename); setbfile(genbuf,currboard,fhdr->filename); if(!delete_file (direct, sizeof(fileheader_t), ent, cmpfilename)) { if(currmode & MODE_SELECT) { /* rocker.011018: �Q��reference��Cloading */ fileheader_t hdr; int num; num = fhdr->money & ~FHR_REFERENCE; setbdir(genbuf, currboard); get_record(genbuf, &hdr, sizeof (hdr), num); /* �A�o�̭ncheck�@�U��Ӫ�dir�̭��O���O���Q�H�ʹL... */ if (strcmp (hdr.filename, fhdr->filename)) { num=getindex(genbuf,fhdr->filename,sizeof(fileheader_t)); get_record(genbuf, &hdr, sizeof (hdr), num); } /* rocker.011018: �o�̭n�٭�Q�}�a��money */ fhdr->money = hdr.money; delete_file (genbuf, sizeof(fileheader_t), num, cmpfilename); } cancelpost(fhdr, not_owned); setbtotal(currbid); if (fhdr->money < 0) fhdr->money = 0; if (not_owned && strcmp(currboard, "Test")){ deumoney(searchuser(fhdr->owner), -fhdr->money); } if(!not_owned && strcmp(currboard, "Test")) { if(cuser.numposts) cuser.numposts--; move(b_lines - 1, 0); clrtoeol(); demoney(-fhdr->money); passwd_update(usernum, &cuser); /* post �� */ prints("%s�A�z���峹� %d �g�A��I�M��O %d ��", msg_del_ok, cuser.numposts,fhdr->money); refresh(); pressanykey(); } return DIRCHANGED; } } return FULLUPDATE; } static int view_postmoney(int ent, fileheader_t *fhdr, char *direct) { move(b_lines - 1, 0); clrtoeol(); prints("�o�@�g�峹�� %d ��", fhdr->money); refresh(); pressanykey(); return FULLUPDATE; } #ifdef OUTJOBSPOOL /* �ݪ��ƥ� */ static int tar_addqueue(int ent, fileheader_t *fhdr, char *direct) { char email[60], qfn[80], ans[2]; FILE *fp; char bakboard, bakman; clear(); showtitle("�ݪ��ƥ�", BBSNAME); move(2, 0); if( !((currmode & MODE_BOARD) || HAS_PERM(PERM_SYSOP)) ) { move(5, 10); outs("�p�n�O���D�άO�����~������� -.-\"\""); pressanykey(); return FULLUPDATE; } sprintf(qfn, BBSHOME "/jobspool/tarqueue.%s", currboard); if( access(qfn, 0) == 0 ){ outs("�w�g�Ʃw��{, �y��|�i��ƥ�"); pressanykey(); return FULLUPDATE; } if( !getdata(4, 0, "�п�J�ت��H�c�G", email, sizeof(email), DOECHO) ) return FULLUPDATE; /* check email -.-"" */ if( strstr(email, "@") == NULL || strstr(email, ".bbs@") != NULL ){ move(6, 0); outs("�z���w���H�c�����T! "); pressanykey(); return FULLUPDATE; } getdata(6, 0, "�n�ƥ��ݪ����e��(Y/N)?[Y]", ans, sizeof(ans), LCECHO); bakboard = (ans[0] == 'n' || ans[0] =='N') ? 0 : 1; getdata(7, 0, "�n�ƥ���ذϤ��e��(Y/N)?[N]", ans, sizeof(ans), LCECHO); bakman = (ans[0] == 'y' || ans[0] =='Y') ? 1 : 0; if( !bakboard && !bakman ){ move(8, 0); outs("�i�O�ڭ̥u��ƥ��ݪ��κ�ذϪ��C ^^\"\"\""); pressanykey(); return FULLUPDATE; } fp = fopen(qfn, "w"); fprintf(fp, "%s\n", cuser.userid); fprintf(fp, "%s\n", email); fprintf(fp, "%d,%d\n", bakboard, bakman); fclose(fp); move(10, 0); outs("�t�Τw�g�N�z���ƥ��ƤJ��{, \n"); outs("�y��N�|�b�t�έt�����C���ɭԱN��ƱH���z~ :) "); pressanykey(); return FULLUPDATE; } #endif static int sequent_ent; static int continue_flag; /* ----------------------------------------------------- */ /* �̧�Ū�s�峹 */ /* ----------------------------------------------------- */ static int sequent_messages(fileheader_t *fptr) { static int idc; char genbuf[200]; if(fptr == NULL) return (idc = 0); if(++idc < sequent_ent) return 0; if(!brc_unread(fptr->filename,brc_num,brc_list)) return 0; if(continue_flag) genbuf[0] = 'y'; else { prints("Ū���峹��G[%s] �@�̡G[%s]\n���D�G[%s]", currboard, fptr->owner, fptr->title); getdata(3, 0, "(Y/N/Quit) [Y]: ", genbuf, 3, LCECHO); } if(genbuf[0] != 'y' && genbuf[0]) { clear(); return (genbuf[0] == 'q' ? QUIT : 0); } setbfile(genbuf, currboard, fptr->filename); brc_addlist(fptr->filename); if(more(genbuf, YEA) == 0) outmsg("\033[31;47m \033[31m(R)\033[30m�^�H \033[31m(��,n)" "\033[30m�U�@�� \033[31m(��,q)\033[30m���} \033[m"); continue_flag = 0; switch(egetch()) { case KEY_LEFT: case 'e': case 'q': case 'Q': break; case 'y': case 'r': case 'Y': case 'R': if(currmode & MODE_POST) { strcpy(quote_file, genbuf); do_reply(fptr); *quote_file = 0; } break; case ' ': case KEY_DOWN: case '\n': case 'n': continue_flag = 1; } clear(); return 0; } static int sequential_read(int ent, fileheader_t *fhdr, char *direct) { char buf[40]; clear(); sequent_messages((fileheader_t *) NULL); sequent_ent = ent; continue_flag = 0; setbdir(buf, currboard); apply_record(buf, sequent_messages, sizeof(fileheader_t)); return FULLUPDATE; } extern char *fn_notes; extern char *msg_cancel; extern char *fn_board; /* ----------------------------------------------------- */ /* �ݪO�Ƨѿ��B��K�B��ذ� */ /* ----------------------------------------------------- */ int b_note_edit_bname(int bid) { char buf[64]; int aborted; boardheader_t *fh=getbcache(bid); setbfile(buf, fh->brdname, fn_notes); aborted = vedit(buf, NA, NULL); if(aborted == -1) { clear(); outs(msg_cancel); pressanykey(); } else { aborted = (fh->bupdate - now ) / 86400 + 1; sprintf(buf,"%d", aborted > 0 ? aborted : 0); getdata_buf(3, 0, "�г]�w���Ĵ���(0 - 9999)�ѡH", buf, 5, DOECHO); aborted = atoi(buf); fh->bupdate = aborted ? now + aborted * 86400 : 0; substitute_record(fn_board, fh, sizeof(boardheader_t), bid); } return 0; } static int b_notes_edit() { if(currmode & MODE_BOARD) { b_note_edit_bname(currbid); return FULLUPDATE; } return 0; } static int b_water_edit() { if(currmode & MODE_BOARD) { friend_edit(BOARD_WATER); return FULLUPDATE; } return 0; } static int visable_list_edit() { if(currmode & MODE_BOARD) { friend_edit(BOARD_VISABLE); hbflreload(currbid); return FULLUPDATE; } return 0; } 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) more("etc/"FN_POST_NOTE , NA); getdata(b_lines - 2, 0, "�O�_�n�Φۭqpost�`�N�ƶ�?", yn, sizeof(yn), LCECHO); if(yn[0] == 'y') vedit(buf, NA, NULL); else unlink(buf); return FULLUPDATE; } return 0; } static int b_application() { char buf[200]; if(currmode & MODE_BOARD) { setbfile(buf, currboard, FN_APPLICATION); vedit(buf, NA, NULL); return FULLUPDATE; } return 0; } static int can_vote_edit() { if(currmode & MODE_BOARD) { friend_edit(FRIEND_CANVOTE); return FULLUPDATE; } return 0; } static int bh_title_edit() { boardheader_t *bp; if(currmode & MODE_BOARD) { char genbuf[BTLEN]; bp = getbcache(currbid); move(1,0); clrtoeol(); getdata_str(1,0,"�п�J�ݪO�s����ԭz:", genbuf, BTLEN - 16, DOECHO, bp->title + 7); if(!genbuf[0]) return 0; strip_ansi( genbuf,genbuf,0); strcpy(bp->title + 7,genbuf); substitute_record(fn_board, bp, sizeof(boardheader_t), currbid); log_usies("SetBoard", currboard); return FULLUPDATE; } return 0; } static int b_notes() { char buf[64]; setbfile(buf, currboard, fn_notes); if(more(buf, NA) == -1) { clear(); move(4, 20); outs("���ݪO�|�L�u�Ƨѿ��v�C"); } pressanykey(); return FULLUPDATE; } int board_select() { char fpath[80]; char genbuf[100]; currmode &= ~MODE_SELECT; sprintf(fpath, "SR.%s", cuser.userid); setbfile(genbuf, currboard, fpath); unlink(genbuf); if(currstat == RMAIL) sethomedir(currdirect, cuser.userid); else setbdir(currdirect, currboard); return NEWDIRECT; } int board_digest() { if(currmode & MODE_SELECT) board_select(); currmode ^= MODE_DIGEST; if(currmode & MODE_DIGEST) currmode &= ~MODE_POST; else if (haspostperm(currboard)) currmode |= MODE_POST; setbdir(currdirect, currboard); return NEWDIRECT; } int board_etc() { if(!HAS_PERM(PERM_SYSOP)) return DONOTHING; currmode ^= MODE_ETC; if(currmode & MODE_ETC) currmode &= ~MODE_POST; else if(haspostperm(currboard)) currmode |= MODE_POST; setbdir(currdirect, currboard); return NEWDIRECT; } extern char *fn_mandex; static int good_post(int ent, fileheader_t *fhdr, char *direct) { char genbuf[200]; char genbuf2[200]; int delta = 0; if((currmode & MODE_DIGEST) || !(currmode & MODE_BOARD)) return DONOTHING; if(fhdr->filemode & FILE_DIGEST) { fhdr->filemode = (fhdr->filemode & ~FILE_DIGEST); if(!strcmp(currboard,"Note") || !strcmp(currboard,"PttBug") || !strcmp(currboard,"Artdsn") || !strcmp(currboard, "PttLaw")) { deumoney(searchuser(fhdr->owner),-1000); if(!(currmode & MODE_SELECT)) fhdr->money -= 1000; else delta = -1000; } } else { fileheader_t digest; char *ptr, buf[64]; memcpy(&digest, fhdr, sizeof(digest)); digest.filename[0] = 'G'; strcpy(buf, direct); ptr = strrchr(buf, '/') + 1; ptr[0] = '\0'; sprintf(genbuf, "%s%s", buf, digest.filename); if(dashf(genbuf)) unlink (genbuf); digest.filemode = 0; sprintf(genbuf2, "%s%s", buf, fhdr->filename); Link(genbuf2, genbuf); strcpy(ptr, fn_mandex); append_record(buf, &digest, sizeof(digest)); fhdr->filemode = (fhdr->filemode & ~FILE_MARKED) | FILE_DIGEST; if(!strcmp(currboard, "Note") || !strcmp(currboard, "PttBug") || !strcmp(currboard,"Artdsn") || !strcmp(currboard, "PttLaw")) { deumoney(searchuser(fhdr->owner), 1000); if(!(currmode & MODE_SELECT)) fhdr->money += 1000; else delta = 1000; } } substitute_record(direct, fhdr, sizeof(*fhdr), ent); touchdircache(currbid); /* rocker.011018: �걵�Ҧ���reference�W�i�IJv */ if ((currmode & MODE_SELECT) && (fhdr->money & FHR_REFERENCE)) { fileheader_t hdr; char genbuf[100]; int num; num = fhdr->money & ~FHR_REFERENCE; setbdir(genbuf, currboard); get_record(genbuf, &hdr, sizeof (hdr), num); /* �A�o�̭ncheck�@�U��Ӫ�dir�̭��O���O���Q�H�ʹL... */ if (strcmp (hdr.filename, fhdr->filename)) { num = getindex(genbuf, fhdr->filename, sizeof(fileheader_t)); get_record(genbuf, &hdr, sizeof (hdr), num); } fhdr->money = hdr.money + delta; substitute_record(genbuf, fhdr, sizeof(*fhdr), num); } return PART_REDRAW; } /* help for board reading */ static char *board_help[] = { "\0���\\��ݪO�ާ@����", "\01�R�O", "(p)(��) �W���@�g�峹 (^P) �o���峹", "(n)(��) �U���@�g�峹 (d) �R���峹", "(P)(PgUp) �W���@�� (S) ��s�����峹", "(N)(PgDn) �U���@�� (##) ���� ## ���峹", "(r)(��) �\\Ū���g�峹 ($) ����̫�@�g�峹", "\01�i���R�O", "(tab)/z ��K�Ҧ�/��ذ� (a/A)(^Q)��M�@��/�@�̸��", "(b/f) �iŪ�Ƨѿ�/�ѻP��L (?)(/) ��M���D", "(V/R) �벼/�d�ߧ벼���G (^W)(X) �ڦb����/���ˤ峹", "(x)(w) ����峹/����y (=)/([]<>-+) ��M���g�峹/�D�D���\\Ū", #ifdef INTERNET_EMAIL "(F) �峹�H�^Internet�l�c (U) �N�峹 uuencode ��H�^�l�c", #endif "(E) ���s�峹 (^H) �C�X�Ҧ��� New Post(s)", "\01�O�D�R�O", "(G) �|���L/����U�`/�}��(W/K/v) �s��Ƨѿ�/�����W��/�i�ݨ��W��", "(M/o) �|��벼/�s�p�벼�W�� (m/c/g) �O�d�峹/������/��K", "(D) �R���@�q�d�峹 (T/B) ���s�峹���D/���s�ݪ����D", "(i) �s��ӽФJ�|���� (t/^D) �аO�峹/�尣�аO���峹", "(O) �s��Post�`�N�ƶ� (H)/(Y) �ݪO����/�{�� �������ˤ峹", NULL }; static int b_help() { show_help(board_help); return FULLUPDATE; } /* ----------------------------------------------------- */ /* �O�D�]�w����/ ������ */ /* ----------------------------------------------------- */ char board_hidden_status; #ifdef BMCHS extern char *fn_board; static int change_hidden(int ent, fileheader_t *fhdr, char *direct) { boardheader_t bh; int bid; char ans[4]; if( !((currmode & MODE_BOARD) || HAS_PERM(PERM_SYSOP)) || currboard[0] == 0 || (bid = getbnum(currboard)) < 0 || get_record(fn_board, &bh, sizeof(bh), bid) == -1 ) return DONOTHING; if( ((bh.brdattr & BRD_HIDE) && (bh.brdattr & BRD_POSTMASK)) ){ getdata(1, 0, "�ثe�O�b���Ϊ��A, �n�����ι�(Y/N)?[N]", ans, sizeof(ans), LCECHO); if( ans[0] != 'y' && ans[0] != 'Y' ) return FULLUPDATE; getdata(2, 0, "�A�T�{�@��, �u���n��O�O���}�� @____@(Y/N)?[N]", ans, sizeof(ans), LCECHO); if( ans[0] != 'y' && ans[0] != 'Y' ) return FULLUPDATE; if( bh.brdattr & BRD_HIDE ) bh.brdattr -= BRD_HIDE; if( bh.brdattr & BRD_POSTMASK ) bh.brdattr -= BRD_POSTMASK; log_usies("OpenBoard", bh.brdname); outs("�g�ߤ��Dz��H�A�L�B���D���q�C\n"); board_hidden_status = 0; hbflreload(bid); } else{ getdata(1, 0, "�ثe�O�b�{�Ϊ��A, �n���ι�(Y/N)?[N]", ans, sizeof(ans), LCECHO); if( ans[0] != 'y' && ans[0] != 'Y' ) return FULLUPDATE; bh.brdattr |= BRD_HIDE; bh.brdattr |= BRD_POSTMASK; log_usies("CloseBoard", bh.brdname); outs("�g�ߤ��w�����A���ߵ��۬í��C\n"); board_hidden_status = 1; } setup_man(&bh); substitute_record(fn_board, &bh, sizeof(bh), bid); reset_board(bid); log_usies("SetBoard", bh.brdname); pressanykey(); return FULLUPDATE; } #endif /* ----------------------------------------------------- */ /* �ݪO�\��� */ /* ----------------------------------------------------- */ struct onekey_t read_comms[] = { {KEY_TAB, board_digest}, {'C', board_etc}, {'b', b_notes}, {'c', cite_post}, {'r', read_post}, {'z', b_man}, {'D', del_range}, {'S', sequential_read}, {'E', edit_post}, {'T', edit_title}, {'s', do_select}, {'R', b_results}, {'V', b_vote}, {'M', b_vote_maintain}, {'B', bh_title_edit}, {'W', b_notes_edit}, {'O', b_post_note}, {'K', b_water_edit}, {'w', b_call_in}, {'v', visable_list_edit}, {'i', b_application}, {'o', can_vote_edit}, {'x', cross_post}, {'X', recommend}, {'Y', recommend_cancel}, {'h', b_help}, #ifndef NO_GAMBLE {'f', join_gamble}, {'G', hold_gamble}, #endif {'g', good_post}, {'y', reply_post}, {'d', del_post}, {'m', mark_post}, {'L', solve_post}, {Ctrl('P'), do_post}, {Ctrl('W'), whereami}, {'Q', view_postmoney}, #ifdef OUTJOBSPOOL {'u', tar_addqueue}, #endif #ifdef BMCHS {'H', change_hidden}, #endif {'\0', NULL} }; time_t board_visit_time; int Read() { int mode0 = currutmp->mode; int stat0 = currstat, tmpbid=currutmp->brc_id; char buf[40]; #ifdef LOG_BOARD time_t usetime = now; #endif setutmpmode(READING); set_board(); if(board_visit_time < board_note_time) { setbfile(buf, currboard, fn_notes); more(buf, NA); pressanykey(); } setutmpbid(currbid); setbdir(buf, currboard); curredit &= ~EDIT_MAIL; i_read(READING, buf, readtitle, readdoent, read_comms, currbid); #ifdef LOG_BOARD log_board(currboard, now - usetime); #endif brc_update(); setutmpbid(tmpbid); currutmp->mode = mode0; currstat = stat0; return 0; } void ReadSelect() { int mode0 = currutmp->mode; int stat0 = currstat; char genbuf[200]; currstat = XMODE; if(do_select(0, 0, genbuf) == NEWDIRECT) Read(); setutmpbid(0); currutmp->mode = mode0; currstat = stat0; } #ifdef LOG_BOARD static void log_board(char *mode, time_t usetime) { char buf[ 256 ]; if(usetime > 30) { sprintf(buf, "USE %-20.20s Stay: %5ld (%s) %s", mode, usetime ,cuser.userid ,ctime(&now)); log_file(FN_USEBOARD,buf); } } #endif int Select() { char genbuf[200]; setutmpmode(SELECT); do_select(0, NULL, genbuf); return 0; }