/** * akick.C: This file contains code for the ChanServ AKICK functions. * * Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team * Rights to this code are as documented in COPYING. * * * Portions of this file were derived from sources bearing the following license: * Copyright © 2005 William Pitcock, et al. * Rights to this code are as documented in doc/pod/license.pod. * * $Id: akick.C,v 1.10 2007/09/22 14:27:27 pippijn Exp $ */ #include "atheme.h" #include #include #include #include #include static void cs_cmd_akick (sourceinfo_t *si, int parc, char *parv[]); static char const rcsid[] = "$Id: akick.C,v 1.10 2007/09/22 14:27:27 pippijn Exp $"; REGISTER_MODULE ("chanserv/akick", false, "The Ermyth Team "); command_t const cs_akick = { "AKICK", N_("Manipulates a channel's AKICK list."), AC_NONE, 4, cs_cmd_akick }; E cmdvec cs_cmdtree; E helpvec cs_helptree; void cs_cmd_akick (sourceinfo_t *si, int parc, char *parv[]) { myuser_t *mu; mychan_t *mc; chanacs_t *ca, *ca2; metadata *md; node_t *n; int operoverride = 0; char *chan; char *cmd; char *uname = parv[2]; char *reason = parv[3]; if (parc < 2) { command_fail (si, fault::needmoreparams, STR_INSUFFICIENT_PARAMS, "AKICK"); command_fail (si, fault::needmoreparams, _("Syntax: AKICK <#channel> ADD|DEL|LIST [reason]")); return; } if (parv[0][0] == '#') chan = parv[0], cmd = parv[1]; else if (parv[1][0] == '#') cmd = parv[0], chan = parv[1]; else { command_fail (si, fault::badparams, STR_INVALID_PARAMS, "AKICK"); command_fail (si, fault::badparams, _("Syntax: AKICK <#channel> ADD|DEL|LIST [reason]")); return; } if ((strcasecmp ("LIST", cmd)) && (!uname)) { command_fail (si, fault::needmoreparams, STR_INSUFFICIENT_PARAMS, "AKICK"); command_fail (si, fault::needmoreparams, _("Syntax: AKICK <#channel> ADD|DEL|LIST [reason]")); return; } /* make sure they're registered, logged in * and the founder of the channel before * we go any further. */ if (!si->smu) { /* if they're opers and just want to LIST, they don't have to log in */ if (!(has_priv (si, PRIV_CHAN_AUSPEX) && !strcasecmp ("LIST", cmd))) { command_fail (si, fault::noprivs, _("You are not logged in.")); return; } } mc = mychan_t::find (chan); if (!mc) { command_fail (si, fault::nosuch_target, _("\2%s\2 is not registered."), chan); return; } if (mc->find_metadata ("private:close:closer")) { command_fail (si, fault::noprivs, _("\2%s\2 is closed."), chan); return; } /* ADD */ if (!strcasecmp ("ADD", cmd)) { if ((chanacs_source_flags (mc, si) & (CA_FLAGS | CA_REMOVE)) != (CA_FLAGS | CA_REMOVE)) { command_fail (si, fault::noprivs, _("You are not authorized to perform this operation.")); return; } mu = myuser_t::find_ext (uname); if (!mu) { /* we might be adding a hostmask */ if (!validhostmask (uname)) { command_fail (si, fault::badparams, _("\2%s\2 is neither a nickname nor a hostmask."), uname); return; } uname = collapse (uname); ca = chanacs_find_host_literal (mc, uname, 0); if (ca != NULL) { if (ca->level & CA_AKICK) command_fail (si, fault::nochange, _("\2%s\2 is already on the AKICK list for \2%s\2"), uname, mc->name); else command_fail (si, fault::alreadyexists, _("\2%s\2 already has flags \2%s\2 on \2%s\2"), uname, bitmask_to_flags (ca->level, chanacs_flags), mc->name); return; } ca = chanacs_find_host (mc, uname, CA_AKICK); if (ca != NULL) { command_fail (si, fault::nochange, _("The more general mask \2%s\2 is already on the AKICK list for \2%s\2"), ca->host, mc->name); return; } /* new entry */ ca2 = chanacs_open (mc, NULL, uname, true); if (chanacs_is_table_full (ca2)) { command_fail (si, fault::toomany, _("Channel %s access list is full."), mc->name); chanacs_close (ca2); return; } chanacs_modify_simple (ca2, CA_AKICK, 0); if (reason != NULL) ca2->add_metadata ("reason", reason); ca2->callback.akick_add (ca2); chanacs_close (ca2); verbose (mc, "\2%s\2 added \2%s\2 to the AKICK list.", get_source_name (si), uname); logcommand (si, CMDLOG_SET, "%s AKICK ADD %s", mc->name, uname); command_success_nodata (si, _("\2%s\2 has been added to the AKICK list for \2%s\2."), uname, mc->name); return; } else { if ((ca = chanacs_find (mc, mu, 0x0))) { if (ca->level & CA_AKICK) command_fail (si, fault::nochange, _("\2%s\2 is already on the AKICK list for \2%s\2"), mu->name, mc->name); else command_fail (si, fault::alreadyexists, _("\2%s\2 already has flags \2%s\2 on \2%s\2"), mu->name, bitmask_to_flags (ca->level, chanacs_flags), mc->name); return; } /* new entry */ ca2 = chanacs_open (mc, mu, NULL, true); if (chanacs_is_table_full (ca2)) { command_fail (si, fault::toomany, _("Channel %s access list is full."), mc->name); chanacs_close (ca2); return; } chanacs_modify_simple (ca2, CA_AKICK, 0); if (reason != NULL) ca2->add_metadata ("reason", reason); ca2->callback.akick_add (ca2); chanacs_close (ca2); command_success_nodata (si, _("\2%s\2 has been added to the AKICK list for \2%s\2."), mu->name, mc->name); verbose (mc, "\2%s\2 added \2%s\2 to the AKICK list.", get_source_name (si), mu->name); logcommand (si, CMDLOG_SET, "%s AKICK ADD %s", mc->name, mu->name); return; } } else if (!strcasecmp ("DEL", cmd)) { if ((chanacs_source_flags (mc, si) & (CA_FLAGS | CA_REMOVE)) != (CA_FLAGS | CA_REMOVE)) { command_fail (si, fault::noprivs, _("You are not authorized to perform this operation.")); return; } mu = myuser_t::find_ext (uname); if (!mu) { /* we might be deleting a hostmask */ ca = chanacs_find_host_literal (mc, uname, CA_AKICK); if (ca == NULL) { ca = chanacs_find_host (mc, uname, CA_AKICK); if (ca != NULL) command_fail (si, fault::nosuch_key, _("\2%s\2 is not on the AKICK list for \2%s\2, however \2%s\2 is."), uname, mc->name, ca->host); else command_fail (si, fault::nosuch_key, _("\2%s\2 is not on the AKICK list for \2%s\2."), uname, mc->name); return; } chanacs_modify_simple (ca, 0, CA_AKICK); chanacs_close (ca); verbose (mc, "\2%s\2 removed \2%s\2 from the AKICK list.", get_source_name (si), uname); logcommand (si, CMDLOG_SET, "%s AKICK DEL %s", mc->name, uname); command_success_nodata (si, _("\2%s\2 has been removed from the AKICK list for \2%s\2."), uname, mc->name); return; } if (!(ca = chanacs_find (mc, mu, CA_AKICK))) { command_fail (si, fault::nosuch_key, _("\2%s\2 is not on the AKICK list for \2%s\2."), mu->name, mc->name); return; } chanacs_modify_simple (ca, 0, CA_AKICK); chanacs_close (ca); command_success_nodata (si, _("\2%s\2 has been removed from the AKICK list for \2%s\2."), mu->name, mc->name); logcommand (si, CMDLOG_SET, "%s AKICK DEL %s", mc->name, mu->name); verbose (mc, "\2%s\2 removed \2%s\2 from the AKICK list.", get_source_name (si), mu->name); return; } else if (!strcasecmp ("LIST", cmd)) { int i = 0; if (!chanacs_source_has_flag (mc, si, CA_ACLVIEW)) { if (has_priv (si, PRIV_CHAN_AUSPEX)) operoverride = 1; else { command_fail (si, fault::noprivs, _("You are not authorized to perform this operation.")); return; } } command_success_nodata (si, _("AKICK list for \2%s\2:"), mc->name); LIST_FOREACH (n, mc->chanacs.head) { ca = (chanacs_t *) n->data; if (ca->level == CA_AKICK) { md = ca->find_metadata ("reason"); if (ca->myuser == NULL) command_success_nodata (si, _("%d: \2%s\2 %s [modified: %s ago]"), ++i, ca->host, md ? md->value : "", time_ago (ca->ts)); else if (!ca->myuser->logins.empty ()) command_success_nodata (si, _("%d: \2%s\2 (logged in) %s [modified: %s ago]"), ++i, ca->myuser->name, md ? md->value : "", time_ago (ca->ts)); else command_success_nodata (si, _("%d: \2%s\2 (not logged in) %s [modified: %s ago]"), ++i, ca->myuser->name, md ? md->value : "", time_ago (ca->ts)); } } command_success_nodata (si, _("Total of \2%d\2 %s in \2%s\2's AKICK list."), i, (i == 1) ? "entry" : "entries", mc->name); if (operoverride) logcommand (si, CMDLOG_ADMIN, "%s AKICK LIST (oper override)", mc->name); else logcommand (si, CMDLOG_GET, "%s AKICK LIST", mc->name); } else command_fail (si, fault::badparams, _("Invalid command. Use \2/%s%s help\2 for a command listing."), (ircd->uses_rcommand == false) ? "msg " : "", si->service->disp); } bool _modinit (module *m) { cs_cmdtree << cs_akick; help_addentry (cs_helptree, "AKICK", "help/chanserv/akick", NULL); return true; } void _moddeinit () { help_delentry (cs_helptree, "AKICK"); cs_cmdtree >> cs_akick; }