mirror of
https://github.com/unrealircd/unrealircd.git
synced 2026-07-01 21:06:38 +02:00
src/extbans.c -> src/api-extbans.c, and the same for extcmodes and umodes.
I suppose what is and what is not an API can be considered a bit arbitrary but for us it is the stuff we expose via the module api. We now have: api-clicap api-command api-event api-extbans api-extcmodes api-history-backend api-isupport api-mtag api-umodes
This commit is contained in:
@@ -0,0 +1,443 @@
|
||||
/************************************************************************
|
||||
* IRC - Internet Relay Chat, extcmodes.c
|
||||
* (C) 2003-2007 Bram Matthys (Syzop) and the UnrealIRCd Team
|
||||
*
|
||||
* See file AUTHORS in IRC package for additional names of
|
||||
* the programmers.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "unrealircd.h"
|
||||
|
||||
/* Channel parameter to slot# mapping */
|
||||
MODVAR unsigned char param_to_slot_mapping[256];
|
||||
|
||||
extern void make_cmodestr(void);
|
||||
|
||||
char extchmstr[4][64];
|
||||
|
||||
Cmode *Channelmode_Table = NULL;
|
||||
unsigned short Channelmode_highest = 0;
|
||||
|
||||
Cmode *ParamTable[MAXPARAMMODES+1];
|
||||
|
||||
void make_extcmodestr()
|
||||
{
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
extchmstr[0][0] = extchmstr[1][0] = extchmstr[2][0] = extchmstr[3][0] = '\0';
|
||||
|
||||
/* type 1: lists (like b/e) */
|
||||
/* [NOT IMPLEMENTED IN EXTCMODES] */
|
||||
|
||||
/* type 2: 1 par to set/unset (has .unset_with_param) */
|
||||
p = extchmstr[1];
|
||||
for (i=0; i <= Channelmode_highest; i++)
|
||||
if (Channelmode_Table[i].paracount && Channelmode_Table[i].flag &&
|
||||
Channelmode_Table[i].unset_with_param)
|
||||
*p++ = Channelmode_Table[i].flag;
|
||||
*p = '\0';
|
||||
|
||||
/* type 3: 1 param to set, 0 params to unset (does not have .unset_with_param) */
|
||||
p = extchmstr[2];
|
||||
for (i=0; i <= Channelmode_highest; i++)
|
||||
if (Channelmode_Table[i].paracount && Channelmode_Table[i].flag &&
|
||||
!Channelmode_Table[i].unset_with_param)
|
||||
*p++ = Channelmode_Table[i].flag;
|
||||
*p = '\0';
|
||||
|
||||
/* type 4: paramless modes */
|
||||
p = extchmstr[3];
|
||||
for (i=0; i <= Channelmode_highest; i++)
|
||||
if (!Channelmode_Table[i].paracount && Channelmode_Table[i].flag)
|
||||
*p++ = Channelmode_Table[i].flag;
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
static char previous_chanmodes[256];
|
||||
|
||||
void extcmodes_check_for_changes(void)
|
||||
{
|
||||
char chanmodes[256];
|
||||
Isupport *isup;
|
||||
|
||||
make_cmodestr();
|
||||
make_extcmodestr();
|
||||
|
||||
snprintf(chanmodes, sizeof(chanmodes), "%s%s", CHPAR1, EXPAR1);
|
||||
safestrdup(me.serv->features.chanmodes[0], chanmodes);
|
||||
snprintf(chanmodes, sizeof(chanmodes), "%s%s", CHPAR2, EXPAR2);
|
||||
safestrdup(me.serv->features.chanmodes[1], chanmodes);
|
||||
snprintf(chanmodes, sizeof(chanmodes), "%s%s", CHPAR3, EXPAR3);
|
||||
safestrdup(me.serv->features.chanmodes[2], chanmodes);
|
||||
snprintf(chanmodes, sizeof(chanmodes), "%s%s", CHPAR4, EXPAR4);
|
||||
safestrdup(me.serv->features.chanmodes[3], chanmodes);
|
||||
|
||||
ircsnprintf(chanmodes, sizeof(chanmodes), "%s,%s,%s,%s",
|
||||
me.serv->features.chanmodes[0],
|
||||
me.serv->features.chanmodes[1],
|
||||
me.serv->features.chanmodes[2],
|
||||
me.serv->features.chanmodes[3]);
|
||||
|
||||
isup = IsupportFind("CHANMODES");
|
||||
if (!isup)
|
||||
{
|
||||
strlcpy(previous_chanmodes, chanmodes, sizeof(previous_chanmodes));
|
||||
return; /* not booted yet. then we are done here. */
|
||||
}
|
||||
|
||||
IsupportSetValue(isup, chanmodes);
|
||||
|
||||
if (*previous_chanmodes && strcmp(chanmodes, previous_chanmodes))
|
||||
{
|
||||
ircd_log(LOG_ERROR, "Channel modes changed at runtime: %s -> %s",
|
||||
previous_chanmodes, chanmodes);
|
||||
sendto_realops("Channel modes changed at runtime: %s -> %s",
|
||||
previous_chanmodes, chanmodes);
|
||||
/* Broadcast change to all (locally connected) servers */
|
||||
sendto_server(&me, 0, 0, NULL, "PROTOCTL CHANMODES=%s", chanmodes);
|
||||
}
|
||||
|
||||
strlcpy(previous_chanmodes, chanmodes, sizeof(previous_chanmodes));
|
||||
}
|
||||
|
||||
void extcmode_init(void)
|
||||
{
|
||||
Cmode_t val = 1;
|
||||
int i;
|
||||
Channelmode_Table = MyMallocEx(sizeof(Cmode) * EXTCMODETABLESZ);
|
||||
for (i = 0; i < EXTCMODETABLESZ; i++)
|
||||
{
|
||||
Channelmode_Table[i].mode = val;
|
||||
val *= 2;
|
||||
}
|
||||
Channelmode_highest = 0;
|
||||
memset(&extchmstr, 0, sizeof(extchmstr));
|
||||
memset(¶m_to_slot_mapping, 0, sizeof(param_to_slot_mapping));
|
||||
*previous_chanmodes = '\0';
|
||||
}
|
||||
|
||||
/* Update letter->slot mapping and slot->handler mapping */
|
||||
void extcmode_para_addslot(Cmode *c, int slot)
|
||||
{
|
||||
if ((slot < 0) || (slot > MAXPARAMMODES))
|
||||
abort();
|
||||
c->slot = slot;
|
||||
ParamTable[slot] = c;
|
||||
param_to_slot_mapping[c->flag] = slot;
|
||||
}
|
||||
|
||||
/* Update letter->slot mapping and slot->handler mapping */
|
||||
void extcmode_para_delslot(Cmode *c, int slot)
|
||||
{
|
||||
if ((slot < 0) || (slot > MAXPARAMMODES))
|
||||
abort();
|
||||
ParamTable[slot] = NULL;
|
||||
param_to_slot_mapping[c->flag] = 0;
|
||||
}
|
||||
|
||||
Cmode *CmodeAdd(Module *module, CmodeInfo req, Cmode_t *mode)
|
||||
{
|
||||
short i = 0, j = 0;
|
||||
int paraslot = -1;
|
||||
int existing = 0;
|
||||
|
||||
while (i < EXTCMODETABLESZ)
|
||||
{
|
||||
if (!Channelmode_Table[i].flag)
|
||||
break;
|
||||
else if (Channelmode_Table[i].flag == req.flag)
|
||||
{
|
||||
if (Channelmode_Table[i].unloaded)
|
||||
{
|
||||
Channelmode_Table[i].unloaded = 0;
|
||||
existing = 1;
|
||||
break;
|
||||
} else {
|
||||
if (module)
|
||||
module->errorcode = MODERR_EXISTS;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (i == EXTCMODETABLESZ)
|
||||
{
|
||||
Debug((DEBUG_DEBUG, "CmodeAdd failed, no space"));
|
||||
if (module)
|
||||
module->errorcode = MODERR_NOSPACE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (req.paracount == 1)
|
||||
{
|
||||
if (existing)
|
||||
{
|
||||
/* Re-use parameter slot of the module with the same modechar that is unloading */
|
||||
paraslot = Channelmode_Table[i].slot;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Allocate a new one */
|
||||
for (paraslot = 0; ParamTable[paraslot]; paraslot++)
|
||||
{
|
||||
if (paraslot == MAXPARAMMODES - 1)
|
||||
{
|
||||
Debug((DEBUG_DEBUG, "CmodeAdd failed, no space for parameter"));
|
||||
if (module)
|
||||
module->errorcode = MODERR_NOSPACE;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*mode = Channelmode_Table[i].mode;
|
||||
/* Update extended channel mode table highest */
|
||||
Channelmode_Table[i].flag = req.flag;
|
||||
Channelmode_Table[i].paracount = req.paracount;
|
||||
Channelmode_Table[i].is_ok = req.is_ok;
|
||||
Channelmode_Table[i].put_param = req.put_param;
|
||||
Channelmode_Table[i].get_param = req.get_param;
|
||||
Channelmode_Table[i].conv_param = req.conv_param;
|
||||
Channelmode_Table[i].free_param = req.free_param;
|
||||
Channelmode_Table[i].dup_struct = req.dup_struct;
|
||||
Channelmode_Table[i].sjoin_check = req.sjoin_check;
|
||||
Channelmode_Table[i].local = req.local;
|
||||
Channelmode_Table[i].unset_with_param = req.unset_with_param;
|
||||
Channelmode_Table[i].owner = module;
|
||||
Channelmode_Table[i].unloaded = 0;
|
||||
|
||||
for (j = 0; j < EXTCMODETABLESZ; j++)
|
||||
if (Channelmode_Table[j].flag)
|
||||
if (j > Channelmode_highest)
|
||||
Channelmode_highest = j;
|
||||
|
||||
if (Channelmode_Table[i].paracount == 1)
|
||||
extcmode_para_addslot(&Channelmode_Table[i], paraslot);
|
||||
|
||||
if (module)
|
||||
{
|
||||
ModuleObject *cmodeobj = MyMallocEx(sizeof(ModuleObject));
|
||||
cmodeobj->object.cmode = &Channelmode_Table[i];
|
||||
cmodeobj->type = MOBJ_CMODE;
|
||||
AddListItem(cmodeobj, module->objects);
|
||||
module->errorcode = MODERR_NOERROR;
|
||||
}
|
||||
return &(Channelmode_Table[i]);
|
||||
}
|
||||
|
||||
void unload_extcmode_commit(Cmode *cmode)
|
||||
{
|
||||
aChannel *chptr;
|
||||
|
||||
if (!cmode)
|
||||
return;
|
||||
|
||||
/* Unset channel mode and send MODE to everyone */
|
||||
|
||||
if (cmode->paracount == 0)
|
||||
{
|
||||
/* Paramless mode, easy */
|
||||
for (chptr = channel; chptr; chptr = chptr->nextch)
|
||||
{
|
||||
if (chptr->mode.extmode && cmode->mode)
|
||||
{
|
||||
MessageTag *mtags = NULL;
|
||||
|
||||
new_message(&me, NULL, &mtags);
|
||||
sendto_channel(chptr, &me, NULL, 0, 0, SEND_LOCAL, mtags,
|
||||
":%s MODE %s -%c",
|
||||
me.name, chptr->chname, cmode->flag);
|
||||
sendto_server(NULL, 0, 0, mtags,
|
||||
":%s MODE %s -%c 0",
|
||||
me.name, chptr->chname, cmode->flag);
|
||||
free_message_tags(mtags);
|
||||
|
||||
chptr->mode.extmode &= ~cmode->mode;
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
/* Parameter mode, more complicated */
|
||||
for (chptr = channel; chptr; chptr = chptr->nextch)
|
||||
{
|
||||
if (chptr->mode.extmode && cmode->mode)
|
||||
{
|
||||
MessageTag *mtags = NULL;
|
||||
|
||||
new_message(&me, NULL, &mtags);
|
||||
if (cmode->unset_with_param)
|
||||
{
|
||||
char *param = cmode->get_param(GETPARASTRUCT(chptr, cmode->flag));
|
||||
sendto_channel(chptr, &me, NULL, 0, 0, SEND_LOCAL, mtags,
|
||||
":%s MODE %s -%c %s",
|
||||
me.name, chptr->chname, cmode->flag, param);
|
||||
sendto_server(NULL, 0, 0, mtags,
|
||||
":%s MODE %s -%c %s 0",
|
||||
me.name, chptr->chname, cmode->flag, param);
|
||||
} else {
|
||||
sendto_channel(chptr, &me, NULL, 0, 0, SEND_LOCAL, mtags,
|
||||
":%s MODE %s -%c",
|
||||
me.name, chptr->chname, cmode->flag);
|
||||
sendto_server(NULL, 0, 0, mtags,
|
||||
":%s MODE %s -%c 0",
|
||||
me.name, chptr->chname, cmode->flag);
|
||||
}
|
||||
free_message_tags(mtags);
|
||||
|
||||
cmode->free_param(GETPARASTRUCT(chptr, cmode->flag));
|
||||
chptr->mode.extmode &= ~cmode->mode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cmode->flag = '\0';
|
||||
extcmode_para_delslot(cmode, cmode->slot);
|
||||
}
|
||||
|
||||
void CmodeDel(Cmode *cmode)
|
||||
{
|
||||
if (loop.ircd_rehashing)
|
||||
cmode->unloaded = 1;
|
||||
else
|
||||
unload_extcmode_commit(cmode);
|
||||
|
||||
if (cmode->owner)
|
||||
{
|
||||
ModuleObject *cmodeobj;
|
||||
for (cmodeobj = cmode->owner->objects; cmodeobj; cmodeobj = cmodeobj->next) {
|
||||
if (cmodeobj->type == MOBJ_CMODE && cmodeobj->object.cmode == cmode) {
|
||||
DelListItem(cmodeobj, cmode->owner->objects);
|
||||
MyFree(cmodeobj);
|
||||
break;
|
||||
}
|
||||
}
|
||||
cmode->owner = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void unload_all_unused_extcmodes(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < EXTCMODETABLESZ; i++)
|
||||
if (Channelmode_Table[i].flag && Channelmode_Table[i].unloaded)
|
||||
{
|
||||
unload_extcmode_commit(&Channelmode_Table[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void extcmode_duplicate_paramlist(void **xi, void **xo)
|
||||
{
|
||||
int i;
|
||||
Cmode *handler;
|
||||
void *inx;
|
||||
|
||||
for (i = 0; i < MAXPARAMMODES; i++)
|
||||
{
|
||||
handler = CMP_GETHANDLERBYSLOT(i);
|
||||
if (!handler)
|
||||
continue; /* nothing there.. */
|
||||
inx = xi[handler->slot]; /* paramter data of input is here */
|
||||
if (!inx)
|
||||
continue; /* not set */
|
||||
xo[handler->slot] = handler->dup_struct(inx); /* call dup_struct with that input and set the output param to that */
|
||||
}
|
||||
}
|
||||
|
||||
void extcmode_free_paramlist(void **ar)
|
||||
{
|
||||
int i;
|
||||
Cmode *handler;
|
||||
|
||||
for (i = 0; i < MAXPARAMMODES; i++)
|
||||
{
|
||||
handler = GETPARAMHANDLERBYSLOT(i);
|
||||
if (!handler)
|
||||
continue; /* nothing here... */
|
||||
handler->free_param(ar[handler->slot]);
|
||||
ar[handler->slot] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
char *cm_getparameter(aChannel *chptr, char mode)
|
||||
{
|
||||
return GETPARAMHANDLERBYLETTER(mode)->get_param(GETPARASTRUCT(chptr, mode));
|
||||
}
|
||||
|
||||
void cm_putparameter(aChannel *chptr, char mode, char *str)
|
||||
{
|
||||
GETPARASTRUCT(chptr, mode) = GETPARAMHANDLERBYLETTER(mode)->put_param(GETPARASTRUCT(chptr, mode), str);
|
||||
}
|
||||
|
||||
void cm_freeparameter(aChannel *chptr, char mode)
|
||||
{
|
||||
GETPARAMHANDLERBYLETTER(mode)->free_param(GETPARASTRUCT(chptr, mode));
|
||||
GETPARASTRUCT(chptr, mode) = NULL;
|
||||
}
|
||||
|
||||
char *cm_getparameter_ex(void **p, char mode)
|
||||
{
|
||||
return GETPARAMHANDLERBYLETTER(mode)->get_param(GETPARASTRUCTEX(p, mode));
|
||||
}
|
||||
|
||||
void cm_putparameter_ex(void **p, char mode, char *str)
|
||||
{
|
||||
GETPARASTRUCTEX(p, mode) = GETPARAMHANDLERBYLETTER(mode)->put_param(GETPARASTRUCTEX(p, mode), str);
|
||||
}
|
||||
|
||||
void cm_freeparameter_ex(void **p, char mode, char *str)
|
||||
{
|
||||
GETPARAMHANDLERBYLETTER(mode)->free_param(GETPARASTRUCTEX(p, mode));
|
||||
GETPARASTRUCTEX(p, mode) = NULL;
|
||||
}
|
||||
|
||||
int extcmode_default_requirechop(aClient *cptr, aChannel *chptr, char mode, char *para, int checkt, int what)
|
||||
{
|
||||
if (IsPerson(cptr) && is_chan_op(cptr, chptr))
|
||||
return EX_ALLOW;
|
||||
if (checkt == EXCHK_ACCESS_ERR) /* can only be due to being halfop */
|
||||
sendnumeric(cptr, ERR_NOTFORHALFOPS, mode);
|
||||
return EX_DENY;
|
||||
}
|
||||
|
||||
int extcmode_default_requirehalfop(aClient *cptr, aChannel *chptr, char mode, char *para, int checkt, int what)
|
||||
{
|
||||
if (IsPerson(cptr) &&
|
||||
(is_chan_op(cptr, chptr) || is_half_op(cptr, chptr)))
|
||||
return EX_ALLOW;
|
||||
return EX_DENY;
|
||||
}
|
||||
|
||||
int module_has_extcmode_param_mode(Module *mod)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (i < EXTCMODETABLESZ)
|
||||
{
|
||||
if ((Channelmode_Table[i].flag) &&
|
||||
(Channelmode_Table[i].owner == mod) &&
|
||||
(Channelmode_Table[i].paracount))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user