New custom channel mode API allowing reloading such modules.
Additionally, attempting to use too many modes or two times the same letter is now detected and prevented. Modules now request that a channel mode be added/orphaned, instead of ugly manipulation from which that request had to be guessed. Slight changes are needed to modules that provide channel modes. From the old API, one important function has been made static, the other important function has been renamed, so loading old modules should fail safely.
This commit is contained in:
parent
4c3f0955bf
commit
19716b9fd6
7 changed files with 59 additions and 63 deletions
|
@ -17,13 +17,14 @@ mapi_hfn_list_av1 adminonly_hfnlist[] = {
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static unsigned int mymode;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_modinit(void)
|
_modinit(void)
|
||||||
{
|
{
|
||||||
chmode_table['A'].mode_type = find_cflag_slot();
|
mymode = cflag_add('A', chm_staff);
|
||||||
chmode_table['A'].set_func = chm_staff;
|
if (mymode == 0)
|
||||||
|
return -1;
|
||||||
construct_noparam_modes();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -31,9 +32,7 @@ _modinit(void)
|
||||||
static void
|
static void
|
||||||
_moddeinit(void)
|
_moddeinit(void)
|
||||||
{
|
{
|
||||||
chmode_table['A'].mode_type = 0;
|
cflag_orphan('A');
|
||||||
|
|
||||||
construct_noparam_modes();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DECLARE_MODULE_AV1(chm_adminonly, _modinit, _moddeinit, NULL, NULL, adminonly_hfnlist, "$Revision$");
|
DECLARE_MODULE_AV1(chm_adminonly, _modinit, _moddeinit, NULL, NULL, adminonly_hfnlist, "$Revision$");
|
||||||
|
@ -44,7 +43,7 @@ h_can_join(hook_data_channel *data)
|
||||||
struct Client *source_p = data->client;
|
struct Client *source_p = data->client;
|
||||||
struct Channel *chptr = data->chptr;
|
struct Channel *chptr = data->chptr;
|
||||||
|
|
||||||
if((chptr->mode.mode & chmode_flags['A']) && !IsAdmin(source_p)) {
|
if((chptr->mode.mode & mymode) && !IsAdmin(source_p)) {
|
||||||
sendto_one_numeric(source_p, 519, "%s :Cannot join channel (+A) - you are not an IRC server administrator", chptr->chname);
|
sendto_one_numeric(source_p, 519, "%s :Cannot join channel (+A) - you are not an IRC server administrator", chptr->chname);
|
||||||
data->approved = ERR_CUSTOM;
|
data->approved = ERR_CUSTOM;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ mapi_hfn_list_av1 operonly_hfnlist[] = {
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static unsigned int mymode;
|
||||||
|
|
||||||
/* This is a simple example of how to use dynamic channel modes.
|
/* This is a simple example of how to use dynamic channel modes.
|
||||||
* Not tested enough yet, use at own risk.
|
* Not tested enough yet, use at own risk.
|
||||||
|
@ -26,27 +26,18 @@ mapi_hfn_list_av1 operonly_hfnlist[] = {
|
||||||
static int
|
static int
|
||||||
_modinit(void)
|
_modinit(void)
|
||||||
{
|
{
|
||||||
/* add the channel mode to the available slot */
|
mymode = cflag_add('O', chm_staff);
|
||||||
chmode_table['O'].mode_type = find_cflag_slot();
|
if (mymode == 0)
|
||||||
chmode_table['O'].set_func = chm_staff;
|
return -1;
|
||||||
|
|
||||||
construct_noparam_modes();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Well, the first ugly thing is that we changle chmode_table in _modinit
|
|
||||||
* and chmode_flags in _moddeinit (different arrays) - must be fixed.
|
|
||||||
* -- dwr
|
|
||||||
*/
|
|
||||||
static void
|
static void
|
||||||
_moddeinit(void)
|
_moddeinit(void)
|
||||||
{
|
{
|
||||||
/* disable the channel mode and remove it from the available list */
|
cflag_orphan('O');
|
||||||
chmode_table['O'].mode_type = 0;
|
|
||||||
|
|
||||||
construct_noparam_modes();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DECLARE_MODULE_AV1(chm_operonly, _modinit, _moddeinit, NULL, NULL, operonly_hfnlist, "$Revision$");
|
DECLARE_MODULE_AV1(chm_operonly, _modinit, _moddeinit, NULL, NULL, operonly_hfnlist, "$Revision$");
|
||||||
|
@ -57,7 +48,7 @@ h_can_join(hook_data_channel *data)
|
||||||
struct Client *source_p = data->client;
|
struct Client *source_p = data->client;
|
||||||
struct Channel *chptr = data->chptr;
|
struct Channel *chptr = data->chptr;
|
||||||
|
|
||||||
if((chptr->mode.mode & chmode_flags['O']) && !IsOper(source_p)) {
|
if((chptr->mode.mode & mymode) && !IsOper(source_p)) {
|
||||||
sendto_one_numeric(source_p, 520, "%s :Cannot join channel (+O) - you are not an IRC operator", chptr->chname);
|
sendto_one_numeric(source_p, 520, "%s :Cannot join channel (+O) - you are not an IRC operator", chptr->chname);
|
||||||
data->approved = ERR_CUSTOM;
|
data->approved = ERR_CUSTOM;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,13 +17,14 @@ mapi_hfn_list_av1 sslonly_hfnlist[] = {
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static unsigned int mymode;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_modinit(void)
|
_modinit(void)
|
||||||
{
|
{
|
||||||
chmode_table['S'].mode_type = find_cflag_slot();
|
mymode = cflag_add('S', chm_simple);
|
||||||
chmode_table['S'].set_func = chm_simple;
|
if (mymode == 0)
|
||||||
|
return -1;
|
||||||
construct_noparam_modes();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -32,9 +33,7 @@ _modinit(void)
|
||||||
static void
|
static void
|
||||||
_moddeinit(void)
|
_moddeinit(void)
|
||||||
{
|
{
|
||||||
chmode_table['S'].mode_type = 0;
|
cflag_orphan('S');
|
||||||
|
|
||||||
construct_noparam_modes();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DECLARE_MODULE_AV1(chm_sslonly, _modinit, _moddeinit, NULL, NULL, sslonly_hfnlist, "$Revision$");
|
DECLARE_MODULE_AV1(chm_sslonly, _modinit, _moddeinit, NULL, NULL, sslonly_hfnlist, "$Revision$");
|
||||||
|
@ -45,7 +44,7 @@ h_can_join(hook_data_channel *data)
|
||||||
struct Client *source_p = data->client;
|
struct Client *source_p = data->client;
|
||||||
struct Channel *chptr = data->chptr;
|
struct Channel *chptr = data->chptr;
|
||||||
|
|
||||||
if((chptr->mode.mode & chmode_flags['S']) && !IsSSLClient(source_p)) {
|
if((chptr->mode.mode & mymode) && !IsSSLClient(source_p)) {
|
||||||
sendto_one_notice(source_p, ":Only users using SSL could join this channel!");
|
sendto_one_notice(source_p, ":Only users using SSL could join this channel!");
|
||||||
data->approved = ERR_CUSTOM;
|
data->approved = ERR_CUSTOM;
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,11 +126,13 @@ struct ChCapCombo
|
||||||
int cap_no;
|
int cap_no;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef void (*ChannelModeFunc)(struct Client *source_p, struct Channel *chptr,
|
||||||
|
int alevel, int parc, int *parn,
|
||||||
|
const char **parv, int *errors, int dir, char c, long mode_type);
|
||||||
|
|
||||||
struct ChannelMode
|
struct ChannelMode
|
||||||
{
|
{
|
||||||
void (*set_func) (struct Client * source_p, struct Channel * chptr,
|
ChannelModeFunc set_func;
|
||||||
int alevel, int parc, int *parn,
|
|
||||||
const char **parv, int *errors, int dir, char c, long mode_type);
|
|
||||||
long mode_type;
|
long mode_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -73,9 +73,9 @@ extern void chm_voice(struct Client *source_p, struct Channel *chptr,
|
||||||
int alevel, int parc, int *parn,
|
int alevel, int parc, int *parn,
|
||||||
const char **parv, int *errors, int dir, char c, long mode_type);
|
const char **parv, int *errors, int dir, char c, long mode_type);
|
||||||
|
|
||||||
extern void construct_noparam_modes(void);
|
extern unsigned int cflag_add(char c, ChannelModeFunc function);
|
||||||
extern void find_orphaned_cflags(void);
|
extern void cflag_orphan(char c);
|
||||||
extern unsigned int find_cflag_slot(void);
|
extern void construct_cflags_strings(void);
|
||||||
extern char cflagsbuf[256];
|
extern char cflagsbuf[256];
|
||||||
extern char cflagsmyinfo[256];
|
extern char cflagsmyinfo[256];
|
||||||
|
|
||||||
|
|
49
src/chmode.c
49
src/chmode.c
|
@ -72,12 +72,11 @@ int chmode_flags[256];
|
||||||
|
|
||||||
/* OPTIMIZE ME! -- dwr */
|
/* OPTIMIZE ME! -- dwr */
|
||||||
void
|
void
|
||||||
construct_noparam_modes(void)
|
construct_cflags_strings(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
char *ptr = cflagsbuf;
|
char *ptr = cflagsbuf;
|
||||||
char *ptr2 = cflagsmyinfo;
|
char *ptr2 = cflagsmyinfo;
|
||||||
static int prev_chmode_flags[256];
|
|
||||||
|
|
||||||
*ptr = '\0';
|
*ptr = '\0';
|
||||||
*ptr2 = '\0';
|
*ptr2 = '\0';
|
||||||
|
@ -99,22 +98,6 @@ construct_noparam_modes(void)
|
||||||
chmode_flags[i] = 0;
|
chmode_flags[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prev_chmode_flags[i] != 0 && prev_chmode_flags[i] != chmode_flags[i])
|
|
||||||
{
|
|
||||||
if (chmode_flags[i] == 0)
|
|
||||||
{
|
|
||||||
chmode_table[i].set_func = chm_orphaned;
|
|
||||||
sendto_realops_snomask(SNO_DEBUG, L_ALL, "Cmode +%c is now orphaned", i);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sendto_realops_snomask(SNO_DEBUG, L_ALL, "Orphaned cmode +%c is picked up by module", i);
|
|
||||||
}
|
|
||||||
chmode_flags[i] = prev_chmode_flags[i];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
prev_chmode_flags[i] = chmode_flags[i];
|
|
||||||
|
|
||||||
switch (chmode_flags[i])
|
switch (chmode_flags[i])
|
||||||
{
|
{
|
||||||
case MODE_EXLIMIT:
|
case MODE_EXLIMIT:
|
||||||
|
@ -158,7 +141,7 @@ construct_noparam_modes(void)
|
||||||
* 0 if no cflags are available
|
* 0 if no cflags are available
|
||||||
* side effects - NONE
|
* side effects - NONE
|
||||||
*/
|
*/
|
||||||
unsigned int
|
static unsigned int
|
||||||
find_cflag_slot(void)
|
find_cflag_slot(void)
|
||||||
{
|
{
|
||||||
unsigned int all_cflags = 0, my_cflag = 0, i;
|
unsigned int all_cflags = 0, my_cflag = 0, i;
|
||||||
|
@ -172,6 +155,34 @@ find_cflag_slot(void)
|
||||||
return my_cflag;
|
return my_cflag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
cflag_add(char c_, ChannelModeFunc function)
|
||||||
|
{
|
||||||
|
int c = (unsigned char)c_;
|
||||||
|
|
||||||
|
if (chmode_table[c].set_func != chm_nosuch &&
|
||||||
|
chmode_table[c].set_func != chm_orphaned)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (chmode_table[c].set_func == chm_nosuch)
|
||||||
|
chmode_table[c].mode_type = find_cflag_slot();
|
||||||
|
if (chmode_table[c].mode_type == 0)
|
||||||
|
return 0;
|
||||||
|
chmode_table[c].set_func = function;
|
||||||
|
construct_cflags_strings();
|
||||||
|
return chmode_table[c].mode_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cflag_orphan(char c_)
|
||||||
|
{
|
||||||
|
int c = (unsigned char)c_;
|
||||||
|
|
||||||
|
s_assert(chmode_flags[c] != 0);
|
||||||
|
chmode_table[c].set_func = chm_orphaned;
|
||||||
|
construct_cflags_strings();
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
get_channel_access(struct Client *source_p, struct membership *msptr)
|
get_channel_access(struct Client *source_p, struct membership *msptr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -649,13 +649,7 @@ main(int argc, char *argv[])
|
||||||
init_monitor();
|
init_monitor();
|
||||||
init_isupport();
|
init_isupport();
|
||||||
|
|
||||||
/* noparam core modes have to be initialized before the module
|
construct_cflags_strings();
|
||||||
* system is initialized, otherwise we have a table collision.
|
|
||||||
*
|
|
||||||
* modules call this after they are done initializing...
|
|
||||||
* --nenolod
|
|
||||||
*/
|
|
||||||
construct_noparam_modes();
|
|
||||||
|
|
||||||
load_all_modules(1);
|
load_all_modules(1);
|
||||||
#ifndef STATIC_MODULES
|
#ifndef STATIC_MODULES
|
||||||
|
|
Loading…
Reference in a new issue