diff --git a/include/channel.h b/include/channel.h index d6514d2..5850db2 100644 --- a/include/channel.h +++ b/include/channel.h @@ -295,6 +295,8 @@ void resv_chan_forcepart(const char *name, const char *reason, int temp_time); extern void set_channel_mode(struct Client *client_p, struct Client *source_p, struct Channel *chptr, struct membership *msptr, int parc, const char *parv[]); +extern void set_channel_mlock(struct Client *client_p, struct Client *source_p, + struct Channel *chptr, int parc, const char *parv[]); extern struct ChannelMode chmode_table[256]; diff --git a/modules/core/m_mode.c b/modules/core/m_mode.c index 759a71d..d4b9ef5 100644 --- a/modules/core/m_mode.c +++ b/modules/core/m_mode.c @@ -46,6 +46,7 @@ struct module_modes ModuleModes; static int m_mode(struct Client *, struct Client *, int, const char **); static int ms_mode(struct Client *, struct Client *, int, const char **); static int ms_tmode(struct Client *, struct Client *, int, const char **); +static int ms_mlock(struct Client *, struct Client *, int, const char **); static int ms_bmask(struct Client *, struct Client *, int, const char **); struct Message mode_msgtab = { @@ -56,12 +57,16 @@ struct Message tmode_msgtab = { "TMODE", 0, 0, 0, MFLG_SLOW, {mg_ignore, mg_ignore, {ms_tmode, 4}, {ms_tmode, 4}, mg_ignore, mg_ignore} }; +struct Message mlock_msgtab = { + "MLOCK", 0, 0, 0, MFLG_SLOW, + {mg_ignore, mg_ignore, {ms_mlock, 4}, {ms_mlock, 4}, mg_ignore, mg_ignore} +}; struct Message bmask_msgtab = { "BMASK", 0, 0, 0, MFLG_SLOW, {mg_ignore, mg_ignore, mg_ignore, {ms_bmask, 5}, mg_ignore, mg_ignore} }; -mapi_clist_av1 mode_clist[] = { &mode_msgtab, &tmode_msgtab, &bmask_msgtab, NULL }; +mapi_clist_av1 mode_clist[] = { &mode_msgtab, &tmode_msgtab, &mlock_msgtab, &bmask_msgtab, NULL }; DECLARE_MODULE_AV1(mode, NULL, NULL, mode_clist, NULL, NULL, "$Revision: 1006 $"); @@ -205,6 +210,37 @@ ms_tmode(struct Client *client_p, struct Client *source_p, int parc, const char return 0; } +static int +ms_mlock(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) +{ + struct Channel *chptr = NULL; + + /* Now, try to find the channel in question */ + if(!IsChanPrefix(parv[2][0]) || !check_channel_name(parv[2])) + { + sendto_one_numeric(source_p, ERR_BADCHANNAME, form_str(ERR_BADCHANNAME), parv[2]); + return 0; + } + + chptr = find_channel(parv[2]); + + if(chptr == NULL) + { + sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, + form_str(ERR_NOSUCHCHANNEL), parv[2]); + return 0; + } + + /* TS is higher, drop it. */ + if(atol(parv[1]) > chptr->channelts) + return 0; + + if(IsServer(source_p)) + set_channel_mlock(client_p, source_p, chptr, parc - 3, parv + 3); + + return 0; +} + static int ms_bmask(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { diff --git a/src/chmode.c b/src/chmode.c index 7de7ba9..eaa4eea 100644 --- a/src/chmode.c +++ b/src/chmode.c @@ -2231,3 +2231,50 @@ set_channel_mode(struct Client *client_p, struct Client *source_p, if(MyClient(source_p) || rb_dlink_list_length(&serv_list) > 1) send_cap_mode_changes(client_p, source_p, chptr, mode_changes, mode_count); } + +/* set_channel_mlock() + * + * inputs - client, source, channel, params + * output - + * side effects - channel mlock is changed / MLOCK is propagated + */ +void +set_channel_mlock(struct Client *client_p, struct Client *source_p, + struct Channel *chptr, int parc, const char *parv[]) +{ + int dir = MODE_ADD; + const char *ml = parv[0]; + char c; + + memset(&chptr->mode_lock, '\0', sizeof(struct Mode)); + + for(; (c = *ml) != 0; ml++) + { + switch (c) + { + case '+': + dir = MODE_ADD; + break; + case '-': + dir = MODE_DEL; + break; + default: + if (chmode_table[(unsigned char) c].set_func == chm_simple) + switch(dir) + { + case MODE_ADD: + chptr->mode_lock.mode |= chmode_table[(unsigned char) c].mode_type; + chptr->mode_lock.off_mode &= ~chmode_table[(unsigned char) c].mode_type; + break; + case MODE_DEL: + chptr->mode_lock.off_mode |= chmode_table[(unsigned char) c].mode_type; + chptr->mode_lock.mode &= ~chmode_table[(unsigned char) c].mode_type; + break; + } + break; + } + } + + sendto_server(client_p, NULL, CAP_TS6 | CAP_MLOCK, NOCAPS, ":%s MLOCK %ld %s %s", + source_p->id, (long) chptr->channelts, chptr->chname, channel_mlock(chptr, &me)); +}