]> jfr.im git - solanum.git/blobdiff - modules/core/m_join.c
implement configurable channel modes (closes #31)
[solanum.git] / modules / core / m_join.c
index c7c04b5b6342c5c2f5329589630ab557d5978ab9..b45728e3b97565bdfa349e39cd55519325460f2f 100644 (file)
@@ -41,6 +41,8 @@
 #include "modules.h"
 #include "packet.h"
 #include "chmode.h"
+#include "ratelimit.h"
+#include "s_assert.h"
 
 static int m_join(struct Client *, struct Client *, int, const char **);
 static int ms_join(struct Client *, struct Client *, int, const char **);
@@ -71,6 +73,7 @@ DECLARE_MODULE_AV1(join, NULL, NULL, join_clist, join_hlist, NULL, "$Revision: 3
 
 static void do_join_0(struct Client *client_p, struct Client *source_p);
 static int check_channel_name_loc(struct Client *source_p, const char *name);
+static void send_join_error(struct Client *source_p, int numeric, const char *name);
 
 static void set_final_mode(struct Mode *mode, struct Mode *oldmode);
 static void remove_our_modes(struct Channel *chptr, struct Client *source_p);
@@ -106,6 +109,8 @@ check_forward(struct Client *source_p, struct Channel *chptr,
 
        while (depth < 16)
        {
+               if (next == NULL)
+                       return NULL;
                chptr = find_channel(next);
                /* Can only forward to existing channels */
                if (chptr == NULL)
@@ -122,8 +127,6 @@ check_forward(struct Client *source_p, struct Channel *chptr,
                i = can_join(source_p, chptr, key, &next);
                if (i == 0)
                        return chptr;
-               if (next == NULL)
-                       return NULL;
                depth++;
        }
 
@@ -255,8 +258,10 @@ m_join(struct Client *client_p, struct Client *source_p, int parc, const char *p
 
                        if(moduledata.approved != 0)
                        {
-                               sendto_one(source_p, form_str(moduledata.approved),
-                                          me.name, source_p->name, name);
+                               if(moduledata.approved != ERR_CUSTOM)
+                                       send_join_error(source_p,
+                                                       moduledata.approved,
+                                                       name);
                                continue;
                        }
 
@@ -302,8 +307,7 @@ m_join(struct Client *client_p, struct Client *source_p, int parc, const char *p
                         * -- dwr
                         */
                        if(i != ERR_CUSTOM)
-                               sendto_one(source_p, form_str(i), me.name, source_p->name, name);
-
+                               send_join_error(source_p, i, name);
                        continue;
                }
                else if(chptr != chptr2)
@@ -325,6 +329,9 @@ m_join(struct Client *client_p, struct Client *source_p, int parc, const char *p
                }
                chptr->join_count++;
 
+               /* credit user for join */
+               credit_client_join(source_p);
+
                /* we send the user their join here, because we could have to
                 * send a mode out next.
                 */
@@ -334,8 +341,7 @@ m_join(struct Client *client_p, struct Client *source_p, int parc, const char *p
                if(flags & CHFL_CHANOP)
                {
                        chptr->channelts = rb_current_time();
-                       chptr->mode.mode |= MODE_TOPICLIMIT;
-                       chptr->mode.mode |= MODE_NOPRIVMSGS;
+                       chptr->mode.mode |= ConfigChannel.autochanmodes;
                        modes = channel_modes(chptr, &me);
 
                        sendto_channel_local(ONLY_CHANOPS, chptr, ":%s MODE %s %s",
@@ -394,7 +400,6 @@ ms_join(struct Client *client_p, struct Client *source_p, int parc, const char *
        time_t newts;
        int isnew;
        int keep_our_modes = YES;
-       int keep_new_modes = YES;
        rb_dlink_node *ptr, *next_ptr;
 
        /* special case for join 0 */
@@ -456,8 +461,6 @@ ms_join(struct Client *client_p, struct Client *source_p, int parc, const char *
                keep_our_modes = NO;
                chptr->channelts = newts;
        }
-       else
-               keep_new_modes = NO;
 
        /* Lost the TS, other side wins, so remove modes on this side */
        if(!keep_our_modes)
@@ -525,7 +528,6 @@ ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char
        int fl;
        int isnew;
        int mlen_uid;
-       int len_nick;
        int len_uid;
        int len;
        int joins = 0;
@@ -536,6 +538,9 @@ ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char
        static char empty[] = "";
        rb_dlink_node *ptr, *next_ptr;
 
+       if(parc < 5)
+               return 0;
+
        if(!IsChannelName(parv[2]) || !check_channel_name(parv[2]))
                return 0;
 
@@ -636,7 +641,7 @@ ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char
 
        if(isnew)
                chptr->channelts = newts;
-       
+
        else if(newts == 0 || oldts == 0)
                chptr->channelts = 0;
        else if(newts == oldts)
@@ -771,7 +776,7 @@ ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char
        mbuf = modebuf;
        para[0] = para[1] = para[2] = para[3] = empty;
        pargs = 0;
-       len_nick = len_uid = 0;
+       len_uid = 0;
 
        /* if theres a space, theres going to be more than one nick, change the
         * first space to \0, so s is just the first nick, and point p to the
@@ -823,13 +828,11 @@ ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char
                        if(fl & CHFL_CHANOP)
                        {
                                *ptr_uid++ = '@';
-                               len_nick++;
                                len_uid++;
                        }
                        if(fl & CHFL_VOICE)
                        {
                                *ptr_uid++ = '+';
-                               len_nick++;
                                len_uid++;
                        }
                }
@@ -1019,6 +1022,40 @@ check_channel_name_loc(struct Client *source_p, const char *name)
        return 1;
 }
 
+/* send_join_error()
+ *
+ * input       - client to send to, reason, channel name
+ * output      - none
+ * side effects - error message sent to client
+ */
+static void
+send_join_error(struct Client *source_p, int numeric, const char *name)
+{
+       /* This stuff is necessary because the form_str macro only
+        * accepts constants.
+        */
+       switch (numeric)
+       {
+#define NORMAL_NUMERIC(i)                                              \
+               case i:                                                 \
+                       sendto_one(source_p, form_str(i),               \
+                                       me.name, source_p->name, name); \
+                       break
+
+               NORMAL_NUMERIC(ERR_BANNEDFROMCHAN);
+               NORMAL_NUMERIC(ERR_INVITEONLYCHAN);
+               NORMAL_NUMERIC(ERR_BADCHANNELKEY);
+               NORMAL_NUMERIC(ERR_CHANNELISFULL);
+               NORMAL_NUMERIC(ERR_NEEDREGGEDNICK);
+               NORMAL_NUMERIC(ERR_THROTTLE);
+
+               default:
+                       sendto_one_numeric(source_p, numeric,
+                                       "%s :Cannot join channel", name);
+                       break;
+       }
+}
+
 static void
 set_final_mode(struct Mode *mode, struct Mode *oldmode)
 {
@@ -1145,8 +1182,8 @@ set_final_mode(struct Mode *mode, struct Mode *oldmode)
  * remove_our_modes
  *
  * inputs      -
- * output      - 
- * side effects        - 
+ * output      -
+ * side effects        -
  */
 static void
 remove_our_modes(struct Channel *chptr, struct Client *source_p)
@@ -1268,7 +1305,8 @@ remove_ban_list(struct Channel *chptr, struct Client *source_p,
                banptr = ptr->data;
 
                /* trailing space, and the mode letter itself */
-               plen = strlen(banptr->banstr) + 2;
+               plen = strlen(banptr->banstr) +
+                       (banptr->forward ? strlen(banptr->forward) + 1 : 0) + 2;
 
                if(count >= MAXMODEPARAMS || (cur_len + plen) > BUFSIZE - 4)
                {
@@ -1286,7 +1324,10 @@ remove_ban_list(struct Channel *chptr, struct Client *source_p,
 
                *mbuf++ = c;
                cur_len += plen;
-               pbuf += rb_sprintf(pbuf, "%s ", banptr->banstr);
+               if (banptr->forward)
+                       pbuf += rb_sprintf(pbuf, "%s$%s ", banptr->banstr, banptr->forward);
+               else
+                       pbuf += rb_sprintf(pbuf, "%s ", banptr->banstr);
                count++;
 
                free_ban(banptr);