summaryrefslogtreecommitdiff
path: root/contrib/m_force.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/m_force.c')
-rw-r--r--contrib/m_force.c329
1 files changed, 329 insertions, 0 deletions
diff --git a/contrib/m_force.c b/contrib/m_force.c
new file mode 100644
index 0000000..9e8265b
--- /dev/null
+++ b/contrib/m_force.c
@@ -0,0 +1,329 @@
+/* contrib/m_force.c
+ * Copyright (C) 2002, 2003, 2004, 2005 Hybrid Development Team
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1.Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2.Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3.The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id$
+ */
+
+#include "stdinc.h"
+#include "client.h"
+#include "ircd.h"
+#include "irc_string.h"
+#include "numeric.h"
+#include "fdlist.h"
+#include "hash.h"
+#include "s_bsd.h"
+#include "conf.h"
+#include "s_serv.h"
+#include "send.h"
+#include "parse.h"
+#include "modules.h"
+#include "channel.h"
+#include "channel_mode.h"
+
+
+/* m_forcejoin()
+ * parv[0] = sender prefix
+ * parv[1] = user to force
+ * parv[2] = channel to force them into
+ */
+static void
+mo_forcejoin(struct Client *client_p, struct Client *source_p,
+ int parc, char *parv[])
+{
+ struct Client *target_p = NULL;
+ struct Channel *chptr = NULL;
+ unsigned int type = 0;
+ char mode = '\0';
+ char sjmode = '\0';
+ char *newch = NULL;
+ dlink_node *ptr = NULL;
+
+ if (!HasUMode(source_p, UMODE_ADMIN))
+ {
+ sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
+ me.name, source_p->name);
+ return;
+ }
+
+ if ((target_p = hash_find_client(parv[1])) == NULL || !IsClient(target_p))
+ {
+ sendto_one(source_p, form_str(ERR_NOSUCHNICK),
+ me.name, source_p->name, parv[1]);
+ return;
+ }
+
+ if (!MyConnect(target_p))
+ {
+ if (target_p->from != client_p)
+ {
+ if (IsCapable(target_p->from, CAP_ENCAP))
+ sendto_one(target_p, ":%s ENCAP %s FORCEJOIN %s %s",
+ source_p->name, target_p->from->name,
+ target_p->name, parv[2]);
+ else
+ sendto_one(target_p, ":%s FORCEJOIN %s %s",
+ source_p->name, target_p->name, parv[2]);
+ }
+
+ return;
+ }
+
+ /* select our modes from parv[2] if they exist... (chanop)*/
+ switch (*parv[2])
+ {
+ case '@':
+ type = CHFL_CHANOP;
+ mode = 'o';
+ sjmode = '@';
+ parv[2]++;
+ break;
+#ifdef HALFOPS
+ case '%':
+ type = CHFL_HALFOP;
+ mode = 'h';
+ sjmode = '%';
+ parv[2]++;
+ break;
+#endif
+ case '+':
+ type = CHFL_VOICE;
+ mode = 'v';
+ sjmode = '+';
+ parv[2]++;
+ break;
+ default:
+ type = 0;
+ mode = sjmode = '\0'; /* make sure sjmode is 0. sjoin depends on it */
+ break;
+ }
+
+ if ((chptr = hash_find_channel(parv[2])) != NULL)
+ {
+ if (IsMember(target_p, chptr))
+ {
+ sendto_one(source_p, ":%s NOTICE %s :*** Notice -- %s is already in %s",
+ me.name, source_p->name, target_p->name, chptr->chname);
+ return;
+ }
+
+ add_user_to_channel(chptr, target_p, type, 0);
+
+ sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s!%s@%s JOIN :%s",
+ target_p->name, target_p->username,
+ target_p->host, chptr->chname);
+
+ if (sjmode)
+ sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s MODE %s +%c %s",
+ me.name, chptr->chname, mode, target_p->name);
+
+ if (chptr->chname[0] == '#')
+ {
+ if (sjmode)
+ {
+ DLINK_FOREACH (ptr, serv_list.head)
+ {
+ struct Client *serv_p = ptr->data;
+ if (serv_p == target_p->from || IsDead(serv_p))
+ continue;
+
+ sendto_one(serv_p, ":%s SJOIN %lu %s + :%c%s",
+ ID_or_name(&me, serv_p), (unsigned long)chptr->channelts,
+ chptr->chname, (sjmode == '%' &&
+ !IsCapable(serv_p, CAP_HOPS)) ? '@' : sjmode,
+ ID_or_name(target_p, serv_p));
+ }
+ }
+ else
+ {
+ sendto_server(target_p, CAP_TS6, NOCAPS,
+ ":%s SJOIN %lu %s + :%s",
+ me.id, (unsigned long)chptr->channelts,
+ chptr->chname, target_p->id);
+ sendto_server(target_p, NOCAPS, CAP_TS6,
+ ":%s SJOIN %lu %s + :%s",
+ me.name, (unsigned long)chptr->channelts,
+ chptr->chname, target_p->name);
+ }
+ }
+
+ if (chptr->topic[0])
+ {
+ sendto_one(target_p, form_str(RPL_TOPIC),
+ me.name, target_p->name,
+ chptr->chname, chptr->topic);
+ sendto_one(target_p, form_str(RPL_TOPICWHOTIME),
+ me.name, target_p->name, chptr->chname,
+ chptr->topic_info, chptr->topic_time);
+ }
+
+ target_p->localClient->last_join_time = CurrentTime;
+ channel_member_names(target_p, chptr, 1);
+ }
+ else
+ {
+ newch = parv[2];
+
+ if (!check_channel_name(newch, 1))
+ {
+ sendto_one(source_p, form_str(ERR_BADCHANNAME),
+ me.name, source_p->name, newch);
+ return;
+ }
+
+ chptr = make_channel(newch);
+ add_user_to_channel(chptr, target_p, CHFL_CHANOP, 0);
+
+ sendto_server(target_p, CAP_TS6, NOCAPS,
+ ":%s SJOIN %lu %s +nt :@%s",
+ me.id, (unsigned long)chptr->channelts,
+ chptr->chname, ID(target_p));
+ sendto_server(target_p, NOCAPS, CAP_TS6,
+ ":%s SJOIN %lu %s +nt :@%s",
+ me.name, (unsigned long)chptr->channelts,
+ chptr->chname, target_p->name);
+
+ sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s!%s@%s JOIN :%s",
+ target_p->name, target_p->username,
+ target_p->host, chptr->chname);
+
+ chptr->mode.mode |= MODE_TOPICLIMIT | MODE_NOPRIVMSGS;
+
+ sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s MODE %s +nt",
+ me.name, chptr->chname);
+
+ target_p->localClient->last_join_time = CurrentTime;
+ channel_member_names(target_p, chptr, 1);
+
+ /* we do this to let the oper know that a channel was created, this will be
+ * seen from the server handling the command instead of the server that
+ * the oper is on.
+ */
+ sendto_one(source_p, ":%s NOTICE %s :*** Notice -- Creating channel %s",
+ me.name, source_p->name, chptr->chname);
+ }
+}
+
+static void
+mo_forcepart(struct Client *client_p, struct Client *source_p,
+ int parc, char *parv[])
+{
+ struct Client *target_p = NULL;
+ struct Channel *chptr = NULL;
+ struct Membership *member = NULL;
+
+ if (!HasUMode(source_p, UMODE_ADMIN))
+ {
+ sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
+ me.name, source_p->name);
+ return;
+ }
+
+ /* if target_p == NULL then let the oper know */
+ if ((target_p = hash_find_client(parv[1])) == NULL || !IsClient(target_p))
+ {
+ sendto_one(source_p, form_str(ERR_NOSUCHNICK),
+ me.name, source_p->name, parv[1]);
+ return;
+ }
+
+ if (!MyConnect(target_p))
+ {
+ if (target_p->from != client_p)
+ {
+ if (IsCapable(target_p->from, CAP_ENCAP))
+ sendto_one(target_p, ":%s ENCAP %s FORCEPART %s %s",
+ source_p->name, target_p->from->name,
+ target_p->name, parv[2]);
+ else
+ sendto_one(target_p, ":%s FORCEPART %s %s",
+ source_p->name, target_p->name, parv[2]);
+ }
+
+ return;
+ }
+
+ if ((chptr = hash_find_channel(parv[2])) == NULL)
+ {
+ sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
+ me.name, source_p->name, parv[2]);
+ return;
+ }
+
+ if ((member = find_channel_link(target_p, chptr)) == NULL)
+ {
+ sendto_one(source_p, form_str(ERR_USERNOTINCHANNEL),
+ me.name, source_p->name, chptr->chname, target_p->name);
+ return;
+ }
+
+ sendto_server(target_p, CAP_TS6, NOCAPS,
+ ":%s PART %s :%s", ID(target_p),
+ chptr->chname, target_p->name);
+ sendto_server(target_p, NOCAPS, CAP_TS6,
+ ":%s PART %s :%s", target_p->name,
+ chptr->chname, target_p->name);
+
+ sendto_channel_local(ALL_MEMBERS, 0, 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(member);
+}
+
+static struct Message forcejoin_msgtab = {
+ "FORCEJOIN", 0, 0, 3, MAXPARA, MFLG_SLOW, 0,
+ { m_ignore, m_not_oper, mo_forcejoin, mo_forcejoin, mo_forcejoin, m_ignore }
+};
+
+static struct Message forcepart_msgtab = {
+ "FORCEPART", 0, 0, 3, MAXPARA, MFLG_SLOW, 0,
+ { m_ignore, m_not_oper, mo_forcepart, mo_forcepart, mo_forcepart, m_ignore }
+};
+
+static void
+module_init(void)
+{
+ mod_add_cmd(&forcejoin_msgtab);
+ mod_add_cmd(&forcepart_msgtab);
+}
+
+static void
+module_exit(void)
+{
+ mod_del_cmd(&forcejoin_msgtab);
+ mod_del_cmd(&forcepart_msgtab);
+}
+
+struct module module_entry = {
+ .node = { NULL, NULL, NULL },
+ .name = NULL,
+ .version = "$Revision$",
+ .handle = NULL,
+ .modinit = module_init,
+ .modexit = module_exit,
+ .flags = 0
+};