/* mode dumps */ #include #include #include #include "eggdrop.h" #include "chan.h" /* buffer for storing mode changes by the bot */ char pls[41]=""; char mns[41]=""; char key[121]=""; char rmkey[121]=""; int limit=(-1); /* data for detecting mass deops */ char deopnick[10]=""; time_t deoptime=0L; int deops=0; /* reversing this mode? */ int reversing=0; /* modes the bot should protect positive */ int mode_pls_prot=0; /* modes the bot should protect negative */ int mode_mns_prot=0; /* channel limit to protect */ int limit_prot=(-1); /* channel key to protect */ char key_prot[121]=""; extern int serv; extern char curchan[]; extern struct chan_t channel; extern int helpsock; extern char gainops[]; extern char botname[]; extern char bothost[]; extern char botuser[]; extern int revenge; extern char cx_file[]; extern int cx_line; extern int perm_bans; memberlist *ismember(); #define PLUS 1 #define MINUS 2 #define CHOP 4 #define BAN 8 #define VOICE 16 struct { char op[512]; int type; } cmode[3]={ {"",0}, {"",0}, {"",0} }; void flush_mode() { char s[512],post[512],*p; int i,ok=0; context; p=s; post[0]=0; if (pls[0]) *p++='+'; for (i=0; i126)) bogus=1; if (bogus) { log(LOG_MODES,"Bogus channel key!"); tprintf(serv,"KICK %s %s :bogus channel key\n",curchan,nick); } if ((reversing) || (bogus) || (mode_mns_prot&CHANKEY)) add_mode('-','k',key); } void got_op(nick,from,who) char *nick,*from,*who; { memberlist *m; char s[161]; context; m=ismember(who); if (m==NULL) { log(LOG_MISC,"* Mode change on nonexistant %s!",who); tprintf(serv,"WHO %s\n",who); return; } sprintf(s,"%s!%s",m->nick,m->userhost); fixfrom(s); if ((!me_op()) && (strcasecmp(who,botname)==0)) newly_chanop(); if ((me_op()) && (match_deop(s)) && (strcasecmp(who,botname)!=0) && (!match_op(s))) add_mode('-','o',who); else if (reversing) add_mode('-','o',who); if (nick[0]==0) { /* server op! */ if ((!match_op(s)) && (!match_friend(s)) && (!(m->flags&CHANOP))) { add_mode('-','o',who); m->flags|=FAKEOP; } } else m->flags&=~FAKEOP; m->flags|=CHANOP; } void got_deop(nick,from,who) char *nick,*from,*who; { memberlist *m; char s[161],s1[161],s2[161]; context; m=ismember(who); if (m==NULL) { log(LOG_MISC,"* Mode change on nonexistant %s!",who); tprintf(serv,"WHO %s\n",who); return; } m->flags&=~CHANOP; m->flags&=~FAKEOP; sprintf(s,"%s!%s",m->nick,m->userhost); fixfrom(s); sprintf(s1,"%s!%s",nick,from); if ((me_op()) && (match_op(s)) && (!match_deop(s)) && (strcasecmp(nick,botname)!=0) && (strcasecmp(who,nick)!=0)) { /* deop'd someone on our oplist */ if (!match_master(s1)) add_mode('+','o',who); /* op him */ else if (reversing) add_mode('+','o',who); if ((!match_master(s1)) && (!match_friend(s1)) && (!match_op(s1)) && (revenge)) { sprintf(s2,"deopped %s",s); unprog_op_and_deop(s1,s2); /* punish bad guy */ } } /* check for mass deop */ if ((!match_master(s1)) && (!match_friend(s1)) && (strcasecmp(nick,botname)!=0)) { if (strcasecmp(nick,deopnick)==0) { time_t tx=time(NULL); if (tx-deoptime <= 10) { deops++; if (deops>=3) { log(LOG_MODES,"Mass deop by %s",s1); tprintf(serv,"KICK %s %s :mass deop, go sit in a corner\n",curchan, nick); deopnick[0]=0; deoptime=0L; deops=0; } } else { deoptime=time(NULL); deops=1; } } else { strcpy(deopnick,nick); deoptime=time(NULL); deops=1; } } /* having op hides your +v status -- so now that someone's lost ops, check to see if they have +v */ if (!(m->flags&CHANVOICE)) tprintf(serv,"WHO %s\n",m->nick); if ((strcasecmp(who,botname)==0) && (revenge)) { /* deopped ME! take revenge */ if (!match_master(s1)) unprog_op_and_deop(s1,"deopped me"); if (gainops[0]) tprintf(serv,"%s\n",gainops); ask_tandem_for_ops(); } } void got_ban(nick,from,who) char *nick,*from,*who; { char me[161],s[161],s1[161]; int check=1,i,bogus; memberlist *m; context; sprintf(me,"%s!%s@%s",botname,botuser,bothost); sprintf(s,"%s!%s",nick,from); newban(who,s); bogus=0; if (strcasecmp(nick,botname)!=0) { /* it's not my ban */ for (i=0; i126)) bogus=1; if (bogus) { if ((match_master(s)) || (match_op(s)) || (match_friend(s))) { /* fix their bogus ban */ strcpy(s1,who); for (i=0; i126)) s1[i]='?'; add_mode('-','b',who); add_mode('+','b',s1); } else { add_mode('-','b',who); tprintf(serv,"KICK %s %s :bogus ban\n",curchan,nick); } return; } if ((wild_match(who,me)) && (me_op())) add_mode('-','b',who); /* ^ don't really feel like being banned today, thank you! */ else if (!match_master(s)) { /* don't contradict master bans */ /* banning an oplisted person who's on the channel? */ m=channel.member; while (m->nick[0]) { sprintf(s1,"%s!%s",m->nick,m->userhost); if ((match_op(s1)) && (wild_match(who,s1))) { add_mode('-','b',who); check=0; } m=m->next; } if (check) kick_banned_members(); } else kick_banned_members(); } else kick_banned_members(); if (reversing) add_mode('-','b',who); } void got_unban(nick,from,who) char *nick,*from,*who; { char s[161]; int i,bogus; killban(who); bogus=0; for (i=0; i126)) bogus=1; if ((bogus) && (strcasecmp(nick,botname)!=0)) { tprintf(serv,"KICK %s %s :bogus ban\n",curchan,nick); return; } if ((equals_ban(who)) && (me_op()) && (perm_bans)) { /* that's a permban! */ sprintf(s,"%s!%s",nick,from); if ((match_master(s)) || (match_op(s))) { hprintf(helpsock,"NOTICE %s :That's in my permban list. You need %s\n", nick,"to use '-ban' in dcc chat if you want it gone for good."); } else add_mode('+','b',who); } if (reversing) add_mode('+','b',who); } #define modechg(x,y) { \ if (pos==1) channel.mode|=(x); else channel.mode&=~(x); \ if ((reversing) || ((pos==1)&&(mode_mns_prot&(x))) || \ ((pos==-1)&&(mode_pls_prot&(x)))) add_mode((pos==1)?'-':'+',y,""); \ } /* a pain in the ass: mode changes */ void gotmode(from,msg) char *from,*msg; { char nick[10],chan[81],op[81],chg[81],s[161]; int pos=0,i; memberlist *m; context; split(chan,msg); nsplit(chg,msg); reversing=0; if (chan[0]!='#') return; /* discard all usermode changes */ log(LOG_MODES,"Mode change '%s %s' by %s",chg,msg,from); splitnick(nick,from); i=0; m=ismember(nick); if (m!=NULL) if ((m->flags&FAKEOP) && (me_op())) { log(LOG_MODES,"Mode change by fake op! Reversing..."); tprintf(serv,"KICK %s %s :abusing ill-gained server ops\n",curchan,nick); reversing=1; } while (chg[i]!=0) { if (chg[i]=='+') pos=1; if (chg[i]=='-') pos=(-1); if (chg[i]=='i') { modechg(CHANINV,'i'); if (m!=NULL) { sprintf(s,"%s!%s",m->nick,m->userhost); fixfrom(s); } } if (chg[i]=='p') modechg(CHANPRIV,'p'); if (chg[i]=='s') modechg(CHANSEC,'s'); if (chg[i]=='m') modechg(CHANMODER,'m'); if (chg[i]=='t') modechg(CHANTOPIC,'t'); if (chg[i]=='n') modechg(CHANNOMSG,'n'); if (chg[i]=='l') { if (pos==-1) { if ((reversing) && (channel.maxmembers!=(-1))) { sprintf(s,"%d",channel.maxmembers); add_mode('+','l',s); } else if (limit_prot!=(-1)) { sprintf(s,"%d",limit_prot); add_mode('+','l',s); } channel.maxmembers=(-1); } else { nsplit(op,msg); channel.maxmembers=atoi(op); if ((reversing) || (mode_mns_prot&CHANLIMIT)) add_mode('-','l',""); } } if (chg[i]=='k') { nsplit(op,msg); if (pos==1) got_key(nick,from,op); else { if ((reversing) && (channel.key[0])) add_mode('+','k',channel.key); else if (key_prot[0]) add_mode('+','k',key_prot); set_key(NULL); } } if (chg[i]=='o') { nsplit(op,msg); if (pos==1) got_op(nick,from,op); else got_deop(nick,from,op); } if (chg[i]=='v') { nsplit(op,msg); m=ismember(op); if (m==NULL) { log(LOG_MISC,"* Mode change on nonexistant %s!",op); tprintf(serv,"WHO %s\n",op); } else { if (pos==1) { m->flags|=CHANVOICE; if (reversing) add_mode('-','v',op); } else { m->flags&=~CHANVOICE; if (reversing) add_mode('+','v',op); } } } if (chg[i]=='b') { nsplit(op,msg); if (pos==1) got_ban(nick,from,op); else got_unban(nick,from,op); } i++; } } /* interpret configfile setting for modes to protect */ #define protmode(x) { \ if (pos==1) mode_pls_prot|=(x); else mode_mns_prot|=(x); \ } void set_mode_protect(set) char *set; { int i,pos=1; char s[121],s1[121]; context; nsplit(s,set); for (i=0; i