- if (chptr) {
- if (check_target_limit(sptr, chptr, chptr->chname, 0))
- continue; /* exceeded target limit */
- else if ((i = can_join(sptr, chptr, keys))) {
-#ifdef OPER_WALK_THROUGH_LMODES
- 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;
- }
-
- /* 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;
- }
-#else
- send_reply(sptr, i, chptr->chname);
- continue;
-#endif
- } /* else if ((i = can_join(sptr, chptr, keys))) { */
+ if (!(chptr = FindChannel(name))) {
+ if (((name[0] == '&') && !feature_bool(FEAT_LOCAL_CHANNELS))
+ || strlen(name) > IRCD_MIN(CHANNELLEN, feature_int(FEAT_CHANNELLEN))) {
+ send_reply(sptr, ERR_NOSUCHCHANNEL, name);
+ continue;
+ }
+
+ if (!(chptr = get_channel(sptr, name, CGT_CREATE)))
+ continue;
+
+ /* Try to add the new channel as a recent target for the user. */
+ if (check_target_limit(sptr, chptr, chptr->chname, 0)) {
+ chptr->members = 0;
+ destruct_channel(chptr);
+ continue;
+ }
+
+ joinbuf_join(&create, chptr, CHFL_CHANOP | CHFL_CHANNEL_MANAGER);
+ } else if (find_member_link(chptr, sptr)) {
+ continue; /* already on channel */
+ } else if (check_target_limit(sptr, chptr, chptr->chname, 0)) {
+ continue;
+ } else {
+ int flags = CHFL_DEOPPED;
+ int err = 0;
+
+ /* Check Apass/Upass -- since we only ever look at a single
+ * "key" per channel now, this hampers brute force attacks. */
+ if (key && !strcmp(key, chptr->mode.apass))
+ flags = CHFL_CHANOP | CHFL_CHANNEL_MANAGER;
+ else if (key && !strcmp(key, chptr->mode.upass))
+ flags = CHFL_CHANOP;
+ else if (chptr->users == 0 && !chptr->mode.apass[0]) {
+ /* Joining a zombie channel (zannel): give ops and increment TS. */
+ flags = CHFL_CHANOP;
+ chptr->creationtime++;
+ } 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 && (!key || strcmp(key, chptr->mode.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)
+ && !(flags & CHFL_CHANOP)
+ && key && !strcmp(key, "OVERRIDE"))
+ {
+ switch (err) {
+ case 0:
+ if (strcmp(chptr->mode.key, "OVERRIDE")
+ && strcmp(chptr->mode.apass, "OVERRIDE")
+ && strcmp(chptr->mode.upass, "OVERRIDE")) {
+ send_reply(sptr, ERR_DONTCHEAT, chptr->chname);
+ continue;
+ }
+ break;
+ case ERR_INVITEONLYCHAN: err = 'i'; break;
+ case ERR_CHANNELISFULL: err = 'l'; break;
+ case ERR_BANNEDFROMCHAN: err = 'b'; break;
+ case ERR_BADCHANNELKEY: err = 'k'; break;
+ case ERR_NEEDREGGEDNICK: err = 'r'; break;
+ default: err = '?'; break;
+ }
+ /* send accountability notice */
+ if (err)
+ sendto_opmask_butone(0, SNO_HACK4, "OPER JOIN: %C JOIN %H "
+ "(overriding +%c)", sptr, chptr, err);
+ err = 0;
+ }
+
+ /* Is there some reason the user may not join? */
+ if (err) {
+ switch(err) {
+ case ERR_NEEDREGGEDNICK:
+ send_reply(sptr,
+ ERR_NEEDREGGEDNICK,
+ chptr->chname,
+ feature_str(FEAT_URLREG));
+ break;
+ default:
+ send_reply(sptr, err, chptr->chname);
+ break;
+ }
+ continue;
+ }