X-Git-Url: http://git.pk910.de/?p=ircu2.10.12-pk.git;a=blobdiff_plain;f=ircd%2Fchannel.c;h=aae13e6e595cfd37babb8773212a6bd0f544393c;hp=d481541955530cc2f4fe00a6f446a71b6ff68905;hb=8fc59ec8ed68be82ca9314ac95a093a73623b882;hpb=6606615f1c605c9000f5f0f217a9495a2c4270c3 diff --git a/ircd/channel.c b/ircd/channel.c index d481541..aae13e6 100644 --- a/ircd/channel.c +++ b/ircd/channel.c @@ -1224,34 +1224,6 @@ static void send_ban_list(struct Client* cptr, struct Channel* chptr) send_reply(cptr, RPL_ENDOFBANLIST, chptr->chname); } -/** Remove bells and commas from channel name - * - * @param cn Channel name to clean, modified in place. - */ -void clean_channelname(char *cn) -{ - int i; - - for (i = 0; cn[i]; i++) { - if (i >= IRCD_MIN(CHANNELLEN, feature_int(FEAT_CHANNELLEN)) - || !IsChannelChar(cn[i])) { - cn[i] = '\0'; - return; - } - if (IsChannelLower(cn[i])) { - cn[i] = ToLower(cn[i]); -#ifndef FIXME - /* - * Remove for .08+ - * toupper(0xd0) - */ - if ((unsigned char)(cn[i]) == 0xd0) - cn[i] = (char) 0xf0; -#endif - } - } -} - /** Get a channel block, creating if necessary. * Get Channel block for chname (and allocate a new channel * block, if it didn't exists before). @@ -1986,7 +1958,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; } @@ -2330,15 +2302,41 @@ mode_parse_limit(struct ParseState *state, int *flag_p) } } -/** Helper function to clean key-like parameters. */ -static void -clean_key(char *s) +/** Helper function to validate key-like parameters. + * + * @param[in] state Parse state for feedback to user. + * @param[in] s Key to validate. + * @param[in] command String to pass for need_more_params() command. + * @return Zero on an invalid key, non-zero if the key was okay. + */ +static int +is_clean_key(struct ParseState *state, char *s, char *command) { - int t_len = KEYLEN; + int ii; - while (*s > ' ' && *s != ':' && *s != ',' && t_len--) - s++; - *s = '\0'; + if (s[0] == '\0') { + if (MyUser(state->sptr)) + need_more_params(state->sptr, command); + return 0; + } + else if (s[0] == ':') { + if (MyUser(state->sptr)) + send_reply(state->sptr, ERR_INVALIDKEY, state->chptr->chname); + return 0; + } + for (ii = 0; (ii <= KEYLEN) && (s[ii] != '\0'); ++ii) { + if ((unsigned char)s[ii] <= ' ' || s[ii] == ',') { + if (MyUser(state->sptr)) + send_reply(state->sptr, ERR_INVALIDKEY, state->chptr->chname); + return 0; + } + } + if (ii > KEYLEN) { + if (MyUser(state->sptr)) + send_reply(state->sptr, ERR_INVALIDKEY, state->chptr->chname); + return 0; + } + return 1; } /* @@ -2383,14 +2381,10 @@ mode_parse_key(struct ParseState *state, int *flag_p) state->done |= DONE_KEY_DEL; } - /* clean up the key string */ - clean_key(t_str); - if (!*t_str || *t_str == ':') { /* warn if empty */ - if (MyUser(state->sptr)) - need_more_params(state->sptr, state->dir == MODE_ADD ? "MODE +k" : - "MODE -k"); + /* If the key is invalid, tell the user and bail. */ + if (!is_clean_key(state, t_str, state->dir == MODE_ADD ? "MODE +k" : + "MODE -k")) return; - } if (!state->mbuf) return; @@ -2495,14 +2489,10 @@ mode_parse_upass(struct ParseState *state, int *flag_p) state->done |= DONE_UPASS_DEL; } - /* clean up the upass string */ - clean_key(t_str); - if (!*t_str || *t_str == ':') { /* warn if empty */ - if (MyUser(state->sptr)) - need_more_params(state->sptr, state->dir == MODE_ADD ? "MODE +U" : - "MODE -U"); + /* If the Upass is invalid, tell the user and bail. */ + if (!is_clean_key(state, t_str, state->dir == MODE_ADD ? "MODE +U" : + "MODE -U")) return; - } if (!state->mbuf) return; @@ -2642,14 +2632,10 @@ mode_parse_apass(struct ParseState *state, int *flag_p) state->done |= DONE_APASS_DEL; } - /* clean up the apass string */ - clean_key(t_str); - if (!*t_str || *t_str == ':') { /* warn if empty */ - if (MyUser(state->sptr)) - need_more_params(state->sptr, state->dir == MODE_ADD ? "MODE +A" : - "MODE -A"); + /* If the Apass is invalid, tell the user and bail. */ + if (!is_clean_key(state, t_str, state->dir == MODE_ADD ? "MODE +A" : + "MODE -A")) return; - } if (!state->mbuf) return; @@ -2933,6 +2919,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, @@ -3003,17 +2990,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 */ @@ -3208,10 +3197,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, @@ -3371,7 +3369,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; @@ -3639,3 +3639,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); +}