- continue; /* exceeded target limit */
- else if (!is_level0_op && (i = can_join(sptr, chptr, keys))) {
- if (i > MAGIC_OPER_OVERRIDE)
- { /* oper overrode mode */
- switch (i - MAGIC_OPER_OVERRIDE)
- {
- case ERR_CHANNELISFULL: /* figure out which mode */
- i = 'l';
- break;
-
- case ERR_INVITEONLYCHAN:
- i = 'i';
- break;
-
- case ERR_BANNEDFROMCHAN:
- i = 'b';
- break;
-
- case ERR_BADCHANNELKEY:
- i = 'k';
- break;
-
- case ERR_NEEDREGGEDNICK:
- i = 'r';
- break;
-
- default:
- i = '?';
- break;
- }
-
- /* send accountability notice */
- sendto_opmask_butone(0, SNO_HACK4, "OPER JOIN: %C JOIN %H "
- "(overriding +%c)", sptr, chptr, i);
- }
- else
- {
- send_reply(sptr, i, chptr->chname);
+ continue;
+
+ /* If we have any more keys, take the first for this channel. */
+ if (!BadPtr(keys)
+ && (keys = strchr(key = keys, ',')))
+ *keys++ = '\0';
+
+ /* Check Apass/Upass -- since we only ever look at a single
+ * "key" per channel now, this hampers brute force attacks. */
+ if (!BadPtr(key) && !strcmp(key, chptr->mode.apass)) {
+ is_level0_op = 1;
+ flags = (flags & ~CHFL_DEOPPED) | CHFL_CHANOP | CHFL_CHANNEL_MANAGER;
+ } else if (!BadPtr(key) && !strcmp(key, chptr->mode.upass)) {
+ is_level0_op = 1;
+ flags = (flags & ~CHFL_DEOPPED) | CHFL_CHANOP;
+ } else if (IsInvited(sptr, chptr)) {
+ /* Invites bypass these other checks. */
+ } else if (chptr->mode.mode & MODE_INVITEONLY)
+ err = ERR_INVITEONLYCHAN;
+ else if (chptr->mode.limit && (chptr->users >= chptr->mode.limit))
+ err = ERR_CHANNELISFULL;
+ else if ((chptr->mode.mode & MODE_REGONLY) && !IsAccount(sptr))
+ err = ERR_NEEDREGGEDNICK;
+ else if (find_ban(sptr, chptr->banlist))
+ err = ERR_BANNEDFROMCHAN;
+ else if (*chptr->mode.key && strcmp(chptr->mode.key, key))
+ err = ERR_BADCHANNELKEY;
+
+ /* An oper with WALK_LCHAN privilege can join a local channel
+ * he otherwise could not join by using "OVERRIDE" as the key.
+ * This will generate a HACK(4) notice, but fails if the oper
+ * could normally join the channel. */
+ if (IsLocalChannel(chptr->chname)
+ && HasPriv(sptr, PRIV_WALK_LCHAN)
+ && !is_level0_op
+ && !BadPtr(key)
+ && !strcmp("OVERRIDE", key))
+ {
+ switch (err) {
+ case 0:
+ send_reply(sptr, ERR_DONTCHEAT, chptr->chname);