/************************************************************************ * IRC - Internet Relay Chat, chanmodes/cm_excepts.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 "msg.h" #include "hook.h" #include "s_conf.h" #include "chanmode.h" static char modebuf[REALMODEBUFLEN], parabuf[REALMODEBUFLEN]; static int add_excepts_id(aClient *cptr, aChannel *chptr, char *id) { int r = 0; r = add_id(cptr, chptr, id, MAXEXCEPTIONS, &(chptr->banexlist)); return r; } static int del_excepts_id(aClient *cptr, aChannel *chptr, char *id) { int r = 0; r = del_id(id, &(chptr->banexlist)); return r; } static int kill_excepts_list(struct hook_data *data) { aClient *cptr = data->client_p; aChannel *chptr = data->channel; remove_nuh_list(cptr, chptr, &chptr->banexlist, 'e'); return 0; } static int send_excepts_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->banexlist, 'e', modebuf, parabuf); return 0; } static int remove_matching_exceptions(struct hook_data *data) { aChannel *chptr = data->channel; aClient *cptr = data->client_p; aClient *from = data->source_p; char letter = data->statchar; if (letter == 'e') remove_matching_nuhs(chptr, cptr, from, &chptr->banexlist, letter); return 0; } static int clear_excepts(struct hook_data *data) { aChannel *chptr = data->channel; dlink_node *nuhptr, *next_ptr; aNUH *nuh; for (nuhptr = chptr->banexlist.head; nuhptr; nuhptr = next_ptr) { next_ptr = nuhptr->next; nuh = nuhptr->data; MyFree(nuh->nuhstr); MyFree(nuh->who); MyFree(nuh); dlinkDeleteNode(nuhptr, &(chptr->banexlist)); } return 0; } /* * adl : add|del|list :P -TimeMr14C */ static int set_exception(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->banexlist.head; l; l = l->next) { nuhptr = l->data; if (nuhptr->nuhstr) send_me_numeric(sptr, RPL_EXCEPTIONLIST, chptr, nuhptr->nuhstr, nuhptr->who, nuhptr->when); } send_me_numeric(cptr, RPL_ENDOFEXCEPLIST, chptr); return nmodes; } if (parv[fargnum] == NULL) { return set_exception(CMODE_LIST, chptr, nmodes, argnum, pidx, mbix, mbuf, pbuf, cptr, sptr, parc, parv); } if (*parv[fargnum] == ':' || *parv[fargnum] == '\0') { send_me_numeric(sptr, ERR_NEEDMOREPARAMS, MSG_MODE); 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++; *argnum = fargnum; return nmodes; } if ((adl == CMODE_ADD) && !add_excepts_id(sptr, chptr, parv[fargnum])) { fargnum++; *argnum = fargnum; return -1; } if ((adl == CMODE_DEL) && !del_excepts_id(sptr, chptr, parv[fargnum])) { fargnum++; *argnum = fargnum; return -1; } mbuf[fmbix++] = 'e'; pptr = parv[fargnum]; if (fpidx) pbuf[fpidx++] = ' '; while (*pptr) pbuf[fpidx++] = *pptr++; fargnum++; nmodes++; *mbix = fmbix; *pidx = fpidx; *argnum = fargnum; return nmodes; } static int se_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 se_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_exception(adl, chptr, nmodes, argnum, pidx, mbix, mbuf, pbuf, cptr, sptr, parc, parv); } static int se_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_exception(adl, chptr, nmodes, argnum, pidx, mbix, mbuf, pbuf, cptr, sptr, parc, parv); } static int se_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_exception(adl, chptr, nmodes, argnum, pidx, mbix, mbuf, pbuf, cptr, sptr, parc, parv); } else send_me_numeric(sptr, ERR_CHANOPRIVSNEEDED, chptr); return nmodes; } static int se_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_exception(adl, chptr, nmodes, argnum, pidx, mbix, mbuf, pbuf, cptr, sptr, parc, parv); else send_me_numeric(sptr, ERR_CHANOPRIVSNEEDED, chptr); return nmodes; } static struct ChanMode mode_exception[] = { {MDFL_EXCEPT, 1, MFLG_LISTABLE | MFLG_IGNORE, CMTYPE_LIST | CMTYPE_PARAMETRIC, se_user, se_oper, se_uline, se_server, se_service} }; #ifndef STATIC_MODULES int _persistent = 1; void _modinit(void) #else void excepts_modinit(void) #endif { hook_add_hook("send mode list", (hookfn *) send_excepts_list); hook_add_hook("sub1 from channel", (hookfn *) clear_excepts); hook_add_hook("kill paramode list", (hookfn *) kill_excepts_list); hook_add_hook("channel svsmode", (hookfn *) remove_matching_exceptions); modetab[(int) 'e'] = mode_exception[0]; GeneralOpts.lists_created = 0; }