]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Added facility for servers to send KICK message (ew, i hate this crap)
authorbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>
Sun, 22 Jan 2006 19:23:20 +0000 (19:23 +0000)
committerbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>
Sun, 22 Jan 2006 19:23:20 +0000 (19:23 +0000)
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@2830 e03df62e-2008-0410-955e-edbf42e46eb7

include/channels.h
include/modules.h
src/channels.cpp
src/modules.cpp
src/modules/m_messageflood.cpp
src/modules/m_spanningtree.cpp

index c00ab054101973b7ba23ad964412d55e52e6e15c..dd6d3b585b64752421af91dbcd82a65e3eb98e08 100644 (file)
@@ -261,6 +261,7 @@ class ucrec : public classbase
 chanrec* add_channel(userrec *user, const char* cn, const char* key, bool override);
 chanrec* del_channel(userrec *user, const char* cname, const char* reason, bool local);
 void kick_channel(userrec *src,userrec *user, chanrec *Ptr, char* reason);
+void server_kick_channel(userrec* user, chanrec* Ptr, char* reason, bool triggerevents);
 
 #endif
 
index d920736a9f325aa9e7f374b7ebb5f28b3362313f..6afb0e181ba85571aef009db89c65415ca69f31d 100644 (file)
@@ -1410,6 +1410,8 @@ class Server : public classbase
         * action after calling this method is to immediately bail from your handler.
         */
        virtual void QuitUser(userrec* user, std::string reason);
+
+       virtual void KickUser(userrec* source, userrec* target, chanrec* chan, std::string reason);
        
        /**  Matches text against a glob pattern.
         * Uses the ircd's internal matching function to match string against a globbing pattern, e.g. *!*@*.com
index 2b1fac5f2d2476468b80ca87f6c26414a868a789..9179c80027f30687ed4cd57df4e514e9c09d9395 100644 (file)
@@ -451,6 +451,52 @@ chanrec* del_channel(userrec *user, const char* cname, const char* reason, bool
         return NULL;
 }
 
+void server_kick_channel(userrec* user, chanrec* Ptr, char* reason, bool triggerevents)
+{
+       if ((!user) || (!Ptr) || (!reason))
+       {
+               return;
+       }
+
+       if (!has_channel(user,Ptr))
+       {
+               /* Not on channel */
+               return;
+       }
+
+       if (triggerevents)
+       {
+               FOREACH_MOD(I_OnUserKick,OnUserKick(NULL,user,Ptr,reason));
+       }
+
+       for (unsigned int i =0; i < user->chans.size(); i++)
+       {
+               if (user->chans[i].channel)
+               if (!strcasecmp(user->chans[i].channel->name,Ptr->name))
+               {
+                       WriteChannelWithServ(Ptr,"KICK %s %s :%s",Ptr->name, user->nick, reason);
+                       user->chans[i].uc_modes = 0;
+                       user->chans[i].channel = NULL;
+                       break;
+               }
+       }
+
+       Ptr->DelUser((char*)user);
+
+        if (!usercount(Ptr))
+        {
+                chan_hash::iterator iter = chanlist.find(Ptr->name);
+                log(DEBUG,"del_channel: destroying channel: %s",Ptr->name);
+                /* kill the record */
+                if (iter != chanlist.end())
+                {
+                        log(DEBUG,"del_channel: destroyed: %s",Ptr->name);
+                        FOREACH_MOD(I_OnChannelDelete,OnChannelDelete(Ptr));
+                        delete Ptr;
+                        chanlist.erase(iter);
+                }
+        }
+}
 
 void kick_channel(userrec *src,userrec *user, chanrec *Ptr, char* reason)
 {
@@ -460,11 +506,6 @@ void kick_channel(userrec *src,userrec *user, chanrec *Ptr, char* reason)
                 return;
         }
 
-        if ((!Ptr) || (!user) || (!src))
-        {
-                return;
-        }
-
         log(DEBUG,"kick_channel: removing: %s %s %s",user->nick,Ptr->name,src->nick);
 
         if (!has_channel(user,Ptr))
index 390efe5bf012cfd6dd066075aae6546a2e7cad29..5ac49e75a3b794b77f3e8a0c71c3d6dae3202761 100644 (file)
@@ -408,6 +408,18 @@ void Server::ChangeUserNick(userrec* user, std::string nickname)
        force_nickchange(user,nickname.c_str());
 }
 
