add opkick command, similar to opmode command, but then for kicking
-priv controlled by LOCAL_OPMODE and OPMODE
+priv controlled by LOCAL_OPOPKICK and OPKICK
feature controlled by OPKICK (disabled by default), new p10 token OK
if implemented, it must not be enabled until ALL servers and services are upgraded
generates HACK(4) snomask notice for accountability with oper as source
probably needs some work (for one i simply copied the header from m_kick.c)
-diff -r f1d6c059e808 include/handlers.h
---- a/include/handlers.h Sun Jan 11 22:38:39 2009 +0000
-+++ b/include/handlers.h Sun Jan 11 22:38:39 2009 +0000
+diff -r a77bd3d09dec include/client.h
+--- a/include/client.h Tue Feb 03 18:16:21 2009 +0100
++++ b/include/client.h Tue Feb 03 18:40:09 2009 +0100
+@@ -116,6 +116,8 @@
+ PRIV_LOCAL_JUPE, /**< oper can local JUPE */
+ PRIV_OPMODE, /**< oper can OP/CLEARMODE */
+ PRIV_LOCAL_OPMODE, /**< oper can local OP/CLEARMODE */
++ PRIV_OPKICK, /**< oper can OPKICK */
++ PRIV_LOCAL_OPKICK, /**< oper can local OPKICK */
+ PRIV_SET, /**< oper can SET */
+ PRIV_WHOX, /**< oper can use /who x */
+ PRIV_BADCHAN, /**< oper can BADCHAN */
+diff -r a77bd3d09dec include/handlers.h
+--- a/include/handlers.h Tue Feb 03 18:16:21 2009 +0100
++++ b/include/handlers.h Tue Feb 03 18:40:09 2009 +0100
@@ -167,6 +167,7 @@
extern int mo_kill(struct Client*, struct Client*, int, char*[]);
extern int mo_notice(struct Client*, struct Client*, int, char*[]);
extern int ms_opmode(struct Client*, struct Client*, int, char*[]);
extern int ms_part(struct Client*, struct Client*, int, char*[]);
extern int ms_ping(struct Client*, struct Client*, int, char*[]);
-diff -r f1d6c059e808 include/ircd_features.h
---- a/include/ircd_features.h Sun Jan 11 22:38:39 2009 +0000
-+++ b/include/ircd_features.h Sun Jan 11 22:38:39 2009 +0000
+diff -r a77bd3d09dec include/ircd_features.h
+--- a/include/ircd_features.h Tue Feb 03 18:16:21 2009 +0100
++++ b/include/ircd_features.h Tue Feb 03 18:40:09 2009 +0100
@@ -105,6 +105,7 @@
/* features that affect all operators */
FEAT_EXTENDED_CHECKCMD,
FEAT_SETHOST,
FEAT_SETHOST_USER,
FEAT_SETHOST_AUTO,
-diff -r f1d6c059e808 include/msg.h
---- a/include/msg.h Sun Jan 11 22:38:39 2009 +0000
-+++ b/include/msg.h Sun Jan 11 22:38:39 2009 +0000
+diff -r a77bd3d09dec include/msg.h
+--- a/include/msg.h Tue Feb 03 18:16:21 2009 +0100
++++ b/include/msg.h Tue Feb 03 18:40:09 2009 +0100
@@ -236,6 +236,10 @@
#define TOK_KICK "K"
#define CMD_KICK MSG_KICK, TOK_KICK
#define MSG_USERHOST "USERHOST" /* USER -> USRH */
#define TOK_USERHOST "USERHOST"
#define CMD_USERHOST MSG_USERHOST, TOK_USERHOST
-diff -r f1d6c059e808 ircd/Makefile.in
---- a/ircd/Makefile.in Sun Jan 11 22:38:39 2009 +0000
-+++ b/ircd/Makefile.in Sun Jan 11 22:38:39 2009 +0000
+diff -r a77bd3d09dec ircd/Makefile.in
+--- a/ircd/Makefile.in Tue Feb 03 18:16:21 2009 +0100
++++ b/ircd/Makefile.in Tue Feb 03 18:40:09 2009 +0100
@@ -151,6 +151,7 @@
m_nick.c \
m_notice.c \
m_opmode.o: m_opmode.c ../config.h ../include/client.h \
../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \
../include/ircd_events.h ../config.h ../include/ircd_handler.h \
-diff -r f1d6c059e808 ircd/ircd_features.c
---- a/ircd/ircd_features.c Sun Jan 11 22:38:39 2009 +0000
-+++ b/ircd/ircd_features.c Sun Jan 11 22:38:39 2009 +0000
+diff -r a77bd3d09dec ircd/client.c
+--- a/ircd/client.c Tue Feb 03 18:16:21 2009 +0100
++++ b/ircd/client.c Tue Feb 03 18:40:09 2009 +0100
+@@ -174,6 +174,7 @@
+ FlagSet(&privs_local, PRIV_LOCAL_GLINE);
+ FlagSet(&privs_local, PRIV_LOCAL_JUPE);
+ FlagSet(&privs_local, PRIV_LOCAL_OPMODE);
++ FlagSet(&privs_local, PRIV_LOCAL_OPKICK);
+ FlagSet(&privs_local, PRIV_WHOX);
+ FlagSet(&privs_local, PRIV_DISPLAY);
+ FlagSet(&privs_local, PRIV_FORCE_LOCAL_OPMODE);
+@@ -222,6 +223,7 @@
+ ClrPriv(client, PRIV_GLINE);
+ ClrPriv(client, PRIV_JUPE);
+ ClrPriv(client, PRIV_OPMODE);
++ ClrPriv(client, PRIV_OPKICK);
+ ClrPriv(client, PRIV_BADCHAN);
+ }
+ }
+@@ -237,7 +239,8 @@
+ P(SHOW_INVIS), P(SHOW_ALL_INVIS), P(UNLIMIT_QUERY), P(KILL),
+ P(LOCAL_KILL), P(REHASH), P(RESTART), P(DIE),
+ P(GLINE), P(LOCAL_GLINE), P(JUPE), P(LOCAL_JUPE),
+- P(OPMODE), P(LOCAL_OPMODE), P(SET), P(WHOX),
++ P(OPMODE), P(LOCAL_OPMODE), P(OPKICK), P(LOCAL_OPKICK),
++ P(SET), P(WHOX),
+ P(BADCHAN), P(LOCAL_BADCHAN), P(SEE_CHAN), P(PROPAGATE),
+ P(DISPLAY), P(SEE_OPERS), P(WIDE_GLINE), P(LIST_CHAN),
+ P(FORCE_OPMODE), P(FORCE_LOCAL_OPMODE), P(APASS_OPMODE),
+diff -r a77bd3d09dec ircd/ircd_features.c
+--- a/ircd/ircd_features.c Tue Feb 03 18:16:21 2009 +0100
++++ b/ircd/ircd_features.c Tue Feb 03 18:40:09 2009 +0100
@@ -359,6 +359,7 @@
/* features that affect all operators */
F_B(EXTENDED_CHECKCMD, 0, 0, 0),
F_B(CONFIG_OPERCMDS, 0, 0, 0),
-+ F_B(OPKICK, 0, 0, 0),
++ F_B(OPKICK, 0, 1, 0),
F_B(SETHOST, 0, 0, 0),
F_B(SETHOST_USER, 0, 0, 0),
F_B(SETHOST_AUTO, 0, 0, 0),
-diff -r f1d6c059e808 ircd/parse.c
---- a/ircd/parse.c Sun Jan 11 22:38:39 2009 +0000
-+++ b/ircd/parse.c Sun Jan 11 22:38:39 2009 +0000
+diff -r a77bd3d09dec ircd/ircd_lexer.l
+--- a/ircd/ircd_lexer.l Tue Feb 03 18:16:21 2009 +0100
++++ b/ircd/ircd_lexer.l Tue Feb 03 18:40:09 2009 +0100
+@@ -132,11 +132,13 @@
+ { "local_jupe", TPRIV_LOCAL_JUPE },
+ { "local_kill", TPRIV_LOCAL_KILL },
+ { "local_opmode", TPRIV_LOCAL_OPMODE },
++ { "local_opkick", TPRIV_LOCAL_OPKICK },
+ { "mb", MBYTES },
+ { "megabytes", MBYTES },
+ { "mode_lchan", TPRIV_MODE_LCHAN },
+ { "operator", OPER },
+ { "opmode", TPRIV_OPMODE },
++ { "opkick", TPRIV_OPKICK },
+ { "password", PASS },
+ { "propagate", TPRIV_PROPAGATE },
+ { "realname", REAL },
+diff -r a77bd3d09dec ircd/ircd_parser.y
+--- a/ircd/ircd_parser.y Tue Feb 03 18:16:21 2009 +0100
++++ b/ircd/ircd_parser.y Tue Feb 03 18:40:09 2009 +0100
+@@ -182,7 +182,8 @@
+ %token TPRIV_CHAN_LIMIT TPRIV_MODE_LCHAN TPRIV_DEOP_LCHAN TPRIV_WALK_LCHAN
+ %token TPRIV_LOCAL_KILL TPRIV_REHASH TPRIV_RESTART TPRIV_DIE
+ %token TPRIV_GLINE TPRIV_LOCAL_GLINE TPRIV_LOCAL_JUPE TPRIV_LOCAL_BADCHAN
+-%token TPRIV_LOCAL_OPMODE TPRIV_OPMODE TPRIV_SET TPRIV_WHOX TPRIV_BADCHAN
++%token TPRIV_LOCAL_OPMODE TPRIV_OPMODE TPRIV_LOCAL_OPKICK TPRIV_OPKICK
++%token TPRIV_SET TPRIV_WHOX TPRIV_BADCHAN
+ %token TPRIV_SEE_CHAN TPRIV_SHOW_INVIS TPRIV_SHOW_ALL_INVIS TPRIV_PROPAGATE
+ %token TPRIV_UNLIMIT_QUERY TPRIV_DISPLAY TPRIV_SEE_OPERS TPRIV_WIDE_GLINE
+ %token TPRIV_FORCE_OPMODE TPRIV_FORCE_LOCAL_OPMODE TPRIV_APASS_OPMODE
+@@ -672,6 +673,8 @@
+ TPRIV_LOCAL_JUPE { $$ = PRIV_LOCAL_JUPE; } |
+ TPRIV_LOCAL_OPMODE { $$ = PRIV_LOCAL_OPMODE; } |
+ TPRIV_OPMODE { $$ = PRIV_OPMODE; }|
++ TPRIV_LOCAL_OPKICK { $$ = PRIV_LOCAL_OPKICK; }|
++ TPRIV_OPKICK { $$ = PRIV_OPKICK; }|
+ TPRIV_SET { $$ = PRIV_SET; } |
+ TPRIV_WHOX { $$ = PRIV_WHOX; } |
+ TPRIV_BADCHAN { $$ = PRIV_BADCHAN; } |
+diff -r a77bd3d09dec ircd/m_opkick.c
+--- /dev/null Thu Jan 01 00:00:00 1970 +0000
++++ b/ircd/m_opkick.c Tue Feb 03 18:40:09 2009 +0100
+@@ -0,0 +1,231 @@
++/*
++ * IRC - Internet Relay Chat, ircd/m_opkick.c
++ * Copyright (C) 1990 Jarkko Oikarinen and
++ * University of Oulu, Computing Center
++ *
++ * See file AUTHORS in IRC package for additional names of
++ * the programmers.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 1, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++/*
++ * m_functions execute protocol messages on this server:
++ *
++ * cptr is always NON-NULL, pointing to a *LOCAL* client
++ * structure (with an open socket connected!). This
++ * identifies the physical socket where the message
++ * originated (or which caused the m_function to be
++ * executed--some m_functions may call others...).
++ *
++ * sptr is the source of the message, defined by the
++ * prefix part of the message if present. If not
++ * or prefix not found, then sptr==cptr.
++ *
++ * (!IsServer(cptr)) => (cptr == sptr), because
++ * prefixes are taken *only* from servers...
++ *
++ * (IsServer(cptr))
++ * (sptr == cptr) => the message didn't
++ * have the prefix.
++ *
++ * (sptr != cptr && IsServer(sptr) means
++ * the prefix specified servername. (?)
++ *
++ * (sptr != cptr && !IsServer(sptr) means
++ * that message originated from a remote
++ * user (not local).
++ *
++ * combining
++ *
++ * (!IsServer(sptr)) means that, sptr can safely
++ * taken as defining the target structure of the
++ * message in this server.
++ *
++ * *Always* true (if 'parse' and others are working correct):
++ *
++ * 1) sptr->from == cptr (note: cptr->from == cptr)
++ *
++ * 2) MyConnect(sptr) <=> sptr == cptr (e.g. sptr
++ * *cannot* be a local connection, unless it's
++ * actually cptr!). [MyConnect(x) should probably
++ * be defined as (x == x->from) --msa ]
++ *
++ * parc number of variable parameter strings (if zero,
++ * parv is allowed to be NULL)
++ *
++ * parv a NULL terminated list of parameter pointers,
++ *
++ * parv[0], sender (prefix string), if not present
++ * this points to an empty string.
++ * parv[1]...parv[parc-1]
++ * pointers to additional parameters
++ * parv[parc] == NULL, *always*
++ *
++ * note: it is guaranteed that parv[0]..parv[parc-1] are all
++ * non-NULL pointers.
++ */
++#include "config.h"
++
++#include "channel.h"
++#include "client.h"
++#include "hash.h"
++#include "ircd.h"
++#include "ircd_log.h"
++#include "ircd_reply.h"
++#include "ircd_string.h"
++#include "msg.h"
++#include "numeric.h"
++#include "numnicks.h"
++#include "send.h"
++#include "ircd_features.h"
++
++/* #include <assert.h> -- Now using assert in ircd_log.h */
++
++/*
++ * mo_opkick - oper message handler
++ *
++ * parv[0] = sender prefix
++ * parv[1] = channel
++ * parv[2] = client to kick
++ * parv[parc-1] = kick comment
++ */
++int mo_opkick(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
++{
++ struct Client *who;
++ struct Channel *chptr;
++ struct Membership *member = 0;
++ struct Membership* member2;
++ char *name, *comment;
++
++ ClrFlag(sptr, FLAG_TS8);
++
++ if (!feature_bool(FEAT_OPKICK))
++ return send_reply(sptr, ERR_DISABLED, "OPKICK");
++
++ if (parc < 3 || *parv[1] == '\0')
++ return need_more_params(sptr, "OPKICK");
++
++ name = parv[1];
++
++ /* simple checks */
++ if (!(chptr = get_channel(sptr, name, CGT_NO_CREATE)))
++ return send_reply(sptr, ERR_NOSUCHCHANNEL, name);
++
++ if (!HasPriv(sptr, IsLocalChannel(chptr->chname) ? PRIV_LOCAL_OPKICK : PRIV_OPKICK))
++ return send_reply(sptr, ERR_NOPRIVILEGES);
++
++ if (!(who = find_chasing(sptr, parv[2], 0, 1)))
++ return 0; /* find_chasing sends the reply for us */
++
++ /* Don't allow the channel service to be kicked */
++ if (IsChannelService(who) && IsService(cli_user(who)->server))
++ return send_reply(sptr, ERR_ISREALSERVICE, cli_name(who), chptr->chname);
++
++ /* check if kicked user is actually on the channel */
++ if (!(member = find_member_link(chptr, who)) || IsZombie(member))
++ return send_reply(sptr, ERR_USERNOTINCHANNEL, cli_name(who), chptr->chname);
++
++ /* We rely on ircd_snprintf to truncate the comment */
++ comment = EmptyString(parv[parc - 1]) ? parv[2] : parv[parc - 1];
++
++ /* propagate it */
++ if (!IsLocalChannel(name))
++ sendcmdto_serv_butone(sptr, CMD_OPKICK, cptr, "%H %C :%s", chptr, who, comment);
++
++ /* If it's a delayed join, only send the KICK to the person doing
++ * the kicking and the victim
++ */
++ if (IsDelayedJoin(member)) {
++ if (MyUser(who))
++ sendcmdto_one(feature_bool(FEAT_HIS_MODEWHO) ? &his : sptr, CMD_KICK, who, "%H %C :%s", chptr, who, comment);
++ /* operator using OPKICK is on the channel */
++ if ((member2 = find_member_link(chptr, sptr)) && !IsZombie(member2)) {
++ sendcmdto_one(who, CMD_JOIN, sptr, "%H", chptr);
++ sendcmdto_one(feature_bool(FEAT_HIS_MODEWHO) ? &his : sptr, CMD_KICK, sptr, "%H %C :%s", chptr, who, comment);
++ }
++ CheckDelayedJoins(chptr);
++ } else
++ sendcmdto_channel_butserv_butone(feature_bool(FEAT_HIS_MODEWHO) ? &his : sptr,
++ CMD_KICK, chptr, NULL, 0, "%H %C :%s", chptr, who, comment);
++
++ /* Send HACK notice and log it */
++ sendto_opmask_butone(0, SNO_HACK4, "HACK(4): %C KICK %H %C %s", sptr, chptr, who, comment);
++ log_write(LS_OPERMODE, L_INFO, LOG_NOSNOTICE, "%#C OPKICK %H %C %s", sptr, chptr, who, comment);
++
++ make_zombie(member, who, cptr, sptr, chptr);
++
++ return 0;
++}
++
++/*
++ * ms_opkick - server message handler
++ *
++ * parv[0] = sender prefix
++ * parv[1] = channel
++ * parv[2] = client to kick
++ * parv[parc-1] = kick comment
++ */
++int ms_opkick(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
++{
++ struct Client *who;
++ struct Channel *chptr;
++ struct Membership *member = 0;
++ char *name, *comment;
++
++ ClrFlag(sptr, FLAG_TS8);
++
++ if (parc < 3 || *parv[1] == '\0')
++ return need_more_params(sptr, "OPKICK");
++
++ name = parv[1];
++ comment = parv[parc - 1];
++
++ /* figure out who gets kicked from what */
++ if (IsLocalChannel(name) ||
++ !(chptr = get_channel(sptr, name, CGT_NO_CREATE)) ||
++ !(who = findNUser(parv[2])))
++ return 0;
++
++ /* We go ahead and pass on the KICK for users not on the channel */
++ if (!(member = find_member_link(chptr, who)) || IsZombie(member)) {
++ if (member) {
++ make_zombie(member, who, cptr, sptr, chptr);
++ member=0;
++ }
++ }
++
++ /* Propagate kick... */
++ sendcmdto_serv_butone(sptr, CMD_OPKICK, cptr, "%H %C :%s", chptr, who, comment);
++
++ if (member) { /* and tell the channel about it */
++ if (IsDelayedJoin(member)) {
++ if (MyUser(who))
++ sendcmdto_one((IsServer(sptr) || feature_bool(FEAT_HIS_MODEWHO)) ? &his : sptr,
++ CMD_KICK, who, "%H %C :%s", chptr, who, comment);
++ } else {
++ sendcmdto_channel_butserv_butone((IsServer(sptr) || feature_bool(FEAT_HIS_MODEWHO)) ? &his : sptr,
++ CMD_KICK, chptr, NULL, 0, "%H %C :%s", chptr, who, comment);
++ }
++
++ /* Send HACK notice and log it */
++ sendto_opmask_butone(0, SNO_HACK4, "HACK(4): %C KICK %H %C %s", sptr, chptr, who, comment);
++ log_write(LS_OPERMODE, L_INFO, LOG_NOSNOTICE, "%#C OPKICK %H %C %s", sptr, chptr, who, comment);
++
++ make_zombie(member, who, cptr, sptr, chptr);
++ }
++ return 0;
++}
+diff -r a77bd3d09dec ircd/parse.c
+--- a/ircd/parse.c Tue Feb 03 18:16:21 2009 +0100
++++ b/ircd/parse.c Tue Feb 03 18:40:09 2009 +0100
@@ -656,6 +656,17 @@
0, MAXPARA, MFLG_SLOW, 0, NULL,
{ m_unregistered, m_not_oper, m_check, m_check, m_ignore }