summaryrefslogtreecommitdiff
path: root/contrib/m_clearchan.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/m_clearchan.c')
-rw-r--r--contrib/m_clearchan.c269
1 files changed, 269 insertions, 0 deletions
diff --git a/contrib/m_clearchan.c b/contrib/m_clearchan.c
new file mode 100644
index 0000000..e818fa3
--- /dev/null
+++ b/contrib/m_clearchan.c
@@ -0,0 +1,269 @@
+/*
+ * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
+ * m_clearchan.c: Performs a channel takeover
+ *
+ * Copyright (C) 2002 by the past and present ircd coders, and others.
+ *
+ * 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 2 of the License, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * $Id$
+ */
+
+#include "stdinc.h"
+#include "list.h"
+#include "channel.h"
+#include "channel_mode.h"
+#include "client.h"
+#include "ircd.h"
+#include "numeric.h"
+#include "log.h"
+#include "s_serv.h"
+#include "send.h"
+#include "irc_string.h"
+#include "sprintf_irc.h"
+#include "hash.h"
+#include "parse.h"
+#include "modules.h"
+#include "conf.h"
+
+
+static void kick_list(struct Client *, struct Channel *);
+static void remove_our_modes(struct Channel *);
+static void remove_a_mode(struct Channel *, int, char);
+
+
+/*
+** mo_clearchan
+** parv[0] = sender prefix
+** parv[1] = channel
+*/
+static void
+mo_clearchan(struct Client *client_p, struct Client *source_p,
+ int parc, char *parv[])
+{
+ struct Channel *chptr = NULL;
+
+ /* admins only */
+ if (!HasUMode(source_p, UMODE_ADMIN))
+ {
+ sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
+ me.name, source_p->name);
+ return;
+ }
+
+ if ((chptr = hash_find_channel(parv[1])) == NULL)
+ {
+ sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
+ me.name, source_p->name, parv[1]);
+ return;
+ }
+
+ if (IsMember(source_p, chptr))
+ {
+ sendto_one(source_p, ":%s NOTICE %s :*** Please part %s before using CLEARCHAN",
+ me.name, source_p->name, chptr->chname);
+ return;
+ }
+
+ sendto_wallops_flags(UMODE_WALLOP, &me, "CLEARCHAN called for [%s] by %s!%s@%s",
+ chptr->chname, source_p->name, source_p->username, source_p->host);
+ sendto_server(NULL, NOCAPS, NOCAPS,
+ ":%s WALLOPS :CLEARCHAN called for [%s] by %s!%s@%s",
+ me.name, chptr->chname, source_p->name, source_p->username,
+ source_p->host);
+ ilog(LOG_TYPE_IRCD, "CLEARCHAN called for [%s] by %s!%s@%s",
+ chptr->chname, source_p->name, source_p->username, source_p->host);
+
+ /*
+ * Kill all the modes we have about the channel..
+ * making everyone a peon
+ */
+ remove_our_modes(chptr);
+
+ /* SJOIN the user to give them ops, and lock the channel */
+ sendto_server(client_p, CAP_TS6, NOCAPS,
+ ":%s JOIN %lu %s +ntsi",
+ source_p->id, (unsigned long)(chptr->channelts - 1),
+ chptr->chname);
+ sendto_server(client_p, NOCAPS, CAP_TS6,
+ ":%s SJOIN %lu %s +ntsi :@%s",
+ me.name, (unsigned long)(chptr->channelts - 1),
+ chptr->chname, source_p->name);
+ sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s!%s@%s JOIN %s",
+ source_p->name, source_p->username,
+ source_p->host, chptr->chname);
+ sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s MODE %s +o %s",
+ me.name, chptr->chname, source_p->name);
+
+
+ /*
+ * Take the TS down by 1, so we don't see the channel taken over
+ * again.
+ */
+ if (chptr->channelts)
+ --chptr->channelts;
+
+ chptr->mode.mode = MODE_SECRET | MODE_TOPICLIMIT |
+ MODE_INVITEONLY | MODE_NOPRIVMSGS;
+
+ set_channel_topic(chptr, "", "", 0);
+ chptr->mode.key[0] = '\0';
+
+ /* Kick the users out and join the oper */
+ kick_list(source_p, chptr);
+}
+
+static void
+kick_list(struct Client *source_p, struct Channel *chptr)
+{
+ dlink_node *ptr = NULL, *ptr_next = NULL;
+ struct Membership *ms = NULL;
+
+ DLINK_FOREACH(ptr, chptr->members.head)
+ {
+ ms = ptr->data;
+
+ sendto_channel_local(ALL_MEMBERS, 0, chptr,
+ ":%s!%s@%s KICK %s %s CLEARCHAN",
+ source_p->name, source_p->username,
+ source_p->host, chptr->chname, ms->client_p->name);
+ sendto_server(NULL, NOCAPS, NOCAPS,
+ ":%s KICK %s %s :CLEARCHAN", source_p->name,
+ chptr->chname, ms->client_p->name);
+ }
+
+ add_user_to_channel(chptr, source_p, CHFL_CHANOP, 0);
+
+ DLINK_FOREACH_SAFE(ptr, ptr_next, chptr->members.head)
+ {
+ ms = ptr->data;
+
+ if (ms->client_p != source_p)
+ remove_user_from_channel(ms);
+ }
+
+ /*
+ * Join the user themselves to the channel down here, so they dont see a nicklist
+ * or people being kicked
+ */
+ sendto_one(source_p, ":%s!%s@%s JOIN %s",
+ source_p->name, source_p->username,
+ source_p->host, chptr->chname);
+ channel_member_names(source_p, chptr, 1);
+}
+
+/* remove_our_modes()
+ *
+ * inputs - hide from ops or not int flag
+ * - pointer to channel to remove modes from
+ * - client pointer
+ * output - NONE
+ * side effects - Go through the local members, remove all their
+ * chanop modes etc., this side lost the TS.
+ */
+static void
+remove_our_modes(struct Channel *chptr)
+{
+ remove_a_mode(chptr, CHFL_CHANOP, 'o');
+#ifdef HALFOPS
+ remove_a_mode(chptr, CHFL_HALFOP, 'h');
+#endif
+ remove_a_mode(chptr, CHFL_VOICE, 'v');
+
+ /* Clear all +beI modes */
+ free_channel_list(&chptr->banlist);
+ free_channel_list(&chptr->exceptlist);
+ free_channel_list(&chptr->invexlist);
+}
+
+/* remove_a_mode()
+ *
+ * inputs -
+ * output - NONE
+ * side effects - remove ONE mode from a channel
+ */
+static void
+remove_a_mode(struct Channel *chptr, int mask, char flag)
+{
+ const dlink_node *ptr = NULL;
+ char lmodebuf[MODEBUFLEN];
+ const char *lpara[4] = { "", "", "", "" };
+ char *mbuf = lmodebuf;
+ int count = 0;
+
+ *mbuf++ = '-';
+
+ DLINK_FOREACH(ptr, chptr->members.head)
+ {
+ struct Membership *ms = ptr->data;
+ if ((ms->flags & mask) == 0)
+ continue;
+
+ ms->flags &= ~mask;
+
+ lpara[count++] = ms->client_p->name;
+
+ *mbuf++ = flag;
+
+ if (count == 4)
+ {
+ *mbuf = '\0';
+ sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s MODE %s %s %s %s %s %s",
+ me.name, chptr->chname, lmodebuf, lpara[0],
+ lpara[1], lpara[2], lpara[3]);
+
+ mbuf = lmodebuf;
+ *mbuf++ = '-';
+ count = 0;
+ lpara[0] = lpara[1] = lpara[2] = lpara[3] = "";
+ }
+ }
+
+ if (count != 0)
+ {
+ *mbuf = '\0';
+ sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s MODE %s %s %s %s %s %s",
+ me.name, chptr->chname, lmodebuf, lpara[0],
+ lpara[1], lpara[2], lpara[3]);
+ }
+}
+
+static struct Message clearchan_msgtab = {
+ "CLEARCHAN", 0, 0, 2, MAXPARA, MFLG_SLOW, 0,
+ { m_unregistered, m_not_oper, m_ignore, m_ignore, mo_clearchan, m_ignore }
+};
+
+static void
+module_init(void)
+{
+ mod_add_cmd(&clearchan_msgtab);
+}
+
+static void
+module_exit(void)
+{
+ mod_del_cmd(&clearchan_msgtab);
+}
+
+struct module module_entry = {
+ .node = { NULL, NULL, NULL },
+ .name = NULL,
+ .version = "$Revision$",
+ .handle = NULL,
+ .modinit = module_init,
+ .modexit = module_exit,
+ .flags = 0
+};