+virtual void KickUser(userrec* source, userrec* target, chanrec* chan, std::string reason)
+{
+       if (source)
+       {
+               kick_channel(source,target,chan,reason);
+       }
+       else
+       {
+               server_kick_channel(target,chan,reason,true);
+       }
+}
+
 void Server::QuitUser(userrec* user, std::string reason)
 {
        kill_link(user,reason.c_str());
index 738857f2988c246d776ee44e2d1a0d7326305e92..0f0878646624e316c3c93ec509f6295ab837f033 100644 (file)
@@ -17,6 +17,7 @@
 using namespace std;
 
 #include <stdio.h>
+#include <map>
 #include "users.h"
 #include "channels.h"
 #include "modules.h"
@@ -30,9 +31,45 @@ class floodsettings
        bool ban;
        int secs;
        int lines;
+       time_t reset;
+       std::map<userrec*,int> counters;
 
        floodsettings() : ban(0), secs(0), lines(0) {};
-       floodsettings(bool a, int b, int c) : ban(a), secs(b), lines(c) {};
+       floodsettings(bool a, int b, int c) : ban(a), secs(b), lines(c) { reset = time(NULL) + secs };
+
+       void addmessage(userrec* who)
+       {
+               std::map<userrec*,int>::iterator iter = counters.find(who);
+               if (iter != counters.end())
+               {
+                       iter->second++;
+                       log(DEBUG,"Count for %s is now %d",who->nick,iter->second);
+               }
+               if (reset > time(NULL))
+               {
+                       counters.clear();
+                       reset = time(NULL) + secs;
+               }
+       }
+
+       bool shouldkick(userrec* who)
+       {
+               std::map<userrec*,int>::iterator iter = counters.find(who);
+               if (iter != counters.end())
+               {
+                       return (iter->second >= this->lines);
+               }
+               else return false;
+       }
+
+       void clear(userrec* who)
+       {
+               std::map<userrec*,int>::iterator iter = counters.find(who);
+               if (iter != counters.end())
+               {
+                       counters.erase(iter);
+               }
+       }
 };
 
 class ModuleMsgFlood : public Module
@@ -124,6 +161,40 @@ class ModuleMsgFlood : public Module
                return 0;
        }
 
+       int ProcessMessages(userrec* user,chanrec* dest,std::string &text)
+       {
+               floodsettings *f = (floodsettings*)c->GetExt("flood");
+               if (f)
+               {
+                       f->addmessage(user);
+                       if (f->shouldkick(user))
+                       {
+                               /* Youre outttta here! */
+                               f->clear(user);
+                               Srv->KickUser(NULL, user, dest, "Channel flood triggered (mode +f)");
+                               return 1;
+                       }
+               }
+       }
+
+        virtual int OnUserPreMessage(userrec* user,void* dest,int target_type, std::string &text)
+        {
+                if (target_type == TYPE_CHANNEL)
+                {
+                        return ProcessMessages(user,(chanrec*)dest,text);
+                }
+                else return 0;
+       }
+
+       virtual int OnUserPreNotice(userrec* user,void* dest,int target_type, std::string &text)
+       {
+               if (target_type == TYPE_CHANNEL)
+               {
+                       return ProcessMessages(user,(chanrec*)dest,text);
+               }
+               else return 0;
+       }
+
        void OnChannelDelete(chanrec* chan)
        {
                if (chan->GetExt("flood"))
index 124583ff1e4961dfacb6cbcfdbf8f7005fe4681f..7204c2435dc1be25ef919f5341dd39e5c2c95b1b 100644 (file)
@@ -2029,6 +2029,14 @@ class TreeSocket : public InspSocket
                                {
                                        return this->ForceTopic(prefix,params);
                                }
+                               else if ((command == "KICK") && (!Srv->FindNick(prefix)))
+                               {
+                                       /* Server kick */
+                                       userrec* who = Srv->FindNick(params[1]);
+                                       chanrec* where = Srv->FindChannel(params[0]);
+                                       server_kick_channel(who, where, (char*)params[2].c_str(), false);
+                                       return true;
+                               }
                                else if (command == "REHASH")
                                {
                                        return this->RemoteRehash(prefix,params);
@@ -3054,7 +3062,16 @@ class ModuleSpanningTree : public Module
 
        virtual void OnUserKick(userrec* source, userrec* user, chanrec* chan, std::string reason)
        {
-               if (source->fd > -1)
+               if (!source)
+               {
+                       /* Server kick (ugh) */
+                       std::deque<std::string> params;
+                       params.push_back(chan->name);
+                       params.push_back(user->nick);
+                       params.push_back(":"+reason);
+                       DoOneToMany(Srv->GetServerName(),"KICK",params);
+               }
+               else if (source->fd > -1)
                {
                        std::deque<std::string> params;
                        params.push_back(chan->name);