X-Git-Url: https://jfr.im/git/irc/rqf/shadowircd.git/blobdiff_plain/3b0e9fa20ed055db5d862caaff4cef4b3b58c0bc..11e91210d712ae0a0418e80f929f2597c454f80b:/src/chmode.c?ds=sidebyside diff --git a/src/chmode.c b/src/chmode.c index 442d6f1..792016a 100644 --- a/src/chmode.c +++ b/src/chmode.c @@ -42,6 +42,7 @@ #include "s_newconf.h" #include "logger.h" #include "chmode.h" +#include "irc_dictionary.h" /* bitmasks for error returns, so we send once per call */ #define SM_ERR_NOTS 0x00000001 /* No TS on channel */ @@ -501,6 +502,8 @@ chm_simple(struct Client *source_p, struct Channel *chptr, { int override = 0; + struct Metadata *md; + struct DictionaryIter iter; if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP) { @@ -540,6 +543,18 @@ chm_simple(struct Client *source_p, struct Channel *chptr, } else if((dir == MODE_DEL) && (chptr->mode.mode & mode_type)) { + /* cleanup metadata when the related mode is removed */ + if(c == 'J') + { + DICTIONARY_FOREACH(md, &iter, chptr->metadata) + { + if(!strcmp(md->value, "KICKNOREJOIN")) + channel_metadata_delete(chptr, md->name, 0); + } + } + if(c == 'K') + channel_metadata_delete(chptr, "NOREPEAT", 0); + chptr->mode.mode &= ~mode_type; mode_changes[mode_count].letter = c; @@ -2066,6 +2081,8 @@ set_channel_mode(struct Client *client_p, struct Client *source_p, source_p->name, source_p->username, source_p->host, chptr->chname); + mlen = 0; + for (override = 0; override < (IsOverride(source_p) && alevel != CHFL_CHANOP ? 2 : 1); ++override) { int was_on_chan = 0; @@ -2093,6 +2110,7 @@ set_channel_mode(struct Client *client_p, struct Client *source_p, for(i = 0; i < mode_count; i++) { if(mode_changes[i].letter == 0 || mode_changes[i].mems != flags) + continue; if(mode_changes[i].override != override) continue; @@ -2111,15 +2129,15 @@ set_channel_mode(struct Client *client_p, struct Client *source_p, * bufsize (4 == +/-,modechar,two spaces) send now. */ if(mode_changes[i].arg != NULL && - ((paracount == MAXMODEPARAMSSERV) || - ((cur_len + paralen + arglen + 4) > (BUFSIZE - 3)))) + ((paracount == MAXMODEPARAMSSERV) || + ((cur_len + paralen + arglen + 4) > (BUFSIZE - 3)))) { *mbuf = '\0'; if(cur_len > mlen) { sendto_channel_local(flags, chptr, "%s%s %s", - cmdbuf, modebuf, parabuf); + cmdbuf, modebuf, parabuf); if(override) sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s is overriding modes on %s: %s %s", @@ -2156,16 +2174,30 @@ set_channel_mode(struct Client *client_p, struct Client *source_p, } } - if(override) + if(paralen && parabuf[paralen - 1] == ' ') + parabuf[paralen - 1] = '\0'; + + *mbuf = '\0'; + if(cur_len > mlen) { - if(!was_on_chan) - remove_user_from_channel(find_channel_membership(chptr, source_p)); - else if (!no_override_deop) - msptr->flags &= ~CHFL_CHANOP; + sendto_channel_local(flags, chptr, "%s%s %s", cmdbuf, modebuf, parabuf); + if(override) + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, + "%s is overriding modes on %s: %s %s", + get_oper_name(source_p), chptr->chname, + modebuf, parabuf); } + } + if(override) + { + if(!was_on_chan) + remove_user_from_channel(find_channel_membership(chptr, source_p)); + else if (!no_override_deop) + msptr->flags &= ~CHFL_CHANOP; + } } + /* only propagate modes originating locally, or if we're hubbing */ if(MyClient(source_p) || rb_dlink_list_length(&serv_list) > 1) send_cap_mode_changes(client_p, source_p, chptr, mode_changes, mode_count); - } }