From 24f73c28e4e06495038ab8be1bae06113cda84f3 Mon Sep 17 00:00:00 2001 From: Bram Matthys Date: Sun, 22 Aug 2021 11:45:08 +0200 Subject: [PATCH] Move channel mode +l to module chanmodes/limit (and all the code related to it) --- doc/conf/modules.default.conf | 1 + include/struct.h | 4 +- src/channel.c | 18 --- src/modules/chanmodes/Makefile.in | 6 +- src/modules/chanmodes/limit.c | 197 ++++++++++++++++++++++++++++++ src/modules/invite.c | 2 +- src/modules/join.c | 18 --- src/modules/mode.c | 55 +-------- src/modules/sjoin.c | 15 --- 9 files changed, 209 insertions(+), 107 deletions(-) create mode 100644 src/modules/chanmodes/limit.c diff --git a/doc/conf/modules.default.conf b/doc/conf/modules.default.conf index d80156eae..f3ec7b528 100644 --- a/doc/conf/modules.default.conf +++ b/doc/conf/modules.default.conf @@ -145,6 +145,7 @@ loadmodule "svswatch"; /*** Channel modes ***/ loadmodule "chanmodes/key"; /* +k */ +loadmodule "chanmodes/limit"; /* +l */ loadmodule "chanmodes/inviteonly"; /* +i */ loadmodule "chanmodes/secret"; /* +s */ loadmodule "chanmodes/private"; /* +p */ diff --git a/include/struct.h b/include/struct.h index d56c23995..b418ec780 100644 --- a/include/struct.h +++ b/include/struct.h @@ -1956,7 +1956,6 @@ struct Mode { long mode; /**< Core modes set on this channel (one of MODE_*) */ Cmode_t extmode; /**< Other ("extended") channel modes set on this channel */ void *extmodeparams[MAXPARAMMODES+1]; /**< Parameters for extended channel modes */ - int limit; /**< The +l limit in effect (eg: 40), if any - otherwise 0 */ }; /* flags for Link if used to contain Watch --k4be */ @@ -2120,14 +2119,13 @@ struct Ban { #define MODE_HALFOP 0x0100 #define MODE_EXCEPT 0x0200 #define MODE_BAN 0x0400 -#define MODE_LIMIT 0x4000 #define MODE_RGSTR 0x8000 #define MODE_INVEX 0x8000000 /* * mode flags which take another parameter (With PARAmeterS) */ -#define MODE_WPARAS (MODE_HALFOP|MODE_CHANOP|MODE_VOICE|MODE_CHANOWNER|MODE_CHANADMIN|MODE_BAN|MODE_KEY|MODE_LIMIT|MODE_EXCEPT|MODE_INVEX) +#define MODE_WPARAS (MODE_HALFOP|MODE_CHANOP|MODE_VOICE|MODE_CHANOWNER|MODE_CHANADMIN|MODE_BAN|MODE_KEY|MODE_EXCEPT|MODE_INVEX) /* * Undefined here, these are used in conjunction with the above modes in * the source. diff --git a/src/channel.c b/src/channel.c index c90208a6f..68f93a231 100644 --- a/src/channel.c +++ b/src/channel.c @@ -53,7 +53,6 @@ static mp_pool_t *channel_pool = NULL; * These are +ntmispklr and also the list modes +vhoaq and +beI. */ CoreChannelModeTable corechannelmodetable[] = { - {MODE_LIMIT, 'l', 1, 1}, {MODE_VOICE, 'v', 1, 1}, {MODE_HALFOP, 'h', 0, 1}, {MODE_CHANOP, 'o', 0, 1}, @@ -596,10 +595,6 @@ int has_channel_mode(Channel *channel, char mode) tab++; } - /* Special handling for +l (needed??) */ - if (channel->mode.limit && (mode == 'l')) - return 1; - return 0; /* Not found */ } @@ -682,19 +677,6 @@ void channel_modes(Client *client, char *mbuf, char *pbuf, size_t mbuf_size, siz } } - if (channel->mode.limit) - { - if (mbuf_size) { - *mbuf++ = 'l'; - mbuf_size--; - } - if (ismember) { - ircsnprintf(pbuf, pbuf_size, "%d ", channel->mode.limit); - pbuf_size-=strlen(pbuf); - pbuf+=strlen(pbuf); - } - } - for (i=0; i <= Channelmode_highest; i++) { if (Channelmode_Table[i].flag && diff --git a/src/modules/chanmodes/Makefile.in b/src/modules/chanmodes/Makefile.in index 2892b55e6..66e500f1c 100644 --- a/src/modules/chanmodes/Makefile.in +++ b/src/modules/chanmodes/Makefile.in @@ -32,7 +32,7 @@ INCLUDES = ../../include/channel.h \ ../../include/version.h ../../include/whowas.h R_MODULES= \ - key.so inviteonly.so secret.so private.so \ + key.so limit.so inviteonly.so secret.so private.so \ noexternalmsgs.so \ nocolor.so stripcolor.so issecure.so permanent.so floodprot.so \ noctcp.so link.so censor.so delayjoin.so noknock.so noinvite.so operonly.so \ @@ -58,6 +58,10 @@ key.so: key.c $(INCLUDES) $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \ -o key.so key.c +limit.so: limit.c $(INCLUDES) + $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \ + -o limit.so limit.c + inviteonly.so: inviteonly.c $(INCLUDES) $(CC) $(CFLAGS) $(MODULEFLAGS) -DDYNAMIC_LINKING \ -o inviteonly.so inviteonly.c diff --git a/src/modules/chanmodes/limit.c b/src/modules/chanmodes/limit.c new file mode 100644 index 000000000..123b6b0de --- /dev/null +++ b/src/modules/chanmodes/limit.c @@ -0,0 +1,197 @@ +/* + * Channel Mode +l + * (C) Copyright 2021 Syzop and the UnrealIRCd team + * + * 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" + +ModuleHeader MOD_HEADER + = { + "chanmodes/limit", + "6.0", + "Channel Mode +l", + "UnrealIRCd Team", + "unrealircd-6", + }; + +typedef struct ChannelLimit ChannelLimit; +struct ChannelLimit { + int limit; +}; + +/* Global variables */ +ModDataInfo *mdlimit = NULL; +Cmode_t EXTMODE_LIMIT = 0L; + +#define IsLimit(x) ((x)->mode.extmode & EXTMODE_LIMIT) + +/* Just for buffers, nothing else */ +#define LIMITLEN 32 + +/* Forward declarations */ +int limit_can_join(Client *client, Channel *channel, char *key, char *parv[]); +int cmode_limit_is_ok(Client *client, Channel *channel, char mode, char *para, int type, int what); +void *cmode_limit_put_param(void *r_in, char *param); +char *cmode_limit_get_param(void *r_in); +char *cmode_limit_conv_param(char *param_in, Client *client, Channel *channel); +void cmode_limit_free_param(void *r); +void *cmode_limit_dup_struct(void *r_in); +int cmode_limit_sjoin_check(Channel *channel, void *ourx, void *theirx); +int transform_channel_limit(char *param); + +MOD_INIT() +{ + CmodeInfo creq; + ModDataInfo mreq; + + MARK_AS_OFFICIAL_MODULE(modinfo); + + memset(&creq, 0, sizeof(creq)); + creq.paracount = 1; + creq.is_ok = cmode_limit_is_ok; + creq.flag = 'l'; + creq.put_param = cmode_limit_put_param; + creq.get_param = cmode_limit_get_param; + creq.conv_param = cmode_limit_conv_param; + creq.free_param = cmode_limit_free_param; + creq.dup_struct = cmode_limit_dup_struct; + creq.sjoin_check = cmode_limit_sjoin_check; + CmodeAdd(modinfo->handle, creq, &EXTMODE_LIMIT); + + HookAdd(modinfo->handle, HOOKTYPE_CAN_JOIN, 0, limit_can_join); + return MOD_SUCCESS; +} + +MOD_LOAD() +{ + return MOD_SUCCESS; +} + +MOD_UNLOAD() +{ + return MOD_SUCCESS; +} + +/** Can the user join the channel? */ +int limit_can_join(Client *client, Channel *channel, char *key, char *parv[]) +{ + ChannelLimit *r = (ChannelLimit *)GETPARASTRUCT(channel, 'l'); + + /* Is the channel +l? */ + if (r && r->limit && (channel->users >= r->limit)) + { + Hook *h; + for (h = Hooks[HOOKTYPE_CAN_JOIN_LIMITEXCEEDED]; h; h = h->next) + { + int i = (*(h->func.intfunc))(client,channel,key,parv); + if (i != 0) + return i; + } + return ERR_CHANNELISFULL; + } + + return 0; +} + +int cmode_limit_is_ok(Client *client, Channel *channel, char mode, char *param, int type, int what) +{ + if ((type == EXCHK_ACCESS) || (type == EXCHK_ACCESS_ERR)) + { + /* Permitted for +hoaq */ + if (IsUser(client) && is_skochanop(client, channel)) + return EX_ALLOW; + return EX_DENY; + } else + if (type == EXCHK_PARAM) + { + /* Actually any value is valid, we just morph it */ + return EX_ALLOW; + } + + /* fallthrough -- should not be used */ + return EX_DENY; +} + +void *cmode_limit_put_param(void *k_in, char *param) +{ + ChannelLimit *fld = (ChannelLimit *)k_in; + + if (!fld) + fld = safe_alloc(sizeof(ChannelLimit)); + + fld->limit = transform_channel_limit(param); + + return fld; +} + +char *cmode_limit_get_param(void *r_in) +{ + ChannelLimit *r = (ChannelLimit *)r_in; + static char retbuf[32]; + + if (!r) + return NULL; + + snprintf(retbuf, sizeof(retbuf), "%d", r->limit); + return retbuf; +} + +char *cmode_limit_conv_param(char *param, Client *client, Channel *channel) +{ + static char retbuf[32]; + int v = transform_channel_limit(param); + snprintf(retbuf, sizeof(retbuf), "%d", v); + return retbuf; +} + +void cmode_limit_free_param(void *r) +{ + safe_free(r); +} + +void *cmode_limit_dup_struct(void *r_in) +{ + ChannelLimit *r = (ChannelLimit *)r_in; + ChannelLimit *w = safe_alloc(sizeof(ChannelLimit)); + + memcpy(w, r, sizeof(ChannelLimit)); + + return (void *)w; +} + +int cmode_limit_sjoin_check(Channel *channel, void *ourx, void *theirx) +{ + ChannelLimit *our = (ChannelLimit *)ourx; + ChannelLimit *their = (ChannelLimit *)theirx; + + if (our->limit == their->limit) + return EXSJ_SAME; + else if (our->limit > their->limit) + return EXSJ_WEWON; + else + return EXSJ_THEYWON; +} + +int transform_channel_limit(char *param) +{ + int v = atoi(param); + if (v <= 0) + v = 1; /* setting +l with a negative number makes no sense */ + if (v > 1000000) + v = 1000000; /* some kind of limit, 1 million (mrah...) */ + return v; +} diff --git a/src/modules/invite.c b/src/modules/invite.c index 273eecaaa..99c3eca4b 100644 --- a/src/modules/invite.c +++ b/src/modules/invite.c @@ -446,7 +446,7 @@ CMD_FUNC(cmd_invite) invite_operoverride_msg(client, channel, "b", "ban"); else if (has_channel_mode(channel, 'i')) invite_operoverride_msg(client, channel, "i", "invite only"); - else if (channel->mode.limit) + else if (has_channel_mode(channel, 'l')) invite_operoverride_msg(client, channel, "l", "user limit"); else if (has_channel_mode(channel, 'k')) invite_operoverride_msg(client, channel, "k", "key"); diff --git a/src/modules/join.c b/src/modules/join.c index 62ad14611..e7df1de95 100644 --- a/src/modules/join.c +++ b/src/modules/join.c @@ -116,24 +116,6 @@ int _can_join(Client *client, Channel *channel, char *key, char *parv[]) if (is_invited(client, channel)) return 0; /* allowed to walk through all the other modes */ - if (channel->users >= channel->mode.limit) - { - /* Hmmm.. don't really like this.. and not at this place */ - - for (h = Hooks[HOOKTYPE_CAN_JOIN_LIMITEXCEEDED]; h; h = h->next) - { - i = (*(h->func.intfunc))(client,channel,key,parv); - if (i != 0) - return i; - } - - /* We later check again for this limit (in case +L was not set) */ - } - - - if ((channel->mode.limit && channel->users >= channel->mode.limit)) - return (ERR_CHANNELISFULL); - if (banned) return (ERR_BANNEDFROMCHAN); diff --git a/src/modules/mode.c b/src/modules/mode.c index c75fead84..55a095f3b 100644 --- a/src/modules/mode.c +++ b/src/modules/mode.c @@ -36,7 +36,7 @@ int do_mode_char(Channel *channel, long modetype, char modechar, char *param, u_int *pcount, char pvar[MAXMODEPARAMS][MODEBUFLEN + 3], long my_access); int do_extmode_char(Channel *channel, Cmode *handler, char *param, u_int what, Client *client, u_int *pcount, char pvar[MAXMODEPARAMS][MODEBUFLEN + 3]); -void make_mode_str(Channel *channel, long oldm, Cmode_t oldem, long oldl, int pcount, +void make_mode_str(Channel *channel, long oldm, Cmode_t oldem, int pcount, char pvar[MAXMODEPARAMS][MODEBUFLEN + 3], char *mode_buf, char *para_buf, size_t mode_buf_size, size_t para_buf_size); @@ -498,7 +498,7 @@ void _do_mode(Channel *channel, Client *client, MessageTag *recv_mtags, int parc * Reconstructs the mode string, to make it look clean. mode_buf will * contain the +x-y stuff, and the parabuf will contain the parameters. */ -void make_mode_str(Channel *channel, long oldm, Cmode_t oldem, long oldl, int pcount, +void make_mode_str(Channel *channel, long oldm, Cmode_t oldem, int pcount, char pvar[MAXMODEPARAMS][MODEBUFLEN + 3], char *mode_buf, char *para_buf, size_t mode_buf_size, size_t para_buf_size) { @@ -592,29 +592,6 @@ void make_mode_str(Channel *channel, long oldm, Cmode_t oldem, long oldl, int pc } *x = '\0'; - /* user limit */ - if (channel->mode.limit != oldl) - { - if (channel->mode.limit == 0) - { - if (what != MODE_DEL) - { - *x++ = '-'; - what = MODE_DEL; - } - *x++ = 'l'; - } - else - { - if (what != MODE_ADD) - { - *x++ = '+'; - what = MODE_ADD; - } - *x++ = 'l'; - ircsnprintf(para_buf, para_buf_size, "%s%d ", para_buf, channel->mode.limit); - } - } /* reconstruct bkov chain */ for (cnt = 0; cnt < pcount; cnt++) { @@ -1003,29 +980,6 @@ process_listmode: (what == MODE_ADD) ? '+' : '-', tc, target->name); (*pcount)++; break; - case MODE_LIMIT: - if (what == MODE_ADD) - { - int v; - REQUIRE_PARAMETER() - v = atoi(param); - if (v < 0) - v = 1; /* setting +l with a negative number makes no sense */ - if (v > 1000000) - v = 1000000; /* some kind of limit, 1 million (mrah...) */ - if (channel->mode.limit == v) - break; - channel->mode.limit = v; - } - else - { - retval = 0; - if (!channel->mode.limit) - break; - channel->mode.limit = 0; - RunHook2(HOOKTYPE_MODECHAR_DEL, channel, (int)modechar); - } - break; case MODE_BAN: REQUIRE_PARAMETER() if (!(tmpstr = mode_ban_handler(client, channel, param, what, EXBTYPE_BAN, &channel->banlist))) @@ -1265,7 +1219,7 @@ void _set_mode(Channel *channel, Client *client, int parc, char *parv[], u_int * int found = 0; int sent_mlock_warning = 0; unsigned int htrig = 0; - long oldm, oldl; + long oldm; int checkrestr = 0, warnrestr = 1; int extm = 1000000; /* (default value not used but stops gcc from complaining) */ Cmode_t oldem; @@ -1274,7 +1228,6 @@ void _set_mode(Channel *channel, Client *client, int parc, char *parv[], u_int * *pcount = 0; oldm = channel->mode.mode; - oldl = channel->mode.limit; oldem = channel->mode.extmode; if (RESTRICT_CHANNELMODES && !ValidatePermissionsForPath("immune:restrict-channelmodes",client,NULL,channel,NULL)) /* "cache" this */ checkrestr = 1; @@ -1398,7 +1351,7 @@ void _set_mode(Channel *channel, Client *client, int parc, char *parv[], u_int * } /* switch(*curchr) */ } /* for loop through mode letters */ - make_mode_str(channel, oldm, oldem, oldl, *pcount, pvar, modebuf, parabuf, sizeof(modebuf), sizeof(parabuf)); + make_mode_str(channel, oldm, oldem, *pcount, pvar, modebuf, parabuf, sizeof(modebuf), sizeof(parabuf)); #ifndef NO_OPEROVERRIDE if ((htrig == 1) && IsUser(client)) diff --git a/src/modules/sjoin.c b/src/modules/sjoin.c index 6bf1077c6..675a9def9 100644 --- a/src/modules/sjoin.c +++ b/src/modules/sjoin.c @@ -707,11 +707,6 @@ getnick: strlcpy(modebuf, "-", sizeof modebuf); parabuf[0] = '\0'; b = 1; - /* however, is this really going to happen at all? may be unneeded */ - if (oldmode.limit && !channel->mode.limit) - { - Addsingle('l'); - } /* First, check if we have something they don't have.. * note that: oldmode.* = us, channel->mode.* = them. @@ -804,16 +799,6 @@ getnick: /* now, if we had diffent para modes - this loop really could be done better, but */ - /* +l (limit) difference? */ - if (oldmode.limit && channel->mode.limit && (oldmode.limit != channel->mode.limit)) - { - channel->mode.limit = MAX(oldmode.limit, channel->mode.limit); - if (oldmode.limit != channel->mode.limit) - { - Addit('l', my_itoa(channel->mode.limit)); - } - } - /* Now, check for any param differences in extended channel modes.. * note that: oldmode.* = us, channel->mode.* = them. * if we win: copy oldmode to channel mode, if they win: send the mode