* note: it is guaranteed that parv[0]..parv[parc-1] are all
* non-NULL pointers.
*/
-#if 0
-/*
- * No need to include handlers.h here the signatures must match
- * and we don't need to force a rebuild of all the handlers everytime
- * we add a new one to the list. --Bleep
- */
-#include "handlers.h"
-#endif /* 0 */
+#include "config.h"
+
#include "channel.h"
#include "client.h"
#include "gline.h"
#include "hash.h"
#include "ircd.h"
#include "ircd_chattr.h"
+#include "ircd_features.h"
+#include "ircd_log.h"
#include "ircd_reply.h"
#include "ircd_string.h"
#include "msg.h"
#include "s_user.h"
#include "send.h"
-#include <assert.h>
+/* #include <assert.h> -- Now using assert in ircd_log.h */
#include <stdlib.h>
#include <string.h>
-#if !defined(XXX_BOGUS_TEMP_HACK)
-#include "handlers.h" /* m_names */
-#endif
-
/*
* Helper function to find last 0 in a comma-separated list of
* channel names.
joinbuf_init(&part, sptr, cptr, JOINBUF_TYPE_PARTALL,
"Left all channels", 0);
- while ((member = sptr->user->channel))
+ while ((member = cli_user(sptr)->channel))
joinbuf_join(&part, member->channel,
- IsZombie(member) ? CHFL_ZOMBIE : 0);
+ IsZombie(member) ? CHFL_ZOMBIE :
+ IsDelayedJoin(member) ? CHFL_DELAYED :
+ 0);
joinbuf_flush(&part);
struct Channel *chptr;
struct JoinBuf join;
struct JoinBuf create;
-#ifdef BADCHAN
struct Gline *gline;
-#endif
unsigned int flags = 0;
- int i;
+ int i, j, k = 0;
char *p = 0;
char *chanlist;
char *name;
keys = parv[2]; /* remember where keys are */
- parv[2] = 0; /* for call to m_names below */
-
for (name = ircd_strtok(&p, chanlist, ","); name;
name = ircd_strtok(&p, 0, ",")) {
clean_channelname(name);
if (join0(&join, cptr, sptr, name)) /* did client do a JOIN 0? */
continue;
- if (!IsChannelName(name)) { /* bad channel name */
+ if (!IsChannelName(name))
+ {
+ /* bad channel name */
+ send_reply(sptr, ERR_NOSUCHCHANNEL, name);
+ continue;
+ }
+
+ /* This checks if the channel contains control codes and rejects em
+ * until they are gone, then we will do it otherwise - *SOB Mode*
+ */
+ for (k = 0, j = 0; name[j]; j++)
+ if (IsCntrl(name[j]))
+ k++;
+ if (k > 0)
+ {
send_reply(sptr, ERR_NOSUCHCHANNEL, name);
continue;
}
-#ifdef BADCHAN
/* BADCHANed channel */
if ((gline = gline_find(name, GLINE_BADCHAN | GLINE_EXACT)) &&
GlineIsActive(gline) && !IsAnOper(sptr)) {
send_reply(sptr, ERR_BANNEDFROMCHAN, name);
continue;
}
-#endif
- if ((chptr = FindChannel(name))) {
+ if ((chptr = FindChannel(name)))
+ {
if (find_member_link(chptr, sptr))
continue; /* already on channel */
flags = CHFL_DEOPPED;
- } else
- flags = IsModelessChannel(name) ? CHFL_DEOPPED : CHFL_CHANOP;
-
- if (sptr->user->joined >= MAXCHANNELSPERUSER
-#ifdef OPER_NO_CHAN_LIMIT
- /* Opers are allowed to join any number of channels */
- && !IsAnOper(sptr)
-#endif
- ) {
+ }
+ else
+ flags = CHFL_CHANOP;
+
+ /* disallow creating local channels */
+ if ((name[0] == '&') && !chptr && !feature_bool(FEAT_LOCAL_CHANNELS)) {
+ send_reply(sptr, ERR_NOSUCHCHANNEL, name);
+ continue;
+ }
+
+ if (cli_user(sptr)->joined >= feature_int(FEAT_MAXCHANNELSPERUSER) &&
+ !HasPriv(sptr, PRIV_CHAN_LIMIT)) {
send_reply(sptr, ERR_TOOMANYCHANNELS, chptr ? chptr->chname : name);
break; /* no point processing the other channels */
}
if (chptr) {
+ int is_level0_op = 0;
+ if (!BadPtr(keys) && *chptr->mode.apass) {
+ /* Don't use compall for the apass, only a single key is allowed. */
+ if (strcmp(chptr->mode.apass, keys) == 0) {
+ is_level0_op = 1;
+ flags &= ~CHFL_DEOPPED;
+ flags |= CHFL_CHANOP | CHFL_CHANNEL_MANAGER;
+ }
+ else if (*chptr->mode.upass && strcmp(chptr->mode.upass, keys) == 0) {
+ is_level0_op = 1;
+ flags &= ~CHFL_DEOPPED;
+ flags |= CHFL_CHANOP;
+ }
+ }
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 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;
}
-#else
- send_reply(sptr, i, chptr->chname);
- continue;
-#endif
- } /* else if ((i = can_join(sptr, chptr, keys))) { */
+ } /* else if ((i = can_join(sptr, chptr, keys))) */
joinbuf_join(&join, chptr, flags);
} else if (!(chptr = get_channel(sptr, name, CGT_CREATE)))
continue; /* couldn't get channel */
- else if (check_target_limit(sptr, chptr, chptr->chname, 1)) {
+ else if (check_target_limit(sptr, chptr, chptr->chname, 1))
+ {
/* Note: check_target_limit will only ever return 0 here */
- sub1_from_channel(chptr); /* created it... */
+ chptr->members = 0;
+ destruct_channel(chptr); /* created it... */
continue;
- } else
- joinbuf_join(&create, chptr, flags);
+ }
+ else
+ joinbuf_join(&create, chptr, flags | CHFL_CHANNEL_MANAGER);
del_invite(sptr, chptr);
struct Membership *member;
struct Channel *chptr;
struct JoinBuf join;
- unsigned int flags = 0;
+ unsigned int flags;
time_t creation = 0;
char *p = 0;
char *chanlist;
char *name;
- if (IsServer(sptr)) {
- return protocol_violation(sptr,"%s tried to JOIN a channel, duh!", sptr->name);
+ if (IsServer(sptr))
+ {
+ return protocol_violation(cptr,
+ "%s tried to JOIN %s, duh!",
+ cli_name(sptr),
+ (parc < 2 || *parv[1] == '\0') ? "a channel" :
+ parv[1]
+ );
}
if (parc < 2 || *parv[1] == '\0')
for (name = ircd_strtok(&p, chanlist, ","); name;
name = ircd_strtok(&p, 0, ",")) {
- clean_channelname(name);
if (join0(&join, cptr, sptr, name)) /* did client do a JOIN 0? */
continue;
+ if (name[0] == '0' && name[1] == ':')
+ {
+ flags = CHFL_CHANOP | CHFL_CHANNEL_MANAGER;
+ name += 2;
+ }
+ else if (name[0] == '1' && name[1] == ':')
+ {
+ flags = CHFL_CHANOP;
+ name += 2;
+ }
+ else
+ flags = CHFL_DEOPPED;
+
if (IsLocalChannel(name) || !IsChannelName(name))
+ {
+ protocol_violation(cptr, "%s tried to join %s", cli_name(sptr), name);
continue;
+ }
- if ((chptr = FindChannel(name))) {
- if ((member = find_member_link(chptr, sptr))) {
+ if (!(chptr = FindChannel(name)))
+ {
+ /* No channel exists, so create one */
+ if (!(chptr = get_channel(sptr, name, CGT_CREATE)))
+ {
+ protocol_violation(sptr,"couldn't get channel %s for %s",
+ name,cli_name(sptr));
+ continue;
+ }
+ flags |= HasFlag(sptr, FLAG_TS8) ? CHFL_SERVOPOK : 0;
+
+ /* when the network is 2.10.11+ then remove MAGIC_REMOTE_JOIN_TS */
+ chptr->creationtime = creation ? creation : MAGIC_REMOTE_JOIN_TS;
+ }
+ else { /* We have a valid channel? */
+ if ((member = find_member_link(chptr, sptr)))
+ {
+ /* It is impossible to get here --Run */
if (!IsZombie(member)) /* already on channel */
continue;
flags = member->status & (CHFL_DEOPPED | CHFL_SERVOPOK);
remove_user_from_channel(sptr, chptr);
chptr = FindChannel(name);
- } else
- flags = CHFL_DEOPPED | ((sptr->flags & FLAGS_TS8) ? CHFL_SERVOPOK : 0);
- } else {
- flags = CHFL_DEOPPED | ((sptr->flags & FLAGS_TS8) ? CHFL_SERVOPOK : 0);
-
- if ((chptr = get_channel(sptr, name, CGT_CREATE)))
- chptr->creationtime = creation ? creation : MAGIC_REMOTE_JOIN_TS;
+ }
else
- continue; /* couldn't get channel */
+ flags |= HasFlag(sptr, FLAG_TS8) ? CHFL_SERVOPOK : 0;
+ /* Always copy the timestamp when it is older, that is the only way to
+ ensure network-wide synchronization of creation times. */
+ if (creation && creation < chptr->creationtime)
+ chptr->creationtime = creation;
}
joinbuf_join(&join, chptr, flags);