]> jfr.im git - solanum.git/blobdiff - src/channel.c
Do not allow a topic change if a user may not send to the channel
[solanum.git] / src / channel.c
index d1acd20b511117ddf299e1751bcfdd5f538cda42..1a159f1477904e39bbaf01bc1482f19300ed282b 100644 (file)
 
 #include "stdinc.h"
 #include "channel.h"
+#include "chmode.h"
 #include "client.h"
 #include "common.h"
 #include "hash.h"
 #include "hook.h"
-#include "irc_string.h"
-#include "sprintf_irc.h"
+#include "match.h"
 #include "ircd.h"
 #include "numeric.h"
 #include "s_serv.h"            /* captab */
 #include "s_newconf.h"
 #include "logger.h"
 
-extern rb_dlink_list global_channel_list;
-
-extern struct config_channel_entry ConfigChannel;
-extern rb_bh *channel_heap;
-extern rb_bh *ban_heap;
-extern rb_bh *topic_heap;
-extern rb_bh *member_heap;
+struct config_channel_entry ConfigChannel;
+rb_dlink_list global_channel_list;
+static rb_bh *channel_heap;
+static rb_bh *ban_heap;
+static rb_bh *topic_heap;
+static rb_bh *member_heap;
 
 static int channel_capabs[] = { CAP_EX, CAP_IE,
        CAP_SERVICE,
@@ -242,8 +241,6 @@ remove_user_from_channel(struct membership *msptr)
        if(client_p->servptr == &me)
                rb_dlinkDelete(&msptr->locchannode, &chptr->locmembers);
 
-       chptr->users_last = rb_current_time();
-
        if(!(chptr->mode.mode & MODE_PERMANENT) && rb_dlink_list_length(&chptr->members) <= 0)
                destroy_channel(chptr);
 
@@ -279,8 +276,6 @@ remove_user_from_channels(struct Client *client_p)
                if(client_p->servptr == &me)
                        rb_dlinkDelete(&msptr->locchannode, &chptr->locmembers);
 
-               chptr->users_last = rb_current_time();
-
                if(!(chptr->mode.mode & MODE_PERMANENT) && rb_dlink_list_length(&chptr->members) <= 0)
                        destroy_channel(chptr);
 
@@ -923,19 +918,14 @@ check_spambot_warning(struct Client *source_p, const char *name)
                        source_p->localClient->oper_warn_count_down--;
                else
                        source_p->localClient->oper_warn_count_down = 0;
-               if(source_p->localClient->oper_warn_count_down == 0)
+               if(source_p->localClient->oper_warn_count_down == 0 &&
+                               name != NULL)
                {
                        /* Its already known as a possible spambot */
-                       if(name != NULL)
-                               sendto_realops_snomask(SNO_BOTS, L_NETWIDE,
-                                                    "User %s (%s@%s) trying to join %s is a possible spambot",
-                                                    source_p->name,
-                                                    source_p->username, source_p->orighost, name);
-                       else
-                               sendto_realops_snomask(SNO_BOTS, L_NETWIDE,
-                                                    "User %s (%s@%s) is a possible spambot",
-                                                    source_p->name,
-                                                    source_p->username, source_p->orighost);
+                       sendto_realops_snomask(SNO_BOTS, L_NETWIDE,
+                                            "User %s (%s@%s) trying to join %s is a possible spambot",
+                                            source_p->name,
+                                            source_p->username, source_p->orighost, name);
                        source_p->localClient->oper_warn_count_down = OPER_SPAM_COUNTDOWN;
                }
        }
@@ -946,7 +936,9 @@ check_spambot_warning(struct Client *source_p, const char *name)
                   JOIN_LEAVE_COUNT_EXPIRE_TIME)
                {
                        decrement_count = (t_delta / JOIN_LEAVE_COUNT_EXPIRE_TIME);
-                       if(decrement_count > source_p->localClient->join_leave_count)
+                       if(name != NULL)
+                               ;
+                       else if(decrement_count > source_p->localClient->join_leave_count)
                                source_p->localClient->join_leave_count = 0;
                        else
                                source_p->localClient->join_leave_count -= decrement_count;
@@ -1001,6 +993,7 @@ check_splitmode(void *unused)
                                             "Network rejoined, deactivating splitmode");
 
                        rb_event_delete(check_splitmode_ev);
