diff --git a/include/channel.h b/include/channel.h index e37dd3ae..090f7659 100644 --- a/include/channel.h +++ b/include/channel.h @@ -259,6 +259,8 @@ extern void send_cap_mode_changes(struct Client *client_p, struct Client *source 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 42df7ed2..219b031c 100644 --- a/modules/core/m_mode.c +++ b/modules/core/m_mode.c @@ -45,6 +45,7 @@ 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 = { @@ -55,12 +56,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 $"); @@ -204,6 +209,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/channel.c b/src/channel.c index 3b0516bd..7483b6e5 100644 --- a/src/channel.c +++ b/src/channel.c @@ -1122,7 +1122,7 @@ channel_modes_real(struct Channel *chptr, struct Mode *mode, struct Client *clie if(pbuf > buf2 || !IsClient(client_p) || IsMember(client_p, chptr)) pbuf += rb_sprintf(pbuf, " %d:%d", mode->join_num, - mode->oin_time); + mode->join_time); } if(*mode->forward && (ConfigChannel.use_forward || !IsClient(client_p))) diff --git a/src/chmode.c b/src/chmode.c index c9069f38..68edd05b 100644 --- a/src/chmode.c +++ b/src/chmode.c @@ -1748,3 +1748,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)); +}