/************************************************************************
* 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;
}
syntax highlighted by Code2HTML, v. 0.9.1