+                       check_splitmode_ev = NULL;
                }
        }
 }
@@ -1068,8 +1061,8 @@ set_channel_topic(struct Channel *chptr, const char *topic, const char *topic_in
        {
                if(chptr->topic == NULL)
                        allocate_topic(chptr);
-               strlcpy(chptr->topic, topic, TOPICLEN + 1);
-               strlcpy(chptr->topic_info, topic_info, USERHOST_REPLYLEN);
+               rb_strlcpy(chptr->topic, topic, TOPICLEN + 1);
+               rb_strlcpy(chptr->topic_info, topic_info, USERHOST_REPLYLEN);
                chptr->topic_time = topicts;
        }
        else
@@ -1080,28 +1073,10 @@ set_channel_topic(struct Channel *chptr, const char *topic, const char *topic_in
        }
 }
 
-const struct mode_letter chmode_flags[] =
-{
-       {MODE_INVITEONLY, 'i'},
-       {MODE_MODERATED, 'm'},
-       {MODE_NOPRIVMSGS, 'n'},
-       {MODE_PRIVATE, 'p'},
-       {MODE_SECRET, 's'},
-       {MODE_TOPICLIMIT, 't'},
-       {MODE_NOCOLOR, 'c'},
-       {MODE_FREEINVITE, 'g'},
-       {MODE_OPMODERATE, 'z'},
-       {MODE_EXLIMIT, 'L'},
-       {MODE_PERMANENT, 'P'},
-       {MODE_FREETARGET, 'F'},
-       {MODE_DISFORWARD, 'Q'},
-       {MODE_REGONLY, 'r'},
-       {0, '\0'}
-};
-
-/* channel_modes()
+/* channel_modes_real()
  *
  * inputs       - pointer to channel
+ *              - pointer to channel Mode struct
  *              - pointer to client
  * output       - string with simple modes
  * side effects - result from previous calls overwritten
@@ -1109,7 +1084,7 @@ const struct mode_letter chmode_flags[] =
  * Stolen from ShadowIRCd 4 --nenolod
  */
 const char *
-channel_modes(struct Channel *chptr, struct Client *client_p)
+channel_modes_real(struct Channel *chptr, struct Mode *mode, struct Client *client_p)
 {
        int i;
        char buf1[BUFSIZE];
@@ -1121,47 +1096,47 @@ channel_modes(struct Channel *chptr, struct Client *client_p)
        *mbuf++ = '+';
        *pbuf = '\0';
 
-       for (i = 0; chmode_flags[i].mode; ++i)
-               if(chptr->mode.mode & chmode_flags[i].mode)
-                       *mbuf++ = chmode_flags[i].letter;
+       for (i = 0; i < 256; i++)
+               if(mode->mode & chmode_flags[i])
+                       *mbuf++ = i;
 
-       if(chptr->mode.limit)
+       if(mode->limit)
        {
                *mbuf++ = 'l';
 
                if(!IsClient(client_p) || IsMember(client_p, chptr))
-                       pbuf += rb_sprintf(pbuf, " %d", chptr->mode.limit);
+                       pbuf += rb_sprintf(pbuf, " %d", mode->limit);
        }
 
-       if(*chptr->mode.key)
+       if(*mode->key)
        {
                *mbuf++ = 'k';
 
                if(pbuf > buf2 || !IsClient(client_p) || IsMember(client_p, chptr))
-                       pbuf += rb_sprintf(pbuf, " %s", chptr->mode.key);
+                       pbuf += rb_sprintf(pbuf, " %s", mode->key);
        }
 
-       if(chptr->mode.join_num)
+       if(mode->join_num)
        {
                *mbuf++ = 'j';
 
                if(pbuf > buf2 || !IsClient(client_p) || IsMember(client_p, chptr))
-                       pbuf += rb_sprintf(pbuf, " %d:%d", chptr->mode.join_num,
-                                          chptr->mode.join_time);
+                       pbuf += rb_sprintf(pbuf, " %d:%d", mode->join_num,
+                                          mode->join_time);
        }
 
-       if(*chptr->mode.forward && (ConfigChannel.use_forward || !IsClient(client_p)))
+       if(*mode->forward && (ConfigChannel.use_forward || !IsClient(client_p)))
        {
                *mbuf++ = 'f';
 
                if(pbuf > buf2 || !IsClient(client_p) || IsMember(client_p, chptr))
-                       pbuf += rb_sprintf(pbuf, " %s", chptr->mode.forward);
+                       pbuf += rb_sprintf(pbuf, " %s", mode->forward);
        }
 
        *mbuf = '\0';
 
-       strlcpy(final, buf1, sizeof final);
-       strlcat(final, buf2, sizeof final);
+       rb_strlcpy(final, buf1, sizeof final);
+       rb_strlcat(final, buf2, sizeof final);
        return final;
 }
 
