- keysOrTS = parv[2]; /* Remember where our keys are or the TS is;
- parv[2] needs to be NULL for the call to
- m_names below -Kev */
- parv[2] = p = NULL;
-
- *jbuf = *mbuf = '\0'; /* clear both join and mode buffers -Kev */
- /*
- * Rebuild list of channels joined to be the actual result of the
- * JOIN. Note that "JOIN 0" is the destructive problem.
- */
- for (name = ircd_strtok(&p, parv[1], ","); name; name = ircd_strtok(&p, NULL, ","))
- {
- size_t len;
- if (MyConnect(sptr))
- clean_channelname(name);
- else if (IsLocalChannel(name))
- continue;
- if (*name == '0' && *(name + 1) == '\0')
- {
- /* Remove the user from all his channels -Kev */
- while ((member = sptr->user->channel))
- {
- chptr = member->channel;
- if (!IsZombie(member))
- sendto_channel_butserv(chptr, sptr, PartFmt2,
- parv[0], chptr->chname, "Left all channels");
- remove_user_from_channel(sptr, chptr);
- }
- /* Just in case */
- *mbuf = *jbuf = '\0';
- mlen = jlen = 0;
- }
- else
- { /* not a /join 0, so treat it as
- a /join #channel -Kev */
- if (!IsChannelName(name))
- {
- if (MyUser(sptr))
- sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], name);
- continue;
- }
-
- if (MyConnect(sptr))
- {
-#ifdef BADCHAN
- if (bad_channel(name) && !IsAnOper(sptr))
- {
- sendto_one(sptr, err_str(ERR_BADCHANNAME), me.name, parv[0], name);
- continue;
- }
-#endif
- /*
- * Local client is first to enter previously nonexistant
- * channel so make them (rightfully) the Channel Operator.
- * This looks kind of ugly because we try to avoid calling the strlen()
- */
- if (ChannelExists(name))
- {
- flags = CHFL_DEOPPED;
- sendcreate = 0;
- }
- else if (strlen(name) > CHANNELLEN)
- {
- *(name + CHANNELLEN) = '\0';
- if (ChannelExists(name))
- {
- flags = CHFL_DEOPPED;
- sendcreate = 0;
- }
- else
- {
- flags = IsModelessChannel(name) ? CHFL_DEOPPED : CHFL_CHANOP;
- sendcreate = 1;
- }
- }
- else
- {
- flags = IsModelessChannel(name) ? CHFL_DEOPPED : CHFL_CHANOP;
- sendcreate = 1;
- }
-
-#ifdef OPER_NO_CHAN_LIMIT
- /*
- * Opers are allowed to join any number of channels
- */
- if (sptr->user->joined >= MAXCHANNELSPERUSER && !IsAnOper(sptr))
-#else
- if (sptr->user->joined >= MAXCHANNELSPERUSER)
-#endif
- {
- chptr = get_channel(sptr, name, CGT_NO_CREATE);
- sendto_one(sptr, err_str(ERR_TOOMANYCHANNELS),
- me.name, parv[0], chptr ? chptr->chname : name);
- /*
- * Can't return, else he won't get on ANY channels!
- * Break out of the for loop instead. -Kev
- */
- break;
- }
- }
- chptr = get_channel(sptr, name, CGT_CREATE);
- if (chptr && (member = find_member_link(chptr, sptr)))
- {
- if (IsZombie(member))
- {
- zombie = 1;
- flags = member->status & (CHFL_DEOPPED | CHFL_SERVOPOK);
- remove_user_from_channel(sptr, chptr);
- chptr = get_channel(sptr, name, CGT_CREATE);
- }
- else
- continue;
- }
- name = chptr->chname;
- if (!chptr->creationtime) /* A remote JOIN created this channel ? */
- chptr->creationtime = MAGIC_REMOTE_JOIN_TS;
- if (parc > 2)
- {
- if (chptr->creationtime == MAGIC_REMOTE_JOIN_TS)
- chptr->creationtime = atoi(keysOrTS);
- else
- parc = 2; /* Don't pass it on */
- }
- if (!zombie)
- {
- if (!MyConnect(sptr))
- flags = CHFL_DEOPPED;
- if (sptr->flags & FLAGS_TS8)
- flags |= CHFL_SERVOPOK;
- }
- if (MyConnect(sptr))
- {
- int created = chptr->users == 0;
- if (check_target_limit(sptr, chptr, chptr->chname, created))
- {
- if (created) /* Did we create the channel? */
- sub1_from_channel(chptr); /* Remove it again! */
- continue;
- }
- if ((i = can_join(sptr, chptr, keysOrTS)))
- {
-#ifdef OPER_WALK_THROUGH_LMODES
- if (i > MAGIC_OPER_OVERRIDE)
- {
- switch(i - MAGIC_OPER_OVERRIDE)
- {
- case ERR_CHANNELISFULL: i = 'l'; break;
- case ERR_INVITEONLYCHAN: i = 'i'; break;
- case ERR_BANNEDFROMCHAN: i = 'b'; break;
- case ERR_BADCHANNELKEY: i = 'k'; break;
- }
- sendto_op_mask(SNO_HACK4,"OPER JOIN: %s JOIN %s (overriding +%c)",sptr->name,chptr->chname,i);
- }
- else
- {
- sendto_one(sptr, err_str(i), me.name, parv[0], chptr->chname);
- continue;
- }
-#else
- sendto_one(sptr, err_str(i), me.name, parv[0], chptr->chname);
- continue;
-#endif
- }
- }
- /*
- * Complete user entry to the new channel (if any)
- */
- add_user_to_channel(chptr, sptr, flags);
-
- /*
- * Notify all other users on the new channel
- */
- sendto_channel_butserv(chptr, sptr, ":%s JOIN :%s", parv[0], name);