X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=ircd%2Fchannel.c;h=8ed3eb9c845011f6d3585f54399e02ae6d3b874b;hb=bb32073dacc5af56cf186bcabe562ef068675eb6;hp=d7e3145845d957b00d56e02cf603871dd49d7822;hpb=0609fbdf9b84cdce18fccc77ff1deceb466fad74;p=ircu2.10.12-pk.git diff --git a/ircd/channel.c b/ircd/channel.c index d7e3145..8ed3eb9 100644 --- a/ircd/channel.c +++ b/ircd/channel.c @@ -832,6 +832,8 @@ void channel_modes(struct Client *cptr, char *mbuf, char *pbuf, int buflen, *mbuf++ = 'D'; else if (MyUser(cptr) && (chptr->mode.mode & MODE_WASDELJOINS)) *mbuf++ = 'd'; + if (chptr->mode.mode & MODE_REGISTERED) + *mbuf++ = 'R'; if (chptr->mode.limit) { *mbuf++ = 'l'; ircd_snprintf(0, pbuf, buflen, "%u", chptr->mode.limit); @@ -914,7 +916,7 @@ void send_channel_modes(struct Client *cptr, struct Channel *chptr) int opped_members_index = 0; struct Membership** opped_members = NULL; int last_oplevel = 0; - int feat_oplevels = (chptr->mode.apass[0]) != '\0'; + int send_oplevels = 0; assert(0 != cptr); assert(0 != chptr); @@ -972,6 +974,9 @@ void send_channel_modes(struct Client *cptr, struct Channel *chptr) ++number_of_ops; else opped_members[opped_members_index++] = member; + /* We also send oplevels if anyone is below the weakest level. */ + if (OpLevel(member) < MAXOPLEVEL) + send_oplevels = 1; } /* Only handle the members with the flags that we are interested in. */ if ((member->status & CHFL_VOICED_OR_OPPED) == current_flags[flag_cnt]) @@ -1012,7 +1017,7 @@ void send_channel_modes(struct Client *cptr, struct Channel *chptr) if (IsChanOp(member)) /* flag_cnt == 2 or 3 */ { /* append the absolute value of the oplevel */ - if (feat_oplevels) + if (send_oplevels) loc += ircd_snprintf(0, tbuf + loc, sizeof(tbuf) - loc, "%u", last_oplevel = member->oplevel); else tbuf[loc++] = 'o'; @@ -1021,7 +1026,7 @@ void send_channel_modes(struct Client *cptr, struct Channel *chptr) msgq_append(&me, mb, tbuf); new_mode = 0; } - else if (feat_oplevels && flag_cnt > 1 && last_oplevel != member->oplevel) + else if (send_oplevels && flag_cnt > 1 && last_oplevel != member->oplevel) { /* * This can't be the first member of a (continued) BURST @@ -1537,6 +1542,7 @@ modebuf_flush_int(struct ModeBuf *mbuf, int all) MODE_NOPRIVMSGS, 'n', MODE_REGONLY, 'r', MODE_DELJOINS, 'D', + MODE_REGISTERED, 'R', /* MODE_KEY, 'k', */ /* MODE_BAN, 'b', */ MODE_LIMIT, 'l', @@ -1806,8 +1812,7 @@ modebuf_flush_int(struct ModeBuf *mbuf, int all) } /* if we're changing oplevels and we know the oplevel, pass it on */ - if (mbuf->mb_channel->mode.apass[0] - && (MB_TYPE(mbuf, i) & MODE_CHANOP) + if ((MB_TYPE(mbuf, i) & MODE_CHANOP) && MB_OPLEVEL(mbuf, i) < MAXOPLEVEL) *strptr_i += ircd_snprintf(0, strptr + *strptr_i, BUFSIZE - *strptr_i, " %s%s:%d", @@ -1951,7 +1956,7 @@ modebuf_mode(struct ModeBuf *mbuf, unsigned int mode) mode &= (MODE_ADD | MODE_DEL | MODE_PRIVATE | MODE_SECRET | MODE_MODERATED | MODE_TOPICLIMIT | MODE_INVITEONLY | MODE_NOPRIVMSGS | MODE_REGONLY | - MODE_DELJOINS | MODE_WASDELJOINS); + MODE_DELJOINS | MODE_WASDELJOINS | MODE_REGISTERED); if (!(mode & ~(MODE_ADD | MODE_DEL))) /* don't add empty modes... */ return; @@ -1981,7 +1986,7 @@ modebuf_mode_uint(struct ModeBuf *mbuf, unsigned int mode, unsigned int uint) assert(0 != mbuf); assert(0 != (mode & (MODE_ADD | MODE_DEL))); - if (mode == (MODE_LIMIT | ((mbuf->mb_dest & MODEBUF_DEST_BOUNCE) ? MODE_ADD : MODE_DEL))) { + if (mode == (MODE_LIMIT | MODE_DEL)) { mbuf->mb_rem |= mode; return; } @@ -2047,6 +2052,20 @@ modebuf_mode_client(struct ModeBuf *mbuf, unsigned int mode, modebuf_flush_int(mbuf, 0); } +/** Check a channel for join-delayed members. + * @param[in] chan Channel to search. + * @return Non-zero if any members are join-delayed; false if none are. + */ +static int +find_delayed_joins(const struct Channel *chan) +{ + const struct Membership *memb; + for (memb = chan->members; memb; memb = memb->next_member) + if (IsDelayedJoin(memb)) + return 1; + return 0; +} + /** The exported binding for modebuf_flush() * * @param mbuf The mode buffer to flush. @@ -2056,19 +2075,22 @@ modebuf_mode_client(struct ModeBuf *mbuf, unsigned int mode, int modebuf_flush(struct ModeBuf *mbuf) { - struct Membership *memb; - - /* Check if MODE_WASDELJOINS should be set */ - if (!(mbuf->mb_channel->mode.mode & (MODE_DELJOINS | MODE_WASDELJOINS)) - && (mbuf->mb_rem & MODE_DELJOINS)) { - for (memb = mbuf->mb_channel->members; memb; memb = memb->next_member) { - if (IsDelayedJoin(memb)) { - mbuf->mb_channel->mode.mode |= MODE_WASDELJOINS; - mbuf->mb_add |= MODE_WASDELJOINS; - mbuf->mb_rem &= ~MODE_WASDELJOINS; - break; - } - } + /* Check if MODE_WASDELJOINS should be set: */ + /* Must be set if going -D and some clients are hidden */ + if ((mbuf->mb_rem & MODE_DELJOINS) + && !(mbuf->mb_channel->mode.mode & (MODE_DELJOINS | MODE_WASDELJOINS)) + && find_delayed_joins(mbuf->mb_channel)) { + mbuf->mb_channel->mode.mode |= MODE_WASDELJOINS; + mbuf->mb_add |= MODE_WASDELJOINS; + mbuf->mb_rem &= ~MODE_WASDELJOINS; + } + /* Must be cleared if +D is set */ + if ((mbuf->mb_add & MODE_DELJOINS) + && ((mbuf->mb_channel->mode.mode & (MODE_WASDELJOINS | MODE_WASDELJOINS)) + == (MODE_WASDELJOINS | MODE_WASDELJOINS))) { + mbuf->mb_channel->mode.mode &= ~MODE_WASDELJOINS; + mbuf->mb_add &= ~MODE_WASDELJOINS; + mbuf->mb_rem |= MODE_WASDELJOINS; } return modebuf_flush_int(mbuf, 1); @@ -2094,6 +2116,7 @@ modebuf_extract(struct ModeBuf *mbuf, char *buf) MODE_KEY, 'k', MODE_APASS, 'A', MODE_UPASS, 'U', + MODE_REGISTERED, 'R', /* MODE_BAN, 'b', */ MODE_LIMIT, 'l', MODE_REGONLY, 'r', @@ -2153,9 +2176,10 @@ modebuf_extract(struct ModeBuf *mbuf, char *buf) return; } -/** Simple function to invalidate bans +/** Simple function to invalidate a channel's ban cache. * - * This function sets all bans as being valid. + * This function marks all members of the channel as being neither + * banned nor banned. * * @param chan The channel to operate on. */ @@ -2184,12 +2208,15 @@ mode_invite_clear(struct Channel *chan) /* What we've done for mode_parse so far... */ #define DONE_LIMIT 0x01 /**< We've set the limit */ -#define DONE_KEY 0x02 /**< We've set the key */ +#define DONE_KEY_ADD 0x02 /**< We've set the key */ #define DONE_BANLIST 0x04 /**< We've sent the ban list */ #define DONE_NOTOPER 0x08 /**< We've sent a "Not oper" error */ #define DONE_BANCLEAN 0x10 /**< We've cleaned bans... */ -#define DONE_UPASS 0x20 /**< We've set user pass */ -#define DONE_APASS 0x40 /**< We've set admin pass */ +#define DONE_UPASS_ADD 0x20 /**< We've set user pass */ +#define DONE_APASS_ADD 0x40 /**< We've set admin pass */ +#define DONE_KEY_DEL 0x80 /**< We've removed the key */ +#define DONE_UPASS_DEL 0x100 /**< We've removed the user pass */ +#define DONE_APASS_DEL 0x200 /**< We've removed the admin pass */ struct ParseState { struct ModeBuf *mbuf; @@ -2342,9 +2369,19 @@ mode_parse_key(struct ParseState *state, int *flag_p) return; } - if (state->done & DONE_KEY) /* allow key to be set only once */ - return; - state->done |= DONE_KEY; + /* allow removing and then adding key, but not adding and then removing */ + if (state->dir == MODE_ADD) + { + if (state->done & DONE_KEY_ADD) + return; + state->done |= DONE_KEY_ADD; + } + else + { + if (state->done & (DONE_KEY_ADD | DONE_KEY_DEL)) + return; + state->done |= DONE_KEY_DEL; + } /* clean up the key string */ clean_key(t_str); @@ -2444,9 +2481,19 @@ mode_parse_upass(struct ParseState *state, int *flag_p) return; } - if (state->done & DONE_UPASS) /* allow upass to be set only once */ - return; - state->done |= DONE_UPASS; + /* allow removing and then adding upass, but not adding and then removing */ + if (state->dir == MODE_ADD) + { + if (state->done & DONE_UPASS_ADD) + return; + state->done |= DONE_UPASS_ADD; + } + else + { + if (state->done & (DONE_UPASS_ADD | DONE_UPASS_DEL)) + return; + state->done |= DONE_UPASS_DEL; + } /* clean up the upass string */ clean_key(t_str); @@ -2581,9 +2628,19 @@ mode_parse_apass(struct ParseState *state, int *flag_p) } } - if (state->done & DONE_APASS) /* allow apass to be set only once */ - return; - state->done |= DONE_APASS; + /* allow removing and then adding apass, but not adding and then removing */ + if (state->dir == MODE_ADD) + { + if (state->done & DONE_APASS_ADD) + return; + state->done |= DONE_APASS_ADD; + } + else + { + if (state->done & (DONE_APASS_ADD | DONE_APASS_DEL)) + return; + state->done |= DONE_APASS_DEL; + } /* clean up the apass string */ clean_key(t_str); @@ -2714,9 +2771,9 @@ int apply_ban(struct Ban **banlist, struct Ban *newban, int do_free) assert(newban->flags & (BAN_ADD|BAN_DEL)); if (newban->flags & BAN_ADD) { size_t totlen = 0; - /* If a less specific entry is found, fail. */ + /* If a less specific *active* entry is found, fail. */ for (ban = *banlist; ban; ban = ban->next) { - if (!bmatch(ban, newban)) { + if (!bmatch(ban, newban) && !(ban->flags & BAN_DEL)) { if (do_free) free_ban(newban); return 1; @@ -3083,8 +3140,8 @@ mode_process_clients(struct ParseState *state) SetOpLevel(member, state->cli_change[i].oplevel); else if (!state->member) SetOpLevel(member, MAXOPLEVEL); - else if (!state->chptr->mode.apass[0] || OpLevel(state->member) == MAXOPLEVEL) - SetOpLevel(member, MAXOPLEVEL); + else if (OpLevel(state->member) >= MAXOPLEVEL) + SetOpLevel(member, OpLevel(state->member)); else SetOpLevel(member, OpLevel(state->member) + 1); } @@ -3125,6 +3182,11 @@ mode_parse_mode(struct ParseState *state, int *flag_p) if (!state->mbuf) return; + /* Local users are not permitted to change registration status */ + if (flag_p[0] == MODE_REGISTERED && !(state->flags & MODE_PARSE_FORCE) && + MyUser(state->sptr)) + return; + if (state->dir == MODE_ADD) { state->add |= flag_p[0]; state->del &= ~flag_p[0]; @@ -3136,10 +3198,6 @@ mode_parse_mode(struct ParseState *state, int *flag_p) state->add &= ~MODE_SECRET; state->del |= MODE_SECRET; } - if (flag_p[0] & MODE_DELJOINS) { - state->add &= ~MODE_WASDELJOINS; - state->del |= MODE_WASDELJOINS; - } } else { state->add &= ~flag_p[0]; state->del |= flag_p[0]; @@ -3172,6 +3230,7 @@ mode_parse(struct ModeBuf *mbuf, struct Client *cptr, struct Client *sptr, MODE_KEY, 'k', MODE_APASS, 'A', MODE_UPASS, 'U', + MODE_REGISTERED, 'R', MODE_BAN, 'b', MODE_LIMIT, 'l', MODE_REGONLY, 'r', @@ -3361,13 +3420,13 @@ mode_parse(struct ModeBuf *mbuf, struct Client *cptr, struct Client *sptr, if (state.chptr->mode.limit && !(state.done & DONE_LIMIT)) modebuf_mode_uint(state.mbuf, MODE_DEL | MODE_LIMIT, state.chptr->mode.limit); - if (*state.chptr->mode.key && !(state.done & DONE_KEY)) + if (*state.chptr->mode.key && !(state.done & DONE_KEY_DEL)) modebuf_mode_string(state.mbuf, MODE_DEL | MODE_KEY, state.chptr->mode.key, 0); - if (*state.chptr->mode.upass && !(state.done & DONE_UPASS)) + if (*state.chptr->mode.upass && !(state.done & DONE_UPASS_DEL)) modebuf_mode_string(state.mbuf, MODE_DEL | MODE_UPASS, state.chptr->mode.upass, 0); - if (*state.chptr->mode.apass && !(state.done & DONE_APASS)) + if (*state.chptr->mode.apass && !(state.done & DONE_APASS_DEL)) modebuf_mode_string(state.mbuf, MODE_DEL | MODE_APASS, state.chptr->mode.apass, 0); } @@ -3574,18 +3633,9 @@ void RevealDelayedJoin(struct Membership *member) void CheckDelayedJoins(struct Channel *chan) { - struct Membership *memb2; - - if (chan->mode.mode & MODE_WASDELJOINS) { - for (memb2=chan->members;memb2;memb2=memb2->next_member) - if (IsDelayedJoin(memb2)) - break; - - if (!memb2) { - /* clear +d */ - chan->mode.mode &= ~MODE_WASDELJOINS; - sendcmdto_channel_butserv_butone(&his, CMD_MODE, chan, NULL, 0, - "%H -d", chan); - } + if ((chan->mode.mode & MODE_WASDELJOINS) && !find_delayed_joins(chan)) { + chan->mode.mode &= ~MODE_WASDELJOINS; + sendcmdto_channel_butserv_butone(&his, CMD_MODE, chan, NULL, 0, + "%H -d", chan); } }