/************************************************************************ * IRC - Internet Relay Conferencing, ircd/note.c * Copyright (C) 1990, 1994 Jarle Lyngaas * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * Author: Jarle Lyngaas * E-mail: jarlel@ii.uib.no */ #include "struct.h" #ifdef NPATH #include "numeric.h" #include #include #include "common.h" #include "sys.h" #include "channel.h" #include "h.h" #define VERSION "v2.8.5" #define NOTE_SAVE_FREQUENCY 30 /* Frequency of save time in minutes */ #define NOTE_MAXSERVER_TIME 120 /* Max days for a request in the server */ #define NOTE_MAXSERVER_MESSAGES 5000 /* Max number of requests in the server */ #define NOTE_MAXUSER_MESSAGES 200 /* Max number of requests for each user */ #define NOTE_MAXSERVER_WILDCARDS 200 /* Max number of server toname w.cards */ #define NOTE_MAXUSER_WILDCARDS 5 /* Max number of user toname wildcards */ #define MAX_DAYS_NO_USE_SPY 31 /* No matches or no user on */ #define ONLY_LOCAL_SPY_ON_CHANNEL /* To save 50% CPU */ #define MIN_DELAY 10 #define BUF_LEN 256 #define MSG_LEN 512 #define REALLOC_SIZE 1024 #define FLAGS_WASOPER (1<<0) #define FLAGS_SIGNOFF_REMOVE (1<<1) #define FLAGS_SORT_BY_TONAME (1<<2) #define FLAGS_FROM_REG (1<<3) #define FLAGS_NEWS (1<<4) #define FLAGS_ON_THIS_SERVER (1<<5) #define FLAGS_REPEAT_UNTIL_TIMEOUT (1<<6) #define FLAGS_ALL_NICK_VALID (1<<7) #define FLAGS_SERVER_GENERATED (1<<8) #define FLAGS_NICK_AND_WILDCARD_VALID (1<<9) #define FLAGS_SERVER_GENERATED_DESTINATION (1<<10) #define FLAGS_DISTRIBUTE (1<<11) #define FLAGS_CHANNEL_PASSWORD (1<<12) #define FLAGS_DISPLAY_IF_DEST_REGISTER (1<<13) #define FLAGS_SEND_ONLY_IF_SENDER_ON_ICN (1<<14) #define FLAGS_CHANNEL (1<<15) #define FLAGS_NO_NICKCHANGE_SPY (1<<16) #define FLAGS_SEND_ONLY_IF_THIS_SERVER (1<<17) #define FLAGS_SEND_ONLY_IF_DESTINATION_OPER (1<<18) #define FLAGS_SEND_ONLY_IF_NICK_NOT_NAME (1<<19) #define FLAGS_SEND_ONLY_IF_NOT_EXCEPTION (1<<20) #define FLAGS_KEY_TO_OPEN_OPER_LOCKS (1<<21) #define FLAGS_FIND_CORRECT_DEST_SEND_ONCE (1<<22) #define FLAGS_DISPLAY_CHANNEL_DEST_REGISTER (1<<23) #define FLAGS_DISPLAY_SERVER_DEST_REGISTER (1<<24) #define FLAGS_PRIVATE_DISPLAYED (1<<25) #define FLAGS_REGISTER_NEWNICK (1<<26) #define FLAGS_NOTICE_RECEIVED_MESSAGE (1<<27) #define FLAGS_RETURN_CORRECT_DESTINATION (1<<28) #define FLAGS_DENY (1<<29) #define FLAGS_NEWNICK_DISPLAYED (1<<30) #define DupNewString(x,y) if (!StrEq(x,y)) { MyFree(x); DupString(x,y); } #define MyEq(x,y) (!strncasecmp(x,y,strlen(x))) #undef strcasecmp #define strcasecmp mystrcasecmp /* strcasecmp sux, making note use double cpu */ #define Userstrcasecmp(x,y) strcasecmp(x,y) #define Key(sptr) KeyFlags(sptr,-1) #define Message(msgclient) get_msg(msgclient, 'm') #define IsOperHere(sptr) (IsOper(sptr) && MyConnect(sptr)) #define NULLCHAR ((char *)0) #define SPY_CTRLCHAR 13 #define DummyChar '~' #define SECONDS_DAY 3600*24 #define SECONDS_WEEK SECONDS_DAY*7 #define SECONDS_MONTH SECONDS_WEEK*31 #define SECONDS_FOR_ALL_DISTRIBUTE SECONDS_DAY/3 #define SECONDS_SERVER_DISTRIBUTE SECONDS_DAY /* Using Message(msgclient) to get message part of *any* message cause the spy function is an ugly hack saving log in this field - Jarle */ typedef int long32; typedef struct MsgClient { char *fromnick, *fromname, *fromhost, *tonick, *toname, *tohost, *message, *passwd; time_t timeout, time; long32 flags, id; } aMsgClient; static int note_mst = NOTE_MAXSERVER_TIME, note_mum = NOTE_MAXUSER_MESSAGES, note_msm = NOTE_MAXSERVER_MESSAGES, note_msw = NOTE_MAXSERVER_WILDCARDS, note_muw = NOTE_MAXUSER_WILDCARDS, note_msf = NOTE_SAVE_FREQUENCY*60, wildcard_index = 0, toname_index = 0, fromname_index = 0, max_toname, max_wildcards, max_fromname, m_id = 0, changes_to_save = 0, fast_distribute_timeout = 0; static time_t saved_clock = 0; static aMsgClient **ToNameList, **FromNameList, **WildCardList; extern aClient *client, *find_person(), *local[]; extern int highest_fd; extern aChannel *channel; extern char *myctime(); extern char *MyMalloc(), *MyRealloc(), *myctime(); static char *ptr = "IRCnote", *note_save_filename_tmp, file_inited = 0; static unsigned char charmap[] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', '\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', }; static int mystrcasecmp(s1, s2) char *s1, *s2; { register unsigned char u1, u2; for (;;) { u1 = (unsigned char) *s1++; u2 = (unsigned char) *s2++; if (charmap[u1] != charmap[u2]) { return charmap[u1] - charmap[u2]; } if (u1 == '\0') { return 0; } } } static char *UserName(sptr) aClient *sptr; { if (*(sptr->user->username) != DummyChar) return sptr->user->username; else return sptr->user->username+1; } static int numeric(string) char *string; { register char *c = string; if (!*c) return 0; while (*c) if (!isdigit(*c)) return 0; else c++; return 1; } static char *clean_spychar(string) char *string; { static char buf[MSG_LEN]; char *c, *bp = buf; for (c = string; *c; c++) if (*c != SPY_CTRLCHAR) *bp++ = *c; *bp = 0; return buf; } static char *myitoa(value) long32 value; { static char buf[BUF_LEN]; sprintf(buf, "%d", value); return buf; } static char *relative_time(seconds) time_t seconds; { static char buf[20]; char *c; long32 d, h, m; if (seconds < 0) seconds = 0; d = seconds / (3600*24); seconds -= d*3600*24; h = seconds / 3600; seconds -= h*3600; m = seconds / 60; seconds -= m*60; sprintf(buf, "%3dd:%2dh:%2dm", d, h, m); c = buf; while (*c) { if (*c == ' ') *c = '0'; c++; } return buf; } static char *mytime(value) long32 value; { return (relative_time(now-value)); } static char *get_msg(msgclient, field) aMsgClient *msgclient; char field; { char *c = msgclient->message; static char buf[MSG_LEN], *empty_char = ""; int t, p; buf[0] = 0; switch(field) { case 'n' : t = 1; break; case 'u' : t = 2; break; case 'h' : t = 3; break; case 'r' : t = 4; break; case '1' : t = 5; break; case '2' : t = 6; break; default: t = 0; } if (!t) { while (*c) c++; while (c != msgclient->message && *c != SPY_CTRLCHAR) c--; if (*c == SPY_CTRLCHAR) c++; return c; } while(t--) { p = 0; while (*c && *c != SPY_CTRLCHAR) buf[p++] = *c++; if (!*c) return empty_char; buf[p] = 0; c++; }; return buf; } static void update_spymsg(msgclient) aMsgClient *msgclient; { long32 t; char *buf, *empty = "-", ctrlbuf[2], mbuf[MSG_LEN]; mbuf[0] = 0; ctrlbuf[0] = SPY_CTRLCHAR; ctrlbuf[1] = 0; buf = get_msg(msgclient, 'n'); if (!*buf) buf = empty; strcat(mbuf, buf); strcat(mbuf, ctrlbuf); buf = get_msg(msgclient, 'u'); if (!*buf) buf = empty; strcat(mbuf, buf); strcat(mbuf, ctrlbuf); buf = get_msg(msgclient, 'h'); if (!*buf) buf = empty; strcat(mbuf, buf); strcat(mbuf, ctrlbuf); buf = get_msg(msgclient, 'r'); if (!*buf) buf = empty; strcat(mbuf, buf); strcat(mbuf, ctrlbuf); buf = get_msg(msgclient, '1'); if (!*buf) buf = empty; strcat(mbuf, buf); strcat(mbuf, ctrlbuf); strcat(mbuf, myitoa(now-msgclient->time)); strcat(mbuf, ctrlbuf); t = MSG_LEN - strlen(mbuf) - 10; strncat(mbuf, clean_spychar(Message(msgclient)), t); strcat(mbuf, "\0"); DupNewString(msgclient->message, mbuf); changes_to_save = 1; } static char *wildcards(string) char *string; { register char *c; for (c = string; *c; c++) if (*c == '*' || *c == '?') return(c); return 0; } static int only_wildcards(string) char *string; { register char *c; for (c = string;*c;c++) if (*c != '*' && *c != '?') return 0; return 1; } static char *split_string(string, field, n) char *string; int field, n; { static char buf[MSG_LEN]; char *c = string; int p, t; buf[0] = 0; while(field--) { p = 0; t = n; while (*c) { if (p > 0 && buf[p-1] != ' ' && *c == ' ' && (field || !--t)) break; buf[p] = *c++; if (*buf != ' ') p++; } if (!*c) if (!field) { buf[p] = 0; return buf; } else { *buf = 0; return buf; } buf[p] = 0; c++; }; return buf; } static char *wild_fromnick(nick, msgclient) char *nick; aMsgClient *msgclient; { static char buf[BUF_LEN]; char *msg, *c; if (msgclient->flags & FLAGS_ALL_NICK_VALID) { strcpy(buf, "*"); return buf; } if (msgclient->flags & FLAGS_NICK_AND_WILDCARD_VALID && MyEq(msgclient->fromnick, nick)) { strcpy(buf, nick); strcat(buf, "*"); return buf; } if (msgclient->flags & FLAGS_DISPLAY_IF_DEST_REGISTER) { msg = Message(msgclient); while (*msg == '%') { msg++; c = split_string(msg, 1, 1); if (!strcasecmp(c, nick)) { strcpy(buf, "*"); return buf; } while (*msg && *msg != ' ') msg++; if (*msg) msg++; } } return NULLCHAR; } static int number_fromname() { register int t, nr = 0; for (t = 1;t <= fromname_index; t++) if (FromNameList[t]->timeout > now && !(FromNameList[t]->flags & FLAGS_SERVER_GENERATED_DESTINATION)) nr++; return nr; } static int first_tnl_indexnode(name) char *name; { register int s, t = toname_index+1, b = 0, tname; aMsgClient *msgclient; if (!t) return 0; while ((s = (b+t) >> 1) != b) { msgclient = ToNameList[s]; tname = (msgclient->flags & FLAGS_SORT_BY_TONAME) ? 1 : 0; if (strcasecmp(tname ? msgclient->toname : msgclient->tonick, name) < 0) b = s; else t = s; } return t; } static int last_tnl_indexnode(name) char *name; { register int s, t = toname_index+1, b = 0, tname; aMsgClient *msgclient; if (!t) return 0; while ((s = (b+t) >> 1) != b) { msgclient = ToNameList[s]; tname = (msgclient->flags & FLAGS_SORT_BY_TONAME) ? 1 : 0; if (strcasecmp(tname ? msgclient->toname : msgclient->tonick, name) > 0) t = s; else b = s; } return b; } static int first_fnl_indexnode(fromname) char *fromname; { register int s, t = fromname_index+1, b = 0; if (!t) return 0; while ((s = (b+t) >> 1) != b) if (strcasecmp(FromNameList[s]->fromname,fromname)<0) b = s; else t = s; return t; } static int last_fnl_indexnode(fromname) char *fromname; { register int s, t = fromname_index+1, b = 0; if (!t) return 0; while ((s = (b+t) >> 1) != b) if (strcasecmp(FromNameList[s]->fromname,fromname)>0) t = s; else b = s; return b; } static int fnl_msgclient(msgclient) aMsgClient *msgclient; { register int t, f, l; aMsgClient **index_p; f = first_fnl_indexnode(msgclient->fromname); l = last_fnl_indexnode(msgclient->fromname); index_p = FromNameList + f; for (t = f; t <= l; t++) if (*(index_p++) == msgclient) return(t); return 0; } static int tnl_msgclient(msgclient) aMsgClient *msgclient; { register int t, f, l, tname; aMsgClient **index_p; if (msgclient->flags & FLAGS_SORT_BY_TONAME || !wildcards(msgclient->tonick)) { tname = (msgclient->flags & FLAGS_SORT_BY_TONAME) ? 1 : 0; f = first_tnl_indexnode(tname ? msgclient->toname : msgclient->tonick); l = last_tnl_indexnode(tname ? msgclient->toname : msgclient->tonick); index_p = ToNameList + f; } else { index_p = WildCardList + 1; f = 1; l = wildcard_index; } for (t = f; t <= l; t++) if (*(index_p++) == msgclient) return(t); return 0; } static aMsgClient *new(passwd,fromnick,fromname,fromhost,tonick, toname,tohost,flags,timeout,time,message) char *passwd,*fromnick,*fromname,*fromhost, *tonick,*toname,*tohost,*message; time_t timeout,time; long32 flags; { register aMsgClient **index_p; register int t; int allocate,first,last,n; aMsgClient *msgclient; if (number_fromname() > note_msm) return NULL; if (fromname_index == max_fromname-1) { max_fromname += REALLOC_SIZE; allocate = max_fromname*sizeof(FromNameList)+1; FromNameList = (aMsgClient **) MyRealloc((char *)FromNameList,allocate); } if (wildcard_index == max_wildcards-1) { max_wildcards += REALLOC_SIZE; allocate = max_wildcards*sizeof(WildCardList)+1; WildCardList = (aMsgClient **) MyRealloc((char *)WildCardList,allocate); } if (toname_index == max_toname-1) { max_toname += REALLOC_SIZE; allocate = max_toname*sizeof(ToNameList)+1; ToNameList = (aMsgClient **) MyRealloc((char *)ToNameList,allocate); } /* Correction if corrupt format */ if (!(flags & FLAGS_SERVER_GENERATED) && !(flags & FLAGS_SERVER_GENERATED_DESTINATION)) flags &= ~FLAGS_SORT_BY_TONAME; if (!wildcards(toname) && wildcards(tonick)) flags |= FLAGS_SORT_BY_TONAME; msgclient = (aMsgClient *)MyMalloc(sizeof(struct MsgClient)); DupString(msgclient->passwd,passwd); DupString(msgclient->fromnick,fromnick); DupString(msgclient->fromname,fromname); DupString(msgclient->fromhost,fromhost); DupString(msgclient->tonick,tonick); DupString(msgclient->toname,toname); DupString(msgclient->tohost,tohost); DupString(msgclient->message,message); msgclient->flags = flags; msgclient->timeout = timeout; msgclient->time = time; if (flags & FLAGS_SORT_BY_TONAME || !wildcards(tonick)) { n = last_tnl_indexnode(flags & FLAGS_SORT_BY_TONAME ? toname : tonick) + 1; index_p = ToNameList+toname_index; toname_index++;t = toname_index-n; while (t--) { index_p[1] = *index_p; index_p--; } ToNameList[n] = msgclient; } else { wildcard_index++; WildCardList[wildcard_index] = msgclient; } first = first_fnl_indexnode(fromname); last = last_fnl_indexnode(fromname); if (!(n = first)) n = 1; index_p = FromNameList+n; while (n <= last && strcasecmp(msgclient->fromhost,(*index_p)->fromhost)>0) { index_p++;n++; } while (n <= last && strcasecmp(msgclient->fromnick,(*index_p)->fromnick)>=0){ index_p++;n++; } index_p = FromNameList+fromname_index; fromname_index++;t = fromname_index-n; while (t--) { index_p[1] = *index_p; index_p--; } FromNameList[n] = msgclient; changes_to_save = 1; msgclient->id = ++m_id; return msgclient; } static void r_code(string,fp) register char *string; register FILE *fp; { register int v; register char c, *cp = ptr; do { if ((v = getc(fp)) == EOF) { exit(-1); } c = v; *string = c-*cp; if (!*cp || !*++cp) cp = ptr; } while (*string++); } static void w_code(string,fp) register char *string; register FILE *fp; { register char *cp = ptr; do { putc((char)(*string+*cp),fp); if (!*cp || !*++cp) cp = ptr; } while (*string++); } static char *Nltoa(i) register long32 i; { static unsigned char c[20]; register unsigned char *p = c; do { *p++ = (i&127) + 1; i >>= 7; } while(i > 0); *p = 0; return (char *) c; } static long32 atol32(c) register unsigned char *c; { register long32 a = 0; register unsigned char *s = c; while (*s != 0) ++s; while (--s >= c) { a <<= 7; a += *s - 1; } return a; } static void init_messages() { static FILE *fp = 0; FILE *fopen(); time_t atime, timeout; long32 flags; int allocate; char passwd[20], fromnick[BUF_LEN], fromname[BUF_LEN], fromhost[BUF_LEN], tonick[BUF_LEN], toname[BUF_LEN], tohost[BUF_LEN], message[MSG_LEN], buf[20]; static int rnd, first_call = 1; if (file_inited) return; if (first_call) { first_call = 0; saved_clock = now; srand48(now%(int)passwd); max_fromname = max_toname = max_wildcards = REALLOC_SIZE; allocate = REALLOC_SIZE*sizeof(FromNameList)+1; ToNameList = (aMsgClient **) MyMalloc(allocate); FromNameList = (aMsgClient **) MyMalloc(allocate); WildCardList = (aMsgClient **) MyMalloc(allocate); note_save_filename_tmp = MyMalloc(strlen(NPATH)+6); sprintf(note_save_filename_tmp,"%s.tmp",NPATH); fp = fopen(NPATH,"r"); if (!fp) { file_inited = 1; return; } r_code(buf,fp);note_msm = atol32(buf); r_code(buf,fp);note_mum = atol32(buf); r_code(buf,fp);note_msw = atol32(buf); r_code(buf,fp);note_muw = atol32(buf); r_code(buf,fp);note_mst = atol32(buf); r_code(buf,fp);note_msf = atol32(buf); } r_code(passwd,fp); if (*passwd) { r_code(fromnick,fp);r_code(fromname,fp); r_code(fromhost,fp);r_code(tonick,fp);r_code(toname,fp); r_code(tohost,fp);r_code(buf,fp),flags = atol32(buf); r_code(buf,fp);timeout = atol32(buf);r_code(buf,fp); atime = atol32(buf);r_code(message,fp); flags &= ~FLAGS_FROM_REG; rnd+=atime; if (timeout > 0 && *toname != DummyChar && *fromname != DummyChar) new(passwd,fromnick,fromname,fromhost,tonick,toname, tohost,flags,timeout,atime,message); } else { srand48((now+rnd)%(int)passwd); file_inited = 1; fclose(fp); } } static int numeric_host(host) char *host; { while (*host) { if (!isdigit(*host) && *host != '.') return 0; host++; } return 1; } static int elements_inhost(host) char *host; { int t = 0; while (*host) { if (*host == '.') t++; host++; } return t; } static int valid_elements(host) char *host; { register char *c = host; register int t = 0, numeric = 0; while (*c) { if (!isdigit(*c) && *c != '.' && *c != '*' && *c != '?' ) break; c++; } if (!*c) numeric = 1; c = host; if (numeric) while (*c && *c != '*' && *c != '?') { if (*c == '.') t++; c++; } else { while (*c++); while (c != host && *c != '*' && *c != '?') { if (*c == '.') t++; c--; } } if (!t && *c != '*' && *c != '?') t = 1; return t; } static char *local_host(host) char *host; { static char buf[BUF_LEN]; char *buf_p = buf, *host_p; int t, e; e = elements_inhost(host); if (e < 2) return host; if (!numeric_host(host)) { if (!e) return host; host_p = host; if (e > 2) t = 2; else t = 1; while (t--) { while (*host_p && *host_p != '.') { host_p++;buf_p++; } if (t && *host_p) { host_p++; buf_p++; } } buf[0] = '*'; strcpy(buf+1, host_p); } else { host_p = buf; strcpy(buf,host); while (*host_p) host_p++; t = 2; while(t--) { while (host_p != buf && *host_p-- != '.'); } host_p+=2; *host_p++ = '*'; *host_p = 0; } return buf; } static int host_check(host1,host2) char *host1,*host2; { char buf[BUF_LEN]; if (numeric_host(host1) != numeric_host(host2)) return 0; strcpy(buf,local_host(host1)); if (!strcasecmp(buf,local_host(host2))) return 1; return 0; } static time_t Mytimegm(tm) struct tm *tm; { static int days[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; register long32 mday = tm->tm_mday-1, mon = tm->tm_mon, year = tm->tm_year-70; mday+=((year+2) >> 2)+days[mon]; if (mon < 2 && !((year+2) & 3)) mday--; return tm->tm_sec+tm->tm_min*60+tm->tm_hour*3600+mday*86400+year*31536000; } static time_t set_date(sptr,time_s) aClient *sptr; char *time_s; { struct tm *tm; time_t tm_gmtoff; int t,t1,month,date,year; char *c = time_s,arg[3][BUF_LEN]; static char *months[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; tm = localtime(&now); tm_gmtoff = Mytimegm(tm)-now; tm->tm_sec = 0; tm->tm_min = 0; tm->tm_hour = 0; if (*time_s == '-') { if (!time_s[1]) return 0; return Mytimegm(tm)-tm_gmtoff-SECONDS_DAY*atoi(time_s+1); } for (t = 0;t<3;t++) { t1 = 0; while (*c && *c != '/' && *c != '.' && *c != '-') arg[t][t1++] = *c++; arg[t][t1] = 0; if (*c) c++; } date = atoi(arg[0]); if (*arg[0] && (date<1 || date>31)) { sendto_one(sptr,"NOTICE %s :#?# Unknown date",sptr->name); return -1; } month = atoi(arg[1]); if (month) month--; else for (t = 0;t<12;t++) { if (MyEq(arg[1],months[t])) { month = t;break; } month = -1; } if (*arg[1] && (month<0 || month>11)) { sendto_one(sptr,"NOTICE %s :#?# Unknown month",sptr->name); return -1; } year = atoi(arg[2]); if (*arg[2] && (year<71 || year>99)) { sendto_one(sptr,"NOTICE %s :#?# Unknown year",sptr->name); return -1; } tm->tm_mday = date; if (*arg[1]) tm->tm_mon = month; if (*arg[2]) tm->tm_year = year; return Mytimegm(tm)-tm_gmtoff; } static int local_check(sptr, msgclient, passwd, flags, tonick, toname, tohost, time_l, id) aClient *sptr; aMsgClient *msgclient; char *passwd, *tonick, *toname, *tohost; long32 flags; time_t time_l; int id; { int chn = 0; if (IsOper(sptr) && (msgclient->flags & FLAGS_CHANNEL || msgclient->flags & FLAGS_DENY)) chn = 1; if (msgclient->flags == flags && (!id || id == msgclient->id) && (chn && (msgclient->flags & FLAGS_SERVER_GENERATED || msgclient->flags & FLAGS_DENY || !matches(msgclient->toname, UserName(sptr)) && !matches(msgclient->tohost, sptr->user->host)) || !Userstrcasecmp(UserName(sptr),msgclient->fromname)) && (chn || !strcasecmp(sptr->name, msgclient->fromnick) || wild_fromnick(sptr->name, msgclient)) && (!time_l || msgclient->time >= time_l && msgclient->time < time_l+SECONDS_DAY) && !matches(tonick,msgclient->tonick) && !matches(toname,msgclient->toname) && !matches(tohost,msgclient->tohost) && (*msgclient->passwd == '*' && !msgclient->passwd[1] || chn || StrEq(passwd,msgclient->passwd)) && (chn || host_check(sptr->user->host,msgclient->fromhost))) return 1; return 0; } static int send_flag(flags) long32 flags; { if (flags & FLAGS_RETURN_CORRECT_DESTINATION || flags & FLAGS_CHANNEL_PASSWORD || flags & FLAGS_KEY_TO_OPEN_OPER_LOCKS || flags & FLAGS_DISPLAY_IF_DEST_REGISTER || flags & FLAGS_SERVER_GENERATED_DESTINATION || flags & FLAGS_DENY || flags & FLAGS_NEWS || flags & FLAGS_CHANNEL || flags & FLAGS_REPEAT_UNTIL_TIMEOUT && !(flags & FLAGS_FIND_CORRECT_DEST_SEND_ONCE)) return 0; return 1; } static void display_flags(flags, c, mode) long32 flags; char *c, mode; { char t = 0; int send = 0; if (send_flag(flags)) send = 1; if (mode != 'q') { if (send) c[t++] = '['; else c[t++] = '<'; } else c[t++] = '+'; if (mode != 'q' && (flags & FLAGS_WASOPER)) c[t++] = 'O'; if (flags & FLAGS_SERVER_GENERATED_DESTINATION) c[t++] = 'H'; if (flags & FLAGS_ALL_NICK_VALID) c[t++] = 'C'; if (flags & FLAGS_SERVER_GENERATED) c[t++] = 'G'; if (flags & FLAGS_DISTRIBUTE) c[t++] = 'D'; if (flags & FLAGS_CHANNEL_PASSWORD) c[t++] = 'P'; if (flags & FLAGS_NEWS) c[t++] = 'S'; if (flags & FLAGS_CHANNEL) c[t++] = 'L'; if (flags & FLAGS_DISPLAY_IF_DEST_REGISTER) c[t++] = 'X'; if (flags & FLAGS_DISPLAY_CHANNEL_DEST_REGISTER) c[t++] = 'J'; if (flags & FLAGS_DISPLAY_SERVER_DEST_REGISTER) c[t++] = 'A'; if (flags & FLAGS_REPEAT_UNTIL_TIMEOUT) c[t++] = 'R'; if (flags & FLAGS_SIGNOFF_REMOVE) c[t++] = 'M'; if (flags & FLAGS_NO_NICKCHANGE_SPY) c[t++] = 'U'; if (flags & FLAGS_NICK_AND_WILDCARD_VALID) c[t++] = 'V'; if (flags & FLAGS_SEND_ONLY_IF_THIS_SERVER) c[t++] = 'I'; if (flags & FLAGS_SEND_ONLY_IF_NICK_NOT_NAME) c[t++] = 'Q'; if (flags & FLAGS_SEND_ONLY_IF_NOT_EXCEPTION) c[t++] = 'E'; if (flags & FLAGS_KEY_TO_OPEN_OPER_LOCKS) c[t++] = 'K'; if (flags & FLAGS_SEND_ONLY_IF_SENDER_ON_ICN) c[t++] = 'Y'; if (flags & FLAGS_NOTICE_RECEIVED_MESSAGE) c[t++] = 'N'; if (flags & FLAGS_RETURN_CORRECT_DESTINATION) c[t++] = 'F'; if (flags & FLAGS_FIND_CORRECT_DEST_SEND_ONCE) c[t++] = 'B'; if (flags & FLAGS_REGISTER_NEWNICK) c[t++] = 'T'; if (flags & FLAGS_SEND_ONLY_IF_DESTINATION_OPER) c[t++] = 'W'; if (flags & FLAGS_DENY) c[t++] = 'Z'; if (t == 1) c[t++] = '-'; if (mode != 'q') { if (send) c[t++] = ']'; else c[t++] = '>'; } c[t] = 0; } static void remove_msg(msgclient) aMsgClient *msgclient; { register aMsgClient **index_p; register int t; int n,allocate; n = tnl_msgclient(msgclient); if (msgclient->flags & FLAGS_SORT_BY_TONAME || !wildcards(msgclient->tonick)) { index_p = ToNameList+n; t = toname_index-n; while (t--) { *index_p = index_p[1]; index_p++; } ToNameList[toname_index] = 0; toname_index--; } else { index_p = WildCardList+n; t = wildcard_index-n; while (t--) { *index_p = index_p[1]; index_p++; } WildCardList[wildcard_index] = 0; wildcard_index--; } n = fnl_msgclient(msgclient); index_p = FromNameList+n;t = fromname_index-n; while (t--) { *index_p = index_p[1]; index_p++; } FromNameList[fromname_index] = 0; fromname_index--; MyFree(msgclient->passwd); MyFree(msgclient->fromnick); MyFree(msgclient->fromname); MyFree(msgclient->fromhost); MyFree(msgclient->tonick); MyFree(msgclient->toname); MyFree(msgclient->tohost); MyFree(msgclient->message); MyFree((char *)msgclient); changes_to_save = 1; if (max_fromname - fromname_index > REALLOC_SIZE *2) { max_fromname -= REALLOC_SIZE; allocate = max_fromname*sizeof(FromNameList)+1; FromNameList = (aMsgClient **) MyRealloc((char *)FromNameList,allocate); } if (max_wildcards - wildcard_index > REALLOC_SIZE * 2) { max_wildcards -= REALLOC_SIZE; allocate = max_wildcards*sizeof(WildCardList)+1; WildCardList = (aMsgClient **) MyRealloc((char *)WildCardList,allocate); } if (max_toname - toname_index > REALLOC_SIZE * 2) { max_toname -= REALLOC_SIZE; allocate = max_toname*sizeof(ToNameList)+1; ToNameList = (aMsgClient **) MyRealloc((char *)ToNameList,allocate); } } static int KeyFlags(sptr, flags) aClient *sptr; long32 flags; { int t,last, first_tnl, last_tnl, nick_list = 1; aMsgClient **index_p,*msgclient; t = first_tnl_indexnode(sptr->name); last = last_tnl_indexnode(sptr->name); first_tnl = first_tnl_indexnode(UserName(sptr)); last_tnl = last_tnl_indexnode(UserName(sptr)); index_p = ToNameList; while (1) { while (last && t <= last) { msgclient = index_p[t]; if (msgclient->flags & FLAGS_KEY_TO_OPEN_OPER_LOCKS && msgclient->flags & flags && !matches(msgclient->tonick,sptr->name) && !matches(msgclient->toname,UserName(sptr)) && !matches(msgclient->tohost,sptr->user->host)) return 1; t++; } if (index_p == ToNameList) { if (nick_list) { nick_list = 0; t = first_tnl; last = last_tnl; } else { index_p = WildCardList; t = 1; last = wildcard_index; } } else return 0; } } static int set_flags(sptr, string, flags, mode, type) aClient *sptr; char *string, mode, *type; long32 *flags; { char *c,on,buf[40],cu; int op,uf = 0; op = IsOperHere(sptr) ? 1:0; for (c = string; *c; c++) { if (*c == '+') { on = 1;continue; } if (*c == '-') { on = 0;continue; } cu = islower(*c)?toupper(*c):*c; switch (cu) { case 'S': if (on) *flags |= FLAGS_NEWS; else *flags &= ~FLAGS_NEWS; break; case 'R': if (on) *flags |= FLAGS_REPEAT_UNTIL_TIMEOUT; else *flags &= ~FLAGS_REPEAT_UNTIL_TIMEOUT; break; case 'U': if (on) *flags |= FLAGS_NO_NICKCHANGE_SPY; else *flags &= ~FLAGS_NO_NICKCHANGE_SPY; break; case 'V': if (on) *flags |= FLAGS_NICK_AND_WILDCARD_VALID; else *flags &= ~FLAGS_NICK_AND_WILDCARD_VALID; break; case 'I': if (on) *flags |= FLAGS_SEND_ONLY_IF_THIS_SERVER; else *flags &= ~FLAGS_SEND_ONLY_IF_THIS_SERVER; break; case 'W': if (on) *flags |= FLAGS_SEND_ONLY_IF_DESTINATION_OPER; else *flags &= ~FLAGS_SEND_ONLY_IF_DESTINATION_OPER; break; case 'Q': if (on) *flags |= FLAGS_SEND_ONLY_IF_NICK_NOT_NAME; else *flags &= ~FLAGS_SEND_ONLY_IF_NICK_NOT_NAME; break; case 'E': if (on) *flags |= FLAGS_SEND_ONLY_IF_NOT_EXCEPTION; else *flags &= ~FLAGS_SEND_ONLY_IF_NOT_EXCEPTION; break; case 'Y': if (on) *flags |= FLAGS_SEND_ONLY_IF_SENDER_ON_ICN; else *flags &= FLAGS_SEND_ONLY_IF_SENDER_ON_ICN; break; case 'N': if (on) *flags |= FLAGS_NOTICE_RECEIVED_MESSAGE; else *flags &= ~FLAGS_NOTICE_RECEIVED_MESSAGE; break; case 'F': if (on) *flags |= FLAGS_RETURN_CORRECT_DESTINATION; else *flags &= ~FLAGS_RETURN_CORRECT_DESTINATION; break; case 'X': if (on) *flags |= FLAGS_DISPLAY_IF_DEST_REGISTER; else *flags &= ~FLAGS_DISPLAY_IF_DEST_REGISTER; break; case 'J': if (on) *flags |= FLAGS_DISPLAY_CHANNEL_DEST_REGISTER; else *flags &= ~FLAGS_DISPLAY_CHANNEL_DEST_REGISTER; break; case 'A': if (on) *flags |= FLAGS_DISPLAY_SERVER_DEST_REGISTER; else *flags &= ~FLAGS_DISPLAY_SERVER_DEST_REGISTER; break; case 'C': if (on) *flags |= FLAGS_ALL_NICK_VALID; else *flags &= ~FLAGS_ALL_NICK_VALID; break; case 'M': if (on) *flags |= FLAGS_SIGNOFF_REMOVE; else *flags &= ~FLAGS_SIGNOFF_REMOVE; break; case 'T': if (KeyFlags(sptr,FLAGS_REGISTER_NEWNICK) || op || mode == 'd' || !on) { if (on) *flags |= FLAGS_REGISTER_NEWNICK; else *flags &= ~FLAGS_REGISTER_NEWNICK; } else buf[uf++] = cu; break; case 'L': if (KeyFlags(sptr,FLAGS_CHANNEL) || IsOper(sptr) || mode == 'd' || !on) { if (on) *flags |= FLAGS_CHANNEL; else *flags &= ~FLAGS_CHANNEL; } else buf[uf++] = cu; break; case 'P': if (KeyFlags(sptr,FLAGS_CHANNEL_PASSWORD) || IsOper(sptr) || mode == 'd' || !on) { if (on) *flags |= FLAGS_CHANNEL_PASSWORD; else *flags &= ~FLAGS_CHANNEL_PASSWORD; } else buf[uf++] = cu; break; case 'D': if (KeyFlags(sptr, FLAGS_DISTRIBUTE) || op || mode == 'd' || !on) { if (on) *flags |= FLAGS_DISTRIBUTE; else *flags &= ~FLAGS_DISTRIBUTE; } else buf[uf++] = cu; break; case 'B': if (KeyFlags(sptr,FLAGS_FIND_CORRECT_DEST_SEND_ONCE) || op || mode == 'd' || !on) { if (on) *flags |= FLAGS_FIND_CORRECT_DEST_SEND_ONCE; else *flags &= ~FLAGS_FIND_CORRECT_DEST_SEND_ONCE; } else buf[uf++] = cu; break; case 'K': if (op || mode == 'd' || !on) { if (on) *flags |= FLAGS_KEY_TO_OPEN_OPER_LOCKS; else *flags &= ~FLAGS_KEY_TO_OPEN_OPER_LOCKS; } else buf[uf++] = cu; break; case 'O': if (mode == 'd') { if (on) *flags |= FLAGS_WASOPER; else *flags &= ~FLAGS_WASOPER; } else buf[uf++] = cu; break; case 'G': if (mode == 'd') { if (on) *flags |= FLAGS_SERVER_GENERATED; else *flags &= ~FLAGS_SERVER_GENERATED; } else buf[uf++] = cu; break; case 'H': if (mode == 'd') { if (on) *flags |= FLAGS_SERVER_GENERATED_DESTINATION; else *flags &= ~FLAGS_SERVER_GENERATED_DESTINATION; } else buf[uf++] = cu; break; case 'Z': if (KeyFlags(sptr,FLAGS_DENY) || IsOper(sptr) || mode == 'd' || !on) { if (on) *flags |= FLAGS_DENY; else *flags &= ~FLAGS_DENY; } else buf[uf++] = cu; break; default: buf[uf++] = cu; } } buf[uf] = 0; if (uf) { sendto_one(sptr,"NOTICE %s :#?# Unknown flag%s: %s %s",sptr->name, uf> 1 ? "s" : "",buf,type); return 0; } if (mode == 's') { if (*flags & FLAGS_KEY_TO_OPEN_OPER_LOCKS) sendto_one(sptr,"NOTICE %s :### %s", sptr->name, "WARNING: Recipient got keys to unlock the secret portal;"); else if (*flags & FLAGS_DISTRIBUTE && *flags & FLAGS_CHANNEL) sendto_one(sptr,"NOTICE %s :### %s",sptr->name, "WARNING: Channel is distributed to other servers;"); else if (*flags & FLAGS_DISTRIBUTE && *flags & FLAGS_DENY) sendto_one(sptr,"NOTICE %s :### %s",sptr->name, "WARNING: Deny is distributed to other servers;"); else if (*flags & FLAGS_DENY) sendto_one(sptr,"NOTICE %s :### %s",sptr->name, "WARNING: Channel and note deny set;"); else if (*flags & FLAGS_FIND_CORRECT_DEST_SEND_ONCE && *flags & FLAGS_REPEAT_UNTIL_TIMEOUT && send_flag(*flags)) sendto_one(sptr,"NOTICE %s :### %s",sptr->name, "WARNING: Broadcast message in action;"); } return 1; } static void split(string, nick, name, host) char *string, *nick, *name, *host; { char *np = string, *fill; *nick = 0; *name = 0; *host = 0; fill = nick; while (*np) { *fill = *np; if (*np == '!') { *fill = 0; fill = name; } else if (*np == '@') { *fill = 0; fill = host; } else fill++; np++; } *fill = 0; if (!*nick) { *nick = '*'; nick[1] = 0; } if (!*name) { *name = '*'; name[1] = 0; } if (!*host) { *host = '*'; host[1] = 0; } } static void garbage_collector() { long32 gflags = 0; aMsgClient *msgclient; char *c, mbuf[MSG_LEN], dibuf[40]; static int t = 1, count; if (!file_inited) return; gflags |= FLAGS_WASOPER; gflags |= FLAGS_SORT_BY_TONAME; gflags |= FLAGS_SERVER_GENERATED; for (count = 0; count < MIN_DELAY; count++) { if (!fromname_index) return; if (t > fromname_index) t = 1; msgclient = FromNameList[t]; if (now > msgclient->timeout) { if (msgclient->timeout && !(msgclient->flags & FLAGS_CHANNEL) && !(msgclient->flags & FLAGS_SERVER_GENERATED) && !(msgclient->flags & FLAGS_SERVER_GENERATED_DESTINATION)) { display_flags(msgclient->flags, dibuf, 'q'); sprintf(mbuf,"Expired: /Note User -%d %s %s!%s@%s %s", (int)((msgclient->timeout - msgclient->time)/3600), dibuf, msgclient->tonick, msgclient->toname, msgclient->tohost, Message(msgclient)); c = wild_fromnick(msgclient->fromnick, msgclient); new(msgclient->passwd,"SERVER_EXPIRED","-","-", c ? c : msgclient->fromnick, msgclient->fromname, local_host(msgclient->fromhost), gflags, SECONDS_WEEK+now, now, mbuf); } remove_msg(msgclient); continue; } t++; } } void save_messages() { aMsgClient *msgclient; FILE *fp,*fopen(); static time_t t2 = MAX_DAYS_NO_USE_SPY*SECONDS_DAY; int t = 1; char mbuf[MSG_LEN]; if (!file_inited || !changes_to_save) return; saved_clock = now; while (fromname_index && t <= fromname_index) { msgclient = FromNameList[t]; if (msgclient->flags & FLAGS_DISPLAY_IF_DEST_REGISTER) { *mbuf = '\0'; while (!*mbuf) { strcpy(mbuf, get_msg(msgclient, '2')); if (!*mbuf) update_spymsg(msgclient); } if (*get_msg(msgclient, 'n') == '-') { if (now > msgclient->time + t2) msgclient->timeout = 0; } else { if (now > msgclient->time + t2 + atoi(mbuf)) msgclient->timeout = 0; } } t++; } fp = fopen(note_save_filename_tmp,"w"); if (!fp) { sendto_ops("Can't open for write: %s", NPATH); return; } t = 1; w_code(Nltoa((long32)note_msm),fp); w_code(Nltoa((long32)note_mum),fp); w_code(Nltoa((long32)note_msw),fp); w_code(Nltoa((long32)note_muw),fp); w_code(Nltoa((long32)note_mst),fp); w_code(Nltoa((long32)note_msf),fp); while (fromname_index && t <= fromname_index) { msgclient = FromNameList[t]; w_code(msgclient->passwd,fp),w_code(msgclient->fromnick,fp); w_code(msgclient->fromname,fp);w_code(msgclient->fromhost,fp); w_code(msgclient->tonick,fp),w_code(msgclient->toname,fp); w_code(msgclient->tohost,fp), w_code(Nltoa(msgclient->flags),fp); w_code(Nltoa(msgclient->timeout),fp); w_code(Nltoa(msgclient->time),fp); w_code(msgclient->message,fp); t++; } w_code("",fp); fclose(fp); fp = fopen(note_save_filename_tmp,"r"); if (!fp || getc(fp) == EOF) { sendto_ops("Error writing: %s", note_save_filename_tmp); if (fp) fclose(fp); return; } fclose (fp); changes_to_save = 0; unlink(NPATH);link(note_save_filename_tmp,NPATH); unlink(note_save_filename_tmp); chmod(NPATH, 432); } static char *flag_send(aptr, sptr, qptr, nick, msgclient, mode, chn) aClient *aptr, *sptr, *qptr; char *nick, mode, *chn; aMsgClient *msgclient; { int t, t1, exception; static char ebuf[BUF_LEN]; char *c, *message; message = Message(msgclient); if (MyConnect(sptr)) msgclient->flags |= FLAGS_ON_THIS_SERVER; else if (mode != 'e' && mode != 'q') msgclient->flags &= ~FLAGS_ON_THIS_SERVER; if (!(msgclient->flags & FLAGS_ON_THIS_SERVER) && msgclient->flags & FLAGS_SEND_ONLY_IF_THIS_SERVER || (msgclient->flags & FLAGS_SEND_ONLY_IF_NICK_NOT_NAME && mode == 'v' && StrEq(nick,UserName(sptr))) || (!IsOper(sptr) && msgclient->flags & FLAGS_SEND_ONLY_IF_DESTINATION_OPER) || (mode == 'v' || mode == 'j' || mode == 'l') && qptr == aptr) return NULLCHAR; if (msgclient->flags & FLAGS_SEND_ONLY_IF_NOT_EXCEPTION) { c = message; for(;;) { exception = 0;t = t1 = 0 ;ebuf[0] = 0; while (*c != '!') { if (!*c || *c == ' ' || t > BUF_LEN) return message; ebuf[t++] = *c++; } if (!*c++) return message; t1 += t;ebuf[t] = 0; if (!matches(ebuf,nick)) exception = 1; t=0;ebuf[0] = 0; while (*c != '@') { if (!*c || *c == ' ' || t > BUF_LEN) return message; ebuf[t++] = *c++; } if (!*c++) return message; t1 += t;ebuf[t] = 0; if (matches(ebuf,UserName(sptr))) exception = 0; t=0;ebuf[0] = 0; if (*c == ' ') return message; while (*c && *c != ' ') { if (t > BUF_LEN) return message; ebuf[t++] = *c++; } if (*c) c++; t1 += t;ebuf[t] = 0; message += t1+2; if (*c) message++; if (exception && !matches(ebuf,sptr->user->host)) return NULLCHAR; } } return message; } static char *check_flags(aptr, sptr, qptr, nick, newnick, qptr_nick, msgclient, repeat, gnew, mode, sptr_chn) aClient *aptr, *sptr, *qptr; aMsgClient *msgclient; char *nick, *newnick, *qptr_nick, mode; int *repeat, *gnew; aChannel *sptr_chn; { char *c, mbuf[MSG_LEN], buf[BUF_LEN], ebuf[BUF_LEN], *message, wmode[2], *spy_channel = NULLCHAR, *spy_server = NULLCHAR; long32 gflags; int t, t1, t2, last, secret = 1, send = 1, right_tonick = 0, show_channel = 0, sptr_chn_exits = 0; aMsgClient *fmsgclient; aChannel *chptr; Link *link; if (mode != 'g') { if (!(msgclient->flags & FLAGS_FROM_REG)) qptr = 0; else for (qptr = client; qptr; qptr = qptr->next) if (qptr->user && !strcmp(UserName(qptr),msgclient->fromname) && (!strcasecmp(qptr->name,msgclient->fromnick) || wild_fromnick(qptr->name, msgclient)) && host_check(qptr->user->host,msgclient->fromhost)) break; if (!qptr) msgclient->flags &= ~FLAGS_FROM_REG; } if (!strcasecmp(nick, msgclient->tonick) || !strcasecmp(nick, get_msg(msgclient, 'n'))) right_tonick = 1; if (!sptr->user->channel && !IsInvisible(sptr)) secret = 0; if (secret && !IsInvisible(sptr)) for (link = sptr->user->channel; link; link = link->next) if (!SecretChannel(link->value.chptr)) secret = 0; if ((mode == 'a' || mode == 'v') && (*sptr->name == '_' || *sptr->info == '_')) secret = 1; wmode[1] = 0; *repeat = 0; *gnew = 0; if (!send_flag(msgclient->flags)) send = 0; if (mode == 'a' || mode == 'v' || mode == 'c' && !wildcards(msgclient->tonick) || mode == 'g' && (!wild_fromnick(qptr->name, msgclient) || StrEq(qptr_nick, qptr->name))) { msgclient->flags &= ~FLAGS_NEWNICK_DISPLAYED; msgclient->flags &= ~FLAGS_PRIVATE_DISPLAYED; } message = flag_send(aptr, sptr, qptr, nick, msgclient, mode, sptr_chn); if (!message || (msgclient->flags & FLAGS_SERVER_GENERATED) && (mode != 'a' && mode != 'v') || msgclient->flags & FLAGS_SEND_ONLY_IF_SENDER_ON_ICN && !qptr) { *repeat = 1; return NULLCHAR; } if ((!secret || right_tonick) && msgclient->flags & FLAGS_DISPLAY_IF_DEST_REGISTER) { mbuf[0] = 0; buf[0] = SPY_CTRLCHAR; buf[1] = 0; strcat(mbuf, clean_spychar(nick)); strcat(mbuf, buf); strcat(mbuf, clean_spychar(UserName(sptr))); strcat(mbuf, buf); strcat(mbuf, clean_spychar(sptr->user->host)); strcat(mbuf, buf); strcat(mbuf, clean_spychar(sptr->info)); strcat(mbuf, buf); strcat(mbuf, myitoa(now-msgclient->time)); strcat(mbuf, buf); if (*get_msg(msgclient, '2')) strcat(mbuf, get_msg(msgclient, '2')); else strcat(mbuf, myitoa(now-msgclient->time)); strcat(mbuf, buf); t = MSG_LEN - strlen(mbuf) - 10; strncat(mbuf, clean_spychar(Message(msgclient)), t); strcat(mbuf, "\0"); DupNewString(msgclient->message, mbuf); message = flag_send(aptr, sptr, qptr, nick, msgclient, mode, sptr_chn); changes_to_save = 1; } if (msgclient->flags & FLAGS_DISPLAY_IF_DEST_REGISTER && qptr && qptr != sptr) { t = first_fnl_indexnode(UserName(qptr)); last = last_fnl_indexnode(UserName(qptr)); while (last && t <= last) { fmsgclient = FromNameList[t]; if (fmsgclient->flags & FLAGS_DISPLAY_IF_DEST_REGISTER && now < fmsgclient->timeout && fmsgclient != msgclient && (!strcasecmp(mode == 'g' ? qptr_nick : qptr->name, fmsgclient->fromnick) || wild_fromnick(mode == 'g' ? qptr_nick :qptr->name, fmsgclient)) && !Userstrcasecmp(UserName(qptr), fmsgclient->fromname) && host_check(qptr->user->host, fmsgclient->fromhost) && !matches(fmsgclient->tonick, nick) && !matches(fmsgclient->toname, UserName(sptr)) && !matches(fmsgclient->tohost, sptr->user->host) && flag_send(aptr, sptr, qptr, nick, fmsgclient, mode, sptr_chn)) { t1 = wildcards(fmsgclient->tonick) ? 1 : 0; t2 = wildcards(msgclient->tonick) ? 1 : 0; if (!t1 && t2) goto end_this_flag; if (t1 && !t2) { t++; continue; } t1 = (fmsgclient->flags & FLAGS_SORT_BY_TONAME) ? 1 : 0; t2 = (msgclient->flags & FLAGS_SORT_BY_TONAME) ? 1 : 0; if (t1 && !t2) goto end_this_flag; if (!t1 && t2) { t++; continue; } if (fnl_msgclient(fmsgclient) < fnl_msgclient(msgclient)) goto end_this_flag; } t++; } mbuf[0] = 0; for (link = sptr->user->channel; link; link = link->next) { chptr = link->value.chptr; if (sptr_chn == chptr) sptr_chn_exits = 1; if (IsMember(qptr, chptr)) { msgclient->flags |= FLAGS_NEWNICK_DISPLAYED; if (mode != 'j' && mode != 'l') goto end_this_flag; } else if (ShowChannel(qptr, chptr)) show_channel = 1; if (ShowChannel(qptr, chptr)) { if (strlen(mbuf)+strlen(chptr->chname) >= MSG_LEN) continue; if (mbuf[0]) strcat(mbuf, " "); strcat(mbuf, chptr->chname); } } for (link = qptr->user->channel; link; link = link->next) if (link->value.chptr == sptr_chn) break; if (link || mbuf[0] && sptr_chn_exits && !PubChannel(sptr_chn)) mbuf[0] = 0; else if (!show_channel) { if (msgclient->flags & FLAGS_PRIVATE_DISPLAYED) mbuf[0] = 0; else { strcpy(mbuf, "*Private*"); msgclient->flags |= FLAGS_PRIVATE_DISPLAYED; } } else if (mbuf[0]) msgclient->flags &= ~FLAGS_PRIVATE_DISPLAYED; if (msgclient->flags & FLAGS_DISPLAY_CHANNEL_DEST_REGISTER && mode != 'v' && mbuf[0]) spy_channel = mbuf; if (msgclient->flags & FLAGS_DISPLAY_SERVER_DEST_REGISTER) spy_server = sptr->user->server->name; if (spy_channel || spy_server) sprintf(ebuf,"%s%s%s%s%s", spy_channel ? " " : "", spy_channel ? spy_channel : "", spy_server ? " (" : "", spy_server ? spy_server : "", spy_server ? ")" : ""); else ebuf[0] = 0; while (*message == '%') { while (*message && *message != ' ') message++; if (*message) message++; } sprintf(buf,"%s@%s",UserName(sptr),sptr->user->host); switch (mode) { case 'm' : case 'l' : case 'j' : if (!(msgclient->flags & FLAGS_NEWNICK_DISPLAYED) && !(only_wildcards(msgclient->tonick) && only_wildcards(msgclient->toname)) && !secret && !right_tonick && !spy_channel) { sendto_one(qptr, "NOTICE %s :### %s (%s) %s%s %s", qptr->name, nick, buf, "signs on", ebuf, message); msgclient->flags |= FLAGS_NEWNICK_DISPLAYED; } else if (spy_channel && (!secret || right_tonick)) { sendto_one(qptr, "NOTICE %s :### %s (%s) is on %s", qptr->name, nick, buf, spy_channel); msgclient->flags |= FLAGS_NEWNICK_DISPLAYED; } break; case 'v' : case 'a' : if (!secret || right_tonick) { sendto_one(qptr, "NOTICE %s :### %s (%s) %s%s %s", qptr->name, nick, buf, "signs on", ebuf, message); msgclient->flags |= FLAGS_NEWNICK_DISPLAYED; } break; case 'c' : if (!(msgclient->flags & FLAGS_NEWNICK_DISPLAYED) && !(only_wildcards(msgclient->tonick) && only_wildcards(msgclient->toname)) && (!secret || right_tonick)) { sendto_one(qptr, "NOTICE %s :### %s (%s) is %s%s %s", qptr->name, nick, buf, spy_channel ? "on" : "here", ebuf,message); msgclient->flags |= FLAGS_NEWNICK_DISPLAYED; } break; case 's' : case 'g' : if ((!secret || right_tonick) && (!(msgclient->flags & FLAGS_NEWNICK_DISPLAYED) && !(only_wildcards(msgclient->tonick) && only_wildcards(msgclient->toname)))) { sendto_one(qptr, "NOTICE %s :### %s (%s) is %s%s %s", qptr->name, nick, buf, spy_channel ? "on" : "on IRC now", ebuf,message); msgclient->flags |= FLAGS_NEWNICK_DISPLAYED; } break; case 'q' : case 'e' : if (!secret || right_tonick) sendto_one(qptr, "NOTICE %s :### %s (%s) %s %s", qptr->name, nick, buf,"signs off", message); break; case 'n' : msgclient->flags &= ~FLAGS_NEWNICK_DISPLAYED; if (secret) { if (right_tonick) sendto_one(qptr, "NOTICE %s :### %s (%s) %s %s", qptr->name, nick, buf, "signs off", message); } else { if (strcasecmp(nick, newnick) && !(msgclient->flags & FLAGS_NO_NICKCHANGE_SPY)) sendto_one(qptr, "NOTICE %s :### %s (%s) %s <%s> %s", qptr->name, nick, buf, "changed name to", newnick, message); if (!matches(msgclient->tonick,newnick)) msgclient->flags |= FLAGS_NEWNICK_DISPLAYED; } } end_this_flag:; } if (send && !right_tonick && secret && !(msgclient->flags & FLAGS_SERVER_GENERATED) && !(msgclient->flags & FLAGS_FIND_CORRECT_DEST_SEND_ONCE)) { if (mode == 'v') nick = msgclient->tonick; else { *repeat = 1; return NULLCHAR; } } if (mode == 'q' || mode == 'e' || mode == 'n') { *repeat = 1; return NULLCHAR; } while (mode != 'g' && (msgclient->flags & FLAGS_RETURN_CORRECT_DESTINATION)){ if (*message && matches(message, sptr->info) || secret && !right_tonick) { *repeat = 1; break; } sprintf(mbuf,"Search for %s!%s@%s (%s): %s!%s@%s (%s)", msgclient->tonick,msgclient->toname,msgclient->tohost, *message ? message : "*", nick, UserName(sptr),sptr->user->host,sptr->info); t1 = 0; t = first_tnl_indexnode(msgclient->fromname); last = last_tnl_indexnode(msgclient->fromname); while (last && t <= last) { if (ToNameList[t]->timeout > now && ToNameList[t]->flags & FLAGS_SERVER_GENERATED && !Userstrcasecmp(ToNameList[t]->toname, msgclient->fromname) && !strcasecmp(ToNameList[t]->tohost, local_host(msgclient->fromhost))) { t1++; if (!strcasecmp(Message(ToNameList[t]),mbuf)) { t1 = -1; break; } } t++; } if (t1 < 0) break; if (t1 > 10) { msgclient->timeout = now-1; break; } gflags = 0; gflags |= FLAGS_WASOPER; gflags |= FLAGS_SORT_BY_TONAME; gflags |= FLAGS_SERVER_GENERATED; *gnew = 1; c = wild_fromnick(msgclient->fromnick, msgclient); new(msgclient->passwd,"SERVER_FIND","-","-", c ? c : msgclient->fromnick, msgclient->fromname, local_host(msgclient->fromhost), gflags, SECONDS_WEEK+now, now, mbuf); break; } if (msgclient->flags & FLAGS_REPEAT_UNTIL_TIMEOUT) *repeat = 1; while (send && qptr != sptr && (msgclient->flags & FLAGS_NOTICE_RECEIVED_MESSAGE)) { if (!right_tonick && secret && now-msgclient->time < SECONDS_WEEK) { *repeat = 1; send = 0; break; } sprintf(buf,"%s (%s@%s) has received note queued %s before delivery.", nick, UserName(sptr), sptr->user->host, mytime(msgclient->time)); if (qptr && (right_tonick || !secret)) { sendto_one(qptr,"NOTICE %s :### %s", qptr->name, buf); break; } gflags = 0; gflags |= FLAGS_WASOPER; gflags |= FLAGS_SERVER_GENERATED; *gnew = 1; c = wild_fromnick(msgclient->fromnick, msgclient); new(msgclient->passwd,"SERVER_RECEIVED","-","-", c ? c : msgclient->fromnick, msgclient->fromname, local_host(msgclient->fromhost), gflags, note_mst*SECONDS_DAY+now, now,buf); break; } while (send && msgclient->flags & FLAGS_FIND_CORRECT_DEST_SEND_ONCE) { if (mode == 'g') { *repeat = 1; send = 0; break; } t = first_tnl_indexnode(UserName(sptr)); last = last_tnl_indexnode(UserName(sptr)); while (last && t <= last) { if (ToNameList[t]->flags & FLAGS_SERVER_GENERATED_DESTINATION && (!strcasecmp(ToNameList[t]->fromnick,msgclient->fromnick) || wild_fromnick(ToNameList[t]->fromnick, msgclient)) && !Userstrcasecmp(ToNameList[t]->fromname,msgclient->fromname) && host_check(ToNameList[t]->fromhost,msgclient->fromhost) && (!(msgclient->flags & FLAGS_REGISTER_NEWNICK) || !strcasecmp(ToNameList[t]->tonick,nick)) && !Userstrcasecmp(ToNameList[t]->toname,UserName(sptr)) && host_check(ToNameList[t]->tohost,sptr->user->host)) { send = 0; break; } t++; } if (!send) break; gflags = 0; gflags |= FLAGS_SORT_BY_TONAME; gflags |= FLAGS_REPEAT_UNTIL_TIMEOUT; gflags |= FLAGS_SERVER_GENERATED_DESTINATION; if (msgclient->flags & FLAGS_ALL_NICK_VALID) gflags |= FLAGS_ALL_NICK_VALID; if (msgclient->flags & FLAGS_NICK_AND_WILDCARD_VALID) gflags |= FLAGS_NICK_AND_WILDCARD_VALID; if (msgclient->flags & FLAGS_WASOPER) gflags |= FLAGS_WASOPER; *gnew = 1; new(msgclient->passwd,msgclient->fromnick, msgclient->fromname, msgclient->fromhost,nick,UserName(sptr), sptr->user->host,gflags,msgclient->timeout,now,""); break; } if (send) return message; else return NULLCHAR; } static void check_messages(aptr, sptr, info, mode) aClient *sptr, *aptr; /* aptr = who activated */ void *info; char mode; { aMsgClient *msgclient, **index_p; char *qptr_nick, dibuf[40], *newnick, *message, *tonick; int last, first_tnl = 0, last_tnl = 0, first_tnil, last_tnil, nick_list = 1, number_matched = 0, t, repeat, gnew; long32 flags; aClient *qptr = sptr; /* qptr points to active person queued a request */ aChannel *sptr_chn = 0; if (!file_inited) return; if (now > saved_clock+note_msf) save_messages(); if (mode == 'm' || mode == 'j' || mode == 'l') { sptr_chn = (aChannel *)info; qptr_nick = sptr->name; } else qptr_nick = (char *)info; tonick = qptr_nick; if (!sptr->user || !*tonick) return; if (mode == 'a' && StrEq(sptr->info,"ICNnote") && StrEq(sptr->name, sptr->info)) { sendto_one(sptr,":%s NOTICE %s : <%s> %s (%d) %s", me.name, tonick, me.name, VERSION, number_fromname(), StrEq(ptr,"ICNnote") ? "" : (!*ptr ? "-" : ptr)); } if (!fromname_index) return; if (mode != 'j' && mode != 'l') { t = first_fnl_indexnode(UserName(sptr)); last = last_fnl_indexnode(UserName(sptr)); while (last && t <= last) { msgclient = FromNameList[t]; if (!host_check(msgclient->fromhost, sptr->user->host)) { t++; continue; } if (!strcasecmp(qptr_nick, msgclient->fromnick) || wild_fromnick(qptr_nick, msgclient)) { if (msgclient->flags & FLAGS_DISPLAY_IF_DEST_REGISTER) update_spymsg(msgclient); if ((mode == 'e' || mode == 'q') && msgclient->flags & FLAGS_SIGNOFF_REMOVE) msgclient->timeout = 0; } msgclient->flags |= FLAGS_FROM_REG; t++; } } if (mode == 'v') { nick_list = 0; /* Rest done with A flag */ } if (mode == 'n') { newnick = tonick;tonick = sptr->name; } if (mode != 'g') { first_tnl = first_tnl_indexnode(UserName(sptr)); last_tnl = last_tnl_indexnode(UserName(sptr)); first_tnil = first_tnl_indexnode(tonick); last_tnil = last_tnl_indexnode(tonick); } if (mode == 's' || mode == 'g') { t = first_fnl_indexnode(UserName(sptr)); last = last_fnl_indexnode(UserName(sptr)); index_p = FromNameList; sptr = client; /* Notice new sptr */ while (sptr && (!sptr->user || !*sptr->name)) sptr = sptr->next; if (!sptr) return; tonick = sptr->name; } else { if (nick_list) { t = first_tnil; last = last_tnil; } else { t = first_tnl; last = last_tnl; } index_p = ToNameList; } while(1) { while (last && t <= last) { msgclient = index_p[t]; if (msgclient->timeout < now) { t++; continue; } gnew = 0; repeat=1; if (!(msgclient->flags & FLAGS_KEY_TO_OPEN_OPER_LOCKS) && !(msgclient->flags & FLAGS_SERVER_GENERATED_DESTINATION) && (index_p != ToNameList || (!nick_list && msgclient->flags & FLAGS_SORT_BY_TONAME) || (nick_list && !(msgclient->flags & FLAGS_SORT_BY_TONAME))) && !matches(msgclient->tonick, tonick) && !matches(msgclient->toname, UserName(sptr)) && !matches(msgclient->tohost, sptr->user->host) && (mode != 's' && mode != 'g' || (wild_fromnick(qptr_nick, msgclient) || !strcasecmp(qptr_nick, msgclient->fromnick)) && host_check(msgclient->fromhost, qptr->user->host))) { message = check_flags(aptr, sptr, qptr, tonick, newnick, qptr_nick, msgclient, &repeat, &gnew, mode, sptr_chn); if (message) { flags = msgclient->flags; display_flags(flags, dibuf, '-'); if (flags & FLAGS_SERVER_GENERATED) sendto_one(sptr,"NOTICE %s :/%s/ %s", tonick, mytime(msgclient->time), message); else if (!is_silenced(qptr, sptr)) sendto_one(sptr, "NOTICE %s :Note from %s!%s@%s /%s/ %s %s", tonick, msgclient->fromnick, msgclient->fromname, msgclient->fromhost, mytime(msgclient->time), dibuf, message); } if (!(msgclient->flags & FLAGS_SORT_BY_TONAME)) number_matched++; } if (!repeat) msgclient->timeout = 0; if (gnew) { if (mode != 'g') { first_tnl = first_tnl_indexnode(UserName(sptr)); last_tnl = last_tnl_indexnode(UserName(sptr)); first_tnil = first_tnl_indexnode(tonick); last_tnil = last_tnl_indexnode(tonick); } if (mode == 's' || mode == 'g') { t = fnl_msgclient(msgclient); last = last_fnl_indexnode(UserName(qptr)); } else { if (index_p == ToNameList) { t = tnl_msgclient(msgclient); if (nick_list) last = last_tnil; else last = last_tnl; } } } if (repeat && (mode == 's' || mode =='g')) { sptr = sptr->next; while (sptr && (!sptr->user || !*sptr->name)) sptr = sptr->next; if (!sptr || number_matched) { number_matched = 0; sptr = client; while (sptr && (!sptr->user || !*sptr->name)) sptr = sptr->next; if (!sptr) return; tonick = sptr->name; t++; continue; } tonick = sptr->name; } else t++; } if (mode == 's' || mode == 'g') return; if (index_p == ToNameList) { if (nick_list) { if (mode == 'a' || mode == 'q') break; nick_list = 0; t = first_tnl; last = last_tnl; } else { index_p = WildCardList; t = 1; last = wildcard_index; } } else { if (mode == 'n') { mode = 'c'; tonick = newnick; first_tnil = first_tnl_indexnode(tonick); last_tnil = last_tnl_indexnode(tonick); t = first_tnil; last = last_tnil; nick_list = 1; index_p = ToNameList; } else break; } } if (mode == 'c' || mode == 'a') check_messages(sptr, sptr, tonick, 'g'); } static int isletter(c) char c; { if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') return 1; return 0; } static char *create_pwd() { static char pwd[BUF_LEN]; char p; int t; for (t = 0; t < 8; t++) { do p = lrand48(); while (!isletter(p) && !isdigit(p)); pwd[t] = p; } pwd[t] = 0; return pwd; } static int note_headchannel(chn) char *chn; { if (*chn != '#' || wildcards(chn) || index(chn, '-')) return 0; if (index(chn,'.')) return 1; return 0; } static int xrm_distribute_privs(fromname, fromhost) char *fromname, *fromhost; { return 1; } /* Format for param: matches.server.name CHANNEL &pwd +flags -hours #chn.name!user@host fromnick!fromname@host matches.server.name DENY &pwd +flags -hours nick!user@host fromnick!fromname@host */ static void distribute(cptr, sptr, param) aClient *cptr, *sptr; char *param; { aClient *acptr; int t, last, first_tnl = 0, last_tnl= 0, create_new = 1, root_access = 0, seconds, deny = 0, channel = 0, root_call = 1, nick_list = 1; char *name, toserver[BUF_LEN], message[MSG_LEN], tonick[BUF_LEN], password_s[BUF_LEN], toname[BUF_LEN], flags[BUF_LEN], *password, tohost[BUF_LEN], timeout_s[BUF_LEN], fromnick[BUF_LEN], fromname[BUF_LEN], fromhost[BUF_LEN], buf[BUF_LEN]; aMsgClient *msgclient, **index_p; long32 gflags = 0; name = split_string(param, 2, 1); if (!strcasecmp(name, "CHANNEL")) channel = 1; else if (!strcasecmp(name, "DENY")) deny = 1; else return; strncpyzt(toserver, split_string(param, 1, 1), BUF_LEN-1); strncpyzt(password_s, split_string(param, 3, 1), BUF_LEN-1); if (*password_s != '&') return; password = password_s + 1; strncpyzt(flags, split_string(param, 4, 1), 10); strncpyzt(timeout_s, split_string(param, 5, 1), 10); name = split_string(param, 6, 1); split(name, tonick, toname, tohost); strncpyzt(buf, split_string(param, 7, 1), BUF_LEN-1); split(buf, fromnick, fromname, fromhost); strncpyzt(message, split_string(param, 8, 0), BUF_LEN-1); if (channel && (!index(toserver, '.') || strlen(message) < 10 || !note_headchannel(tonick))) return; if (!strcasecmp(me.name, sptr->name) || !xrm_distribute_privs(fromname, fromhost)) goto just_distribute; #ifdef EPATH if (*timeout_s == '+') seconds = atoi(timeout_s + 1) * SECONDS_DAY; else if (*timeout_s == '-') seconds = atoi(timeout_s + 1) * 3600; if (index(flags, 'G')) root_call = 0; if (index(flags, 'D')) gflags |= FLAGS_DISTRIBUTE; if (index(flags, 'P')) gflags |= FLAGS_CHANNEL_PASSWORD; gflags |= FLAGS_WASOPER; if (channel) gflags |= FLAGS_CHANNEL; if (deny) gflags |= FLAGS_DENY; gflags |= FLAGS_SERVER_GENERATED; t = first_tnl_indexnode(tonick); last = last_tnl_indexnode(tonick); if (!channel) { first_tnl = first_tnl_indexnode(toname); last_tnl = last_tnl_indexnode(toname); } index_p = ToNameList; while (1) { while (last && t <= last) { msgclient = index_p[t]; if (now < msgclient->timeout && (!channel || msgclient->flags & FLAGS_CHANNEL) && (!deny || msgclient->flags & FLAGS_DENY) && !strcasecmp(msgclient->tonick, tonick) && (channel || !strcasecmp(msgclient->toname, toname)) && (channel || !strcasecmp(msgclient->tohost, tohost))) { index_p = WildCardList; break; } t++; } if (!channel && index_p == ToNameList) { if (nick_list) { nick_list = 0; t = first_tnl; last = last_tnl; } else { index_p = WildCardList; t = 1; last = wildcard_index; } } else break; } /* Don't change or queue anything if this server called distribute */ if (t <= last && now < msgclient->timeout) { /* If new request isn't equal, but matches old, remove old */ if (!matches(toname, msgclient->toname) && !matches(tohost, msgclient->tohost) && (strcasecmp(toname, msgclient->toname) || strcasecmp(tohost, msgclient->tohost))) msgclient->timeout = 0; /* If old request matches new... */ else if (!matches(msgclient->toname, toname) && !matches(msgclient->tohost, tohost)) { if (root_call && (!strcmp(password, msgclient->passwd) || !strcasecmp(fromname, msgclient->fromname) && host_check(fromhost, msgclient->fromhost) || !*msgclient->passwd || !msgclient->passwd[1])) root_access = 1; /* Remove requests we don't need. Notice that a root_call removes other roots if password known or not valid */ if (!(msgclient->flags & FLAGS_SERVER_GENERATED) && (root_access || !(msgclient->flags & FLAGS_DISTRIBUTE)) || (channel && strlen(Message(msgclient)) < 10)) msgclient->timeout = 0; else { /* If it's distributing, and there is no root access: If updated or a root (not server generated) - return */ if (!root_access && msgclient->flags & FLAGS_DISTRIBUTE && (!(msgclient->flags & FLAGS_SERVER_GENERATED) || (now - msgclient->time < SECONDS_SERVER_DISTRIBUTE))) return; /* If fromname has changed queue new, else just update */ if (strcmp(msgclient->fromname, fromname)) msgclient->timeout = 0; else { create_new = 0; msgclient->time = now; if (msgclient->timeout < now + seconds) msgclient->timeout = now + seconds; if (gflags & FLAGS_CHANNEL_PASSWORD) msgclient->flags |= FLAGS_CHANNEL_PASSWORD; else msgclient->flags &= ~FLAGS_CHANNEL_PASSWORD; if (strcmp(Message(msgclient), message)) DupNewString(msgclient->message, message); DupNewString(msgclient->fromhost, fromhost); DupNewString(msgclient->fromnick, fromnick); } } } } if (create_new) { new(password, fromnick, fromname, fromhost, tonick, toname, tohost, gflags, now + seconds, now, message); } #endif just_distribute: for (t = 0; t <= highest_fd; t++) { if (!(acptr = local[t])) continue; if (IsServer(acptr) && acptr != cptr && (deny || !matches(toserver, acptr->name))) sendto_one(acptr, ":%s NOTE %s", sptr->name, param); } } static int number_distribute() { register int t, nr = 0; for (t = 1; t <= fromname_index; t++) if (FromNameList[t]->timeout > now && FromNameList[t]->flags & FLAGS_DISTRIBUTE) nr++; return nr; } static void msg_distribute(sptr, seconds) aClient *sptr; int seconds; { if (!seconds) { sendto_one(sptr,"NOTICE %s :### Tell me for how many seconds", sptr->name); return; } if (seconds > SECONDS_DAY) { sendto_one(sptr,"NOTICE %s :### Don't try fucin' up the net", sptr->name); return; } if (IsOperHere(sptr)) { fast_distribute_timeout = now + seconds; sendto_one(sptr,"NOTICE %s :### Distributing every second for %d sec.", sptr->name, seconds); } else sendto_one(sptr,"NOTICE %s :### Don't even think about it...", sptr->name); } static void request_distributor() { aMsgClient *msgclient; static int t = 0, seconds_between_distr = 0; static time_t last_count_distribute = 0, last_call = 0; int delay, f, count, hours = 24*7; char buf[MSG_LEN+BUF_LEN], flags[BUF_LEN], *d_wildcards = "*.*", *toserver; if (now - last_count_distribute > 1800) { last_count_distribute = now; f = number_distribute(); if (!f) return; seconds_between_distr = SECONDS_FOR_ALL_DISTRIBUTE/f; if (!seconds_between_distr) seconds_between_distr = 1; } delay = seconds_between_distr; if (now < fast_distribute_timeout) delay = 1; if (!fromname_index || (now - last_call < delay)) return; last_call = now; for (count = 0; count < (fromname_index >> 3) || count < 10; count++) { t++; if (t > fromname_index) t = 1; msgclient = FromNameList[t]; if (now < msgclient->timeout && (msgclient->flags & FLAGS_CHANNEL || msgclient->flags & FLAGS_DENY) && msgclient->flags & FLAGS_DISTRIBUTE) { if (msgclient->tohost[0] == '*' && !msgclient->tohost[1]) toserver = d_wildcards; else toserver = msgclient->tohost; f = 0; if (msgclient->flags & FLAGS_SERVER_GENERATED) { if (now - msgclient->time < SECONDS_SERVER_DISTRIBUTE) continue; /* Sniff :'( Nobody has distributed me for a day. I'll go distribute myself if I live more than 1 hour */ hours = (msgclient->timeout - msgclient->time)/3600; if (hours < 2) continue; hours--; flags[f++] = 'G'; } flags[f++] = 'D'; if (msgclient->flags & FLAGS_CHANNEL_PASSWORD) flags[f++] = 'P'; flags[f] = 0; sprintf(buf, "%s %s &%s +%s -%d %s!%s@%s %s!%s@%s %s", toserver, msgclient->flags & FLAGS_DENY ? "DENY" : "CHANNEL", msgclient->passwd, flags, hours, msgclient->tonick, msgclient->toname, msgclient->tohost, msgclient->fromnick, msgclient->fromname, msgclient->fromhost, Message(msgclient)); if (!seconds_between_distr) last_count_distribute = 0; distribute(&me, &me, buf); return; } } } void note_delay(delay) time_t *delay; { static time_t last_call = 0; if (!file_inited) { *delay = 0; init_messages(); return; /* Don't do anything more before save file is read */ } if (now > saved_clock+note_msf) save_messages(); if (*delay > MIN_DELAY) *delay = MIN_DELAY; request_distributor(); if (now - last_call < MIN_DELAY) return; last_call = now; garbage_collector(); } void note_oper(sptr) aClient *sptr; { check_messages(sptr, sptr, sptr->name, 'm'); } void note_signon(sptr) aClient *sptr; { check_messages(sptr, sptr, sptr->name, 'a'); /* nick on */ check_messages(sptr, sptr, sptr->name, 'v'); /* !user and @host */ } void note_signoff(sptr) aClient *sptr; { check_messages(sptr, sptr, sptr->name, 'e'); /* nick, !user and @host */ } void note_leave(sptr, chptr) aClient *sptr; aChannel *chptr; { #ifdef ONLY_LOCAL_SPY_ON_CHANNEL if (!MyConnect(sptr)) return; #endif check_messages(sptr, sptr, chptr, 'l'); } void note_join(sptr, chptr) aClient *sptr; aChannel *chptr; { #ifdef ONLY_LOCAL_SPY_ON_CHANNEL if (*sptr->name != '_' && *sptr->info != '_' && !MyConnect(sptr)) return; #endif check_messages(sptr, sptr, chptr, 'j'); } void note_nickchange(sptr, newnick) aClient *sptr; char *newnick; { check_messages(sptr, sptr, newnick, 'n'); } static void remote_remove_notice(sptr, msgclient, message) aClient *sptr; aMsgClient *msgclient; char *message; { long32 gflags = 0; char buf[MSG_LEN], *c; if ((!strcasecmp(sptr->name, msgclient->fromnick) || wild_fromnick(sptr->name, msgclient)) && !Userstrcasecmp(UserName(sptr),msgclient->fromname) && host_check(sptr->user->host, msgclient->fromhost)) return; sprintf(buf,"%s (%s@%s) %s for %s@%s", sptr->name, UserName(sptr), sptr->user->host, message, msgclient->toname, msgclient->tohost); c = wild_fromnick(msgclient->fromnick, msgclient); gflags |= FLAGS_WASOPER; gflags |= FLAGS_SERVER_GENERATED; new(msgclient->passwd,"SERVER_REMOTE_RM","-","-", c ? c : msgclient->fromnick, msgclient->fromname, local_host(msgclient->fromhost), gflags, note_mst*SECONDS_DAY+now, now, buf); } static void msg_remove(sptr, arg, passwd, flag_s, id_s, name, time_s) aClient *sptr; char *arg, *passwd, *flag_s, *id_s, *name, *time_s; { aMsgClient *msgclient; int removed = 0, t, last, id, xrm = 0; time_t flags = 0, time_l; char dibuf[40], tonick[BUF_LEN], toname[BUF_LEN], tohost[BUF_LEN]; if (!strcasecmp(arg,"XRM")) xrm = 1; if (xrm && (!IsOper(sptr) || !xrm_distribute_privs(sptr->user->username, sptr->user->host))) { sendto_one(sptr,"NOTICE %s :#?# Privileged command", sptr->name); return; } if (!set_flags(sptr,flag_s, &flags,'d',"")) return; if (!*time_s) time_l = 0; else { time_l = set_date(sptr,time_s); if (time_l < 0) return; } split(name, tonick, toname, tohost); if (id_s) id = atoi(id_s); else id = 0; t = first_fnl_indexnode(UserName(sptr)); last = last_fnl_indexnode(UserName(sptr)); if (xrm) { t = 1; last = fromname_index; } while (last && t <= last) { msgclient = FromNameList[t]; flags = msgclient->flags; if (now > msgclient->timeout || xrm && !(msgclient->flags & FLAGS_CHANNEL) && !(msgclient->flags & FLAGS_DENY) || xrm && msgclient->flags & FLAGS_CHANNEL_PASSWORD && msgclient->flags & FLAGS_SERVER_GENERATED && !IsOperHere(sptr)) { t++; continue; } set_flags(sptr, flag_s, &flags, 'd',""); if (local_check(sptr,msgclient,passwd,flags, tonick,toname,tohost,time_l,id)) { display_flags(msgclient->flags, dibuf, '-'), sendto_one(sptr,"NOTICE %s :### Removed -> %s %s (%s@%s)", sptr->name,dibuf,msgclient->tonick, msgclient->toname,msgclient->tohost); if (!MyConnect(sptr) && xrm && !(msgclient->flags & FLAGS_SERVER_GENERATED)) { if (msgclient->flags & FLAGS_DISTRIBUTE && msgclient->flags & FLAGS_DENY) { remote_remove_notice(sptr, msgclient, "has deactivated your Note Deny"); last = last_fnl_indexnode(UserName(sptr)); } msgclient->flags &= ~FLAGS_DISTRIBUTE; removed++; t++; continue; } msgclient->timeout = 0; removed++; } else t++; } if (!removed) sendto_one(sptr,"NOTICE %s :#?# No such request(s) found", sptr->name); } static void msg_save(sptr) aClient *sptr; { if (!changes_to_save) { sendto_one(sptr,"NOTICE %s :### No changes to save",sptr->name); return; } if (!file_inited) { sendto_one(sptr,"NOTICE %s :### Busy reading save file. Check stats", sptr->name); return; } if (IsOperHere(sptr)) { save_messages(); sendto_one(sptr,"NOTICE %s :### Requests are now saved",sptr->name); } else sendto_one(sptr,"NOTICE %s :### Save the fhiles...",sptr->name); } static void setvar(sptr,msg,l,value) aClient *sptr; int *msg,l; char *value; { int max; static char *message[] = { "Max server messages:", "I don't think that this is a good idea...", "Max server messages are set to:", "Max server messages with wildcards:", "Too many wildcards makes life too hard...", "Max server messages with wildcards are set to:", "Max user messages:", "Too cheeky fingers on keyboard error...", "Max user messages are set to:", "Max user messages with wildcards:", "Give me $$$, and I may fix your problem...", "Max user messages with wildcards are set to:", "Max server days:", "Can't remember that long time...", "Max server days are set to:", "Note save frequency:", "Save frequency may not be like that...", "Note save frequency is set to:" }; if (*value) { max = atoi(value); if (!IsOperHere(sptr)) sendto_one(sptr,"NOTICE %s :### %s",sptr->name,message[l+1]); else { if (!max && (msg == ¬e_mst || msg == ¬e_msf)) max = 1; *msg = max;if (msg == ¬e_msf) *msg *= 60; sendto_one(sptr,"NOTICE %s :### %s %d",sptr->name,message[l+2],max); changes_to_save = 1; } } else { max = *msg; if (msg == ¬e_msf) max /= 60; sendto_one(sptr,"NOTICE %s :### %s %d",sptr->name,message[l],max); } } static void msg_stats(sptr, arg, value) aClient *sptr; char *arg, *value; { char buf[BUF_LEN], *fromhost = NULLCHAR, *fromnick, *fromname; int tonick_wildcards = 0,toname_wildcards = 0,tohost_wildcards = 0,any = 0, nicks = 0,names = 0,hosts = 0,t = 1,last = fromname_index,flag_notice = 0, flag_destination = 0, all_wildcards = 0; aMsgClient *msgclient; if (*arg) { if (!strcasecmp(arg,"MSM")) setvar(sptr,¬e_msm,0,value); else if (!strcasecmp(arg,"MSW")) setvar(sptr,¬e_msw,3,value); else if (!strcasecmp(arg,"MUM")) setvar(sptr,¬e_mum,6,value); else if (!strcasecmp(arg,"MUW")) setvar(sptr,¬e_muw,9,value); else if (!strcasecmp(arg,"MST")) setvar(sptr,¬e_mst,12,value); else if (!strcasecmp(arg,"MSF")) setvar(sptr,¬e_msf,15,value); else if (MyEq(arg,"USED")) { while (last && t <= last) { msgclient = FromNameList[t]; if (now > msgclient->timeout) { t++; continue; } any++; if (msgclient->flags & FLAGS_SERVER_GENERATED_DESTINATION) flag_destination++; else if (msgclient->flags & FLAGS_SERVER_GENERATED) flag_notice++; else if (IsOperHere(sptr) || Key(sptr)) if (!fromhost || !host_check(msgclient->fromhost,fromhost)) { nicks++;names++;hosts++; fromhost = msgclient->fromhost; fromname = msgclient->fromname; fromnick = msgclient->fromnick; } else if (Userstrcasecmp(msgclient->fromname,fromname)) { nicks++;names++; fromname = msgclient->fromname; fromnick = msgclient->fromnick; } else if (strcasecmp(msgclient->fromnick,fromnick)) { nicks++; fromnick = msgclient->fromnick; } if (wildcards(msgclient->tonick) && wildcards(msgclient->toname)) all_wildcards++; if (wildcards(msgclient->tonick)) tonick_wildcards++; if (wildcards(msgclient->toname)) toname_wildcards++; if (wildcards(msgclient->tohost)) tohost_wildcards++; t++; } if (!any) sendto_one(sptr,"NOTICE %s :#?# No request(s) found",sptr->name); else { if (IsOperHere(sptr) || Key(sptr)) { sprintf(buf,"%s%d %s%d %s%d %s (%s%d %s%d %s%d %s%d)", "Nicks:",nicks,"Names:",names, "Hosts:",hosts,"W.cards", "Nicks:",tonick_wildcards, "Names:",toname_wildcards, "Hosts:",tohost_wildcards, "All:",all_wildcards); sendto_one(sptr,"NOTICE %s :### %s",sptr->name,buf); } sprintf(buf,"%s %s%d / %s%d", "Server generated", "G-notice: ",flag_notice, "H-header: ",flag_destination); sendto_one(sptr,"NOTICE %s :### %s",sptr->name,buf); } } else if (!strcasecmp(arg,"RESET")) { if (!IsOperHere(sptr)) sendto_one(sptr,"NOTICE %s :### %s",sptr->name, "Wrong button - try another next time..."); else { note_mst = NOTE_MAXSERVER_TIME, note_mum = NOTE_MAXUSER_MESSAGES, note_msm = NOTE_MAXSERVER_MESSAGES, note_msw = NOTE_MAXSERVER_WILDCARDS, note_muw = NOTE_MAXUSER_WILDCARDS; note_msf = NOTE_SAVE_FREQUENCY*60; sendto_one(sptr,"NOTICE %s :### %s", sptr->name,"Stats have been reset"); changes_to_save = 1; } } } else { t = number_fromname(); sprintf(buf,"%s%d /%s%d /%s%d /%s%d /%s%d /%s%d /%s%d", "QUEUE:",t, "MSM:",note_msm, "MSW:",note_msw, "MUM:",note_mum, "MUW:",note_muw, "MST:",note_mst, "MSF:",note_msf/60); sendto_one(sptr,"NOTICE %s :### %s",sptr->name,buf); } } static int denied(sptr) aClient *sptr; { int last, t, first_tnl, last_tnl, nick_list = 1; aMsgClient *msgclient, **index_p; char *msg, buf[BUF_LEN]; t = first_tnl_indexnode(sptr->name); last = last_tnl_indexnode(sptr->name); first_tnl = first_tnl_indexnode(UserName(sptr)); last_tnl = last_tnl_indexnode(UserName(sptr)); index_p = ToNameList; while (1) { while (last && t <= last) { msgclient = index_p[t]; if (now > msgclient->timeout) { t++; continue; } msg = flag_send((aClient *)0, sptr, (aClient *)0 , sptr->name, msgclient, '-', NULLCHAR); if (msg && msgclient->flags & FLAGS_DENY && (!only_wildcards(msgclient->tonick) || !only_wildcards(msgclient->toname) || !only_wildcards(msgclient->tohost)) && !(msgclient->flags & FLAGS_KEY_TO_OPEN_OPER_LOCKS) && !matches(msgclient->tonick,sptr->name) && !matches(msgclient->toname,UserName(sptr)) && !matches(msgclient->tohost,sptr->user->host)) { sprintf(buf,"doesn't allow %s!%s@%s:", msgclient->tonick, msgclient->toname, msgclient->tohost); sendto_one(sptr,"NOTICE %s :### %s (%s@%s) %s %s", sptr->name, msgclient->fromnick, msgclient->fromname, msgclient->fromhost, buf, msg); return 1; } t++; } if (index_p == ToNameList) { if (nick_list) { nick_list = 0; t = first_tnl; last = last_tnl; } else { index_p = WildCardList; t = 1; last = wildcard_index; } } else break; } return 0; } static int check_channel(sptr, mode, name, toname, tohost) aClient *sptr; char mode, *name, *toname, *tohost; { int t, last, found = 0; aMsgClient *msgclient; if (wildcards(name) || mode == 'l') { t = 1; last = toname_index; } else { t = first_tnl_indexnode(name); last = last_tnl_indexnode(name); } while (last && t <= last) { msgclient = ToNameList[t]; if (msgclient->timeout < now) { t++; continue; } if (msgclient->flags & FLAGS_CHANNEL && note_headchannel(msgclient->tonick) && !(msgclient->flags & FLAGS_SORT_BY_TONAME) && (!matches(name, msgclient->tonick) || MyEq(name, msgclient->tonick)) && (!*toname || !matches(msgclient->toname, toname)) && (!*tohost || !matches(msgclient->tohost, tohost)) && !matches(msgclient->toname, UserName(sptr)) && !matches(msgclient->tohost, sptr->user->host)) { found++; if (mode == 'c') return t; sendto_one(sptr,"NOTICE %s :*** %-30.29s : %.40s", sptr->name, msgclient->tonick, Message(msgclient)); } t++; } return found; } static int note_channel(cptr, sptr, mode, name) aClient *cptr, *sptr; char mode, *name; { char *c; aChannel *chptr; char buf[BUF_LEN], *wildcard = "*"; int ret = 0, only_users = 0, only_head = 0; if (mode == 'l' && (MyEq("tail", name) || !*name)) only_users = 1; if (mode == 'l' && (MyEq("head", name) || !strcasecmp(name, "."))) { only_head = 1; name = wildcard; } if (!only_users) ret = check_channel(sptr, mode, name, "", ""); if (!only_head && (only_users || mode == 'l')) for (chptr = channel; chptr; chptr = chptr->nextch) if (index(chptr->chname,'.')) { strncpyzt(buf, chptr->chname, BUF_LEN-5); if (c = index(buf, '-')) *c = 0; if ((!matches(name, chptr->chname) || MyEq(name, chptr->chname) || only_users) && check_channel(sptr, 'c', buf, "", "")) sendto_one(sptr,"NOTICE %s :*** %-30.29s > %.40s", sptr->name, chptr->chname, chptr->topic); } return ret; } static int msg_send(sptr, silent, passwd, flag_s, timeout_s, name, message) aClient *sptr; int silent; char *passwd, *flag_s, *timeout_s, *name, *message; { aMsgClient *msgclient; int sent_wild = 0, sent = 0, t, first, last, join = 0; time_t timeout; long32 flags = 0; char buf[BUF_LEN], dibuf[40], *empty_char = "", tonick[BUF_LEN], toname[BUF_LEN], tohost[BUF_LEN]; if (!file_inited) { sendto_one(sptr,"NOTICE %s :### Busy reading save file", sptr->name); return -1; } if (denied(sptr)) return -1; if (number_fromname() >= note_msm && !IsOperHere(sptr) && !Key(sptr)) { if (!note_msm || !note_mum) sendto_one(sptr, "NOTICE %s :#?# The notesystem is closed for no-operators", sptr->name); else sendto_one(sptr,"NOTICE %s :#?# No more than %d request%s %s", sptr->name, note_msm, note_msm < 2 ? "" : "s", "allowed in the server"); return -1; } if (!set_flags(sptr,flag_s,&flags,'s',"")) return -1; split(name, tonick, toname, tohost); if (IsOper(sptr)) flags |= FLAGS_WASOPER; if (*timeout_s == '+') timeout = atoi(timeout_s + 1) * 24; else if (*timeout_s == '-') timeout = atoi(timeout_s + 1); if (timeout > note_mst*24 && !(flags & FLAGS_WASOPER) && !Key(sptr)) { sendto_one(sptr,"NOTICE %s :#?# Max time allowed is %d day%s", sptr->name,note_mst,note_mst > 1 ? "s" : ""); return -1; } if (!message) { if (!send_flag(flags)) message = empty_char; else { sendto_one(sptr,"NOTICE %s :#?# No message specified",sptr->name); return -1; } } if (*toname == DummyChar) { sendto_one(sptr, "NOTICE %s :#?# Please skip that first character in username", sptr->name); return -1; } first = first_fnl_indexnode(UserName(sptr)); last = last_fnl_indexnode(UserName(sptr)); t = first; while (last && t <= last) { msgclient = FromNameList[t]; if (now > msgclient->timeout) { t++; continue; } if (!strcasecmp(sptr->name, msgclient->fromnick) && !Userstrcasecmp(UserName(sptr), msgclient->fromname) && host_check(sptr->user->host, msgclient->fromhost) && StrEq(msgclient->tonick, tonick) && StrEq(msgclient->toname, toname) && StrEq(msgclient->tohost, tohost) && StrEq(msgclient->passwd, passwd) && StrEq(Message(msgclient), clean_spychar(message)) && msgclient->flags == (msgclient->flags | flags)) { msgclient->timeout = timeout*3600+now; join = 1; } t++; } if (!join && !(flags & FLAGS_WASOPER) && !Key(sptr)) { t = first; while (last && t <= last) { if (!Userstrcasecmp(UserName(sptr),FromNameList[t]->fromname)) { if (host_check(sptr->user->host,FromNameList[t]->fromhost)) { sent++; if (wildcards(FromNameList[t]->tonick) && wildcards(FromNameList[t]->toname)) sent_wild++; } } t++; } if (sent >= note_mum) { sendto_one(sptr,"NOTICE %s :#?# No more than %d request%s %s", sptr->name,note_mum,note_mum < 2?"":"s", "for each user allowed in the server"); return -1; } while (wildcards(tonick) && wildcards(toname)) { if (!note_msw || !note_muw) sendto_one(sptr, "NOTICE %s :#?# No-operators are not allowed %s", sptr->name, "to specify nick and username with wildcards"); else if (wildcard_index >= note_msw) sendto_one(sptr,"NOTICE %s :#?# No more than %d req. %s", sptr->name, note_msw, "with nick and username w.cards allowed."); else if (sent_wild >= note_muw) sendto_one(sptr,"NOTICE %s :#?# No more than %d %s %s", sptr->name, note_muw, note_muw < 2 ? "request ":" requests", "with nick and username w.cards allowed."); else break; return -1; } } while ((send_flag(flags) || flags & FLAGS_DISPLAY_IF_DEST_REGISTER) && wildcards(tonick) && wildcards(toname)) { if ((flags & FLAGS_WASOPER || Key(sptr)) && !valid_elements(tohost)) sendto_one(sptr, "NOTICE %s :#?# This matches more than one country.", sptr->name); else if (!(flags & FLAGS_WASOPER) && !Key(sptr) && matches(local_host(sptr->user->host), tohost)) sendto_one(sptr, "NOTICE %s :#?# %s must be a local host.", sptr->name, local_host(sptr->user->host)); else break; return -1; } if (flags & FLAGS_CHANNEL && *tonick != '#') { sendto_one(sptr, "NOTICE %s :#?# Channel names begin with #", sptr->name); return -1; } if (flags & FLAGS_CHANNEL && wildcards(tonick)) { sendto_one(sptr, "NOTICE %s :#?# No wildcards allowed in channel name", sptr->name); return -1; } if (note_headchannel(tonick)) { if (!(flags & FLAGS_CHANNEL)) { sendto_one(sptr, "NOTICE %s :#?# Channel flag missing", sptr->name); return -1; } if (check_channel(sptr, 'c', tonick, toname, tohost)) { if (MyConnect(sptr) && !silent) sendto_one(sptr, "NOTICE %s :#?# Already registered channel: %s", sptr->name, tonick); return -1; } } if (!join) { flags |= FLAGS_FROM_REG; msgclient = new(passwd,sptr->name, UserName(sptr), sptr->user->host, tonick, toname, tohost, flags, timeout*3600+now, now, clean_spychar(message)); if (flags & FLAGS_DISPLAY_IF_DEST_REGISTER) update_spymsg(msgclient); } display_flags(flags, dibuf, '-'); sprintf(buf, "%s %s %s!%s@%s for %s", join ? "Joined..." : "Queued...",dibuf, tonick, toname, tohost, relative_time(timeout*3600)); if (!silent) { sendto_one(sptr,"NOTICE %s :### %s",sptr->name, buf); if (send_flag(flags)) check_messages(sptr, sptr, sptr->name, 's'); } if (join) return 0; else return 1; } static void msg_news(sptr, silent, passwd, flag_s, timeout_s, name, message) aClient *sptr; int silent; char *passwd, *flag_s, *timeout_s, *name, *message; { aMsgClient *msgclient; int joined = 0, queued = 0, ret, t = 1, msg_len; char *c, tonick[BUF_LEN], toname[BUF_LEN], tohost[BUF_LEN], anyname[BUF_LEN], buf[MSG_LEN]; split(name, tonick, toname, tohost); if (MyEq("ADMIN.", tonick) && !IsOper(sptr) && !KeyFlags(sptr, FLAGS_NEWS)) { sendto_one(sptr, "NOTICE %s :#?# No privileges for admin group.", sptr->name); return; } sprintf(buf, "[News:%s] ", tonick); msg_len = MSG_LEN-strlen(buf)-1; strncat(buf, message, msg_len); strcat(flag_s, "-RS"); while (fromname_index && t <= fromname_index) { msgclient = FromNameList[t]; if (!Userstrcasecmp(UserName(sptr), msgclient->fromname) && (!strcasecmp(sptr->name, msgclient->fromnick) || wild_fromnick(sptr->name, msgclient) && host_check(sptr->user->host,msgclient->fromhost))) { t++; continue; } if (now < msgclient->timeout && !(msgclient->flags & FLAGS_SERVER_GENERATED) && !(msgclient->flags & FLAGS_SERVER_GENERATED_DESTINATION) && (msgclient->flags & FLAGS_NEWS && !matches(msgclient->tonick, tonick) && !matches(msgclient->toname, UserName(sptr)) && !matches(msgclient->tohost, sptr->user->host) && (!matches(toname, msgclient->tonick) || matches(toname, tonick) && !strcasecmp(msgclient->tonick, tonick)) && (!*Message(msgclient) || !matches(Message(msgclient), message)) || !strcasecmp(tonick, "admin.users")) && !matches(tohost, msgclient->fromhost) && !(msgclient->flags & FLAGS_KEY_TO_OPEN_OPER_LOCKS)) { c = wild_fromnick(msgclient->fromnick, msgclient); sprintf(anyname, "%s!%s@%s", c ? c : msgclient->fromnick, msgclient->fromname, local_host(msgclient->fromhost)); ret = msg_send(sptr, 1, passwd, flag_s, timeout_s, anyname, buf); if (!ret) joined++; else if (ret < 0) return; else { queued++; t = fnl_msgclient(msgclient); } } t++; } strcpy(buf, "user"); if (queued > 1) strcat(buf, "s"); if (joined) { strcat(buf, ", "); strcat(buf, myitoa(joined)); strcat(buf, " joined"); } sendto_one(sptr,"NOTICE %s :### News to %d %s", sptr->name, queued, buf); } static void msg_list(sptr, arg, passwd, flag_s, id_s, name, time_s) aClient *sptr; char *arg, *passwd, *flag_s, *id_s, *name, *time_s; { aMsgClient *msgclient; int number = 0, t, last, ls = 0, count = 0, found = 0, log = 0, id, id_count = 0, channel = 0; time_t time_l, time_queued; long32 flags = 0; char tonick[BUF_LEN], toname[BUF_LEN], tohost[BUF_LEN], *message, buf[BUF_LEN], dibuf[40], mbuf[MSG_LEN], *dots = "...", *wildcard = "*"; if (MyEq(arg,"ls")) ls = 1; else if (MyEq(arg,"count")) count = 1; else if (MyEq(arg,"log")) log = 1; else if (MyEq(arg,"xls")) channel = 1; else if (MyEq(arg,"llog")) log = 3; else { sendto_one(sptr,"NOTICE %s :#?# No such option: %s",sptr->name,arg); return; } if (channel && !IsOper(sptr)) { sendto_one(sptr,"NOTICE %s :#?# Priviliegied command", sptr->name); return; } if (!*name && !id_s && !*flag_s) { if (log) log++; if (ls) ls++; name = wildcard; } if (!set_flags(sptr,flag_s, &flags,'d',"")) return; if (!*time_s) time_l = 0; else { time_l = set_date(sptr,time_s); if (time_l < 0) return; } split(name, tonick, toname, tohost); if (id_s) id = atoi(id_s); else id = 0; t = first_fnl_indexnode(UserName(sptr)); last = last_fnl_indexnode(UserName(sptr)); if (channel) { t = 1; last = fromname_index; } while (last && t <= last) { msgclient = FromNameList[t]; msgclient->id = ++id_count; flags = msgclient->flags; if (now > msgclient->timeout || channel && !(msgclient->flags & FLAGS_CHANNEL) && !(msgclient->flags & FLAGS_DENY)) { t++; continue; } set_flags(sptr,flag_s,&flags,'d',""); if (local_check(sptr,msgclient,passwd,flags, tonick,toname,tohost,time_l, id)) { message = Message(msgclient); number++; if (ls == 2 && *message) message = dots; display_flags(msgclient->flags, dibuf, '-'); if (log) { if (!(msgclient->flags & FLAGS_DISPLAY_IF_DEST_REGISTER)) { t++ ; continue; } strcpy(mbuf, get_msg(msgclient, 'n')); if (*mbuf == '-') *mbuf = '\0'; if (*mbuf) { strcat(mbuf, "!"); strcat(mbuf, get_msg(msgclient, 'u')); strcat(mbuf, "@"); strcat(mbuf, get_msg(msgclient, 'h')); time_queued = atoi(get_msg(msgclient, '1'))+msgclient->time; } if (log == 1 || log == 3) { found++; if (*mbuf) { strcat(mbuf, " ("); strcat(mbuf, get_msg(msgclient, 'r')); strcat(mbuf, ")"); } else { time_queued = now; strcpy(mbuf, ""); } sendto_one(sptr,"NOTICE %s :### %s: %s!%s@%s => %s", sptr->name, log == 1 ? mytime(time_queued) : myctime(time_queued), msgclient->tonick, msgclient->toname, msgclient->tohost, mbuf); } else if (*mbuf) { found++; sendto_one(sptr,"NOTICE %s :### %s: %s", sptr->name, log == 2 ? mytime(time_queued) : myctime(time_queued), mbuf); } } else if (!count) { found++; if (msgclient->flags & FLAGS_CHANNEL || msgclient->flags & FLAGS_DENY) sprintf(mbuf,"[%s!%s@%s] %s", msgclient->fromnick, msgclient->fromname, msgclient->fromhost, dibuf); else strcpy(mbuf,dibuf); sprintf(buf,"for %s", relative_time(msgclient->timeout-now)); sendto_one(sptr,"NOTICE %s :%d: %s %s (%s@%s) %s: %s", sptr->name, msgclient->id, mbuf, msgclient->tonick, msgclient->toname, msgclient->tohost, buf, message); } } t++; } if (count) sendto_one(sptr,"NOTICE %s :### %s %s (%s@%s): %d", sptr->name,"Number of requests to", tonick ? tonick : "*", toname ? toname:"*", tohost ? tohost : "*", number); else if (!found) sendto_one(sptr,"NOTICE %s :#?# No such %s", sptr->name, log ? "log(s)" : "request(s) found"); } static void msg_flag(sptr, passwd, flag_s, id_s, name, newflag_s) aClient *sptr; char *passwd, *flag_s, *id_s, *name, *newflag_s; { aMsgClient *msgclient; int flagged = 0, t, last, id; long32 flags = 0; char tonick[BUF_LEN], toname[BUF_LEN], tohost[BUF_LEN], dibuf1[40], dibuf2[40]; if (!*newflag_s) { sendto_one(sptr,"NOTICE %s :#?# No flag changes specified",sptr->name); return; } if (!set_flags(sptr, flag_s, &flags,'d',"in matches flag")) return; if (!set_flags(sptr, newflag_s, &flags,'c',"in flag changes")) return; split(name, tonick, toname, tohost); if (id_s) id = atoi(id_s); else id = 0; t = first_fnl_indexnode(UserName(sptr)); last = last_fnl_indexnode(UserName(sptr)); while (last && t <= last) { msgclient = FromNameList[t];flags = msgclient->flags; if (now > msgclient->timeout) { t++; continue; } set_flags(sptr,flag_s,&flags,'d',""); if (local_check(sptr,msgclient,passwd,flags, tonick,toname,tohost,0,id)) { flags = msgclient->flags; display_flags(flags, dibuf1, '-'); set_flags(sptr,newflag_s,&msgclient->flags,'s',""); display_flags(msgclient->flags, dibuf2, '-'); if (flags == msgclient->flags) sendto_one(sptr,"NOTICE %s :### %s -> %s %s (%s@%s)", sptr->name, "No flag change for", dibuf1, msgclient->tonick, msgclient->toname,msgclient->tohost); else sendto_one(sptr,"NOTICE %s :### %s -> %s %s (%s@%s) to %s", sptr->name,"Flag change",dibuf1,msgclient->tonick, msgclient->toname, msgclient->tohost, dibuf2); flagged++; } t++; } if (!flagged) sendto_one(sptr,"NOTICE %s :#?# No such request(s) found",sptr->name); } static void msg_sent(sptr, arg, name, time_s, delete) aClient *sptr; char *arg, *name, *time_s, *delete; { aMsgClient *msgclient,*next_msgclient; char fromnick[BUF_LEN], fromname[BUF_LEN], fromhost[BUF_LEN]; int number = 0, t, t1, last, nick = 0, count = 0, users = 0; time_t time_l; if (!*arg) nick = 1; else if (MyEq(arg,"COUNT")) count = 1; else if (MyEq(arg,"USERS")) users = 1; else if (!MyEq(arg,"NAME")) { sendto_one(sptr,"NOTICE %s :#?# No such option: %s",sptr->name, arg); return; } if (users) { if (!IsOperHere(sptr)) { sendto_one(sptr,"NOTICE %s :### %s",sptr->name, "A dragon is guarding the names..."); return; } if (!*time_s) time_l = 0; else { time_l = set_date(sptr,time_s); if (time_l < 0) return; } split(name, fromnick, fromname, fromhost); for (t = 1; t <= fromname_index; t++) { msgclient = FromNameList[t]; t1 = t; do next_msgclient = t1 < fromname_index ? FromNameList[++t1] : 0; while (next_msgclient && next_msgclient->timeout <= now); if (msgclient->timeout > now && (!time_l || msgclient->time >= time_l && msgclient->time < time_l+SECONDS_DAY) && (!matches(fromnick,msgclient->fromnick)) && (!matches(fromname,msgclient->fromname)) && (!matches(fromhost,msgclient->fromhost)) && (!*delete || !strcasecmp(delete,"RM") || !strcasecmp(delete,"RMBF") && (msgclient->flags & FLAGS_RETURN_CORRECT_DESTINATION || msgclient->flags & FLAGS_FIND_CORRECT_DEST_SEND_ONCE))) { if (*delete || !next_msgclient || strcasecmp(next_msgclient->fromnick,msgclient->fromnick) || strcasecmp(next_msgclient->fromname,msgclient->fromname) || !(host_check(next_msgclient->fromhost, msgclient->fromhost))) { sendto_one(sptr,"NOTICE %s :### %s[%d] %s (%s@%s) @%s", sptr->name, *delete ? "Removing -> " : "", *delete ? 1 : count+1, msgclient->fromnick,msgclient->fromname, local_host(msgclient->fromhost), msgclient->fromhost); if (*delete) msgclient->timeout = now-1; count = 0; number = 1; } else count++; } } if (!number) sendto_one(sptr, "NOTICE %s :#?# No request(s) from such user(s) found", sptr->name); return; } t = first_fnl_indexnode(UserName(sptr)); last = last_fnl_indexnode(UserName(sptr)); while (last && t <= last) { msgclient = FromNameList[t]; if (now > msgclient->timeout) { t++; continue; } if (!Userstrcasecmp(UserName(sptr),msgclient->fromname) && (!nick || !strcasecmp(sptr->name,msgclient->fromnick))) { if (host_check(sptr->user->host,msgclient->fromhost)) { if (!count) sendto_one(sptr,"NOTICE %s :### Queued %s from host %s", sptr->name, mytime(msgclient->time), msgclient->fromhost); number++; } } t++; } if (!number) sendto_one(sptr,"NOTICE %s :#?# No such request(s) found",sptr->name); else if (count) sendto_one(sptr,"NOTICE %s :### %s %d",sptr->name, "Number of requests queued:",number); } static int name_len_error(sptr, name) aClient *sptr; char *name; { if (strlen(name) >= BUF_LEN) { sendto_one(sptr, "NOTICE %s :#?# Nick!name@host can't be longer than %d chars", sptr->name, BUF_LEN-1); return 1; } return 0; } static int flag_len_error(sptr, flag_s) aClient *sptr; char *flag_s; { if (strlen(flag_s) >= BUF_LEN) { sendto_one(sptr,"NOTICE %s :#?# Flag string can't be longer than %d chars", sptr->name,BUF_LEN-1); return 1; } return 0; } static int alias_send(sptr, option, flags, msg, timeout) aClient *sptr; char *option, **flags, **msg, **timeout; { static char flag_s[BUF_LEN+10], *month = "+31", *year = "+365", *waitfor_message = "[Waiting]"; if (MyEq(option,"SEND")) { sprintf(flag_s,"+N%s", *flags); if (!*timeout) *timeout = month; } else if (MyEq(option,"NEWS")) { sprintf(flag_s,"+RS%s", *flags); if (!*timeout) *timeout = month; } else if (MyEq(option,"CHANNEL")) { sprintf(flag_s,"+LR%s", *flags); if (!*timeout) *timeout = year; } else if (MyEq(option,"WAITFOR")) { sprintf(flag_s,"+YN%s", *flags); if (!*msg) *msg = waitfor_message; } else if (MyEq(option,"SPY")) sprintf(flag_s,"+RX%s", *flags); else if (MyEq(option,"FIND")) sprintf(flag_s,"+FR%s", *flags); else if (MyEq(option,"KEY")) sprintf(flag_s,"+KR%s", *flags); else if (MyEq(option,"WALL")) sprintf(flag_s,"+BR%s", *flags); else if (MyEq(option,"WALLOPS")) sprintf(flag_s,"+BRW%s", *flags); else if (MyEq(option,"DENY")) sprintf(flag_s,"+RZ%s", *flags); else return 0; *flags = flag_s; return 1; } static void antiwall(sptr) aClient *sptr; { int t = 1, wall = 0; aMsgClient *msgclient; if (!IsOper(sptr)) { sendto_one(sptr,"NOTICE %s :#?# Only ghosts may travel through walls...", sptr->name); return; } while (fromname_index && t <= fromname_index) { msgclient = FromNameList[t]; if (msgclient->flags & FLAGS_FIND_CORRECT_DEST_SEND_ONCE && !matches(msgclient->tonick, sptr->name) && !matches(msgclient->toname, UserName(sptr)) && !matches(msgclient->tohost, sptr->user->host) && flag_send((aClient *)0, sptr, (aClient *)0, sptr->name, msgclient, '-', NULLCHAR)) { msgclient->flags &= ~FLAGS_FIND_CORRECT_DEST_SEND_ONCE; sendto_one(sptr, "NOTICE %s :### Note wall to %s!%s@%s deactivated.", sptr->name, msgclient->tonick, msgclient->toname, msgclient->tohost); remote_remove_notice(sptr, msgclient, "has deactivated your Note Wall"); wall = 1; } t++; } if (!wall) { sendto_one(sptr,"NOTICE %s :#?# Hunting for ghost walls?", sptr->name); return; } } #ifdef EPATH int m_mode(cptr, sptr, parc, parv) aClient *cptr; aClient *sptr; int parc; char *parv[]; { aChannel *chptr; Reg1 Link *lp; /* if (parc > 1 && !check_registered_user(sptr)) { chptr = find_channel(parv[1], NullChn); if (chptr != NullChn && note_headchannel(chptr->chname) && (lp = find_user_link(chptr->members, sptr))) { chptr->mode.mode |= MODE_NOPRIVMSGS; if (IsOper(sptr)) lp->flags |= CHFL_CHANOP; } } */ return n_mode(cptr, sptr, parc, parv); } static void make_password(sptr, hostname) aClient *sptr; char *hostname; { long32 gflags = 0; char *password, buf1[BUF_LEN], buf2[BUF_LEN]; password = create_pwd(); gflags |= FLAGS_CHANNEL; gflags |= FLAGS_WASOPER; gflags |= FLAGS_SORT_BY_TONAME; gflags |= FLAGS_REPEAT_UNTIL_TIMEOUT; gflags |= FLAGS_CHANNEL_PASSWORD; gflags |= FLAGS_SERVER_GENERATED; new(password,"SERVER_PASSWORD","-","-", "*", UserName(sptr), local_host(sptr->user->host), gflags, 365*SECONDS_DAY+now, now, ""); sprintf(buf1, "%s@%s", UserName(sptr), hostname); sprintf(buf2, "%s@%s", UserName(sptr), sptr->user->host); if (!fork()) { execl(EPATH, EPATH, buf1, buf2, password, (char *)0); exit(-1); } sendto_one(sptr, "NOTICE %s :### Password (valid 365 days) mailed to %s@%s", sptr->name, UserName(sptr), hostname); } static int fake_email(c) char *c; { while (*c) { if (!isletter(*c) && *c != '.' && !isdigit(*c)) return 1; c++; } return 0; } static int no_password(sptr, chn, pwd) aClient *sptr; int chn; char *pwd; { int last, t, found = 0; aMsgClient *msgclient; char *c, *msg, *name, username[BUF_LEN], hostname[BUF_LEN]; name = ToNameList[chn]->tonick; if (!(ToNameList[chn]->flags & FLAGS_CHANNEL_PASSWORD) && matches("#pwd.*", name) && matches("*.pwd.*", name)) return 0; if (strlen(pwd) > BUF_LEN) { sendto_one(sptr, "NOTICE %s :#?# Too long argument", sptr->name); return 1; } t = first_tnl_indexnode(UserName(sptr)); last = last_tnl_indexnode(UserName(sptr)); while (last && t <= last) { msgclient = ToNameList[t]; if (now > msgclient->timeout) { t++; continue; } msg = flag_send((aClient *)0, sptr, (aClient *)0 , sptr->name, msgclient, '-', NULLCHAR); if (msg && msgclient->flags & FLAGS_CHANNEL && !matches(msgclient->tonick,sptr->name) && !matches(msgclient->toname,UserName(sptr)) && !matches(msgclient->tohost,sptr->user->host)) { found++; if (!strcmp(pwd, msgclient->passwd)) return 0; } t++; } if (index(pwd, '@') != NULL) { if (found) { sendto_one(sptr, "NOTICE %s :#?# You've already got password", sptr->name); return 1; } strcpy(username, pwd); c = username; c = index(username, '@'); strcpy(hostname, c+1); *c = 0; if (strcmp(username, UserName(sptr)) || matches(local_host(sptr->user->host), hostname) || fake_email(hostname) || fake_email(UserName(sptr)) || fake_email(sptr->user->host)) { sendto_one(sptr, "NOTICE %s :#?# %s@%s doesn't matches %s", sptr->name, UserName(sptr), local_host(sptr->user->host), pwd); return 1; } make_password(sptr, hostname); return 1; } if (*pwd == '*' || !found) { if (*pwd != '*') sendto_one(sptr, "NOTICE %s :#?# You haven't requested password yet", sptr->name); sendto_one(sptr, "NOTICE %s :#?# %s %s", sptr->name, "Password protected channel. /join #chn ", "or /join #chn to request password"); return 1; } sendto_one(sptr, "NOTICE %s :#?# Wrong password", sptr->name); return 1; } int m_join(cptr, sptr, parc, parv) aClient *cptr, *sptr; int parc; char *parv[]; { int i, chn; char *c, *p = NULL, *name, buf[BUF_LEN]; aChannel *chptr; if (MyConnect(sptr)) { if (check_registered_user(sptr)) return 0; if (parc < 2 || *parv[1] == '\0') { sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "JOIN"); return 0; } for (i = 0, name = strtoken(&p, parv[1], ","); name; name = strtoken(&p, NULL, ",")) if (!wildcards(name) && index(name,'.')) { if (denied(sptr)) return 0; if (*name != '#') { sendto_one(sptr, "NOTICE %s :#?# '#' missing in channel name", sptr->name); return 0; } strncpyzt(buf, name, BUF_LEN-5); if (c = index(buf, '-')) *c = 0; chn = note_channel(cptr, sptr, 'c', buf); if (!chn) { if (c) sendto_one(sptr, "NOTICE %s :#?# No head channel %s for %s", sptr->name, buf, name); else sendto_one(sptr, "NOTICE %s :#?# No such head channel: %s", sptr->name, buf); return 0; } if (no_password(sptr, chn, parc < 3 ? "*" : parv[2])) return 0; } } return n_join(cptr, sptr, parc, parv); } int m_list(cptr, sptr, parc, parv) aClient *cptr, *sptr; int parc; char *parv[]; { char *name, *p = NULL, *empty = ""; if (parc < 2 || BadPtr(parv[1])) name = empty; else name = strtoken(&p, parv[1], ","); if (!strcasecmp(name, "all") || !note_channel(cptr, sptr, 'c', "*" )) return n_list(cptr, sptr, parc, parv); note_channel(cptr, sptr, 'l', name); if (!strcasecmp(name, "help")) sendto_one(sptr, "NOTICE %s :*** /list #first_characters_in_chn %s", sptr->name, "or /list . (opermade) or /list (usermade)"); sendto_one(sptr, rpl_str(RPL_LISTEND), me.name, parv[0]); return 1; } int m_names(cptr, sptr, parc, parv) aClient *cptr, *sptr; int parc; char *parv[]; { int ret; ret = n_names(cptr, sptr, parc, parv); return ret; } #endif int m_note(cptr, sptr, parc, parv) aClient *cptr, *sptr; int parc; char *parv[]; { char *option, *arg, *timeout = NULLCHAR, *passwd = NULLCHAR, *param, *id = NULLCHAR, *flags = NULLCHAR, *name = NULLCHAR, *msg = NULLCHAR, *wildcard = "*", *c, *default_timeout = "+1", *deft = "+31"; static char buf1[BUF_LEN], buf2[BUF_LEN], buf3[BUF_LEN], buf4[BUF_LEN], msg_buf[MSG_LEN], passwd_buf[BUF_LEN], timeout_buf[BUF_LEN], option_buf[BUF_LEN], id_buf[BUF_LEN], flags_buf[BUF_LEN + 3]; int t, silent = 0, remote = 0; aClient *acptr; if (!file_inited) init_messages(); if (parc < 2) { sendto_one(sptr,"NOTICE %s :#?# No option specified.", sptr->name); return -1; } param = parv[1]; if (parc > 1 && !strncasecmp(param,"service ",8)) { if (!IsOperHere(sptr)) { sendto_one(sptr,"NOTICE %s :### %s",sptr->name, "Beyond your power poor soul..."); return 0; } sptr = find_person(split_string(param, 2, 1), (aClient *)0); if (!sptr) return 0; t = 0; while (*param && t < 2) { if (*param == ' ') t++; param++; } if (!*param) parc = 0; } else { c = split_string(param, 1, 1); if (index(c,'.')) { if (IsServer(sptr)) { distribute(cptr, sptr, param); return 0; } if (wildcards(c)) for (t = 0; t <= highest_fd; t++) { if (!(acptr = local[t])) continue; if (IsServer(acptr) && acptr != cptr) sendto_one(acptr, ":%s NOTE %s", sptr->name, param); } else for (acptr = client; acptr; acptr = acptr->next) if (IsServer(acptr) && acptr != cptr && !strcasecmp(c, acptr->name)) { sendto_one(acptr, ":%s NOTE %s", sptr->name, param); break; } if (!matches(c, me.name)) { if (wildcards(c)) remote = -1; else remote = 1; while (*param && *param != ' ') param++; if (*param) param++; if (!*param) { sendto_one(sptr, "NOTICE %s :#?# No option specified.", sptr->name); return -1; } } else return 0; } } if (!IsRegistered(sptr)) { sendto_one(sptr, ":%s %d * :You have not registered as an user", me.name, ERR_NOTREGISTERED); return -1; } if (strlen(param) >= MSG_LEN) { sendto_one(sptr,"NOTICE %s :#?# Line can't be longer than %d chars", sptr->name, MSG_LEN-1); return -1; } strncpyzt(option_buf, split_string(param, 1, 1), BUF_LEN-1); option = option_buf; for (t = 2; t < 10; t++) { arg = split_string(param, t, 1); switch (*arg) { case '&' : case '$' : passwd = passwd_buf;strncpyzt(passwd,arg+1,10); break; case '%' : passwd = passwd_buf;strncpyzt(passwd,arg+1,10); silent = 1; break; case '+' : case '-' : if (numeric(arg+1)) { timeout = timeout_buf; strncpyzt(timeout,arg,BUF_LEN); } else { flags = flags_buf; strncpyzt(flags,arg,BUF_LEN); } break; default : if (numeric(arg) && (MyEq(option, "RM") || MyEq(option, "XRM") || MyEq(option, "XLS") || MyEq(option, "LS"))) { id = id_buf; strncpyzt(id,arg,BUF_LEN); t++; } goto end_loop_case; } } end_loop_case:; strncpyzt(buf1, split_string(param, t, 1), BUF_LEN-1); strncpyzt(buf2, split_string(param, t+1, 1), BUF_LEN-1); strncpyzt(buf3, split_string(param, t+2, 1), BUF_LEN-1); strncpyzt(buf4, split_string(param, t+3, 1), BUF_LEN-1); strcpy(msg_buf, split_string(param, t+1, 0)); msg = msg_buf; c = msg; while (*c) c++; while (c != msg && *--c == ' '); if (c != msg) c++; *c = 0; if (!*msg) msg = NULLCHAR; if (!passwd || !*passwd) passwd = wildcard; if (!flags) flags = (char *) ""; if (flags && flag_len_error(sptr, flags)) return 0; if (MyEq(option,"STATS")) msg_stats(sptr, buf1, buf2); else if (MyEq(option,"VERSION")) sendto_one(sptr,"NOTICE %s :Running version %s", sptr->name, VERSION); else if (remote < 0 && strcasecmp(option, "NEWS") && strcasecmp(option, "XRM") && strcasecmp(option, "FLAG") && strcasecmp(option, "DENY") && strcasecmp(option, "XLS")) return 0; else if (alias_send(sptr,option, &flags, &msg, &timeout) || MyEq(option,"USER")) { if (!*buf1) { if (MyEq(option,"SPY")) check_messages(sptr, sptr, sptr->name, 'g'); else sendto_one(sptr, "NOTICE %s :#?# Please specify at least one argument", sptr->name); return 0; } name = buf1;if (!*name) name = wildcard; if (name_len_error(sptr, name)) return 0; if (!timeout || !*timeout) timeout = default_timeout; if (strcasecmp(option, "NEWS") || !msg) { msg_send(sptr, silent, passwd, flags, timeout, name, msg); } else msg_news(sptr, silent, passwd, flags, timeout == default_timeout ? deft : timeout, name, msg); } else if (MyEq(option,"XLS") || MyEq(option,"LS") || MyEq(option,"COUNT") || MyEq(option,"LOG") || MyEq(option,"LLOG")) { name = buf1;if (name_len_error(sptr, name)) return 0; msg_list(sptr, option, passwd, flags, id, name, buf2); } else if (MyEq(option,"SAVE")) msg_save(sptr); else if (MyEq(option,"ANTIWALL")) antiwall(sptr); else if (MyEq(option,"FLAG")) { name = buf1;if (!*name) name = wildcard; if (name_len_error(sptr, name)) return 0; msg_flag(sptr, passwd, flags, id, name, buf2); } else if (MyEq(option,"SENT")) { name = buf2;if (!*name) name = wildcard; if (name_len_error(sptr, name)) return 0; msg_sent(sptr, buf1, name, buf3, buf4); } else if (MyEq(option,"DISTRIBUTE")) { t = atoi(buf1); msg_distribute(sptr, t); } else if (MyEq(option,"LIST")) { name = buf1; if (name_len_error(sptr, name)) return 0; note_channel(cptr, sptr, 'l', name); } else if (!strcasecmp(option,"RM") || !strcasecmp(option,"XRM")) { if (!*buf1 && !id && !*flags) { sendto_one(sptr, "NOTICE %s :#?# Please specify at least one argument", sptr->name); return 0; } name = buf1;if (!*name) name = wildcard; if (name_len_error(sptr, name)) return 0; msg_remove(sptr, option, passwd, flags, id, name, buf2); } else sendto_one(sptr,"NOTICE %s :#?# No such option: %s", sptr->name, option); return 0; } #endif