/************************************************************************ * IRC - Internet Relay Chat, chanmodes/cm_ban.c * * Copyright (C)2000-2003 TR-IRCD Development * Copyright (C) 1990 Jarkko Oikarinen and * University of Oulu, Co Center * * 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 2, 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. */ #include "struct.h" #include "common.h" #include "sys.h" #include "numeric.h" #include "channel.h" #include "h.h" #include "hook.h" #include "msg.h" #include "s_conf.h" #include "chanmode.h" static char modebuf[REALMODEBUFLEN], parabuf[REALMODEBUFLEN]; static int add_ban_id(aClient *cptr, aChannel *chptr, char *id) { struct ChanMember *cm; dlink_node *ptr; aClient *acptr; int r = 0; char *s, nickuhost[NICKLEN + USERLEN + HOSTLEN + 6]; char fakeuhost[NICKLEN + USERLEN + HOSTLEN + 6]; r = add_id(cptr, chptr, id, MAXBANS, &(chptr->banlist)); if (r == 1) { for (ptr = chptr->members.head; ptr; ptr = ptr->next) { cm = ptr->data; acptr = cm->client_p; if (!MyConnect(acptr)) continue; s = make_nick_user_host(acptr->name, acptr->user->username, acptr->user->host); strcpy(nickuhost, make_nick_user_host(acptr->name, acptr->user->username, acptr->hostip)); strcpy(fakeuhost, make_nick_user_host(acptr->name, acptr->user->username, acptr->user->fakehost)); if (match(id, nickuhost) == 0 || match(id, s) == 0 || match(id, fakeuhost) == 0) cm->bans++; } } return r; } static int del_ban_id(aClient *cptr, aChannel *chptr, char *id) { struct ChanMember *cm; dlink_node *ptr; aClient *acptr; int r = 0; char *s, nickuhost[NICKLEN + USERLEN + HOSTLEN + 6]; char fakeuhost[NICKLEN + USERLEN + HOSTLEN + 6]; r = del_id(id, &(chptr->banlist)); for (ptr = chptr->members.head; ptr; ptr = ptr->next) { cm = ptr->data; acptr = cm->client_p; if (!MyConnect(acptr) || (cm->bans == 0)) continue; strcpy(nickuhost, make_nick_user_host(acptr->name, acptr->user->username, acptr->hostip)); strcpy(fakeuhost, make_nick_user_host(acptr->name, acptr->user->username, acptr->user->fakehost)); s = make_nick_user_host(acptr->name, acptr->user->username, acptr->user->host); if (match(id, nickuhost) == 0 || match(id, s) == 0 || match(id, fakeuhost) == 0) cm->bans--; } return r; } static int kill_ban_list(struct hook_data *data) { struct ChanMember *cm; dlink_node *ptr; aClient *cptr = data->client_p; aClient *acptr; aChannel *chptr = data->channel; remove_nuh_list(cptr, chptr, &chptr->banlist, 'b'); for (ptr = chptr->members.head; ptr; ptr = ptr->next) { cm = ptr->data; acptr = cm->client_p; if (MyConnect(acptr)) cm->bans = 0; } return 0; } static int send_ban_list(struct hook_data *data) { aClient *cptr = data->client_p; aChannel *chptr = data->channel; *parabuf = '\0'; *modebuf = '+'; modebuf[1] = '\0'; send_nuh_list(cptr, chptr, &chptr->banlist, 'b', modebuf, parabuf); return 0; } static int remove_matching_bans(struct hook_data *data) { aChannel *chptr = data->channel; aClient *cptr = data->client_p; aClient *from = data->source_p; char letter = data->statchar; if (letter == 'b') remove_matching_nuhs(chptr, cptr, from, &chptr->banlist, letter); return 0; } static int clear_bans(struct hook_data *data) { aChannel *chptr = data->channel; dlink_node *nuhptr, *next_ptr; aNUH *nuh; for (nuhptr = chptr->banlist.head; nuhptr; nuhptr = next_ptr) { next_ptr = nuhptr->next; nuh = nuhptr->data; MyFree(nuh->nuhstr); MyFree(nuh->who); MyFree(nuh); dlinkDeleteNode(nuhptr, &(chptr->banlist)); } return 0; } /* * adl : add|del|list :P -TimeMr14C */ static int set_ban(int adl, aChannel *chptr, int nmodes, int *argnum, int *pidx, int *mbix, char *mbuf, char *pbuf, aClient *cptr, aClient *sptr, int parc, char **parv) { aNUH *nuhptr = NULL; dlink_node *l; char *pptr; /* temporary paramater pointer */ char *morig = mbuf; /* beginning of mbuf */ char nuhbuf[NICKLEN + USERLEN + HOSTLEN + 6]; int prelen = strlen(cptr->name) + strlen(chptr->chname) + 16; int fargnum = *argnum; int fmbix = *mbix; int fpidx = *pidx; if (adl == CMODE_LIST) { for (l = chptr->banlist.head; l; l = l->next) { nuhptr = l->data; if (nuhptr->nuhstr) send_me_numeric(sptr, RPL_BANLIST, chptr, nuhptr->nuhstr, nuhptr->who, nuhptr->when); } send_me_numeric(cptr, RPL_ENDOFBANLIST, chptr); return nmodes; } if (parv[fargnum] == NULL) { return set_ban(CMODE_LIST, chptr, nmodes, argnum, pidx, mbix, mbuf, pbuf, cptr, sptr, parc, parv); } if (*parv[fargnum] == ':' || *parv[fargnum] == '\0') { fargnum++; *argnum = fargnum; return nmodes; } strlcpy_irc(nuhbuf, collapse(pretty_mask(parv[fargnum])), NICKLEN + USERLEN + HOSTLEN + 6); parv[fargnum] = nuhbuf; if ((prelen + (mbuf - morig) + fpidx + NICKLEN + USERLEN + HOSTLEN + 6 + 1) > REALMODEBUFLEN) { fargnum++; send_me_numeric(sptr, ERR_NEEDMOREPARAMS, MSG_MODE); *argnum = fargnum; return nmodes; } if ((adl == CMODE_ADD) && !add_ban_id(sptr, chptr, parv[fargnum])) { fargnum++; *argnum = fargnum; return -1; } if ((adl == CMODE_DEL) && !del_ban_id(sptr, chptr, parv[fargnum])) { fargnum++; *argnum = fargnum; return -1; } mbuf[fmbix++] = 'b'; pptr = parv[fargnum]; if (fpidx) pbuf[fpidx++] = ' '; while (*pptr) pbuf[fpidx++] = *pptr++; fargnum++; nmodes++; *mbix = fmbix; *pidx = fpidx; *argnum = fargnum; return nmodes; } static int sb_service(int adl, aChannel *chptr, int nmodes, int *argnum, int *pidx, int *mbix, char *mbuf, char *pbuf, aClient *cptr, aClient *sptr, int parc, char **parv) { if (MyClient(sptr)) send_me_numeric(sptr, ERR_CHANOPRIVSNEEDED, chptr); else ircstp->is_fake++; return nmodes; } static int sb_server(int adl, aChannel *chptr, int nmodes, int *argnum, int *pidx, int *mbix, char *mbuf, char *pbuf, aClient *cptr, aClient *sptr, int parc, char **parv) { return set_ban(adl, chptr, nmodes, argnum, pidx, mbix, mbuf, pbuf, cptr, sptr, parc, parv); } static int sb_uline(int adl, aChannel *chptr, int nmodes, int *argnum, int *pidx, int *mbix, char *mbuf, char *pbuf, aClient *cptr, aClient *sptr, int parc, char **parv) { return set_ban(adl, chptr, nmodes, argnum, pidx, mbix, mbuf, pbuf, cptr, sptr, parc, parv); } static int sb_oper(int adl, aChannel *chptr, int nmodes, int *argnum, int *pidx, int *mbix, char *mbuf, char *pbuf, aClient *cptr, aClient *sptr, int parc, char **parv) { if (IsChanUser(sptr, chptr, CHFL_CHANOP) || IsOperMode(sptr) || IsServer(cptr) || (adl ==0)) { return set_ban(adl, chptr, nmodes, argnum, pidx, mbix, mbuf, pbuf, cptr, sptr, parc, parv); } else send_me_numeric(sptr, ERR_CHANOPRIVSNEEDED, chptr); return nmodes; } static int sb_user(int adl, aChannel *chptr, int nmodes, int *argnum, int *pidx, int *mbix, char *mbuf, char *pbuf, aClient *cptr, aClient *sptr, int parc, char **parv) { if (IsChanUser(sptr, chptr, CHFL_CHANOP) || (adl == 0)) return set_ban(adl, chptr, nmodes, argnum, pidx, mbix, mbuf, pbuf, cptr, sptr, parc, parv); else send_me_numeric(sptr, ERR_CHANOPRIVSNEEDED, chptr); return nmodes; } struct ChanMode mode_ban[] = { {MDFL_BAN, 1, MFLG_LISTABLE | MFLG_IGNORE, CMTYPE_LIST | CMTYPE_PARAMETRIC, sb_user, sb_oper, sb_uline, sb_server, sb_service} }; #ifndef STATIC_MODULES int _persistent = 1; void _modinit(void) #else void ban_modinit(void) #endif { hook_add_hook("send mode list", (hookfn *) send_ban_list); hook_add_hook("sub1 from channel", (hookfn *) clear_bans); hook_add_hook("kill paramode list", (hookfn *) kill_ban_list); hook_add_hook("channel svsmode", (hookfn *) remove_matching_bans); modetab[(int) 'b'] = mode_ban[0]; GeneralOpts.lists_created = 0; }