]> jfr.im git - solanum.git/blobdiff - modules/core/m_kick.c
ircd: send tags on every message
[solanum.git] / modules / core / m_kick.c
index a7d5e2a7399ef83f17180af32bbe9e0c6ecffd5d..17231ecf9cb4c8a2b1ca9e4fa6e5ce13b18c1315 100644 (file)
@@ -20,8 +20,6 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
  *  USA
- *
- *  $Id: m_kick.c 3317 2007-03-28 23:17:06Z jilles $
  */
 
 #include "stdinc.h"
 #include "hash.h"
 #include "packet.h"
 #include "s_serv.h"
+#include "hook.h"
+
+static const char kick_desc[] = "Provides the KICK command to remove a user from a channel";
 
-static int m_kick(struct Client *, struct Client *, int, const char **);
+static void m_kick(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
 #define mg_kick { m_kick, 3 }
 
 struct Message kick_msgtab = {
-       "KICK", 0, 0, 0, MFLG_SLOW,
+       "KICK", 0, 0, 0, 0,
        {mg_unreg, mg_kick, mg_kick, mg_kick, mg_ignore, mg_kick}
 };
 
 mapi_clist_av1 kick_clist[] = { &kick_msgtab, NULL };
 
-DECLARE_MODULE_AV1(kick, NULL, NULL, kick_clist, NULL, NULL, "$Revision: 3317 $");
+DECLARE_MODULE_AV2(kick, NULL, NULL, kick_clist, NULL, NULL, NULL, NULL, kick_desc);
 
 /*
 ** m_kick
-**      parv[0] = sender prefix
 **      parv[1] = channel
 **      parv[2] = client to kick
 **      parv[3] = kick comment
 */
-static int
-m_kick(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
+static void
+m_kick(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
 {
        struct membership *msptr;
        struct Client *who;
@@ -83,7 +83,7 @@ m_kick(struct Client *client_p, struct Client *source_p, int parc, const char *p
        if(chptr == NULL)
        {
                sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), name);
-               return 0;
+               return;
        }
 
        if(!IsServer(source_p))
@@ -94,16 +94,16 @@ m_kick(struct Client *client_p, struct Client *source_p, int parc, const char *p
                {
                        sendto_one_numeric(source_p, ERR_NOTONCHANNEL,
                                           form_str(ERR_NOTONCHANNEL), name);
-                       return 0;
+                       return;
                }
 
-               if(!is_chanop(msptr))
+               if(get_channel_access(source_p, chptr, msptr, MODE_ADD, NULL) < CHFL_CHANOP)
                {
                        if(MyConnect(source_p))
                        {
                                sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
                                           me.name, source_p->name, name);
-                               return 0;
+                               return;
                        }
 
                        /* If its a TS 0 channel, do it the old way */
@@ -111,30 +111,10 @@ m_kick(struct Client *client_p, struct Client *source_p, int parc, const char *p
                        {
                                sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
                                           get_id(&me, source_p), get_id(source_p, source_p), name);
-                               return 0;
+                               return;
                        }
                }
 
-               /* Its a user doing a kick, but is not showing as chanop locally
-                * its also not a user ON -my- server, and the channel has a TS.
-                * There are two cases we can get to this point then...
-                *
-                *     1) connect burst is happening, and for some reason a legit
-                *        op has sent a KICK, but the SJOIN hasn't happened yet or 
-                *        been seen. (who knows.. due to lag...)
-                *
-                *     2) The channel is desynced. That can STILL happen with TS
-                *        
-                *     Now, the old code roger wrote, would allow the KICK to 
-                *     go through. Thats quite legit, but lets weird things like
-                *     KICKS by users who appear not to be chanopped happen,
-                *     or even neater, they appear not to be on the channel.
-                *     This fits every definition of a desync, doesn't it? ;-)
-                *     So I will allow the KICK, otherwise, things are MUCH worse.
-                *     But I will warn it as a possible desync.
-                *
-                *     -Dianora
-                */
        }
 
        if((p = strchr(parv[2], ',')))
@@ -144,7 +124,7 @@ m_kick(struct Client *client_p, struct Client *source_p, int parc, const char *p
 
        if(!(who = find_chasing(source_p, user, &chasing)))
        {
-               return 0;
+               return;
        }
 
        msptr = find_channel_membership(chptr, who);
@@ -155,7 +135,24 @@ m_kick(struct Client *client_p, struct Client *source_p, int parc, const char *p
                {
                        sendto_one(source_p, form_str(ERR_ISCHANSERVICE),
                                   me.name, source_p->name, who->name, chptr->chname);
-                       return 0;
+                       return;
+               }
+
+               if(MyClient(source_p))
+               {
+                       hook_data_channel_approval hookdata;
+
+                       hookdata.client = source_p;
+                       hookdata.chptr = chptr;
+                       hookdata.msptr = msptr;
+                       hookdata.target = who;
+                       hookdata.approved = 1;
+                       hookdata.dir = MODE_ADD;        /* ensure modules like override speak up */
+
+                       call_hook(h_can_kick, &hookdata);
+
+                       if (!hookdata.approved)
+                               return;
                }
 
                comment = LOCAL_COPY((EmptyString(parv[3])) ? who->name : parv[3]);
@@ -170,10 +167,10 @@ m_kick(struct Client *client_p, struct Client *source_p, int parc, const char *p
                 *   be sent anyways.  Just waiting for some oper to abuse it...
                 */
                if(IsServer(source_p))
-                       sendto_channel_local(ALL_MEMBERS, chptr, ":%s KICK %s %s :%s",
+                       sendto_channel_local(source_p, ALL_MEMBERS, chptr, ":%s KICK %s %s :%s",
                                             source_p->name, name, who->name, comment);
                else
-                       sendto_channel_local(ALL_MEMBERS, chptr,
+                       sendto_channel_local(source_p, ALL_MEMBERS, chptr,
                                             ":%s!%s@%s KICK %s %s :%s",
                                             source_p->name, source_p->username,
                                             source_p->host, name, who->name, comment);
@@ -181,14 +178,9 @@ m_kick(struct Client *client_p, struct Client *source_p, int parc, const char *p
                sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
                              ":%s KICK %s %s :%s",
                              use_id(source_p), chptr->chname, use_id(who), comment);
-               sendto_server(client_p, chptr, NOCAPS, CAP_TS6,
-                             ":%s KICK %s %s :%s",
-                             source_p->name, chptr->chname, who->name, comment);
                remove_user_from_channel(msptr);
        }
        else if (MyClient(source_p))
                sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL,
                                   form_str(ERR_USERNOTINCHANNEL), user, name);
-
-       return 0;
 }