[more]
Код: /* * ==================================================================
* Filename: m_spy.c
* Description: Real-time spying
* Written by: AngryWolf <angrywolf@flashmail.com>
* The idea was born by: Toxyc <toxyc@freemail.hu>
* ==================================================================
*/
#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
// ==================================================================
// Definitions & macros
// ==================================================================
#define MSG_SPY "spy"
#define TOK_SPY "spy"
#define MSG_SPYCHANNEL "SPYCHAN"
#define TOK_SPYCHANNEL "SPC"
#define MSG_SPYSEND "SPYSEND"
#define TOK_SPYSEND "SPE"
#define MSG_SPYCHSEND "SPYCHSEND"
#define TOK_SPYCHSEND "SPT"
#define MSG_SPYFORWARD "SPYFORWARD"
#define TOK_SPYFORWARD "SPF"
#define MSG_SPYCHFORWARD "SPYCHFORWARD"
#define TOK_SPYCHFORWARD "SPG"
#define MSG_SPYSTATS "SPYSTATS"
#define TOK_SPYSTATS "SPS"
#define MyMod SpyModInfo->handle
#define FlagSpy 'P'
#define LockFlag '@'
#define LockFlagStr "@"
#define SPY_NOTICE ":%s NOTICE %s :*** "
#define SPY_LINE "=================================================="
#define ircfree(x) if (x) free(x)
#define ircstrdup(x,y) if (x) MyFree(x); if (!y) x = NULL; else x = strdup(y)
#define DelSnomask(x) if (x) SnomaskDel(x); x = NULL
#define DelHook(x) if (x) HookDel(x); x = NULL
#define DelCommand(x) if (x) CommandDel(x); x = NULL
#define IsParam(x) (parc > (x) && !BadPtr(parv[(x)]))
#define IsValidParam(x) (parc > (x) && !BadPtr(parv[(x)]) && *parv[(x)] != '*')
#define AddLock(lock) (lock ? LockFlagStr : "")
#define GetLock(str) (*str == LockFlag ? 1 : 0)
#define SplitLock(lock, str) del_prefix(str, &(lock), &(str))
#define MergeLock(lock, str) AddLock(lock), str
#define MergeLockOpt(lock, str) str ? AddLock(lock) : "", str ? str : "*"
#define MergeLockEmp(lock, str) str ? AddLock(lock) : "", str ? str : ""
#define SpyForward5(cptr, cmd, who, nick1, nick2, channel, lock1, lock2) \
sendto_serv_butone_token(cptr, me.name, MSG_SPYFORWARD, TOK_SPYFORWARD, \
"%s %s %s%s %s%s %s", \
cmd, who, MergeLock(lock1, nick1), MergeLockOpt(lock2, nick2), \
channel ? channel : "*")
#define SpyForward4(cptr, cmd, who, nick1, nick2, lock1, lock2) \
sendto_serv_butone_token(cptr, me.name, MSG_SPYFORWARD, TOK_SPYFORWARD, \
"%s %s %s%s %s%s", \
cmd, who, MergeLock(lock1, nick1), MergeLockOpt(lock2, nick2))
#define SpyForward3(cptr, cmd, who, nick1, lock1) \
sendto_serv_butone_token(cptr, me.name, MSG_SPYFORWARD, TOK_SPYFORWARD, \
"%s %s %s%s", \
cmd, who, MergeLock(lock1, nick1))
#define SpyForward2(cptr, cmd, who) \
sendto_serv_butone_token(cptr, me.name, MSG_SPYFORWARD, TOK_SPYFORWARD, \
"%s %s", \
cmd, who)
#define SpyForward1(cptr, cmd) \
sendto_serv_butone_token(cptr, me.name, MSG_SPYFORWARD, TOK_SPYFORWARD, \
"%s", \
cmd)
#define SpyChForward4(cptr, cmd, who, channel, sendto, lock) \
sendto_serv_butone_token(cptr, me.name, MSG_SPYCHFORWARD, TOK_SPYCHFORWARD, \
"%s %s %s%s %s", \
cmd, who, MergeLock(lock, channel), sendto ? sendto : "*")
#define SpyChForward3(cptr, cmd, who, channel, lock) \
sendto_serv_butone_token(cptr, me.name, MSG_SPYCHFORWARD, TOK_SPYCHFORWARD, \
"%s %s %s%s", \
cmd, who, MergeLock(lock, channel))
#define SpyChForward2(cptr, cmd, who) \
sendto_serv_butone_token(cptr, me.name, MSG_SPYCHFORWARD, TOK_SPYCHFORWARD, \
"%s %s", \
cmd, who)
typedef struct _spystruct SpyStruct;
typedef struct _spychstruct SpyChStruct;
struct _spystruct
{
SpyStruct *prev, *next;
aClient *who; /* Who is spying */
char *nick1; /* First nick to spy */
char *nick2; /* Second nick to spy (may be NULL) */
char *chname; /* Where to put messages (may be NULL) */
u_int lock1:1; /* 1 if nick1 is locked, otherwise 0 */
u_int lock2:1; /* 1 if nick2 is locked, otherwise 0 */
};
struct _spychstruct
{
SpyChStruct *prev, *next;
aClient *who; /* Who is spying */
char *channel; /* Channel to be spyed */
char *sendto; /* Where to put messages (may be NULL) */
u_int lock; /* True if nick1 is locked, otherwise 0 */
};
static SpyStruct *FindSpyItem1(aClient *acptr, char *nick);
static SpyStruct *FindSpyItem2(aClient *acptr, char *nick1, char *nick2);
static SpyChStruct *FindSpyChItem(aClient *acptr, char *channel);
static void AddSpyItem(aClient *acptr, char *nick1, char *nick2, char *chname, u_int lock1, u_int lock2);
static void AddSpyChItem(aClient *acptr, char *channel, char *sendto, u_int lock);
static void DelSpyItem(SpyStruct *s);
static void DelSpyChItem(SpyChStruct *s);
static unsigned int spy_paramcheck(aClient *cptr, int parc, char *parv[], char **nick1, char **nick2, char **channel, u_int *lock1, u_int *lock2);
static unsigned int spych_paramcheck(aClient *cptr, int parc, char *parv[], char **channel, char **sendto, u_int *lock);
static void spy_send_client(aClient *acptr, int notice, char *nick1, char *nick2, char *text);
static void spy_send_channel(aClient *cptr, char *channel, int notice, char *nick1, char *nick2, char *text);
static void spych_send_client(aClient *acptr, int notice, char *nick, char *channel, char *text);
static void spych_send_channel(aClient *cptr, char *sendto, int notice, char *nick, char *channel, char *text);
static void del_prefix(char *str, u_int *lock, char **newstr);
static Command *AddCommand(char *msg, char *token, int (*func)());
DLLFUNC int m_spy(aClient *cptr, aClient *sptr, int parc, char *parv[]);
DLLFUNC int m_spychannel(aClient *cptr, aClient *sptr, int parc, char *parv[]);
DLLFUNC int m_spysend(aClient *cptr, aClient *sptr, int parc, char *parv[]);
DLLFUNC int m_spychsend(aClient *cptr, aClient *sptr, int parc, char *parv[]);
DLLFUNC int m_spyforward(aClient *cptr, aClient *sptr, int parc, char *parv[]);
DLLFUNC int m_spychforward(aClient *cptr, aClient *sptr, int parc, char *parv[]);
DLLFUNC int m_spystats(aClient *cptr, aClient *sptr, int parc, char *parv[]);
DLLFUNC char *spy_on_privmsg(aClient *, aClient *, aClient *, char *, int);
DLLFUNC char *spy_on_chanmsg(aClient *, aClient *, aChannel *, char *, int);
DLLFUNC int spy_on_quit(aClient *, char *);
DLLFUNC int spy_on_remote_quit(aClient *, char *);
DLLFUNC int spy_on_server_connect(aClient *);
DLLFUNC int spy_on_local_nickchange(aClient *, char *);
DLLFUNC int spy_on_remote_nickchange(aClient *, aClient *, char *);
DLLFUNC int spy_on_channel_destroy(aChannel *);
// ==================================================================
// Module header
// ==================================================================
ModuleHeader MOD_HEADER(m_spy)
= {
"falanfilan",
"$Id: m_spy.c,v 3.6 2003/12/01 18:31:45 angrywolf Exp $",
"iyi bişiy",
"3.2-b8-1",
NULL
};
// ==================================================================
// Main declarations
// ==================================================================
static char *SpyHelp[] =
{
SPY_NOTICE "\2Usage:\2",
SPY_NOTICE "/spy add <nick1> [<nick2> [<#channel>]]",
SPY_NOTICE "/spy del <nick1> [<nick2>]",
SPY_NOTICE "/spy list [<nick1> [<nick2>]] [<#channel>]",
SPY_NOTICE "/spy clear",
SPY_NOTICE "\2Examples:\2",
SPY_NOTICE "/spy add AngryWolf Toxyc #secret",
SPY_NOTICE "/spy del AngryWolf",
SPY_NOTICE "/spy list #secret",
NULL
};
static char *SpyChHelp[] =
{
SPY_NOTICE "\2Usage:\2",
SPY_NOTICE "/spychan add <#channel> [<#sendto>]]",
SPY_NOTICE "/spychan del <#channel>",
SPY_NOTICE "/spychan list [<#channel>]",
SPY_NOTICE "/spychan clear",
SPY_NOTICE "\2Examples:\2",
SPY_NOTICE "/spychan add #----- #spy",
SPY_NOTICE "/spychan del #-----",
SPY_NOTICE "/spychan list",
NULL
};
ModuleInfo *SpyModInfo;
Command *CmdSpy, *CmdSpychannel, *CmdSpysend, *CmdSpychsend;
Command *CmdSpyforward, *CmdSpychforward, *CmdSpystats;
Snomask *SpySnomask;
long SNO_SPY;
static Hook *HookPrivMsg;
static Hook *HookChanMsg;
static Hook *HookQuit;
static Hook *HookRemoteQuit;
static Hook *HookServConn;
static Hook *HookLocalNick;
static Hook *HookRemoteNick;
static Hook *HookChanDest;
static SpyStruct *SpyList = NULL;
static SpyChStruct *SpyChList = NULL;
// ==================================================================
// Module initalization, loading and unloading
// ==================================================================
static Command *AddCommand(char *msg, char *token, int (*func)())
{
Command *cmd;
if (CommandExists(msg))
{
config_error("Command %s already exists", msg);
return NULL;
}
if (CommandExists(token))
{
config_error("Token %s already exists", token);
return NULL;
}
cmd = CommandAdd(MyMod, msg, token, func, MAXPARA, 0);
#ifndef _WIN32
if (ModuleGetError(MyMod) != MODERR_NOERROR || !cmd)
#else
if (!cmd)
#endif
{
#ifndef _WIN32
config_error("Error adding command %s: %s", msg,
ModuleGetErrorStr(MyMod));
#else
config_error("Error adding command %s", msg);
#endif
return NULL; /* just to be sure */
}
return cmd;
}
static Snomask *AddSnomask(char flag, int (*allowed)(aClient *sptr, int what), long *mode)
{
Snomask *s;
*mode = 0;
s = SnomaskAdd(MyMod, flag, allowed, mode);
#ifndef _WIN32
if ((ModuleGetError(MyMod) != MODERR_NOERROR) || !s)
#else
if (!s)
#endif
{
#ifndef _WIN32
sendto_realops("[\2m_spy\2] Error adding snomask %c: %s",
flag, ModuleGetErrorStr(MyMod));
#else
sendto_realops("[\2m_spy\2] Error adding snomask %c",
flag);
#endif
return NULL;
}
return s;
}
DLLFUNC int MOD_INIT(m_spy)(ModuleInfo *modinfo)
{
int ret = MOD_SUCCESS;
SpyModInfo = modinfo;
HookPrivMsg = HookAddPCharEx(MyMod, HOOKTYPE_USERMSG, spy_on_privmsg);
HookChanMsg = HookAddPCharEx(MyMod, HOOKTYPE_CHANMSG, spy_on_chanmsg);
HookQuit = HookAddEx(MyMod, HOOKTYPE_LOCAL_QUIT, spy_on_quit);
HookRemoteQuit = HookAddEx(MyMod, HOOKTYPE_REMOTE_QUIT, spy_on_remote_quit);
HookServConn = HookAddEx(MyMod, HOOKTYPE_SERVER_CONNECT, spy_on_server_connect);
HookLocalNick = HookAddEx(MyMod, HOOKTYPE_LOCAL_NICKCHANGE, spy_on_local_nickchange);
HookRemoteNick = HookAddEx(MyMod, HOOKTYPE_REMOTE_NICKCHANGE, spy_on_remote_nickchange);
HookChanDest = HookAddEx(MyMod, HOOKTYPE_CHANNEL_DESTROY, spy_on_channel_destroy);
CmdSpy = AddCommand(MSG_SPY, TOK_SPY, m_spy);
CmdSpychannel = AddCommand(MSG_SPYCHANNEL, TOK_SPYCHANNEL, m_spychannel);
CmdSpysend = AddCommand(MSG_SPYSEND, TOK_SPYSEND, m_spysend);
CmdSpychsend = AddCommand(MSG_SPYCHSEND, TOK_SPYCHSEND, m_spychsend);
CmdSpyforward = AddCommand(MSG_SPYFORWARD, TOK_SPYFORWARD, m_spyforward);
CmdSpychforward = AddCommand(MSG_SPYCHFORWARD, TOK_SPYCHFORWARD, m_spychforward);
CmdSpystats = AddCommand(MSG_SPYSTATS, TOK_SPYSTATS, m_spystats);
SpySnomask = AddSnomask(FlagSpy, umode_allow_opers, &SNO_SPY);
if (!SpySnomask || !CmdSpy || !CmdSpychannel || !CmdSpysend || !CmdSpychsend)
ret = MOD_FAILED;
if (!CmdSpyforward || !CmdSpychforward || !CmdSpystats)
ret = MOD_FAILED;
return ret;
}
DLLFUNC int MOD_LOAD(m_spy)(int module_load)
{
return MOD_SUCCESS;
}
DLLFUNC int MOD_UNLOAD(m_spy)(int module_unload)
{
SpyStruct *s;
SpyChStruct *sc;
ListStruct *next;
DelSnomask(SpySnomask);
DelCommand(CmdSpystats);
DelCommand(CmdSpychforward);
DelCommand(CmdSpyforward);
DelCommand(CmdSpychsend);
DelCommand(CmdSpysend);
DelCommand(CmdSpychannel);
DelCommand(CmdSpy);
DelHook(HookChanDest);
DelHook(HookRemoteNick);
DelHook(HookLocalNick);
DelHook(HookServConn);
DelHook(HookRemoteQuit);
DelHook(HookQuit);
DelHook(HookChanMsg);
DelHook(HookPrivMsg);
for (s = SpyList; s; s = (SpyStruct *) next)
{
next = (ListStruct *) s->next;
DelSpyItem(s);
}
for (sc = SpyChList; sc; sc = (SpyChStruct *) next)
{
next = (ListStruct *) sc->next;
DelSpyChItem(sc);
}
return MOD_SUCCESS;
}
// ==================================================================
// Functions for nicknames, channel names and prefixes
// ==================================================================
static void del_prefix(char *str, u_int *lock, char **newstr)
{
*lock = 0;
if (*str == LockFlag)
{
*lock = 1;
str++;
}
*newstr = str;
}
// ==================================================================
// Misc functions
// ==================================================================
static SpyStruct *FindSpyItem1(aClient *acptr, char *nick)
{
SpyStruct *s;
for (s = SpyList; s; s = s->next)
if (s->who == acptr && !s->nick2 && !strcasecmp(s->nick1, nick))
break;
return s;
}
static SpyStruct *FindSpyItem2(aClient *acptr, char *nick1, char *nick2)
{
SpyStruct *s;
for (s = SpyList; s; s = s->next)
if (s->who == acptr && !strcasecmp(s->nick1, nick1)
&& (s->nick2 && !strcasecmp(s->nick2, nick2)))
break;
return s;
}
static SpyChStruct *FindSpyChItem(aClient *acptr, char *channel)
{
SpyChStruct *sc;
for (sc = SpyChList; sc; sc = sc->next)
if (sc->who == acptr && !strcasecmp(sc->channel, channel))
break;
return sc;
}
static void AddSpyItem(aClient *acptr, char *nick1, char *nick2, char *chname, u_int lock1, u_int lock2)
{
SpyStruct *s;
s = (SpyStruct *) MyMalloc(sizeof(SpyStruct));
s->who = acptr;
s->nick1 = strdup(nick1);
s->nick2 = BadPtr(nick2) ? NULL : strdup(nick2);
s->chname = BadPtr(chname) ? NULL : strdup(chname);
s->lock1 = lock1;
s->lock2 = lock2;
AddListItem(s, SpyList);
}
static void AddSpyChItem(aClient *acptr, char *channel, char *sendto, u_int lock)
{
SpyChStruct *sc;
sc = (SpyChStruct *) MyMalloc(sizeof(SpyChStruct));
sc->who = acptr;
sc->channel = strdup(channel);
sc->sendto = BadPtr(sendto) ? NULL : strdup(sendto);
sc->lock = lock;
AddListItem(sc, SpyChList);
}
static void DelSpyItem(SpyStruct *s)
{
DelListItem(s, SpyList);
MyFree(s->nick1);
ircfree(s->nick2);
ircfree(s->chname);
MyFree(s);
}
static void DelSpyChItem(SpyChStruct *sc)
{
DelListItem(sc, SpyChList);
MyFree(sc->channel);
ircfree(sc->sendto);
MyFree(sc);
}
// ==================================================================
// display_text: a general function to display two or more lines
// of text to a user
// ==================================================================
static void display_text(aClient *cptr, char *text[])
{
char **pp;
for (pp = text; *pp; pp++)
sendto_one(cptr, *pp, me.name, cptr->name);
/* let user take 7 seconds to read it! */
if (MyClient(cptr))
cptr->since += 7;
}
// ==================================================================
// spy_paramcheck: checks for validity of /spy parameters
// ==================================================================
static unsigned int spy_paramcheck(aClient *cptr, int parc, char *parv[],
char **nick1, char **nick2, char **channel, u_int *lock1, u_int *lock2)
{
*nick1 = NULL;
*nick2 = NULL;
*channel = NULL;
*lock1 = 0;
*lock2 = 0;
if (IsParam(2))
{
if (*parv[2] == '#')
*channel = parv[2];
else
*nick1 = parv[2];
}
if (IsParam(3))
{
if (*channel)
return 0;
else if (*parv[3] == '#')
{
*nick2 = NULL;
*channel = parv[3];
}
else
*nick2 = parv[3];
}
if (IsParam(4))
{
if (*channel)
return 0;
*channel = parv[4];
}
if (*nick1)
SplitLock(*lock1, *nick1);
if (*nick2)
SplitLock(*lock2, *nick2);
return 1;
}
// ==================================================================
// spych_paramcheck: checks for validity of /spychannel parameters
// ==================================================================
static unsigned int spych_paramcheck(aClient *cptr, int parc, char *parv[],
char **channel, char **sendto, u_int *lock)
{
*channel = NULL;
*sendto = NULL;
*lock = 0;
if (!IsParam(2))
return 0;
*channel = parv[2];
if (IsParam(3))
*sendto = parv[3];
if (*channel)
SplitLock(*lock, *channel);
return 1;
}
// ==================================================================
// spy_send_client & spy_send_channel: handle sending users's private
// messages to clients & channels
// ==================================================================
static void spy_send_client(aClient *acptr, int notice, char *nick1, char *nick2, char *text)
{
if (MyClient(acptr))
sendto_one(acptr, ":IRC!IRC@%s PRIVMSG %s :[%s %c> %s] %s",
me.name, acptr->name,
nick1, (notice ? '-' : '>'), nick2, text);
else
sendto_one(acptr->from, "%s %s %c %s %s :%s",
IsToken(acptr->from) ? TOK_SPYSEND : MSG_SPYSEND,
acptr->name, (notice ? 'N' : 'P'),
nick1, nick2, text);
}
static void spy_send_channel(aClient *cptr, char *channel, int notice, char *nick1, char *nick2, char *text)
{
aChannel *chptr;
if ((chptr = find_channel(channel, NullChn)) == NullChn)
return;
sendto_channel_butserv(chptr, &me, ":IRC!IRC@%s PRIVMSG %s :[%s %c> %s] %s",
me.name, chptr->chname,
nick1, (notice ? '-' : '>'), nick2, text);
sendto_serv_butone_token(cptr, me.name, MSG_SPYSEND, TOK_SPYSEND,
"%s %c %s %s :%s",
chptr->chname, (notice ? 'N' : 'P'),
nick1, nick2, text);
}
static void spych_send_client(aClient *acptr, int notice, char *nick, char *channel, char *text)
{
if (MyClient(acptr))
sendto_one(acptr, ":IRC!IRC@%s PRIVMSG %s :[%s] %c%s%c %s",
me.name, acptr->name, channel,
(notice ? '-' : '<'), nick, (notice ? '-' : '>'), text);
else
sendto_one(acptr->from, "%s %s %c %s %s :%s",
IsToken(acptr->from) ? TOK_SPYCHSEND : MSG_SPYCHSEND,
acptr->name, (notice ? 'N' : 'P'),
nick, channel, text);
}
static void spych_send_channel(aClient *cptr, char *sendto, int notice, char *nick, char *channel, char *text)
{
aChannel *chptr;
if ((chptr = find_channel(sendto, NullChn)) == NullChn)
return;
sendto_channel_butserv(chptr, &me, ":IRC!IRC@%s PRIVMSG %s :[%s] %c%s%c %s",
me.name, chptr->chname, channel,
(notice ? '-' : '<'), nick, (notice ? '-' : '>'), text);
sendto_serv_butone_token(cptr, me.name, MSG_SPYCHSEND, TOK_SPYCHSEND,
"%s %c %s %s :%s",
chptr->chname, (notice ? 'N' : 'P'),
nick, channel, text);
}
// ==================================================================
// Events
// ==================================================================
DLLFUNC int spy_on_quit(aClient *sptr, char *comment)
{
SpyStruct *s;
SpyChStruct *sc;
ListStruct *next;
// sendto_realops("(spy_on_quit) sptr->name=[%s]", sptr->name);
for (s = SpyList; s; s = (SpyStruct *) next)
{
next = (ListStruct *) s->next;
if (s->who == sptr)
DelSpyItem(s);
else if (!s->lock1 && !strcasecmp(s->nick1, sptr->name))
DelSpyItem(s);
else if (s->nick2 && !s->lock2 && !strcasecmp(s->nick2, sptr->name))
DelSpyItem(s);
}
for (sc = SpyChList; sc; sc = (SpyChStruct *) next)
{
next = (ListStruct *) sc->next;
if (sc->who == sptr)
DelSpyChItem(sc);
}
return 0;
}
// ==================================================================
DLLFUNC int spy_on_remote_quit(aClient *sptr, char *comment)
{
SpyStruct *s;
SpyChStruct *sc;
ListStruct *next;
// sendto_realops("(spy_on_remote_quit) sptr->name=[%s]", sptr->name);
for (s = SpyList; s; s = (SpyStruct *) next)
{
next = (ListStruct *) s->next;
if (s->who == sptr)
DelSpyItem(s);
else if (!s->lock1 && !strcasecmp(s->nick1, sptr->name))
DelSpyItem(s);
else if (s->nick2 && !s->lock2 && !strcasecmp(s->nick2, sptr->name))
DelSpyItem(s);
}
for (sc = SpyChList; sc; sc = (SpyChStruct *) next)
{
next = (ListStruct *) sc->next;
if (sc->who == sptr)
DelSpyChItem(sc);
}
return 0;
}
// ==================================================================
DLLFUNC int spy_on_local_nickchange(aClient *sptr, char *nick)
{
SpyStruct *s;
for (s = SpyList; s; s = s->next)
{
if (!s->lock1 && !strcasecmp(s->nick1, sptr->name))
{
ircstrdup(s->nick1, nick);
}
if (s->nick2 && !s->lock2 && !strcasecmp(s->nick2, sptr->name))
{
ircstrdup(s->nick2, nick);
}
}
return 0;
}
DLLFUNC int spy_on_remote_nickchange(aClient *cptr, aClient *sptr, char *nick)
{
SpyStruct *s;
for (s = SpyList; s; s = s->next)
{
if (!s->lock1 && !strcasecmp(s->nick1, sptr->name))
{
ircstrdup(s->nick1, nick);
}
if (s->nick2 && !s->lock2 && !strcasecmp(s->nick2, sptr->name))
{
ircstrdup(s->nick2, nick);
}
}
return 0;
}
// ==================================================================
DLLFUNC int spy_on_channel_destroy(aChannel *chptr)
{
SpyChStruct *sc;
ListStruct *next;
for (sc = SpyChList; sc; sc = (SpyChStruct *) next)
{
next = (ListStruct *) sc->next;
if (!sc->lock && !strcasecmp(sc->channel, chptr->chname))
DelSpyChItem(sc);
}
return 0;
}
// ==================================================================
DLLFUNC int spy_on_server_connect(aClient *sptr)
{
SpyStruct *s;
SpyChStruct *sc;
// sendto_realops("(spy_on_server_connect) sptr->name=[%s]", sptr->name);
/* TODO: optimize this! */
sendto_one(sptr, ":%s %s CONNECT",
me.name, (IsToken(sptr) ? TOK_SPYFORWARD : MSG_SPYFORWARD));
sendto_one(sptr, ":%s %s CONNECT",
me.name, (IsToken(sptr) ? TOK_SPYCHFORWARD : MSG_SPYCHFORWARD));
for (s = SpyList; s; s = s->next)
{
sendto_one(sptr, ":%s %s ADD2 %s %s%s %s%s %s",
me.name,
(IsToken(sptr) ? TOK_SPYFORWARD : MSG_SPYFORWARD),
s->who->name,
MergeLock(s->lock1, s->nick1),
MergeLockOpt(s->lock2, s->nick2),
s->chname ? s->chname : "*");
}
for (sc = SpyChList; sc; sc = sc->next)
{
sendto_one(sptr, ":%s %s ADD2 %s %s%s %s",
me.name,
(IsToken(sptr) ? TOK_SPYCHFORWARD : MSG_SPYCHFORWARD),
sc->who->name,
MergeLock(sc->lock, sc->channel),
sc->sendto ? sc->sendto : "*");
}
return 0;
}
// ==================================================================
DLLFUNC char *spy_on_privmsg(aClient *cptr, aClient *sptr, aClient *acptr, char *text, int notice)
{
SpyStruct *s;
aChannel *chptr;
char *nick1, *nick2;
if (!MyClient(sptr))
return text;
/* First do some sorting */
if (smycmp(sptr->name, acptr->name) > 0)
{
nick1 = acptr->name;
nick2 = sptr->name;
}
else
{
nick1 = sptr->name;
nick2 = acptr->name;
}
for (s = SpyList; s; s = s->next)
{
if (
/* spy every messages sent and received by one client */
(
!s->nick2 &&
(!strcasecmp(s->nick1, sptr->name) || !strcasecmp(s->nick1, acptr->name))
) ||
/* spy messages between two specific users */
(
!strcasecmp(s->nick1, nick1) && !strcasecmp(s->nick2, nick2)
)
)
{
if (s->chname)
spy_send_channel(&me, s->chname, notice,
sptr->name, acptr->name, text);
else
spy_send_client(s->who, notice,
sptr->name, acptr->name, text);
}
}
return text;
}
DLLFUNC char *spy_on_chanmsg(aClient *cptr, aClient *sptr, aChannel *chptr, char *text, int notice)
{
SpyChStruct *sc;
if (!MyClient(sptr))
return text;
for (sc = SpyChList; sc; sc = sc->next)
{
if (!strcasecmp(chptr->chname, sc->channel))
{
if (sc->sendto)
spych_send_channel(&me, sc->sendto, notice,
sptr->name, chptr->chname, text);
else
spy_send_client(sc->who, notice,
sptr->name, chptr->chname, text);
}
}
return text;
}
// ==================================================================
// m_spy: Adds, removes or lists nicknames in spy list
// ==================================================================
DLLFUNC int m_spy(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
SpyStruct *s;
char *tmp = NULL, *cmd;
char *nick1, *nick2, *channel;
u_int lock1, lock2;
if (!MyClient(cptr) || !IsOper(cptr) || !IsSAdmin(cptr))
{
sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
return -1;
}
cmd = IsParam(1) ? parv[1] : NULL;
if (!cmd)
{
display_text(cptr, SpyHelp);
return -1;
}
/* ADD */
if (!strcasecmp(cmd, "add"))
{
if (!spy_paramcheck(cptr, parc, parv, &nick1, &nick2, &channel, &lock1, &lock2))
{
display_text(cptr, SpyHelp);
return -1;
}
if (!nick1 || IsParam(5))
{
display_text(cptr, SpyHelp);
return -1;
}
if (nick2 && !strcasecmp(nick1, nick2))
{
sendto_one(sptr, ":%s NOTICE %s :*** %s %s: Nicks cannot be the same",
me.name, sptr->name,
nick1, nick2);
return -1;
}
if (channel && *channel != '#')
{
sendto_one(sptr, ":%s NOTICE %s :*** %s: Invalid channel name",
me.name, sptr->name, channel);
return -1;
}
if (nick2 && (smycmp(nick1, nick2) > 0))
{
tmp = nick1;
nick1 = nick2;
nick2 = tmp;
}
if ((nick2 && FindSpyItem2(sptr, nick1, nick2)) || (!nick2 && FindSpyItem1(sptr, nick1)))
{
sendto_one(sptr, ":%s NOTICE %s :*** %s %s: Already on your private spy list",
me.name, sptr->name,
nick1, nick2 ? nick2 : "<irc>");
return -1;
}
AddSpyItem(sptr, nick1, nick2, channel, lock1, lock2);
sendto_one(sptr, ":%s NOTICE %s :*** %s %s: Added to your private spy list",
me.name, sptr->name,
nick1, nick2 ? nick2 : "<irc>");
SpyForward5(&me, "ADD", sptr->name, nick1, nick2, channel, lock1, lock2);
sendto_snomask(SNO_SPY, "*** [\2m_spy\2] %s used /SPY ADD %s%s" "%s" "%s%s" "%s" "%s",
sptr->name, MergeLock(lock1, nick1),
nick2 ? " " : "", MergeLockEmp(lock2, nick2),
channel ? " " : "", channel ? channel : "");
}
/* DEL */
else if (!strcasecmp(cmd, "del"))
{
if (!spy_paramcheck(cptr, parc, parv, &nick1, &nick2, &channel, &lock1, &lock2))
{
display_text(cptr, SpyHelp);
return -1;
}
if (!nick1 || channel || IsParam(4))
{
display_text(cptr, SpyHelp);
return -1;
}
if (nick2 && (smycmp(nick1, nick2) > 0))
{
tmp = nick1;
nick1 = nick2;
nick2 = tmp;
}
if ((nick2 && !(s = FindSpyItem2(sptr, nick1, nick2))) || (!nick2 && !(s = FindSpyItem1(sptr, nick1))))
{
sendto_one(sptr, ":%s NOTICE %s :*** %s %s: Not yet on your private spy list",
me.name, sptr->name,
nick1, nick2 ? nick2 : "<irc>");
return -1;
}
SpyForward4(&me, "DEL", s->who->name, s->nick1, s->nick2, 0, 0);
sendto_one(sptr, ":%s NOTICE %s :*** %s %s: Deleted from your private spy list",
me.name, sptr->name,
nick1, nick2 ? nick2 : "<irc>");
sendto_snomask(SNO_SPY, "*** [\2m_spy\2] %s used /SPY DEL %s%s%s",
sptr->name, s->nick1, s->nick2 ? " " : "", s->nick2 ? s->nick2 : "");
DelSpyItem(s);
}
/* LIST */
else if (!strcasecmp(cmd, "list"))
{
enum ListType { LT_n1n2c, LT_n1n2, LT_n1c, LT_n1, LT_c, LT_none };
unsigned int found = 0, type = 0, show = 0, empty = 1;
if (!spy_paramcheck(cptr, parc, parv, &nick1, &nick2, &channel, &lock1, &lock2))
{
display_text(cptr, SpyHelp);
return -1;
}
if (channel)
{
if (nick2)
type = LT_n1n2c;
else if (nick1)
type = LT_n1c;
else
type = LT_c;
}
else if (nick2)
type = LT_n1n2;
else if (nick1)
type = LT_n1;
else
type = LT_none;
if (nick1 && nick2 && (smycmp(nick1, nick2) > 0))
{
tmp = nick1;
nick1 = nick2;
nick2 = tmp;
}
for (s = SpyList; s; s = s->next)
if (s->who == sptr)
{
empty = 0;
show = 0;
switch (type)
{
case LT_n1n2c:
if (
s->nick2 &&
s->chname &&
!strcasecmp(s->nick1, nick1) &&
!strcasecmp(s->nick2, nick2) &&
!strcasecmp(s->chname, channel)
)
show = 1;
break;
case LT_n1n2:
if (
s->nick2 &&
!strcasecmp(s->nick1, nick1) &&
!strcasecmp(s->nick2, nick2)
)
show = 1;
break;
case LT_n1c:
if (
s->chname &&
!strcasecmp(s->nick1, nick1) &&
!strcasecmp(s->chname, channel)
)
show = 1;
break;
case LT_n1:
if (!strcasecmp(s->nick1, nick1))
show = 1;
break;
case LT_c:
if (s->chname && !strcasecmp(s->chname, channel))
show = 1;
break;
default:
show = 1;
}
if (show)
{
found++;
sendto_one(sptr, ":%s NOTICE %s :*** %s%s %s%s %s",
me.name, sptr->name,
MergeLock(s->lock1, s->nick1),
MergeLockOpt(s->lock2, s->nick2),
s->chname ? s->chname : "<irc>");
}
}
if (!found)
{
sendto_one(sptr, ":%s NOTICE %s :*** %s",
me.name, sptr->name,
empty ? "Your spy list is empty" : "No matching entries");
}
else
{
sendto_one(sptr, ":%s NOTICE %s :*** " SPY_LINE,
me.name, sptr->name);
sendto_one(sptr, ":%s NOTICE %s :*** %d entr%s",
me.name, sptr->name,
found, found > 1 ? "ies" : "y");
}
}
/* CLEAR */
else if (!strcasecmp(cmd, "clear"))
{
ListStruct *next;
for (s = SpyList; s; s = (SpyStruct *) next)
{
next = (ListStruct *) s->next;
if (s->who == sptr)
DelSpyItem(s);
}
sendto_one(sptr, ":%s NOTICE %s :*** Your private spy list is now empty",
me.name, sptr->name);
SpyForward2(&me, "CLEAR", sptr->name);
}
/* <INVALID OPTION> */
else
{
sendto_one(sptr, ":%s NOTICE %s :*** Invalid option %s",
me.name, sptr->name, cmd);
return -1;
}
return 0;
}
// ==================================================================
// m_spychannel: Adds, removes or lists channel names in channel
// spy list
// ==================================================================
DLLFUNC int m_spychannel(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
SpyChStruct *sc;
char *cmd, *channel, *sendto;
u_int lock;
if (!MyClient(cptr) || !IsOper(cptr) || !IsSAdmin(cptr))
{
sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
return -1;
}
cmd = IsParam(1) ? parv[1] : NULL;
if (!cmd)
{
display_text(cptr, SpyChHelp);
return -1;
}
/* ADD */
if (!strcasecmp(cmd, "add"))
{
if (!spych_paramcheck(cptr, parc, parv, &channel, &sendto, &lock))
{
display_text(cptr, SpyChHelp);
return -1;
}
if (*channel != '#')
{
sendto_one(sptr, ":%s NOTICE %s :*** %s: Invalid channel name",
me.name, sptr->name, channel);
return -1;
}
if (sendto && *sendto != '#')
{
sendto_one(sptr, ":%s NOTICE %s :*** %s: Invalid channel name",
me.name, sptr->name, sendto);
return -1;
}
if (FindSpyChItem(sptr, channel))
{
sendto_one(sptr, ":%s NOTICE %s :*** %s: Already on your channel spy list",
me.name, sptr->name, channel);
return -1;
}
if (sendto && !strcasecmp(channel, sendto))
{
sendto_one(sptr, ":%s NOTICE %s :*** %s %s: Source and target channels cannot be the same",
me.name, sptr->name, channel, sendto);
return -1;
}
AddSpyChItem(sptr, channel, sendto, lock);
sendto_one(sptr, ":%s NOTICE %s :*** %s: Added to your channel spy list",
me.name, sptr->name, channel);
SpyChForward4(&me, "ADD", sptr->name, channel, sendto, lock);
sendto_snomask(SNO_SPY, "*** [\2m_spy\2] %s used /SPYCHANNEL ADD %s%s" "%s" "%s",
sptr->name, MergeLock(lock, channel), sendto ? " " : "",
sendto ? sendto : "");
}
/* DEL */
else if (!strcasecmp(cmd, "del"))
{
if (!spych_paramcheck(cptr, parc, parv, &channel, &sendto, &lock))
{
display_text(cptr, SpyChHelp);
return -1;
}
if (!(sc = FindSpyChItem(sptr, channel)))
{
sendto_one(sptr, ":%s NOTICE %s :*** %s: Not yet on your channel spy list",
me.name, sptr->name, channel);
return -1;
}
SpyChForward3(&me, "DEL", sc->who->name, sc->channel, 0);
sendto_one(sptr, ":%s NOTICE %s :*** %s: Deleted from your channel spy list",
me.name, sptr->name, channel);
sendto_snomask(SNO_SPY, "*** [\2m_spy\2] %s used /SPYCHANNEL DEL %s",
sptr->name, sc->channel);
DelSpyChItem(sc);
}
/* LIST */
else if (!strcasecmp(cmd, "list"))
{
unsigned int found = 0, empty = 1;
sendto = NULL;
channel = IsParam(2) ? parv[2] : NULL;
if (channel)
SplitLock(lock, channel);
for (sc = SpyChList; sc; sc = sc->next)
if (sc->who == sptr)
{
empty = 0;
if (!channel || !strcasecmp(sc->channel, channel))
{
found++;
sendto_one(sptr, ":%s NOTICE %s :*** %s%s %s",
me.name, sptr->name,
MergeLock(sc->lock, sc->channel),
sc->sendto ? sc->sendto : "<irc>");
}
}
if (!found)
{
sendto_one(sptr, ":%s NOTICE %s :*** %s",
me.name, sptr->name,
empty ? "Your channel spy list is empty" : "No matching entries");
}
else
{
sendto_one(sptr, ":%s NOTICE %s :*** " SPY_LINE,
me.name, sptr->name);
sendto_one(sptr, ":%s NOTICE %s :*** %d entr%s",
me.name, sptr->name,
found, found > 1 ? "ies" : "y");
}
}
/* CLEAR */
else if (!strcasecmp(cmd, "clear"))
{
ListStruct *next;
for (sc = SpyChList; sc; sc = (SpyChStruct *) next)
{
next = (ListStruct *) sc->next;
if (sc->who == sptr)
DelSpyChItem(sc);
}
sendto_one(sptr, ":%s NOTICE %s :*** Your channel spy list is now empty",
me.name, sptr->name);
SpyChForward2(&me, "CLEAR", sptr->name);
}
/* <INVALID OPTION> */
else
{
sendto_one(sptr, ":%s NOTICE %s :*** Invalid option %s",
me.name, sptr->name, cmd);
return -1;
}
return 0;
}
// ==================================================================
// m_spyforward: Keeps SpyList updated on all servers
// ==================================================================
DLLFUNC int m_spyforward(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
SpyStruct *s;
ListStruct *next;
aClient *acptr;
char *tmp, *cmd, *who, *nick1, *nick2, *channel;
u_int lock1, lock2;
if (IsClient(cptr))
{
sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
return -1;
}
cmd = IsParam(1) ? parv[1] : NULL;
who = IsParam(2) ? parv[2] : NULL;
nick1 = IsParam(3) ? parv[3] : NULL;
nick2 = IsValidParam(4) ? parv[4] : NULL;
channel = IsValidParam(5) ? parv[5] : NULL;
/* sendto_realops("(\2m_spyforward\2) cptr=%s, sptr=%s, cmd=%s who=%s nick1=%s nick2=%s channel=%s",
cptr->name, sptr->name,
cmd ? cmd : "(null)",
who ? who : "(null)",
nick1 ? nick1 : "(null)",
nick2 ? nick2 : "(null)",
channel ? channel : "(null)"); */
if (!cmd)
return -1;
if (nick1)
SplitLock(lock1, nick1);
if (nick2)
SplitLock(lock2, nick2);
/* ADD */
if (!strcasecmp(cmd, "add"))
{
if (!nick1)
return -1;
if (nick2 && !strcasecmp(nick1, nick2))
return -1;
if (nick2 && (smycmp(nick1, nick2) > 0))
{
tmp = nick1;
nick1 = nick2;
nick2 = tmp;
}
if (!(acptr = find_person(who, NULL)))
return -1;
if ((nick2 && FindSpyItem2(acptr, nick1, nick2)) || (!nick2 && FindSpyItem1(acptr, nick1)))
return -1;
AddSpyItem(acptr, nick1, nick2, channel, lock1, lock2);
SpyForward5(cptr, "ADD", acptr->name, nick1, nick2, channel, lock1, lock2);
sendto_snomask(SNO_SPY, "*** [\2m_spy\2] %s used /SPY ADD %s%s" "%s" "%s%s" "%s" "%s",
acptr->name, MergeLock(lock1, nick1),
nick2 ? " " : "", MergeLockEmp(lock2, nick2),
channel ? " " : "", channel ? channel : "");
}
/* ADD2 -- Like ADD, but without forwarding */
if (!strcasecmp(cmd, "add2"))
{
if (!nick1)
return -1;
if (nick2 && !strcasecmp(nick1, nick2))
return -1;
if (nick2 && (smycmp(nick1, nick2) > 0))
{
tmp = nick1;
nick1 = nick2;
nick2 = tmp;
}
if (!(acptr = find_person(who, NULL)))
return -1;
if ((nick2 && FindSpyItem2(acptr, nick1, nick2)) || (!nick2 && FindSpyItem1(acptr, nick1)))
return -1;
AddSpyItem(acptr, nick1, nick2, channel, lock1, lock2);
}
/* DEL */
else if (!strcasecmp(cmd, "del"))
{
if (!nick1)
return -1;
if (nick2 && (smycmp(nick1, nick2) > 0))
{
tmp = nick1;
nick1 = nick2;
nick2 = tmp;
}
if (!(acptr = find_person(who, NULL)))
return -1;
if ((nick2 && !(s = FindSpyItem2(acptr, nick1, nick2))) || (!nick2 && !(s = FindSpyItem1(acptr, nick1))))
return -1;
sendto_snomask(SNO_SPY, "*** [\2m_spy\2] %s used /SPY DEL %s%s%s",
acptr->name, s->nick1, s->nick2 ? " " : "", s->nick2 ? s->nick2 : "");
SpyForward4(cptr, "DEL", acptr->name, s->nick1, s->nick2, 0, 0);
DelSpyItem(s);
}
/* CLEAR */
else if (!strcasecmp(cmd, "clear"))
{
if (!who)
return -1;
if (!(acptr = find_person(who, NULL)))
return -1;
for (s = SpyList; s; s = (SpyStruct *) next)
{
next = (ListStruct *) s->next;
if (s->who == acptr)
DelSpyItem(s);
}
SpyForward2(cptr, "CLEAR", acptr->name);
}
/* CONNECT */
else if (!strcasecmp(cmd, "connect"))
{
for (s = SpyList; s; s = s->next)
/* act as a client who is just adding a spy entry */
SpyForward5(&me, "ADD", s->who->name, s->nick1, s->nick2,
s->chname, s->lock1, s->lock2);
}
/* <INVALID OPTION> */
else
{
return -1;
}
return 0;
}
// ==================================================================
// m_spychforward: Keeps SpyChList updated on all servers
// ==================================================================
DLLFUNC int m_spychforward(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
SpyChStruct *sc;
ListStruct *next;
aClient *acptr;
char *cmd, *who, *channel, *sendto;
u_int lock;
if (IsClient(cptr))
{
sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
return -1;
}
cmd = IsParam(1) ? parv[1] : NULL;
who = IsParam(2) ? parv[2] : NULL;
channel = IsValidParam(3) ? parv[3] : NULL;
sendto = IsValidParam(4) ? parv[4] : NULL;
/* sendto_realops("(\2m_spychforward\2) cptr=%s, sptr=%s, cmd=%s who=%s channel=%s sendto=%s",
cptr->name, sptr->name,
cmd ? cmd : "(null)",
who ? who : "(null)",
channel ? channel : "(null)",
sendto ? sendto : "(null)"); */
if (!cmd)
return -1;
if (channel)
SplitLock(lock, channel);
/* ADD */
if (!strcasecmp(cmd, "add"))
{
if (!channel)
return -1;
if (!(acptr = find_person(who, NULL)))
return -1;
if (FindSpyChItem(acptr, channel))
return -1;
AddSpyChItem(acptr, channel, sendto, lock);
SpyChForward4(cptr, "ADD", acptr->name, channel, sendto, lock);
sendto_snomask(SNO_SPY, "*** [\2m_spy\2] %s used /SPYCHANNEL ADD %s%s" "%s" "%s",
acptr->name, MergeLock(lock, channel),
sendto ? " " : "", sendto ? sendto : "");
}
/* ADD2 -- Like ADD, but without forwarding */
if (!strcasecmp(cmd, "add2"))
{
if (!channel)
return -1;
if (!(acptr = find_person(who, NULL)))
return -1;
if (FindSpyChItem(acptr, channel))
return -1;
AddSpyChItem(acptr, channel, sendto, lock);
}
/* DEL */
else if (!strcasecmp(cmd, "del"))
{
if (!channel)
return -1;
if (!(acptr = find_person(who, NULL)))
return -1;
if (!(sc = FindSpyChItem(acptr, channel)))
return -1;
sendto_snomask(SNO_SPY, "*** [\2m_spy\2] %s used /SPYCHANNEL DEL %s",
acptr->name, sc->channel);
SpyChForward3(cptr, "DEL", acptr->name, sc->channel, 0);
DelSpyChItem(sc);
}
/* CLEAR */
else if (!strcasecmp(cmd, "clear"))
{
if (!who)
return -1;
if (!(acptr = find_person(who, NULL)))
return -1;
for (sc = SpyChList; sc; sc = (SpyChStruct *) next)
{
next = (ListStruct *) sc->next;
if (sc->who == acptr)
DelSpyChItem(sc);
}
SpyChForward2(cptr, "CLEAR", acptr->name);
}
/* CONNECT */
else if (!strcasecmp(cmd, "connect"))
{
for (sc = SpyChList; sc; sc = sc->next)
/* act as a client who is just adding a channel spy entry */
SpyChForward4(&me, "ADD", sc->who->name, sc->channel,
sc->sendto, sc->lock);
}
/* <INVALID OPTION> */
else
{
return -1;
}
return 0;
}
// ==================================================================
// m_spysend: Sends users' private messages to a client on the network
// Easier way?
// ==================================================================
DLLFUNC int m_spysend(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
aClient *acptr;
char *from, *to, *cmd, *nick1, *nick2, *text;
unsigned notice;
if (!IsServer(sptr) || !IsParam(5))
return -1;
to = IsParam(1) ? parv[1] : NULL;
cmd = IsParam(2) ? parv[2] : NULL;
nick1 = IsParam(3) ? parv[3] : NULL;
nick2 = IsParam(4) ? parv[4] : NULL;
text = IsParam(5) ? parv[5] : NULL;
if (!text)
return -1;
notice = *cmd == 'N' ? 1 : 0;
if (*to == '#')
spy_send_channel(cptr, to, notice,
nick1, nick2, text);
else
{
if (!(acptr = find_person(to, NULL)))
return -1;
spy_send_client(acptr, notice,
nick1, nick2, text);
}
return 0;
}
// ==================================================================
// m_spychsend: Sends users' channel messages to a client on the network
// Easier way?
// ==================================================================
DLLFUNC int m_spychsend(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
aClient *acptr;
char *to, *cmd, *nick, *channel, *text;
unsigned notice;
if (!IsServer(sptr) || !IsParam(5))
return -1;
to = IsParam(1) ? parv[1] : NULL;
cmd = IsParam(2) ? parv[2] : NULL;
nick = IsParam(3) ? parv[3] : NULL;
channel = IsParam(4) ? parv[4] : NULL;
text = IsParam(5) ? parv[5] : NULL;
if (!text)
return -1;
notice = *cmd == 'N' ? 1 : 0;
if (*to == '#')
spy_send_channel(cptr, to, notice,
nick, channel, text);
else
{
if (!(acptr = find_person(to, NULL)))
return -1;
spy_send_client(acptr, notice,
nick, channel, text);
}
return 0;
}
/*
* m_spystats
*
* Displays SpyList statistics based on a given nickname. If you leave out
* <nickname>, all SpyList entries will be displayed.
*
*
![](http://i.ru-board.com/s/tongue.gif)
refix SPYSTATS [<nickname>]
* parv[0] - (sender)
* parv[1] - channel|message
* parv[2] - <nickname> (optional)
*
*/
DLLFUNC int m_spystats(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
SpyStruct *s;
SpyChStruct *sc;
aClient *acptr = NULL;
unsigned long item = 0, count = 0, total = 0;
unsigned long subcount = 0, subtotal = 0;
char *cmd;
if (!MyClient(cptr) || !IsOper(cptr) || !IsSAdmin(cptr))
{
sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
return -1;
}
if (!IsParam(1))
{
sendto_one(sptr, ":%s NOTICE %s :*** Usage: /spystats private|channel [<nickname>]",
me.name, sptr->name);
return 0;
}
cmd = parv[1];
/* PRIVATE */
if (!strcasecmp(cmd, "private"))
{
if (!SpyList)
{
sendto_one(sptr, ":%s NOTICE %s :*** Private spy list is empty",
me.name, sptr->name);
return 0;
}
if (IsParam(2) && !(acptr = find_person(parv[2], NULL)))
{
sendto_one(sptr, err_str(ERR_NOSUCHNICK),
me.name, sptr->name, parv[2]);
return -1;
}
for (s = SpyList; s; s = s->next)
{
item = sizeof(*s) + 1; /* 1 byte is the size of (lock1 + lock2) */
item += sizeof(char) * (strlen(s->nick1) + 1);
if (s->nick2)
item += sizeof(char) * (strlen(s->nick2) + 1);
if (s->chname)
item += sizeof(char) * (strlen(s->chname) + 1);
if (acptr && s->who == acptr)
{
subtotal += item;
subcount++;
}
total += item;
count++;
if (!acptr || s->who == acptr)
sendto_one(sptr, ":%s NOTICE %s :*** %s (%s%s): %s%s %s (mem: %ld)",
me.name, sptr->name,
s->who->name,
MergeLock(s->lock1, s->nick1),
MergeLockOpt(s->lock2, s->nick2),
s->chname ? s->chname : "<irc>",
item);
}
if (acptr)
{
sendto_one(sptr, ":%s NOTICE %s :*** " SPY_LINE,
me.name, sptr->name);
sendto_one(sptr, ":%s NOTICE %s :*** Sub total (%s): %ld entr%s (mem: %ld)",
me.name, sptr->name,
acptr->name,
subcount, count > 1 ? "ies" : "y",
subtotal);
}
sendto_one(sptr, ":%s NOTICE %s :*** " SPY_LINE,
me.name, sptr->name);
sendto_one(sptr, ":%s NOTICE %s :*** Total: %d entr%s (mem: %ld)",
me.name, sptr->name,
count, count > 1 ? "ies" : "y",
total);
}
/* CHANNEL */
else if (!strcasecmp(cmd, "channel"))
{
if (!SpyChList)
{
sendto_one(sptr, ":%s NOTICE %s :*** Channel spy list is empty",
me.name, sptr->name);
return 0;
}
if (IsParam(2) && !(acptr = find_person(parv[2], NULL)))
{
sendto_one(sptr, err_str(ERR_NOSUCHNICK),
me.name, sptr->name, parv[2]);
return -1;
}
for (sc = SpyChList; sc; sc = sc->next)
{
item = sizeof(*sc) + sizeof(sc->lock);
item += sizeof(char) * (strlen(sc->channel) + 1);
if (sc->sendto)
item += sizeof(char) * (strlen(sc->sendto) + 1);
if (acptr && sc->who == acptr)
{
subtotal += item;
subcount++;
}
total += item;
count++;
if (!acptr || sc->who == acptr)
sendto_one(sptr, ":%s NOTICE %s :*** %s (%s%s): %s (mem: %ld)",
me.name, sptr->name,
sc->who->name,
MergeLock(sc->lock, sc->channel),
sc->sendto ? sc->sendto : "<irc>",
item);
}
if (acptr)
{
sendto_one(sptr, ":%s NOTICE %s :*** " SPY_LINE,
me.name, sptr->name);
sendto_one(sptr, ":%s NOTICE %s :*** Sub total (%s): %ld entr%s (mem: %ld)",
me.name, sptr->name,
acptr->name,
subcount, count > 1 ? "ies" : "y",
subtotal);
}
sendto_one(sptr, ":%s NOTICE %s :*** " SPY_LINE,
me.name, sptr->name);
sendto_one(sptr, ":%s NOTICE %s :*** Total: %d entr%s (mem: %ld)",
me.name, sptr->name,
count, count > 1 ? "ies" : "y",
total);
}
/* <INVALID OPTION> */
else
{
sendto_one(sptr, ":%s NOTICE %s :*** Invalid option %s",
me.name, sptr->name, cmd);
return -1;
}
return 0;
}