X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=ircd%2Fchannel.c;h=9c0f192d2a3cd79502fda636e5d7ada15bfaec89;hb=refs%2Fheads%2Fupstream;hp=46fb060de01ad897f2ff9fe682802d434d810531;hpb=53db8a34fb699436ab64a51fe5ac88e88e8c1bec;p=ircu2.10.12-pk.git diff --git a/ircd/channel.c b/ircd/channel.c index 46fb060..9c0f192 100644 --- a/ircd/channel.c +++ b/ircd/channel.c @@ -1489,6 +1489,20 @@ build_string(char *strptr, int *strptr_i, const char *str1, strptr[(*strptr_i)] = '\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; +} + /** Flush out the modes * This is the workhorse of our ModeBuf suite; this actually generates the * output MODE commands, HACK notices, or whatever. It's pretty complicated. @@ -1568,6 +1582,23 @@ modebuf_flush_int(struct ModeBuf *mbuf, int all) else app_source = mbuf->mb_source; + /* 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; + } + + /* +d must be cleared if +D is set */ + if ((mbuf->mb_add & MODE_DELJOINS) + && (mbuf->mb_channel->mode.mode & MODE_WASDELJOINS)) { + mbuf->mb_channel->mode.mode &= ~MODE_WASDELJOINS; + mbuf->mb_add &= ~MODE_WASDELJOINS; + mbuf->mb_rem |= MODE_WASDELJOINS; + } + /* * Account for user we're bouncing; we have to get it in on the first * bounced MODE, or we could have problems @@ -2024,47 +2055,15 @@ 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. - * + * * @see modebuf_flush_int() */ int modebuf_flush(struct ModeBuf *mbuf) { - /* 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); } @@ -2919,6 +2918,7 @@ mode_process_bans(struct ParseState *state) len -= banlen; } else { if (state->flags & MODE_PARSE_SET && MyUser(state->sptr) && + !(state->mbuf->mb_dest & MODEBUF_DEST_OPMODE) && (len > (feature_int(FEAT_AVBANLEN) * feature_int(FEAT_MAXBANS)) || count > feature_int(FEAT_MAXBANS))) { send_reply(state->sptr, ERR_BANLISTFULL, state->chptr->chname, @@ -2989,17 +2989,19 @@ mode_parse_client(struct ParseState *state, int *flag_p) if (colon != NULL) { *colon++ = '\0'; req_oplevel = atoi(colon); - if (!(state->flags & MODE_PARSE_FORCE) + if (*flag_p == CHFL_VOICE || state->dir == MODE_DEL) { + /* Ignore the colon and its argument. */ + } else if (!(state->flags & MODE_PARSE_FORCE) && state->member && (req_oplevel < OpLevel(state->member) || (req_oplevel == OpLevel(state->member) && OpLevel(state->member) < MAXOPLEVEL) - || req_oplevel > MAXOPLEVEL)) + || req_oplevel > MAXOPLEVEL)) { send_reply(state->sptr, ERR_NOTLOWEROPLEVEL, t_str, state->chptr->chname, OpLevel(state->member), req_oplevel, "op", OpLevel(state->member) == req_oplevel ? "the same" : "a higher"); - else if (req_oplevel <= MAXOPLEVEL) + } else if (req_oplevel <= MAXOPLEVEL) oplevel = req_oplevel; } /* find client we're manipulating */ @@ -3194,10 +3196,19 @@ mode_parse_mode(struct ParseState *state, int *flag_p) (state->add & (MODE_SECRET | MODE_PRIVATE))); } -/* +/** * This routine is intended to parse MODE or OPMODE commands and effect the - * changes (or just build the bounce buffer). We pass the starting offset - * as a + * changes (or just build the bounce buffer). + * + * \param[out] mbuf Receives parsed representation of mode change. + * \param[in] cptr Connection that sent the message to this server. + * \param[in] sptr Original source of the message. + * \param[in] chptr Channel whose modes are being changed. + * \param[in] parc Number of valid strings in \a parv. + * \param[in] parv Text arguments representing mode change, with the + * zero'th element containing a string like "+m" or "-o". + * \param[in] flags Set of bitwise MODE_PARSE_* flags. + * \param[in] member If non-null, the channel member attempting to change the modes. */ int mode_parse(struct ModeBuf *mbuf, struct Client *cptr, struct Client *sptr, @@ -3357,7 +3368,9 @@ mode_parse(struct ModeBuf *mbuf, struct Client *cptr, struct Client *sptr, } else { /* Server is desynced; bounce the mode and deop the source * to fix it. */ - state.mbuf->mb_dest &= ~MODEBUF_DEST_CHANNEL; + state.flags &= ~MODE_PARSE_SET; + state.flags |= MODE_PARSE_BOUNCE; + state.mbuf->mb_dest &= ~(MODEBUF_DEST_CHANNEL | MODEBUF_DEST_HACK4); state.mbuf->mb_dest |= MODEBUF_DEST_BOUNCE | MODEBUF_DEST_HACK2; if (!IsServer(state.cptr)) state.mbuf->mb_dest |= MODEBUF_DEST_DEOP; @@ -3625,3 +3638,12 @@ void CheckDelayedJoins(struct Channel *chan) "%H -d", chan); } } + +/** Send a join for the user if (s)he is a hidden member of the channel. + */ +void RevealDelayedJoinIfNeeded(struct Client *sptr, struct Channel *chptr) +{ + struct Membership *member = find_member_link(chptr, sptr); + if (member && IsDelayedJoin(member)) + RevealDelayedJoin(member); +}