diff --git a/include/channel.h b/include/channel.h index 4ce46aa..d471e6c 100644 --- a/include/channel.h +++ b/include/channel.h @@ -38,7 +38,6 @@ struct Client; struct Mode { unsigned int mode; - unsigned int off_mode; int limit; char key[KEYLEN]; unsigned int join_num; @@ -51,7 +50,7 @@ struct Channel { rb_dlink_node node; struct Mode mode; - struct Mode mode_lock; + char *mode_lock; char *topic; char *topic_info; time_t topic_time; @@ -294,7 +293,7 @@ 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[]); + struct Channel *chptr, const char *newmlock); extern struct ChannelMode chmode_table[256]; diff --git a/modules/core/m_mode.c b/modules/core/m_mode.c index d4b9ef5..5549203 100644 --- a/modules/core/m_mode.c +++ b/modules/core/m_mode.c @@ -236,7 +236,7 @@ ms_mlock(struct Client *client_p, struct Client *source_p, int parc, const char return 0; if(IsServer(source_p)) - set_channel_mlock(client_p, source_p, chptr, parc - 3, parv + 3); + set_channel_mlock(client_p, source_p, chptr, parv[3]); return 0; } diff --git a/src/channel.c b/src/channel.c index af30d4e..9cb71e8 100644 --- a/src/channel.c +++ b/src/channel.c @@ -142,6 +142,7 @@ free_channel(struct Channel *chptr) { channel_metadata_clear(chptr); rb_free(chptr->chname); + rb_free(chptr->mode_lock); rb_bh_free(channel_heap, chptr); } diff --git a/src/chmode.c b/src/chmode.c index dbf47f6..042fbea 100644 --- a/src/chmode.c +++ b/src/chmode.c @@ -530,7 +530,7 @@ chm_simple(struct Client *source_p, struct Channel *chptr, return; /* setting + */ - if((dir == MODE_ADD) && !(chptr->mode.mode & mode_type) && !(chptr->mode_lock.off_mode & mode_type)) + if((dir == MODE_ADD) && !(chptr->mode.mode & mode_type)) { /* if +f is disabled, ignore an attempt to set +QF locally */ if(!ModuleModes.MODE_FORWARD && MyClient(source_p) && @@ -595,7 +595,7 @@ chm_orphaned(struct Client *source_p, struct Channel *chptr, mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count++].arg = NULL; } - else if((dir == MODE_DEL) && (chptr->mode.mode & mode_type) && !(chptr->mode_lock.mode & mode_type)) + else if((dir == MODE_DEL) && (chptr->mode.mode & mode_type)) { chptr->mode.mode &= ~mode_type; @@ -2084,6 +2084,9 @@ set_channel_mode(struct Client *client_p, struct Client *source_p, dir = MODE_QUERY; break; default: + /* If this mode char is locked, don't allow local users to change it. */ + if (MyClient(source_p) && chptr->mode_lock && strchr(chptr->mode_lock, c)) + continue; chmode_table[(unsigned char) c].set_func(fakesource_p, chptr, alevel, parc, &parn, parv, &errors, dir, c, @@ -2240,41 +2243,11 @@ set_channel_mode(struct Client *client_p, struct Client *source_p, */ void set_channel_mlock(struct Client *client_p, struct Client *source_p, - struct Channel *chptr, int parc, const char *parv[]) + struct Channel *chptr, const char *newmlock) { - 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; - } - } + rb_free(chptr->mode_lock); + chptr->mode_lock = rb_strdup(newmlock); 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)); + source_p->id, (long) chptr->channelts, chptr->chname, chptr->mode_lock); }