@@ -1304,13 +1279,9 @@ send_cap_mode_changes(struct Client *client_p, struct Client *source_p,
                cap = chcap_combos[j].cap_yes;
                nocap = chcap_combos[j].cap_no;
 
-               if(cap & CAP_TS6)
-                       mbl = preflen = rb_sprintf(modebuf, ":%s TMODE %ld %s ",
-                                                  use_id(source_p), (long) chptr->channelts,
-                                                  chptr->chname);
-               else
-                       mbl = preflen = rb_sprintf(modebuf, ":%s MODE %s ",
-                                                  source_p->name, chptr->chname);
+               mbl = preflen = rb_sprintf(modebuf, ":%s TMODE %ld %s ",
+                                          use_id(source_p), (long) chptr->channelts,
+                                          chptr->chname);
 
                /* loop the list of - modes we have */
                for (i = 0; i < mode_count; i++)
@@ -1324,7 +1295,7 @@ send_cap_mode_changes(struct Client *client_p, struct Client *source_p,
                           || ((nocap & mode_changes[i].nocaps) != mode_changes[i].nocaps))
                                continue;
 
-                       if((cap & CAP_TS6) && !EmptyString(mode_changes[i].id))
+                       if(!EmptyString(mode_changes[i].id))
                                arg = mode_changes[i].id;
                        else
                                arg = mode_changes[i].arg;
@@ -1387,3 +1358,54 @@ send_cap_mode_changes(struct Client *client_p, struct Client *source_p,
                        sendto_server(client_p, chptr, cap, nocap, "%s %s", modebuf, parabuf);
        }
 }
+
+void 
+resv_chan_forcepart(const char *name, const char *reason, int temp_time)
+{
+       rb_dlink_node *ptr;
+       rb_dlink_node *next_ptr;
+       struct Channel *chptr;
+       struct membership *msptr;
+       struct Client *target_p;
+
+       if(!ConfigChannel.resv_forcepart)
+               return;
+
+       /* for each user on our server in the channel list
+        * send them a PART, and notify opers.
+        */
+       chptr = find_channel(name);
+       if(chptr != NULL)
+       {
+               RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->locmembers.head)
+               {
+                       msptr = ptr->data;
+                       target_p = msptr->client_p;
+
+                       if(IsExemptResv(target_p))
+                               continue;
+
+                       sendto_server(target_p, chptr, CAP_TS6, NOCAPS,
+                                     ":%s PART %s", target_p->id, chptr->chname);
+
+                       sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s :%s",
+                                            target_p->name, target_p->username,
+                                            target_p->host, chptr->chname, target_p->name);
+
+                       remove_user_from_channel(msptr);
+
+                       /* notify opers & user they were removed from the channel */
+                       sendto_realops_snomask(SNO_GENERAL, L_ALL,
+                                            "Forced PART for %s!%s@%s from %s (%s)",
+                                            target_p->name, target_p->username, 
+                                            target_p->host, name, reason);
+
+                       if(temp_time > 0)
+                               sendto_one_notice(target_p, ":*** Channel %s is temporarily unavailable on this server.",
+                                          name);
+                       else
+                               sendto_one_notice(target_p, ":*** Channel %s is no longer available on this server.",
+                                          name);
+               }
+       }
+}