/* $Id: friend.c,v 1.5 2002/04/28 19:35:29 in2 Exp $ */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/file.h>
#include "config.h"
#include "pttstruct.h"
#include "common.h"
#include "perm.h"
#include "proto.h"
#include "modes.h"
extern userec_t cuser;
extern int currmode;
extern char currboard[]; /* name of currently selected board */
extern char *fn_overrides;
extern userinfo_t *currutmp;
extern char *fn_reject;
extern int usernum;
extern char *str_space;
extern char *msg_uid;
/* ------------------------------------- */
/* 特別名單 */
/* ------------------------------------- */
/* Ptt 其他特別名單的檔名 */
static char special_list[] = "list.0";
static char special_des[] = "ldes.0";
/* 特別名單的上限 */
static unsigned int friend_max[8] = {
MAX_FRIEND,
MAX_REJECT,
MAX_LOGIN_INFO,
MAX_POST_INFO,
MAX_NAMELIST,
MAX_NAMELIST,
MAX_NAMELIST,
MAX_NAMELIST
};
/* 雖然好友跟壞人名單都是 * 2 但是一次最多load到shm只能有128 */
/* Ptt 各種特別名單的檔名 */
char *friend_file[8] = {
FN_OVERRIDES,
FN_REJECT,
"alohaed",
"postlist",
"",
FN_CANVOTE,
FN_WATER,
FN_VISABLE
};
/* Ptt 各種特別名單的補述 */
static char *friend_desc[8] = {
"友誼描述:",
"惡形惡狀:",
"",
"",
"描述一下:",
"投票者描述:",
"惡形惡狀:",
"看板好友描述"
};
/* Ptt 各種特別名單的中文敘述 */
static char *friend_list[8] = {
"好友名單",
"壞人名單",
"上線通知",
"新文章通知",
"其它特別名單",
"私人投票名單",
"看板禁聲名單",
"看板好友名單"
};
static void setfriendfile(char *fpath, int type) {
if (type <= 4) /* user list Ptt */
setuserfile(fpath, friend_file[type]);
else /* board list */
setbfile(fpath, currboard, friend_file[type]);
}
static int friend_count(char *fname) {
FILE *fp;
int count = 0;
char buf[200];
#if 0
if ((fp = fopen(fname, "r")))
while (fgets(buf, 200, fp))
count++;
#endif
/*rocker.011018: 忘記關檔了... */
if ((fp = fopen(fname, "r")))
{
while (fgets(buf, 200, fp)) count++;
fclose (fp);
}
return count;
}
void friend_add(char *uident, int type) {
char fpath[80];
setfriendfile(fpath, type);
if (friend_count(fpath) > friend_max[type])
return;
if ((uident[0] > ' ') && !belong(fpath, uident))
{
FILE *fp;
char buf[40] = "";
char t_uident[IDLEN + 1];
/* Thor: avoid uident run away when get data */
strcpy(t_uident, uident);
if (type != FRIEND_ALOHA && type != FRIEND_POST)
getdata(2, 0, friend_desc[type], buf, sizeof(buf), DOECHO);
if ((fp = fopen(fpath, "a")))
{
flock(fileno(fp), LOCK_EX);
fprintf(fp, "%-13s%s\n", t_uident, buf);
flock(fileno(fp), LOCK_UN);
fclose(fp);
}
}
}
static void friend_special() {
char genbuf[70], i, fname[70];
friend_file[FRIEND_SPECIAL] = special_list;
for (i = 0; i <= 9; i++)
{
sprintf(genbuf, " (\033[36m%d\033[m) .. ", i);
special_des[5] = i + '0';
setuserfile(fname, special_des);
if (dashf(fname))
{
/* no NULL check?? */
FILE *fp = fopen(fname, "r");
fgets(genbuf + 15, 40, fp);
genbuf[47] = 0;
}
move(i + 12, 0);
clrtoeol();
outs(genbuf);
}
getdata(22, 0, "請選擇第幾號特別名單 (0~9)[0]?", genbuf, 3, LCECHO);
if (genbuf[0] >= '0' && genbuf[0] <= '9')
{
special_list[5] = genbuf[0];
special_des[5] = genbuf[0];
}
else
{
special_list[5] = '0';
special_des[5] = '0';
}
}
static void friend_append(int type, int count) {
char fpath[80], i, j, buf[80], sfile[80];
FILE *fp, *fp1;
setfriendfile(fpath, type);
do
{
move(2, 0);
clrtobot();
outs("要引入哪一個名單?\n");
for (j = i = 0; i <= 4; i++)
if( i != type ){
++j;
sprintf(buf, " (%d) %-s\n", i + 1, friend_list[(int) i]);
outs(buf);
}
if( HAVE_PERM(PERM_SYSOP) || currmode & MODE_BOARD )
for( ; i < 8 ; ++i )
if( i != type ){
++j;
sprintf(buf, " (%d) %s 版的 %s\n", j, currboard,
friend_list[(int) i]);
outs(buf);
}
outs(" (S) 選擇其他看板的特別名單");
getdata(11, 0, "請選擇 或 直接[Enter] 放棄:", buf, 3, LCECHO);
if (!buf[0])
return;
if (buf[0] == 's')
Select();
j = buf[0] - '1';
if (j >= type)
j++;
if( !(HAVE_PERM(PERM_SYSOP) || currmode & MODE_BOARD) && j >= 4 )
return;
}
while (buf[0] < '1' || buf[0] > '9');
if (j == FRIEND_SPECIAL)
friend_special();
setfriendfile(sfile, j);
fp = fopen(sfile, "r");
while (fgets(buf, 80, fp) && count <= friend_max[type])
{
char the_id[15];
sscanf(buf, "%s", the_id);
if (!belong(fpath, the_id))
{
if ((fp1 = fopen(fpath, "a")))
{
flock(fileno(fp1), LOCK_EX);
fputs(buf, fp1);
flock(fileno(fp1), LOCK_UN);
fclose(fp1);
}
}
}
fclose(fp);
}
void friend_delete(char *uident, int type) {
FILE *fp, *nfp;
char fn[80], fnnew[80];
char genbuf[200];
setfriendfile(fn, type);
sprintf(fnnew, "%s-", fn);
if ((fp = fopen(fn, "r")) && (nfp = fopen(fnnew, "w")))
{
int length = strlen(uident);
while (fgets(genbuf, STRLEN, fp))
if ((genbuf[0] > ' ') && strncmp(genbuf, uident, length))
fputs(genbuf, nfp);
fclose(fp);
fclose(nfp);
Rename(fnnew, fn);
}
}
static void friend_editdesc(char *uident, int type) {
FILE *fp, *nfp;
char fnnew[200], genbuf[200], fn[200];
setfriendfile(fn, type);
sprintf(fnnew, "%s-", fn);
if ((fp = fopen(fn, "r")) && (nfp = fopen(fnnew, "w")))
{
int length = strlen(uident);
while (fgets(genbuf, STRLEN, fp))
{
if ((genbuf[0] > ' ') && strncmp(genbuf, uident, length))
fputs(genbuf, nfp);
else if (!strncmp(genbuf, uident, length))
{
char buf[50] = "";
getdata(2, 0, "修改描述:", buf, 40, DOECHO);
fprintf(nfp, "%-13s%s\n", uident, buf);
}
}
fclose(fp);
fclose(nfp);
Rename(fnnew, fn);
}
}
void friend_load() {
FILE *fp;
int myfriends[MAX_FRIEND];
int myrejects[MAX_REJECT];
int friendcount, rejectedcount;
char genbuf[200];
memset(myfriends, 0, sizeof(myfriends));
friendcount = 0;
setuserfile(genbuf, fn_overrides);
if ((fp = fopen(genbuf, "r")))
{
int unum;
while (fgets(genbuf, STRLEN, fp) && friendcount < MAX_FRIEND - 1)
if (strtok(genbuf, str_space))
if ((unum = searchuser(genbuf)))
myfriends[friendcount++] = unum;
fclose(fp);
}
memcpy(currutmp->friend, myfriends, sizeof(myfriends));
memset(myrejects, 0, sizeof(myrejects));
rejectedcount = 0;
setuserfile(genbuf, fn_reject);
if ((fp = fopen(genbuf, "r")))
{
int unum;
while (fgets(genbuf, STRLEN, fp) && rejectedcount < MAX_REJECT - 1)
if (strtok(genbuf, str_space))
if ((unum = searchuser(genbuf)))
myrejects[rejectedcount++] = unum;
fclose(fp);
}
memcpy(currutmp->reject, myrejects, sizeof(myrejects));
if(currutmp->friendtotal)
logout_friend_online(currutmp);
login_friend_online();
}
extern userec_t cuser;
static void friend_water(char *message, int type) { /* 群體水球 added by Ptt */
char fpath[80], line[80], userid[IDLEN + 1];
FILE *fp;
setfriendfile(fpath, type);
if ((fp = fopen(fpath, "r")))
while(fgets(line, 80, fp)) {
userinfo_t *uentp;
int tuid;
sscanf(line, "%s", userid);
if((tuid = searchuser(userid)) && tuid != usernum &&
(uentp = (userinfo_t *) search_ulist(tuid)) &&
isvisible_uid(tuid))
my_write(uentp->pid, message, uentp->userid, 1, NULL);
}
fclose(fp);
}
void friend_edit(int type) {
char fpath[80], line[80], uident[20];
int count, column, dirty;
FILE *fp;
char genbuf[200];
if (type == FRIEND_SPECIAL)
friend_special();
setfriendfile(fpath, type);
if (type == FRIEND_ALOHA || type == FRIEND_POST)
{
if (dashf(fpath))
{
sprintf(genbuf, "/bin/cp %s %s.old", fpath, fpath);
system(genbuf);
}
}
dirty = 0;
while (1)
{
stand_title(friend_list[type]);
move(0, 40);
sprintf(line, "(名單上限:%d個人)", friend_max[type]);
outs(line);
count = 0;
CreateNameList();
if ((fp = fopen(fpath, "r")))
{
move(3, 0);
column = 0;
while (fgets(genbuf, STRLEN, fp))
{
if (genbuf[0] <= ' ')
continue;
strtok(genbuf, str_space);
AddNameList(genbuf);
prints("%-13s", genbuf);
count++;
if (++column > 5)
{
column = 0;
outc('\n');
}
}
fclose(fp);
}
getdata(1, 0, (count ?
"(A)增加(D)刪除(E)修改(P)引入(L)詳細列出"
"(K)刪除整個名單(W)丟水球(Q)結束?[Q]" :
"(A)增加 (P)引入其他名單 (Q)結束?[Q]"),
uident, 3, LCECHO);
if (*uident == 'a')
{
move(1, 0);
usercomplete(msg_uid, uident);
if (uident[0] && searchuser(uident) && !InNameList(uident))
{
friend_add(uident, type);
dirty = 1;
}
}
else if (*uident == 'p')
{
friend_append(type, count);
dirty = 1;
}
else if (*uident == 'e' && count)
{
move(1, 0);
namecomplete(msg_uid, uident);
if (uident[0] && InNameList(uident))
{
friend_editdesc(uident, type);
}
}
else if (*uident == 'd' && count)
{
move(1, 0);
namecomplete(msg_uid, uident);
if (uident[0] && InNameList(uident))
{
friend_delete(uident, type);
dirty = 1;
}
}
else if (*uident == 'l' && count)
more(fpath, YEA);
else if (*uident == 'k' && count)
{
getdata(2, 0, "整份名單將會被刪除,您確定嗎 (a/N)?", uident, 3,
LCECHO);
if (*uident == 'a')
unlink(fpath);
dirty = 1;
}
else if (*uident == 'w' && count)
{
char wall[60];
if (!getdata(0, 0, "群體水球:", uident, sizeof(wall), DOECHO))
continue;
if (getdata(0, 0, "確定丟出群體水球? [Y]", line, 4, LCECHO) &&
*line == 'n')
continue;
friend_water(wall, type);
}
else
break;
}
if (dirty)
{
move(2, 0);
outs("更新資料中..請稍候.....");
refresh();
if (type == FRIEND_ALOHA || type == FRIEND_POST)
{
sprintf(genbuf, "%s.old", fpath);
if ((fp = fopen(genbuf, "r")))
{
while (fgets(line, 80, fp))
{
sscanf(line, "%s", uident);
sethomefile(genbuf, uident,
type == FRIEND_ALOHA ? "aloha" : "postnotify");
del_distinct(genbuf, cuser.userid);
}
fclose(fp);
}
sprintf(genbuf, "%s", fpath);
if ((fp = fopen(genbuf, "r")))
{
while (fgets(line, 80, fp))
{
sscanf(line, "%s", uident);
sethomefile(genbuf, uident,
type == FRIEND_ALOHA ? "aloha" : "postnotify");
add_distinct(genbuf, cuser.userid);
}
fclose(fp);
}
}
else if (type == FRIEND_SPECIAL)
{
genbuf[0] = 0;
setuserfile(line, special_des);
if ((fp = fopen(line, "r")))
{
fgets(genbuf, 30, fp);
fclose(fp);
}
getdata_buf(2, 0, " 請為此特別名單取一個簡短名稱:", genbuf, 30,
DOECHO);
if ((fp = fopen(line, "w")))
{
fprintf(fp, "%s", genbuf);
fclose(fp);
}
}
friend_load();
}
}
int t_override() {
friend_edit(FRIEND_OVERRIDE);
return 0;
}
int t_reject() {
friend_edit(FRIEND_REJECT);
return 0;
}