X-Git-Url: https://jfr.im/git/irc/rqf/shadowircd.git/blobdiff_plain/b869e117f01851f05ff6d02b65b2719e829057a7..d3b90aaad30cb5d29ffdb0dab22b8ced5254db31:/src/chmode.c diff --git a/src/chmode.c b/src/chmode.c index f6c3934..e8494cd 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,16 @@ chm_simple(struct Client *source_p, struct Channel *chptr, } else if((dir == MODE_DEL) && (chptr->mode.mode & mode_type)) { + /* cleanup KICKNOREJOIN metadata on -J */ + if(c == 'J') + { + DICTIONARY_FOREACH(md, &iter, chptr->metadata) + { + if(!strcmp(md->name, "KICKNOREJOIN")) + channel_metadata_delete(chptr, md->name, 0); + } + } + chptr->mode.mode &= ~mode_type; mode_changes[mode_count].letter = c; @@ -587,6 +600,59 @@ chm_orphaned(struct Client *source_p, struct Channel *chptr, } } +void +chm_hidden(struct Client *source_p, struct Channel *chptr, + int alevel, int parc, int *parn, + const char **parv, int *errors, int dir, char c, long mode_type) +{ + if(!IsOper(source_p) && !IsServer(source_p)) + { + if(!(*errors & SM_ERR_NOPRIVS)) + sendto_one_numeric(source_p, ERR_NOPRIVILEGES, form_str(ERR_NOPRIVILEGES)); + *errors |= SM_ERR_NOPRIVS; + return; + } + if(MyClient(source_p) && !IsOperAdmin(source_p)) + { + if(!(*errors & SM_ERR_NOPRIVS)) + sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, + source_p->name, "cmodes"); + *errors |= SM_ERR_NOPRIVS; + return; + } + + if(MyClient(source_p) && (++mode_limit_simple > MAXMODES_SIMPLE)) + return; + + /* setting + */ + if((dir == MODE_ADD) && !(chptr->mode.mode & mode_type)) + { + chptr->mode.mode |= mode_type; + + mode_changes[mode_count].letter = c; + mode_changes[mode_count].dir = MODE_ADD; + mode_changes[mode_count].caps = 0; + mode_changes[mode_count].nocaps = 0; + mode_changes[mode_count].id = NULL; + mode_changes[mode_count].mems = ONLY_OPERS; + mode_changes[mode_count].override = 0; + mode_changes[mode_count++].arg = NULL; + } + else if((dir == MODE_DEL) && (chptr->mode.mode & mode_type)) + { + chptr->mode.mode &= ~mode_type; + + mode_changes[mode_count].letter = c; + mode_changes[mode_count].dir = MODE_DEL; + mode_changes[mode_count].caps = 0; + mode_changes[mode_count].nocaps = 0; + mode_changes[mode_count].mems = ONLY_OPERS; + mode_changes[mode_count].id = NULL; + mode_changes[mode_count].override = 0; + mode_changes[mode_count++].arg = NULL; + } +} + void chm_staff(struct Client *source_p, struct Channel *chptr, int alevel, int parc, int *parn, @@ -730,7 +796,12 @@ chm_ban(struct Client *source_p, struct Channel *chptr, mode_type != CHFL_QUIET) { if(IsOverride(source_p)) - override = 1; + { + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, + "%s is overriding modes on %s: (%s list)", + get_oper_name(source_p), chptr->chname, + mode_type == CHFL_INVEX ? "invex" : "exempt"); + } else { @@ -914,8 +985,11 @@ chm_owner(struct Client *source_p, struct Channel *chptr, if(targ_p == source_p) { no_override_deop = 1; + /* Don't reject modes from remote. It desyncs, and this is perfectly + * legitimate from a remote override oper. if(!override) return; + */ } mode_changes[mode_count].letter = c; @@ -1015,8 +1089,11 @@ chm_op(struct Client *source_p, struct Channel *chptr, if(targ_p == source_p) { no_override_deop = 1; + /* Don't reject modes from remote. It desyncs, and this is perfectly + * legitimate from a remote override oper. if(!override) return; + */ } mode_changes[mode_count].letter = c; @@ -1125,8 +1202,11 @@ chm_halfop(struct Client *source_p, struct Channel *chptr, if(targ_p == source_p) { no_override_deop = 1; + /* Don't reject modes from remote. It desyncs, and this is perfectly + * legitimate from a remote override oper. if(!override) return; + */ } mode_changes[mode_count].letter = c; @@ -1731,7 +1811,7 @@ struct ChannelMode chmode_table[256] = {chm_simple, MODE_NOREJOIN }, /* J */ {chm_simple, MODE_NOREPEAT }, /* K */ {chm_staff, MODE_EXLIMIT }, /* L */ - {chm_nosuch, 0 }, /* M */ + {chm_hidden, MODE_NOOPERKICK }, /* M */ {chm_simple, MODE_NONICK }, /* N */ {chm_nosuch, 0 }, /* O */ {chm_staff, MODE_PERMANENT }, /* P */ @@ -1949,6 +2029,7 @@ set_channel_mode(struct Client *client_p, struct Client *source_p, const char *ml = parv[0]; char c; struct Client *fakesource_p; + int flags_list[3] = { ALL_MEMBERS, ONLY_CHANOPS, ONLY_OPERS }; mask_pos = 0; mode_count = 0; @@ -1998,7 +2079,9 @@ set_channel_mode(struct Client *client_p, struct Client *source_p, source_p->name, source_p->username, source_p->host, chptr->chname); - for (override = 0; override < (IsOverride(source_p) ? 2 : 1); ++override) + mlen = 0; + + for (override = 0; override < (IsOverride(source_p) && alevel != CHFL_CHANOP ? 2 : 1); ++override) { int was_on_chan = 0; @@ -2013,7 +2096,7 @@ set_channel_mode(struct Client *client_p, struct Client *source_p, add_user_to_channel(chptr, source_p, CHFL_CHANOP); } - for(j = 0, flags = ALL_MEMBERS; j < 2; j++, flags = ONLY_CHANOPS) + for(j = 0, flags = flags_list[0]; j < 3; j++, flags = flags_list[j]) { cur_len = mlen; mbuf = modebuf + mlen; @@ -2088,16 +2171,29 @@ 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); - } }