Add CHANNELLEN feature, analogous to NICKLEN feature.
[ircu2.10.12-pk.git] / ircd / m_join.c
index d2bfcfecabce299f1d6b4503f1279bc1f82d306b..469fbd8f0a1ea09a06d14fbf523fb5d4dd1b6fba 100644 (file)
@@ -88,6 +88,7 @@
 #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"
@@ -97,7 +98,7 @@
 #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>
 
@@ -152,7 +153,9 @@ join0(struct JoinBuf *join, struct Client *cptr, struct Client *sptr,
 
   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);
 
@@ -167,7 +170,6 @@ int m_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
   struct Channel *chptr;
   struct JoinBuf join;
   struct JoinBuf create;
-  struct ModeBuf mbuf;
   struct Gline *gline;
   unsigned int flags = 0;
   int i, j, k = 0;
@@ -229,6 +231,12 @@ int m_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
     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);
@@ -238,8 +246,7 @@ int m_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
     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.
-          Test Apass first in case someone set Apass and upass equal. */
+        /* 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;
@@ -295,16 +302,6 @@ int m_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
       } /* else if ((i = can_join(sptr, chptr, keys))) */
 
       joinbuf_join(&join, chptr, flags);
-      if (is_level0_op)
-      {
-       joinbuf_flush(&join);
-       modebuf_init(&mbuf, &me, cptr, chptr,
-           MODEBUF_DEST_CHANNEL |              /* Send mode to channel */
-           MODEBUF_DEST_SERVER);               /* And send it to the other servers */
-       modebuf_mode_client(&mbuf,
-           MODE_ADD | MODE_CHANOP, sptr);      /* Give ops to the level0 op */
-       modebuf_flush(&mbuf);
-      }
     } else if (!(chptr = get_channel(sptr, name, CGT_CREATE)))
       continue; /* couldn't get channel */
     else if (check_target_limit(sptr, chptr, chptr->chname, 1))
@@ -342,7 +339,7 @@ int ms_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
   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;
@@ -370,11 +367,23 @@ int ms_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
 
   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);
@@ -390,9 +399,9 @@ int ms_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
                           name,cli_name(sptr));
        continue;
       }
-      flags = CHFL_DEOPPED | (HasFlag(sptr, FLAG_TS8) ? CHFL_SERVOPOK : 0);
+      flags |= HasFlag(sptr, FLAG_TS8) ? CHFL_SERVOPOK : 0;
 
-      /* when the network is 2.10.11+ then remove MAGIC_REMOTE_JOIN_TS */ 
+      /* 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? */
@@ -407,12 +416,12 @@ int ms_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
        chptr = FindChannel(name);
       }
       else
-        flags = CHFL_DEOPPED | (HasFlag(sptr, FLAG_TS8) ? CHFL_SERVOPOK : 0);
+        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);
   }