Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * =================================================================
- * Filename: cmdshun.c
- * Description: Command shun
- * Author: AngryWolf <angrywolf@flashmail.com>
- * Documentation: cmdshun.txt (comes with the package)
- * =================================================================
- */
- #include "config.h"
- #include "struct.h"
- #include "common.h"
- #include "sys.h"
- #include "numeric.h"
- #include "msg.h"
- #include "channel.h"
- #include <time.h>
- #include <sys/stat.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #ifdef _WIN32
- #include <io.h>
- #endif
- #include <fcntl.h>
- #include "h.h"
- #ifdef STRIPBADWORDS
- #include "badwords.h"
- #endif
- #ifdef _WIN32
- #include "version.h"
- #endif
- typedef struct _cmdentry CmdEntry;
- typedef struct _cmdshun CmdShun;
- typedef struct _ovrentry OvrEntry;
- /*
- * CmdEntry:
- * list of commands disabled for a user@host
- *
- * cmd: info about the disabled command
- * opt: additional options for PRIVSMG & NOTICE
- */
- struct _cmdentry
- {
- CmdEntry *prev, *next;
- OvrEntry *cmd;
- char opt;
- };
- /*
- * OvrEntry:
- * list of command overrides used by this module
- *
- * ovr: an override entry for the command
- * name: name of the command
- * used: how many times the command is used in CmdShuns
- * temporary: has a true value if the command belongs to temporarily
- * created command lists
- */
- struct _ovrentry
- {
- OvrEntry *prev, *next;
- Cmdoverride *ovr;
- char *name;
- unsigned short used;
- unsigned char temporary;
- };
- /*
- * CmdShun:
- * data structure for a command shun
- * primary keys: usermask, hostmask, cmdlist
- *
- * commands: a copy of the command list given the second parameter of
- * /cmdshun
- * cmdlist: a parsed form of the command list
- * numofcmds: how many commands are in the command list
- * event: an event to remove an expired cmdshun
- */
- struct _cmdshun
- {
- CmdShun *prev, *next;
- char *usermask, *hostmask;
- char *setby, *reason, *commands;
- CmdEntry *cmdlist;
- struct irc_netmask *netmask;
- Event *event;
- u_short numofcmds;
- TS set_at;
- TS expire_at;
- };
- extern void sendto_one(aClient *to, char *pattern, ...);
- extern void sendto_realops(char *pattern, ...);
- extern void sendto_serv_butone_token(aClient *one, char *prefix, char *command, char *token, char *pattern, ...);
- #define ERR_DISABLED ":%s 517 %s %s :Command disabled (%s)" /* ircu */
- #define MSG_CMDSHUN "CMDSHUN"
- #define TOK_CMDSHUN NULL
- #define MSG_CMDSHUNFWD "CMDSHUNFWD"
- #define TOK_CMDSHUNFWD "SF"
- #define OPT_FLAG '#'
- #define IsParam(x) (parc > (x) && !BadPtr(parv[(x)]))
- #define IsNotParam(x) (parc <= (x) || BadPtr(parv[(x)]))
- #define DelHook(x) if (x) HookDel(x); x = NULL
- #define DelCommand(x) if (x) CommandDel(x); x = NULL
- #define DelOverride(cmd, ovr) if (ovr && CommandExists(cmd)) CmdoverrideDel(ovr); ovr = NULL
- static Command *AddCommand(Module *module, char *msg, char *token, iFP func, unsigned char parameters, int flags);
- static Cmdoverride *AddOverride(char *msg, iFP cb);
- static int m_cmdshun(aClient *, aClient *, int, char *[]);
- static int m_cmdshunfwd(aClient *, aClient *, int, char *[]);
- static int ovr_cmd(Cmdoverride *, aClient *, aClient *, int, char *[]);
- static int cb_rehash();
- static int cb_rehash_complete();
- static int cb_server_connect(aClient *);
- static void del_cmdshun(CmdShun *s);
- static ModuleInfo *ModCmdshun;
- static Hook *HookRehashDone, *HookRehash, *HookServConn;
- static Command *CmdCmdshun, *CmdCmdshunfwd;
- static CmdShun *CmdShunList;
- static OvrEntry *OverridesList;
- static CmdEntry *tmp_cmdlist;
- static aClient *SetBy;
- static u_char module_loaded = 0;
- static char buf[BUFSIZE];
- static u_short tmp_numofcmds;
- #ifndef STATIC_LINKING
- static ModuleInfo *MyModInfo = NULL;
- #define MyMod MyModInfo->handle
- #define SAVE_MODINFO MyModInfo = modinfo;
- #else
- #define MyMod NULL
- #define SAVE_MODINFO
- #endif
- ModuleHeader MOD_HEADER(cmdshun)
- = {
- "cmdshun",
- "$Id: cmdshun.c,v 1.1 2004/08/16 13:31:25 angrywolf Exp $",
- "Command Shun",
- "3.2-b8-1",
- NULL
- };
- DLLFUNC int MOD_TEST(cmdshun)(ModuleInfo *modinfo)
- {
- return MOD_SUCCESS;
- }
- DLLFUNC int MOD_INIT(cmdshun)(ModuleInfo *modinfo)
- {
- SAVE_MODINFO
- #ifndef STATIC_LINKING
- ModuleSetOptions(modinfo->handle, MOD_OPT_PERM);
- #endif
- ModCmdshun = modinfo;
- CmdShunList = NULL;
- OverridesList = NULL;
- SetBy = NULL;
- tmp_cmdlist = NULL;
- tmp_numofcmds = 0;
- HookRehash = HookAddEx(modinfo->handle, HOOKTYPE_REHASH,
- cb_rehash);
- HookRehashDone = HookAddEx(modinfo->handle, HOOKTYPE_REHASH_COMPLETE,
- cb_rehash_complete);
- HookServConn = HookAddEx(modinfo->handle, HOOKTYPE_SERVER_CONNECT,
- cb_server_connect);
- CmdCmdshun = AddCommand(modinfo->handle, MSG_CMDSHUN, TOK_CMDSHUN,
- m_cmdshun, 4, 0);
- CmdCmdshunfwd = AddCommand(modinfo->handle, MSG_CMDSHUNFWD, TOK_CMDSHUNFWD,
- m_cmdshunfwd, MAXPARA, M_SERVER);
- if (!CmdCmdshun || !CmdCmdshunfwd)
- return MOD_FAILED;
- return MOD_SUCCESS;
- }
- DLLFUNC int MOD_LOAD(cmdshun)(int module_load)
- {
- cb_rehash_complete();
- return MOD_SUCCESS;
- }
- DLLFUNC int MOD_UNLOAD(cmdshun)(int module_unload)
- {
- CmdShun *s;
- ListStruct *next;
- DelHook(HookServConn);
- DelHook(HookRehashDone);
- DelHook(HookRehash);
- DelCommand(CmdCmdshunfwd);
- DelCommand(CmdCmdshun);
- cb_rehash();
- for (s = CmdShunList; s; s = (CmdShun *) next)
- {
- next = (ListStruct *) s->next;
- del_cmdshun(s);
- }
- return MOD_SUCCESS;
- }
- static int cb_rehash()
- {
- OvrEntry *o;
- module_loaded = 0;
- /*
- * What I do here is just deleting command overrides.
- * (Only command shun removals may delete OvrEntry structures.)
- */
- for (o = OverridesList; o; o = o->next)
- if (o->ovr)
- {
- DelOverride(o->name, o->ovr);
- }
- return 0;
- }
- static int cb_rehash_complete()
- {
- OvrEntry *o;
- if (!module_loaded)
- {
- for (o = OverridesList; o; o = o->next)
- if (!o->ovr)
- o->ovr = AddOverride(o->name, ovr_cmd);
- module_loaded = 1;
- }
- return 0;
- }
- static Command *AddCommand(Module *module, char *msg, char *token, iFP func,
- unsigned char parameters, int flags)
- {
- Command *cmd;
- if (CommandExists(msg))
- {
- config_error("Command %s already exists", msg);
- return NULL;
- }
- if (token && CommandExists(token))
- {
- config_error("Token %s already exists", token);
- return NULL;
- }
- cmd = CommandAdd(module, msg, token, func, parameters, flags);
- #ifndef STATIC_LINKING
- if (ModuleGetError(module) != MODERR_NOERROR || !cmd)
- #else
- if (!cmd)
- #endif
- {
- #ifndef STATIC_LINKING
- config_error("Error adding command %s: %s", msg,
- ModuleGetErrorStr(module));
- #else
- config_error("Error adding command %s", msg);
- #endif
- return NULL;
- }
- return cmd;
- }
- static Cmdoverride *AddOverride(char *msg, iFP cb)
- {
- Cmdoverride *ovr = CmdoverrideAdd(MyMod, msg, cb);
- #ifndef STATIC_LINKING
- if (ModuleGetError(MyMod) != MODERR_NOERROR || !ovr)
- #else
- if (!ovr)
- #endif
- {
- #ifndef STATIC_LINKING
- config_error("Error replacing command %s when loading module %s: %s",
- msg, MOD_HEADER(cmdshun).name, ModuleGetErrorStr(MyMod));
- #else
- config_error("Error replacing command %s when loading module %s",
- msg, MOD_HEADER(cmdshun).name);
- #endif
- return NULL;
- }
- return ovr;
- }
- /*
- * cb_server_connect:
- * Distribute our CmdShuns to other servers on the network
- * when they are connecting to us or we to them.
- */
- static int cb_server_connect(aClient *cptr)
- {
- CmdShun *s;
- for (s = CmdShunList; s; s = s->next)
- {
- sendto_one(cptr, ":%s %s ! %s %s %s %s %ld %ld :%s",
- me.name, IsToken(cptr) ? TOK_CMDSHUNFWD : MSG_CMDSHUNFWD,
- s->usermask, s->hostmask, s->commands, s->setby,
- (long) s->set_at, (long) s->expire_at,
- s->reason ? s->reason : "");
- }
- return 0;
- }
- /*
- * find_Cmd_quick:
- * This is a quick way to search for commands names.
- */
- static inline aCommand *find_Cmd_quick(char *cmd)
- {
- aCommand *p;
- for (p = CommandHash[toupper(*cmd)]; p; p = p->next)
- if (!stricmp(p->cmd, cmd))
- break;
- return p;
- }
- /*
- * find_cmdentry:
- * Look through a list of commands, and search for a command with
- * the given options (c->opt).
- */
- static CmdEntry *find_cmdentry(char *name, CmdEntry *list, char *param)
- {
- CmdEntry *c;
- for (c = list; c; c = c->next)
- if (!stricmp(c->cmd->name, name))
- {
- if (c->opt)
- {
- if (!param)
- continue;
- if (!stricmp(name, "privmsg") ||
- !stricmp(name, "notice"))
- {
- if (c->opt == 'p' && param[0] == '#')
- continue;
- if (c->opt == 'c' && param[0] != '#')
- continue;
- }
- }
- break;
- }
- return c;
- }
- static OvrEntry *find_ovrentry(char *name)
- {
- OvrEntry *o;
- for (o = OverridesList; o; o = o->next)
- if (!stricmp(o->name, name))
- break;
- return o;
- }
- /*
- * del_cmdlist:
- * Delete a list of command entries with their overrides.
- */
- static void del_cmdlist(CmdEntry **list)
- {
- CmdEntry *c;
- OvrEntry *o;
- ListStruct *next;
- for (c = *list; c; c = (CmdEntry *) next)
- {
- next = (ListStruct *) c->next;
- o = c->cmd;
- DelListItem(c, *list);
- if (!--o->used)
- {
- DelListItem(o, OverridesList);
- DelOverride(o->name, o->ovr);
- if (!o->temporary)
- {
- MyFree(o->name);
- MyFree(o);
- }
- }
- MyFree(c);
- }
- }
- /*
- * del_cmdlist_noovr:
- * Delete a list of command entries, but keep the overrides (this is
- * used with make_cmdlist, see below).
- */
- static void del_cmdlist_noovr(CmdEntry **list)
- {
- CmdEntry *c;
- OvrEntry *o;
- ListStruct *next;
- for (c = *list; c; c = (CmdEntry *) next)
- {
- next = (ListStruct *) c->next;
- o = c->cmd;
- DelListItem(c, *list);
- if (!o->used)
- {
- MyFree(o->name);
- MyFree(o);
- }
- else
- o->temporary = 0;
- MyFree(c);
- }
- }
- /*
- * make_cmdlist:
- * Create an initial list of command entries without overrides.
- * ('commands' may not be NULL.) Also return the number of
- * commands in the list through 'num'.
- */
- static CmdEntry *make_cmdlist(char *commands, u_short *num)
- {
- CmdEntry *entry, *cmdlist = NULL;
- OvrEntry *o;
- char *tmp = strdup(commands);
- char *c, *p = NULL;
- char *opt;
- u_short count = 0;
- for (c = strtoken(&p, tmp, ","); c; c = strtoken(&p, NULL, ","))
- {
- entry = (CmdEntry *) MyMallocEx(sizeof(CmdEntry));
- if ((opt = strchr(c, OPT_FLAG)))
- {
- opt[0] = 0;
- /*
- * Syntax is: <command>#<flag>. Set entry->opt to
- * OPT_FLAG when <flag> is missing or long than
- * one character.
- */
- entry->opt = (!opt[1] || opt[2])
- ? OPT_FLAG : opt[1];
- }
- if (!(o = find_ovrentry(c)))
- {
- o = (OvrEntry *) MyMallocEx(sizeof(OvrEntry));
- o->name = strdup(c);
- }
- if (opt)
- opt[0] = OPT_FLAG;
- o->temporary = 1;
- entry->cmd = o;
- AddListItem(entry, cmdlist);
- count++;
- }
- MyFree(tmp);
- *num = count;
- return cmdlist;
- }
- static void del_cmdshun(CmdShun *s)
- {
- DelListItem(s, CmdShunList);
- MyFree(s->usermask);
- MyFree(s->hostmask);
- MyFree(s->commands);
- MyFree(s->setby);
- MyFree(s->reason);
- del_cmdlist(&s->cmdlist);
- if (s->netmask)
- MyFree(s->netmask);
- if (s->event)
- EventDel(s->event);
- MyFree(s);
- }
- static void del_tmp_data()
- {
- del_cmdlist_noovr(&tmp_cmdlist);
- tmp_numofcmds = 0;
- }
- static void event_cmdshunexpire(CmdShun *s)
- {
- char gmt[64], *settime, *p;
- TS now = TStime();
- if (s->expire_at > now)
- {
- /*
- * I don't know how feasible this can be, but at least
- * inform opers if such a thing happens...
- */
- if (s->expire_at)
- {
- char gmt2[64];
- strlcpy(gmt2, asctime(gmtime(&s->expire_at)), sizeof gmt);
- iCstrip(gmt2);
- sendto_realops("event_cmdshunexpire(): expire for "
- "non-yet-expired CmdShun %s@%s with "
- "command%s %s (should expire on %s GMT)",
- s->usermask, s->hostmask,
- s->cmdlist->next ? "s" : "", s->commands,
- gmt);
- }
- else
- {
- sendto_realops("event_cmdshunexpire(): expire for "
- "permanent CmdShun %s@%s with command%s %s",
- s->usermask, s->hostmask,
- s->cmdlist->next ? "s" : "", s->commands,
- gmt);
- }
- return;
- }
- /* notification */
- strlcpy(gmt, asctime(gmtime(&s->set_at)), sizeof gmt);
- iCstrip(gmt);
- settime = pretty_time_val(TStime() - s->set_at);
- if (*(p = settime + strlen(settime) - 1) == ' ')
- *p = 0;
- snprintf(buf, sizeof buf, "Expiring CmdShun (%s@%s with command%s "
- "%s) made by %s (Reason: %s) set %s ago)",
- s->usermask, s->hostmask, s->cmdlist->next ? "s" : "",
- s->commands, s->setby, s->reason ? s->reason : "no reason",
- settime);
- sendto_snomask(SNO_TKL, "*** %s", buf);
- ircd_log(LOG_TKL, "%s", buf);
- del_cmdshun(s);
- }
- static int ovr_cmd(Cmdoverride *ovr, aClient *cptr, aClient *sptr, int parc, char *parv[])
- {
- if (MyConnect(sptr) && !IsULine(sptr) && IsPerson(sptr) && !IsAnOper(sptr))
- {
- CmdShun *s;
- char *param = IsParam(1) ? parv[1] : NULL;
- char *ip = GetIP(sptr);
- char *user = sptr->user->username;
- char *host = sptr->sockhost;
- char *cmd = ovr->command->cmd;
- for (s = CmdShunList; s; s = s->next)
- {
- if (!find_cmdentry(cmd, s->cmdlist, param))
- continue;
- if (match(s->usermask, user))
- continue;
- if (s->netmask)
- {
- if (match_ip(sptr->ip, NULL, NULL, s->netmask))
- break;
- continue;
- }
- if (!match(s->hostmask, host))
- break;
- if (!match(s->hostmask, ip))
- break;
- }
- if (s)
- {
- sendto_one(sptr, ERR_DISABLED, me.name, sptr->name,
- cmd, s->reason ? s->reason : "no reason");
- return 0;
- }
- }
- return CallCmdoverride(ovr, cptr, sptr, parc, parv);
- }
- /*
- ** m_cmdshun
- ** ---------
- **
- ** Used by IRCOps to add/remove CmdShuns.
- **
- ** parv[1]: u@h mask or nick
- ** parv[2]: commands
- ** parv[3]: expire time (optional)
- ** parv[4]: reason (optional)
- **
- */
- #define PFrom 0
- #define PWhat 1
- #define PUserMask 2
- #define PHostMask 3
- #define PCommands 4
- #define PSetBy 5
- #define PSetAt 6
- #define PExpireAt 7
- #define PReason 8
- static int m_cmdshun(aClient *cptr, aClient *sptr, int parc, char *parv[])
- {
- char *params[9];
- char *p, *mask, *usermask, *hostmask;
- char set_at[BUFSIZE], expire_at[BUFSIZE];
- u_char add;
- if (!MyConnect(sptr) || !IsPerson(sptr))
- return 0;
- if (!IsAnOper(sptr) && !IsULine(sptr))
- {
- sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, sptr->name);
- return 0;
- }
- if (IsNotParam(1))
- {
- CmdShun *s;
- char gmt[64], *expiretime = NULL, *p;
- for (s = CmdShunList; s; s = s->next)
- {
- strlcpy(gmt, asctime(gmtime(&s->set_at)), sizeof gmt);
- iCstrip(gmt);
- if (s->expire_at)
- {
- expiretime = pretty_time_val(s->expire_at - TStime());
- if (*(p = expiretime + strlen(expiretime) - 1) == ' ')
- *p = 0;
- }
- sendto_one(sptr, ":%s %i %s :CmdShun %s@%s %s (set at: %s, "
- "%s%s, reason: %s)",
- me.name, RPL_TEXT, sptr->name,
- s->usermask, s->hostmask, s->commands, gmt,
- s->expire_at ? "expires in: " : "never expires",
- s->expire_at ? expiretime : "",
- s->reason ? s->reason : "no reason");
- }
- sendnotice(sptr, "End of /CMDSHUN list");
- return 0;
- }
- if (!IsULine(sptr) && !OPCanTKL(sptr))
- {
- sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, sptr->name);
- return 0;
- }
- /* add or remove? */
- mask = parv[1];
- add = 1;
- switch(*mask)
- {
- case '-':
- add = 0;
- case '+':
- mask++;
- }
- /* no mask & command(s)? */
- if (!*mask || IsNotParam(2))
- {
- sendnotice(sptr, "*** \2Usage:\2 /cmdshun [+]<user@host>|<nick> <command-list> [<expiretime>] :<reason>]");
- sendnotice(sptr, "*** /cmdshun -<user@host>|<nick> <command-list>");
- sendnotice(sptr, "*** <command-list>: a comma-separated list of one or more command names");
- sendnotice(sptr, "*** <expiretime>: a time value in the usual format");
- sendnotice(sptr, "*** \2Examples:\2 /cmdshun *user@*.host1 whois,whowas 2h5s This is your punishment");
- sendnotice(sptr, "*** /cmdshun -*user@*.host1 whois,whowas");
- return 0;
- }
- /* check if it's a hostmask and legal */
- if ((p = strchr(mask, '@')))
- {
- if (add && strchr(mask, '!'))
- {
- sendnotice(sptr, "[error] Cannot have ! in masks.");
- return 0;
- }
- /*
- * I know buggy OS'es shouldn't be supported, but since I'm developing
- * modules on a Linux with glibc-2.3.2, I don't want to see that
- * strtok() bug again with /cmdshun +@ ... (see m_tkl_line if you don't
- * know what I'm talking about). Also: I don't think my solution is
- * slower.
- *
- * http://www.mail-archive.com/bug-glibc@gnu.org/msg01210.html
- * http://lists.gnu.org/archive/html/bug-glibc/2001-02/msg00117.html
- */
- *p = 0;
- usermask = mask;
- hostmask = p + 1;
- if (!*hostmask)
- {
- if (!*usermask)
- {
- sendnotice(sptr, "[error] Syntax error in mask.");
- return 0;
- }
- /* convert "user@" to "*@user" */
- hostmask = usermask;
- usermask = "*";
- }
- else if (!*usermask)
- /* convert "@host" to "*@host" */
- usermask = "*";
- }
- else
- {
- aClient *acptr;
- /* It's seemingly a nick .. let's see if we can find the user */
- if (!(acptr = find_person(mask, NULL)))
- {
- sendto_one(sptr, rpl_str(ERR_NOSUCHNICK), me.name,
- sptr->name, mask);
- return 0;
- }
- usermask = "*";
- hostmask = acptr->user->realhost;
- }
- /* do other checkings & build up params list */
- if (add)
- {
- struct tm *t;
- OvrEntry *o;
- CmdEntry *c, *c2;
- TS secs, now;
- int i = 0;
- for (p = hostmask; *p; p++)
- if (*p != '*' && *p != '.' && *p != '?')
- i++;
- if (i < 4)
- {
- sendnotice(sptr, "*** [error] Too broad mask");
- return 0;
- }
- /* Prepare temporary cmdlist for m_cmdshunfwd */
- tmp_cmdlist = make_cmdlist(parv[2], &tmp_numofcmds);
- /* Check if valid command names & options are given */
- for (c = tmp_cmdlist; c; c = c->next)
- {
- o = c->cmd;
- if (!find_Cmd_quick(o->name))
- {
- /*
- * It may happen that a command exists on
- * a server while it doesn't on other servers
- * of the network. I think the best is to
- * accept non-existing commands only remotely.
- * The goal is to not have desynchs between
- * servers.
- */
- sendnotice(sptr, "[error] No such command: "
- "%s", o->name);
- del_tmp_data();
- return 0;
- }
- if (!stricmp(o->name, "privmsg") ||
- !stricmp(o->name, "notice"))
- {
- if (!c->opt)
- continue;
- if (c->opt == OPT_FLAG)
- {
- sendnotice(sptr, "[error] Syntax "
- "error after command '%s'",
- o->name);
- del_tmp_data();
- return 0;
- }
- if (c->opt != 'p' && c->opt != 'c')
- {
- sendnotice(sptr, "[error] Option '%c' "
- "is invalid for command '%s'",
- c->opt, o->name);
- del_tmp_data();
- return 0;
- }
- }
- else if (c->opt)
- {
- sendnotice(sptr, "[error] No options "
- "available for command %s",
- o->name);
- del_tmp_data();
- return 0;
- }
- }
- /* Check for duplicated commands */
- for (c = tmp_cmdlist; c; c = c->next)
- for (c2 = c->next; c2; c2 = c2->next)
- if (!stricmp(c->cmd->name, c2->cmd->name))
- {
- sendnotice(sptr, "[error] Command '%s' "
- "is already on the given list",
- c->cmd->name);
- del_tmp_data();
- return 0;
- }
- secs = 0;
- if (IsParam(3))
- {
- secs = atime(parv[3]);
- if (secs < 0)
- {
- sendnotice(sptr, "*** [error] The time you "
- "specified is out of range!");
- return 0;
- }
- }
- else if (DEFAULT_BANTIME)
- secs = DEFAULT_BANTIME;
- now = TStime();
- if (secs)
- secs += now;
- ircsprintf(set_at, "%ld", now);
- ircsprintf(expire_at, "%ld", secs);
- i = atol(expire_at);
- t = gmtime((TS *)&i);
- if (!t)
- {
- sendnotice(sptr, "*** [error] The time you specified "
- "is out of range");
- return 0;
- }
- params[PWhat] = "+";
- params[PSetAt] = set_at;
- params[PExpireAt] = expire_at;
- params[PReason] = IsParam(4) ? parv[4] : "";
- }
- else
- {
- params[PWhat] = "-";
- }
- params[PFrom] = me.name;
- params[PUserMask] = usermask;
- params[PHostMask] = hostmask;
- params[PCommands] = parv[2];
- params[PSetBy] = make_nick_user_host(sptr->name,
- sptr->user->username, GetHost(sptr));
- SetBy = sptr;
- m_cmdshunfwd(&me, &me, 9, params);
- SetBy = NULL;
- return 0;
- }
- /*
- ** m_cmdshunfwd
- ** ------------
- **
- ** Used by servers to distribute CmdShuns.
- **
- ** parv[0]: server name
- ** parv[1]: + (add) / - (remove) / ! (sync)
- ** parv[2]: usermask
- ** parv[3]: hostmask
- ** parv[4]: commands
- ** parv[5]: setby (or removed by)
- ** parv[6]: set_at
- ** parv[7]: expire_at
- ** parv[8]: reason (optional)
- **
- ** Note: NO PARAM CHECKING! You shouldn't really know anything
- ** about the existence of this command. Otherwise
- ** don't complain about server crashes!
- */
- static int m_cmdshunfwd(aClient *cptr, aClient *sptr, int parc, char *parv[])
- {
- char *usermask = parv[PUserMask], *hostmask = parv[PHostMask];
- char *commands = parv[PCommands];
- char gmt[64], gmt2[64], what = *parv[PWhat];
- CmdEntry *c, *c2;
- CmdShun *s;
- if (!tmp_cmdlist)
- tmp_cmdlist = make_cmdlist(commands, &tmp_numofcmds);
- switch(what)
- {
- case '!':
- case '+':
- {
- struct irc_netmask tmp;
- OvrEntry *o;
- TS setat = atol(parv[PSetAt]);
- TS expireat = atol(parv[PExpireAt]);
- /* Preliminary checks on commands list */
- for (c = tmp_cmdlist; c; c = c->next)
- if (c->cmd->used >= 5000) /* just to be sure */
- {
- if (SetBy)
- sendnotice(SetBy, "[error] Too much "
- "cmdshuns for command %s",
- c->cmd->name);
- del_tmp_data();
- return 0;
- }
- /* Check if the cmdshun is added */
- for (s = CmdShunList; s; s = s->next)
- {
- if (stricmp(s->usermask, usermask) ||
- stricmp(s->hostmask, hostmask))
- continue;
- for (c = s->cmdlist; c; c = c->next)
- for (c2 = tmp_cmdlist; c2; c2 = c2->next)
- if (!stricmp(c->cmd->name,
- c2->cmd->name))
- goto loopend;
- }
- loopend: if (s) /* found */
- {
- /*
- * I haven't got definite plans about allowing
- * updates of CmdShuns. Currently the sync fight
- * idea seems to work, and I'll leave it here
- * until I work out the new method to handle
- * duplicate entries.
- */
- if (what != '!')
- {
- if (SetBy)
- sendnotice(SetBy, "[error] A cmdshun "
- "with mask %s@%s and one of "
- "the specified command(s) is "
- "already set",
- usermask, hostmask);
- del_tmp_data();
- return 0;
- }
- else /* sync problem, begin fight */
- {
- enum Results { r_WeWon, r_TheyWon };
- u_char result = r_WeWon;
- if (s->numofcmds > tmp_numofcmds)
- /* we won */;
- else if (s->numofcmds < tmp_numofcmds)
- result = r_TheyWon;
- else if (s->set_at < setat)
- /* we won */;
- else if (s->set_at > setat)
- result = r_TheyWon;
- else if (s->expire_at > expireat)
- /* we won */;
- else if (s->expire_at < expireat)
- result = r_TheyWon;
- else if (stricmp(s->reason, parv[PReason]) < 0)
- /* we won */;
- else if (stricmp(s->reason, parv[PReason]) > 0)
- result = r_TheyWon;
- else if (stricmp(s->commands, commands) < 0)
- /* we won */;
- else if (stricmp(s->commands, commands) > 0)
- result = r_TheyWon;
- /* default:
- same cmdshuns -> we won */
- /* sendto_realops("cmdshun sync-time fight: result=[%s], ours=[%s@%s %s %ld %ld] theirs=[%s@%s %s %ld %ld]",
- result == r_TheyWon ? "r_TheyWon" : "r_WeWon",
- s->usermask, s->hostmask, s->commands, (long) s->set_at, (long) s->expire_at,
- usermask, hostmask, commands, setat, expireat); */
- if (result == r_TheyWon)
- {
- /* replace the cmdshun with the new one */
- del_cmdshun(s);
- }
- else
- {
- /* don't accept the new cmdshun */
- del_tmp_data();
- return 0;
- }
- }
- }
- /* Create a cmdshun entry */
- s = (CmdShun *) MyMallocEx(sizeof(CmdShun));
- s->usermask = strdup(usermask);
- s->hostmask = strdup(hostmask);
- s->commands = strdup(commands);
- s->setby = strdup(parv[PSetBy]);
- s->reason = *parv[PReason] ? strdup(parv[PReason]) : NULL;
- for (c = tmp_cmdlist; c; c = c->next)
- {
- o = c->cmd;
- o->temporary = 0;
- if (!o->used++)
- {
- o->ovr = AddOverride(o->name, ovr_cmd);
- AddListItem(o, OverridesList);
- }
- }
- s->cmdlist = tmp_cmdlist;
- s->numofcmds = tmp_numofcmds;
- s->set_at = setat;
- s->expire_at = expireat;
- if ((tmp.type = parse_netmask(hostmask, &tmp)) != HM_HOST)
- {
- s->netmask = MyMallocEx(sizeof(struct irc_netmask));
- bcopy(&tmp, s->netmask, sizeof(struct irc_netmask));
- }
- AddListItem(s, CmdShunList);
- tmp_cmdlist = NULL;
- /* Notification */
- if (what == '+')
- {
- strlcpy(gmt, asctime(gmtime(&s->set_at)), sizeof gmt);
- iCstrip(gmt);
- if(s->expire_at)
- {
- s->event = EventAddEx(MyMod, "cmdshunexpire",
- s->expire_at - TStime(), 1,
- event_cmdshunexpire, s);
- strlcpy(gmt2, asctime(gmtime(&s->expire_at)),
- sizeof gmt2);
- iCstrip(gmt2);
- snprintf(buf, sizeof buf, "Timed CmdShun added "
- "for %s@%s with command%s %s on %s GMT "
- "(from %s to expire at %s GMT: %s)",
- usermask, hostmask,
- s->cmdlist->next ? "s" : "",
- commands, gmt, parv[PSetBy], gmt2,
- s->reason ? s->reason : "no reason");
- }
- else
- {
- snprintf(buf, sizeof buf, "Permanent CmdShun "
- "added for %s@%s with command%s %s on "
- "%s GMT (from %s: %s)",
- usermask, hostmask,
- s->cmdlist->next ? "s" : "",
- commands, gmt, parv[PSetBy],
- s->reason ? s->reason : "no reason");
- }
- sendto_snomask(SNO_TKL, "*** %s", buf);
- ircd_log(LOG_TKL, "%s", buf);
- }
- sendto_serv_butone_token(NULL, parv[PFrom], MSG_CMDSHUNFWD,
- TOK_CMDSHUNFWD, "%c %s %s %s %s %s %s :%s",
- what, usermask, hostmask, commands, parv[PSetBy],
- parv[PSetAt], parv[PExpireAt], parv[PReason]);
- break;
- }
- case '-':
- {
- u_char required, found;
- /* Check if the cmdshun is added */
- for (s = CmdShunList; s; s = s->next)
- {
- if (stricmp(s->usermask, usermask) ||
- stricmp(s->hostmask, hostmask))
- continue;
- required = found = 0;
- for (c = s->cmdlist; c; c = c->next)
- {
- required++;
- for (c2 = tmp_cmdlist; c2; c2 = c2->next)
- if (!stricmp(c->cmd->name,
- c2->cmd->name))
- found++;
- }
- if (required == found)
- break;
- }
- if (!s)
- {
- if (SetBy)
- sendnotice(SetBy, "[error] No cmdshun "
- "is set with mask %s@%s and "
- "command%s %s",
- usermask, hostmask,
- strchr(commands, ',') ? "s" : "",
- commands);
- del_tmp_data();
- return 0;
- }
- /* Notification */
- strlcpy(gmt, asctime(gmtime(&s->set_at)), sizeof gmt);
- iCstrip(gmt);
- snprintf(buf, sizeof buf, "%s removed CmdShun %s@%s set "
- "with command%s %s (at %s - reason: %s)",
- parv[PSetBy], usermask, hostmask,
- s->cmdlist->next ? "s" : "", commands,
- gmt, s->reason ? s->reason : "no reason");
- sendto_snomask(SNO_TKL, "*** %s", buf);
- ircd_log(LOG_TKL, "%s", buf);
- /* Delete cmdshun entry & temporary stuff */
- del_cmdshun(s);
- del_tmp_data();
- sendto_serv_butone_token(NULL, parv[PFrom],
- MSG_CMDSHUNFWD, TOK_CMDSHUNFWD,
- "- %s %s %s %s",
- usermask, hostmask, commands, parv[PSetBy]);
- break;
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement