Guest User

m_spy.c Angrywolf Unrealircd Module

a guest
Sep 17th, 2017
1,884
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 46.10 KB | None | 0 0
  1. /* * ==================================================================
  2.  * Filename:             m_spy.c
  3.  * Description:          Real-time spying
  4.  * Written by:   AngryWolf <[email protected]>
  5.  * The idea was born by: Toxyc <[email protected]>
  6.  * ==================================================================
  7.  */
  8. #include "config.h"
  9. #include "struct.h"
  10. #include "common.h"
  11. #include "sys.h"
  12. #include "numeric.h"
  13. #include "msg.h"
  14. #include "channel.h"
  15. #include <time.h>
  16. #include <sys/stat.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #ifdef _WIN32
  21. #include <io.h>
  22. #endif
  23. #include <fcntl.h>
  24. #include "h.h"
  25. #ifdef STRIPBADWORDS
  26. #include "badwords.h"
  27. #endif
  28. #ifdef _WIN32
  29. #include "version.h"
  30. #endif
  31. // ==================================================================
  32. // Definitions & macros
  33. // ==================================================================
  34. #define MSG_SPY   "spy"
  35. #define TOK_SPY   "spy"
  36. #define MSG_SPYCHANNEL   "SPYCHAN"
  37. #define TOK_SPYCHANNEL  "SPC"
  38. #define MSG_SPYSEND   "SPYSEND"
  39. #define TOK_SPYSEND   "SPE"
  40. #define MSG_SPYCHSEND   "SPYCHSEND"
  41. #define TOK_SPYCHSEND   "SPT"
  42. #define MSG_SPYFORWARD   "SPYFORWARD"
  43. #define TOK_SPYFORWARD   "SPF"
  44. #define MSG_SPYCHFORWARD  "SPYCHFORWARD"
  45. #define TOK_SPYCHFORWARD  "SPG"
  46. #define MSG_SPYSTATS   "SPYSTATS"
  47. #define TOK_SPYSTATS   "SPS"
  48. #define MyMod   SpyModInfo->handle
  49. #define FlagSpy   'P'
  50. #define LockFlag  '@'
  51. #define LockFlagStr  "@"
  52. #define SPY_NOTICE  ":%s NOTICE %s :*** "
  53. #define SPY_LINE  "=================================================="
  54. #define ircfree(x)  if (x) free(x)
  55. #define ircstrdup(x,y)  if (x) MyFree(x); if (!y) x = NULL; else x = strdup(y)
  56. #define DelSnomask(x)  if (x) SnomaskDel(x); x = NULL
  57. #define DelHook(x)  if (x) HookDel(x); x = NULL
  58. #define DelCommand(x)  if (x) CommandDel(x); x = NULL
  59.  
  60. #define IsParam(x)  (parc > (x) && !BadPtr(parv[(x)]))
  61. #define IsValidParam(x)  (parc > (x) && !BadPtr(parv[(x)]) && *parv[(x)] != '*')
  62. #define AddLock(lock)  (lock ? LockFlagStr : "")
  63. #define GetLock(str)  (*str == LockFlag ? 1 : 0)
  64. #define SplitLock(lock, str) del_prefix(str, &(lock), &(str))
  65. #define MergeLock(lock, str) AddLock(lock), str
  66. #define MergeLockOpt(lock, str) str ? AddLock(lock) : "", str ? str : "*"
  67. #define MergeLockEmp(lock, str) str ? AddLock(lock) : "", str ? str : ""
  68. #define SpyForward5(cptr, cmd, who, nick1, nick2, channel, lock1, lock2) \
  69.   sendto_serv_butone_token(cptr, me.name, MSG_SPYFORWARD, TOK_SPYFORWARD, \
  70.   "%s %s %s%s %s%s %s", \
  71.   cmd, who, MergeLock(lock1, nick1), MergeLockOpt(lock2, nick2), \
  72.   channel ? channel : "*")
  73. #define SpyForward4(cptr, cmd, who, nick1, nick2, lock1, lock2) \
  74.   sendto_serv_butone_token(cptr, me.name, MSG_SPYFORWARD, TOK_SPYFORWARD, \
  75.   "%s %s %s%s %s%s", \
  76.   cmd, who, MergeLock(lock1, nick1), MergeLockOpt(lock2, nick2))
  77. #define SpyForward3(cptr, cmd, who, nick1, lock1) \
  78.   sendto_serv_butone_token(cptr, me.name, MSG_SPYFORWARD, TOK_SPYFORWARD, \
  79.   "%s %s %s%s", \
  80.   cmd, who, MergeLock(lock1, nick1))
  81. #define SpyForward2(cptr, cmd, who) \
  82.   sendto_serv_butone_token(cptr, me.name, MSG_SPYFORWARD, TOK_SPYFORWARD, \
  83.   "%s %s", \
  84.   cmd, who)
  85. #define SpyForward1(cptr, cmd) \
  86.   sendto_serv_butone_token(cptr, me.name, MSG_SPYFORWARD, TOK_SPYFORWARD, \
  87.   "%s", \
  88.   cmd)
  89. #define SpyChForward4(cptr, cmd, who, channel, sendto, lock) \
  90.   sendto_serv_butone_token(cptr, me.name, MSG_SPYCHFORWARD, TOK_SPYCHFORWARD, \
  91.   "%s %s %s%s %s", \
  92.   cmd, who, MergeLock(lock, channel), sendto ? sendto : "*")
  93. #define SpyChForward3(cptr, cmd, who, channel, lock) \
  94.   sendto_serv_butone_token(cptr, me.name, MSG_SPYCHFORWARD, TOK_SPYCHFORWARD, \
  95.   "%s %s %s%s", \
  96.   cmd, who, MergeLock(lock, channel))
  97. #define SpyChForward2(cptr, cmd, who) \
  98.   sendto_serv_butone_token(cptr, me.name, MSG_SPYCHFORWARD, TOK_SPYCHFORWARD, \
  99.   "%s %s", \
  100.   cmd, who)
  101. typedef struct _spystruct SpyStruct;
  102. typedef struct _spychstruct SpyChStruct;
  103. struct _spystruct
  104. {
  105.  SpyStruct *prev, *next;
  106.  aClient  *who;  /* Who is spying */
  107.  char  *nick1;  /* First nick to spy */
  108.  char  *nick2;  /* Second nick to spy (may be NULL) */
  109.  char  *chname; /* Where to put messages (may be NULL) */
  110.  u_int  lock1:1;  /* 1 if nick1 is locked, otherwise 0 */
  111.  u_int  lock2:1;  /* 1 if nick2 is locked, otherwise 0 */
  112. };
  113. struct _spychstruct
  114. {
  115.  SpyChStruct *prev, *next;
  116.  aClient  *who;  /* Who is spying */
  117.  char  *channel; /* Channel to be spyed */
  118.  char  *sendto; /* Where to put messages (may be NULL) */
  119.  u_int  lock;  /* True if nick1 is locked, otherwise 0 */
  120. };
  121. static SpyStruct *FindSpyItem1(aClient *acptr, char *nick);
  122. static SpyStruct *FindSpyItem2(aClient *acptr, char *nick1, char *nick2);
  123. static SpyChStruct *FindSpyChItem(aClient *acptr, char *channel);
  124. static void  AddSpyItem(aClient *acptr, char *nick1, char *nick2, char *chname, u_int lock1, u_int lock2);
  125. static void  AddSpyChItem(aClient *acptr, char *channel, char *sendto, u_int lock);
  126. static void  DelSpyItem(SpyStruct *s);
  127. static void  DelSpyChItem(SpyChStruct *s);
  128. static unsigned int spy_paramcheck(aClient *cptr, int parc, char *parv[], char **nick1, char **nick2, char **channel, u_int *lock1, u_int *lock2);
  129. static unsigned int spych_paramcheck(aClient *cptr, int parc, char *parv[], char **channel, char **sendto, u_int *lock);
  130. static void  spy_send_client(aClient *acptr, int notice, char *nick1, char *nick2, char *text);
  131. static void  spy_send_channel(aClient *cptr, char *channel, int notice, char *nick1, char *nick2, char *text);
  132. static void  spych_send_client(aClient *acptr, int notice, char *nick, char *channel, char *text);
  133. static void  spych_send_channel(aClient *cptr, char *sendto, int notice, char *nick, char *channel, char *text);
  134. static void  del_prefix(char *str, u_int *lock, char **newstr);
  135. static Command  *AddCommand(char *msg, char *token, int (*func)());
  136. DLLFUNC int  m_spy(aClient *cptr, aClient *sptr, int parc, char *parv[]);
  137. DLLFUNC int  m_spychannel(aClient *cptr, aClient *sptr, int parc, char *parv[]);
  138. DLLFUNC int  m_spysend(aClient *cptr, aClient *sptr, int parc, char *parv[]);
  139. DLLFUNC int  m_spychsend(aClient *cptr, aClient *sptr, int parc, char *parv[]);
  140. DLLFUNC int  m_spyforward(aClient *cptr, aClient *sptr, int parc, char *parv[]);
  141. DLLFUNC int  m_spychforward(aClient *cptr, aClient *sptr, int parc, char *parv[]);
  142. DLLFUNC int  m_spystats(aClient *cptr, aClient *sptr, int parc, char *parv[]);
  143. DLLFUNC char  *spy_on_privmsg(aClient *, aClient *, aClient *, char *, int);
  144. DLLFUNC char  *spy_on_chanmsg(aClient *, aClient *, aChannel *, char *, int);
  145. DLLFUNC int  spy_on_quit(aClient *, char *);
  146. DLLFUNC int  spy_on_remote_quit(aClient *, char *);
  147. DLLFUNC int  spy_on_server_connect(aClient *);
  148. DLLFUNC int  spy_on_local_nickchange(aClient *, char *);
  149. DLLFUNC int  spy_on_remote_nickchange(aClient *, aClient *, char *);
  150. DLLFUNC int  spy_on_channel_destroy(aChannel *);
  151. // ==================================================================
  152. // Module header
  153. // ==================================================================
  154. ModuleHeader MOD_HEADER(m_spy)
  155.   = {
  156.  "falanfilan",
  157.  "$Id: m_spy.c,v 3.6 2003/12/01 18:31:45 angrywolf Exp $",
  158.  "iyi bişiy",
  159.  "3.2-b8-1",
  160.  NULL
  161.     };
  162. // ==================================================================
  163. // Main declarations
  164. // ==================================================================
  165. static char *SpyHelp[] =
  166. {
  167.     SPY_NOTICE "\2Usage:\2",
  168.     SPY_NOTICE "/spy add <nick1> [<nick2> [<#channel>]]",
  169.     SPY_NOTICE "/spy del <nick1> [<nick2>]",
  170.     SPY_NOTICE "/spy list [<nick1> [<nick2>]] [<#channel>]",
  171.     SPY_NOTICE "/spy clear",
  172.     SPY_NOTICE "\2Examples:\2",
  173.     SPY_NOTICE "/spy add AngryWolf Toxyc #secret",
  174.     SPY_NOTICE "/spy del AngryWolf",
  175.     SPY_NOTICE "/spy list #secret",
  176.     NULL
  177. };
  178. static char *SpyChHelp[] =
  179. {
  180.     SPY_NOTICE "\2Usage:\2",
  181.     SPY_NOTICE "/spychan add <#channel> [<#sendto>]]",
  182.     SPY_NOTICE "/spychan del <#channel>",
  183.     SPY_NOTICE "/spychan list [<#channel>]",
  184.     SPY_NOTICE "/spychan clear",
  185.     SPY_NOTICE "\2Examples:\2",
  186.     SPY_NOTICE "/spychan add #----- #spy",
  187.     SPY_NOTICE "/spychan del #-----",
  188.     SPY_NOTICE "/spychan list",
  189.     NULL
  190. };
  191. ModuleInfo  *SpyModInfo;
  192. Command   *CmdSpy, *CmdSpychannel, *CmdSpysend, *CmdSpychsend;
  193. Command   *CmdSpyforward, *CmdSpychforward, *CmdSpystats;
  194. Snomask   *SpySnomask;
  195. long   SNO_SPY;
  196. static Hook  *HookPrivMsg;
  197. static Hook  *HookChanMsg;
  198. static Hook  *HookQuit;
  199. static Hook  *HookRemoteQuit;
  200. static Hook  *HookServConn;
  201. static Hook  *HookLocalNick;
  202. static Hook  *HookRemoteNick;
  203. static Hook  *HookChanDest;
  204. static SpyStruct *SpyList = NULL;
  205. static SpyChStruct *SpyChList = NULL;
  206. // ==================================================================
  207. // Module initalization, loading and unloading
  208. // ==================================================================
  209. static Command *AddCommand(char *msg, char *token, int (*func)())
  210. {
  211.  Command *cmd;
  212.  if (CommandExists(msg))
  213.      {
  214.   config_error("Command %s already exists", msg);
  215.   return NULL;
  216.      }
  217.      if (CommandExists(token))
  218.  {
  219.   config_error("Token %s already exists", token);
  220.   return NULL;
  221.      }
  222.  cmd = CommandAdd(MyMod, msg, token, func, MAXPARA, 0);
  223. #ifndef _WIN32
  224.  if (ModuleGetError(MyMod) != MODERR_NOERROR || !cmd)
  225. #else
  226.  if (!cmd)
  227. #endif
  228.  {
  229. #ifndef _WIN32
  230.   config_error("Error adding command %s: %s", msg,
  231.    ModuleGetErrorStr(MyMod));
  232. #else
  233.   config_error("Error adding command %s", msg);
  234. #endif
  235.   return NULL; /* just to be sure */
  236.  }
  237.  return cmd;
  238. }
  239. static Snomask *AddSnomask(char flag, int (*allowed)(aClient *sptr, int what), long *mode)
  240. {
  241.         Snomask *s;
  242.         *mode = 0;
  243.         s = SnomaskAdd(MyMod, flag, allowed, mode);
  244. #ifndef _WIN32
  245.         if ((ModuleGetError(MyMod) != MODERR_NOERROR) || !s)
  246. #else
  247.         if (!s)
  248. #endif
  249.         {
  250. #ifndef _WIN32
  251.                 sendto_realops("[\2m_spy\2] Error adding snomask %c: %s",
  252.                         flag, ModuleGetErrorStr(MyMod));
  253. #else
  254.                 sendto_realops("[\2m_spy\2] Error adding snomask %c",
  255.                         flag);
  256. #endif
  257.                 return NULL;
  258.         }
  259.         return s;
  260. }
  261. DLLFUNC int MOD_INIT(m_spy)(ModuleInfo *modinfo)
  262. {
  263.  int ret = MOD_SUCCESS;
  264.  SpyModInfo = modinfo;
  265.  HookPrivMsg = HookAddPCharEx(MyMod, HOOKTYPE_USERMSG, spy_on_privmsg);
  266.  HookChanMsg = HookAddPCharEx(MyMod, HOOKTYPE_CHANMSG, spy_on_chanmsg);
  267.  HookQuit = HookAddEx(MyMod, HOOKTYPE_LOCAL_QUIT, spy_on_quit);
  268.  HookRemoteQuit = HookAddEx(MyMod, HOOKTYPE_REMOTE_QUIT, spy_on_remote_quit);
  269.  HookServConn = HookAddEx(MyMod, HOOKTYPE_SERVER_CONNECT, spy_on_server_connect);
  270.  HookLocalNick = HookAddEx(MyMod, HOOKTYPE_LOCAL_NICKCHANGE, spy_on_local_nickchange);
  271.  HookRemoteNick = HookAddEx(MyMod, HOOKTYPE_REMOTE_NICKCHANGE, spy_on_remote_nickchange);
  272.  HookChanDest = HookAddEx(MyMod, HOOKTYPE_CHANNEL_DESTROY, spy_on_channel_destroy);
  273.  CmdSpy  = AddCommand(MSG_SPY, TOK_SPY, m_spy);
  274.  CmdSpychannel = AddCommand(MSG_SPYCHANNEL, TOK_SPYCHANNEL, m_spychannel);
  275.  CmdSpysend = AddCommand(MSG_SPYSEND, TOK_SPYSEND, m_spysend);
  276.  CmdSpychsend = AddCommand(MSG_SPYCHSEND, TOK_SPYCHSEND, m_spychsend);
  277.  CmdSpyforward = AddCommand(MSG_SPYFORWARD, TOK_SPYFORWARD, m_spyforward);
  278.  CmdSpychforward = AddCommand(MSG_SPYCHFORWARD, TOK_SPYCHFORWARD, m_spychforward);
  279.  CmdSpystats = AddCommand(MSG_SPYSTATS, TOK_SPYSTATS, m_spystats);
  280.  SpySnomask = AddSnomask(FlagSpy, umode_allow_opers, &SNO_SPY);
  281.         if (!SpySnomask || !CmdSpy || !CmdSpychannel || !CmdSpysend || !CmdSpychsend)
  282.   ret = MOD_FAILED;
  283.  if (!CmdSpyforward || !CmdSpychforward || !CmdSpystats)
  284.   ret = MOD_FAILED;
  285.  return ret;
  286. }
  287. DLLFUNC int MOD_LOAD(m_spy)(int module_load)
  288. {
  289.  return MOD_SUCCESS;
  290. }
  291. DLLFUNC int MOD_UNLOAD(m_spy)(int module_unload)
  292. {
  293.  SpyStruct *s;
  294.  SpyChStruct *sc;
  295.  ListStruct  *next;
  296.  DelSnomask(SpySnomask);
  297.  DelCommand(CmdSpystats);
  298.  DelCommand(CmdSpychforward);
  299.  DelCommand(CmdSpyforward);
  300.  DelCommand(CmdSpychsend);
  301.  DelCommand(CmdSpysend);
  302.  DelCommand(CmdSpychannel);
  303.  DelCommand(CmdSpy);
  304.  DelHook(HookChanDest);
  305.  DelHook(HookRemoteNick);
  306.  DelHook(HookLocalNick);
  307.  DelHook(HookServConn);
  308.  DelHook(HookRemoteQuit);
  309.  DelHook(HookQuit);
  310.  DelHook(HookChanMsg);
  311.  DelHook(HookPrivMsg);
  312.  for (s = SpyList; s; s = (SpyStruct *) next)
  313.  {
  314.   next = (ListStruct *) s->next;
  315.   DelSpyItem(s);
  316.  }
  317.  for (sc = SpyChList; sc; sc = (SpyChStruct *) next)
  318.  {
  319.   next = (ListStruct *) sc->next;
  320.   DelSpyChItem(sc);
  321.  }
  322.  return MOD_SUCCESS;
  323. }
  324. // ==================================================================
  325. // Functions for nicknames, channel names and prefixes
  326. // ==================================================================
  327. static void del_prefix(char *str, u_int *lock, char **newstr)
  328. {
  329.  *lock = 0;
  330.  if (*str == LockFlag)
  331.  {
  332.   *lock = 1;
  333.   str++;
  334.  }
  335.  *newstr = str;
  336. }
  337. // ==================================================================
  338. // Misc functions
  339. // ==================================================================
  340. static SpyStruct *FindSpyItem1(aClient *acptr, char *nick)
  341. {
  342.  SpyStruct *s;
  343.  
  344.  for (s = SpyList; s; s = s->next)
  345.   if (s->who == acptr && !s->nick2 && !strcasecmp(s->nick1, nick))
  346.    break;
  347.  return s;
  348. }
  349. static SpyStruct *FindSpyItem2(aClient *acptr, char *nick1, char *nick2)
  350. {
  351.  SpyStruct *s;
  352.  
  353.  for (s = SpyList; s; s = s->next)
  354.   if (s->who == acptr && !strcasecmp(s->nick1, nick1)
  355.     && (s->nick2 && !strcasecmp(s->nick2, nick2)))
  356.    break;
  357.  return s;
  358. }
  359. static SpyChStruct *FindSpyChItem(aClient *acptr, char *channel)
  360. {
  361.  SpyChStruct *sc;
  362.  
  363.  for (sc = SpyChList; sc; sc = sc->next)
  364.   if (sc->who == acptr && !strcasecmp(sc->channel, channel))
  365.    break;
  366.  return sc;
  367. }
  368. static void AddSpyItem(aClient *acptr, char *nick1, char *nick2, char *chname, u_int lock1, u_int lock2)
  369. {
  370.  SpyStruct *s;
  371.  s  = (SpyStruct *) MyMalloc(sizeof(SpyStruct));
  372.  s->who  = acptr;
  373.  s->nick1 = strdup(nick1);
  374.  s->nick2 = BadPtr(nick2) ? NULL : strdup(nick2);
  375.  s->chname = BadPtr(chname) ? NULL : strdup(chname);
  376.  s->lock1 = lock1;
  377.  s->lock2 = lock2;
  378.  AddListItem(s, SpyList);
  379. }
  380. static void AddSpyChItem(aClient *acptr, char *channel, char *sendto, u_int lock)
  381. {
  382.  SpyChStruct *sc;
  383.  sc  = (SpyChStruct *) MyMalloc(sizeof(SpyChStruct));
  384.  sc->who  = acptr;
  385.  sc->channel = strdup(channel);
  386.  sc->sendto = BadPtr(sendto) ? NULL : strdup(sendto);
  387.  sc->lock = lock;
  388.  AddListItem(sc, SpyChList);
  389. }
  390. static void DelSpyItem(SpyStruct *s)
  391. {
  392.  DelListItem(s, SpyList);
  393.  MyFree(s->nick1);
  394.  ircfree(s->nick2);
  395.  ircfree(s->chname);
  396.  MyFree(s);
  397. }
  398. static void DelSpyChItem(SpyChStruct *sc)
  399. {
  400.  DelListItem(sc, SpyChList);
  401.  MyFree(sc->channel);
  402.  ircfree(sc->sendto);
  403.  MyFree(sc);
  404. }
  405. // ==================================================================
  406. // display_text: a general function to display two or more lines
  407. //     of text to a user
  408. // ==================================================================
  409. static void display_text(aClient *cptr, char *text[])
  410. {
  411.  char **pp;
  412.  for (pp = text; *pp; pp++)
  413.       sendto_one(cptr, *pp, me.name, cptr->name);
  414.  /* let user take 7 seconds to read it! */
  415.         if (MyClient(cptr))
  416.                 cptr->since += 7;
  417. }
  418. // ==================================================================
  419. // spy_paramcheck: checks for validity of /spy parameters
  420. // ==================================================================
  421. static unsigned int spy_paramcheck(aClient *cptr, int parc, char *parv[],
  422.  char **nick1, char **nick2, char **channel, u_int *lock1, u_int *lock2)
  423. {
  424.  *nick1  = NULL;
  425.  *nick2  = NULL;
  426.  *channel = NULL;
  427.  *lock1  = 0;
  428.  *lock2  = 0;
  429.  if (IsParam(2))
  430.  {
  431.   if (*parv[2] == '#')
  432.    *channel = parv[2];
  433.   else
  434.    *nick1 = parv[2];
  435.  }
  436.  if (IsParam(3))
  437.  {
  438.   if (*channel)
  439.    return 0;
  440.   else if (*parv[3] == '#')
  441.   {
  442.    *nick2  = NULL;
  443.    *channel = parv[3];
  444.   }
  445.   else
  446.    *nick2  = parv[3];
  447.  }
  448.  if (IsParam(4))
  449.  {
  450.   if (*channel)
  451.    return 0;
  452.   *channel = parv[4];
  453.  }
  454.  if (*nick1)
  455.   SplitLock(*lock1, *nick1);
  456.  if (*nick2)
  457.   SplitLock(*lock2, *nick2);
  458.  return 1;
  459. }
  460. // ==================================================================
  461. // spych_paramcheck: checks for validity of /spychannel parameters
  462. // ==================================================================
  463. static unsigned int spych_paramcheck(aClient *cptr, int parc, char *parv[],
  464.  char **channel, char **sendto, u_int *lock)
  465. {
  466.  *channel = NULL;
  467.  *sendto  = NULL;
  468.  *lock  = 0;
  469.  if (!IsParam(2))
  470.   return 0;
  471.  *channel = parv[2];
  472.  if (IsParam(3))
  473.   *sendto = parv[3];
  474.  if (*channel)
  475.   SplitLock(*lock, *channel);
  476.  return 1;
  477. }
  478. // ==================================================================
  479. // spy_send_client & spy_send_channel: handle sending users's private
  480. // messages to clients & channels
  481. // ==================================================================
  482. static void spy_send_client(aClient *acptr, int notice, char *nick1, char *nick2, char *text)
  483. {
  484.  if (MyClient(acptr))
  485.       sendto_one(acptr, ":IRC!IRC@%s PRIVMSG %s :[%s %c> %s] %s",
  486.               me.name, acptr->name,
  487.    nick1, (notice ? '-' : '>'), nick2, text);
  488.  else
  489.   sendto_one(acptr->from, "%s %s %c %s %s :%s",
  490.    IsToken(acptr->from) ? TOK_SPYSEND : MSG_SPYSEND,
  491.    acptr->name, (notice ? 'N' : 'P'),
  492.    nick1, nick2, text);
  493. }
  494. static void spy_send_channel(aClient *cptr, char *channel, int notice, char *nick1, char *nick2, char *text)
  495. {
  496.  aChannel *chptr;
  497.  if ((chptr = find_channel(channel, NullChn)) == NullChn)
  498.   return;
  499.         sendto_channel_butserv(chptr, &me, ":IRC!IRC@%s PRIVMSG %s :[%s %c> %s] %s",
  500.                 me.name, chptr->chname,
  501.   nick1, (notice ? '-' : '>'), nick2, text);
  502.  sendto_serv_butone_token(cptr, me.name, MSG_SPYSEND, TOK_SPYSEND,
  503.   "%s %c %s %s :%s",
  504.   chptr->chname, (notice ? 'N' : 'P'),
  505.   nick1, nick2, text);
  506. }
  507. static void spych_send_client(aClient *acptr, int notice, char *nick, char *channel, char *text)
  508. {
  509.  if (MyClient(acptr))
  510.       sendto_one(acptr, ":IRC!IRC@%s PRIVMSG %s :[%s] %c%s%c %s",
  511.               me.name, acptr->name, channel,
  512.    (notice ? '-' : '<'), nick, (notice ? '-' : '>'), text);
  513.  else
  514.   sendto_one(acptr->from, "%s %s %c %s %s :%s",
  515.    IsToken(acptr->from) ? TOK_SPYCHSEND : MSG_SPYCHSEND,
  516.    acptr->name, (notice ? 'N' : 'P'),
  517.    nick, channel, text);
  518. }
  519. static void spych_send_channel(aClient *cptr, char *sendto, int notice, char *nick, char *channel, char *text)
  520. {
  521.  aChannel *chptr;
  522.  if ((chptr = find_channel(sendto, NullChn)) == NullChn)
  523.   return;
  524.         sendto_channel_butserv(chptr, &me, ":IRC!IRC@%s PRIVMSG %s :[%s] %c%s%c %s",
  525.                 me.name, chptr->chname, channel,
  526.   (notice ? '-' : '<'), nick, (notice ? '-' : '>'), text);
  527.  sendto_serv_butone_token(cptr, me.name, MSG_SPYCHSEND, TOK_SPYCHSEND,
  528.   "%s %c %s %s :%s",
  529.   chptr->chname, (notice ? 'N' : 'P'),
  530.   nick, channel, text);
  531. }
  532. // ==================================================================
  533. // Events
  534. // ==================================================================
  535. DLLFUNC int spy_on_quit(aClient *sptr, char *comment)
  536. {
  537.  SpyStruct *s;
  538.  SpyChStruct *sc;
  539.  ListStruct  *next;
  540.  // sendto_realops("(spy_on_quit) sptr->name=[%s]", sptr->name);
  541.  for (s = SpyList; s; s = (SpyStruct *) next)
  542.  {
  543.   next = (ListStruct *) s->next;
  544.   if (s->who == sptr)
  545.    DelSpyItem(s);
  546.   else if (!s->lock1 && !strcasecmp(s->nick1, sptr->name))
  547.    DelSpyItem(s);
  548.   else if (s->nick2 && !s->lock2 && !strcasecmp(s->nick2, sptr->name))
  549.    DelSpyItem(s);
  550.  }
  551.  for (sc = SpyChList; sc; sc = (SpyChStruct *) next)
  552.  {
  553.   next = (ListStruct *) sc->next;
  554.   if (sc->who == sptr)
  555.    DelSpyChItem(sc);
  556.  }
  557.  return 0;
  558. }
  559. // ==================================================================
  560. DLLFUNC int spy_on_remote_quit(aClient *sptr, char *comment)
  561. {
  562.  SpyStruct *s;
  563.  SpyChStruct *sc;
  564.  ListStruct  *next;
  565.  // sendto_realops("(spy_on_remote_quit) sptr->name=[%s]", sptr->name);
  566.  for (s = SpyList; s; s = (SpyStruct *) next)
  567.  {
  568.   next = (ListStruct *) s->next;
  569.   if (s->who == sptr)
  570.    DelSpyItem(s);
  571.   else if (!s->lock1 && !strcasecmp(s->nick1, sptr->name))
  572.    DelSpyItem(s);
  573.   else if (s->nick2 && !s->lock2 && !strcasecmp(s->nick2, sptr->name))
  574.    DelSpyItem(s);
  575.  }
  576.  for (sc = SpyChList; sc; sc = (SpyChStruct *) next)
  577.  {
  578.   next = (ListStruct *) sc->next;
  579.   if (sc->who == sptr)
  580.    DelSpyChItem(sc);
  581.  }
  582.  return 0;
  583. }
  584. // ==================================================================
  585. DLLFUNC int spy_on_local_nickchange(aClient *sptr, char *nick)
  586. {
  587.  SpyStruct *s;
  588.  for (s = SpyList; s; s = s->next)
  589.  {
  590.   if (!s->lock1 && !strcasecmp(s->nick1, sptr->name))
  591.   {
  592.    ircstrdup(s->nick1, nick);
  593.   }
  594.   if (s->nick2 && !s->lock2 && !strcasecmp(s->nick2, sptr->name))
  595.   {
  596.    ircstrdup(s->nick2, nick);
  597.   }
  598.  }
  599.  return 0;
  600. }
  601. DLLFUNC int spy_on_remote_nickchange(aClient *cptr, aClient *sptr, char *nick)
  602. {
  603.  SpyStruct *s;
  604.  for (s = SpyList; s; s = s->next)
  605.  {
  606.   if (!s->lock1 && !strcasecmp(s->nick1, sptr->name))
  607.   {
  608.    ircstrdup(s->nick1, nick);
  609.   }
  610.   if (s->nick2 && !s->lock2 && !strcasecmp(s->nick2, sptr->name))
  611.   {
  612.    ircstrdup(s->nick2, nick);
  613.   }
  614.  }
  615.  return 0;
  616. }
  617. // ==================================================================
  618. DLLFUNC int spy_on_channel_destroy(aChannel *chptr)
  619. {
  620.  SpyChStruct *sc;
  621.  ListStruct *next;
  622.  for (sc = SpyChList; sc; sc = (SpyChStruct *) next)
  623.  {
  624.   next = (ListStruct *) sc->next;
  625.   if (!sc->lock && !strcasecmp(sc->channel, chptr->chname))
  626.    DelSpyChItem(sc);
  627.  }
  628.  return 0;
  629. }
  630. // ==================================================================
  631. DLLFUNC int spy_on_server_connect(aClient *sptr)
  632. {
  633.  SpyStruct *s;
  634.  SpyChStruct *sc;
  635.  // sendto_realops("(spy_on_server_connect) sptr->name=[%s]", sptr->name);
  636.  /* TODO: optimize this! */
  637.  sendto_one(sptr, ":%s %s CONNECT",
  638.   me.name, (IsToken(sptr) ? TOK_SPYFORWARD : MSG_SPYFORWARD));
  639.  sendto_one(sptr, ":%s %s CONNECT",
  640.   me.name, (IsToken(sptr) ? TOK_SPYCHFORWARD : MSG_SPYCHFORWARD));
  641.  for (s = SpyList; s; s = s->next)
  642.  {
  643.   sendto_one(sptr, ":%s %s ADD2 %s %s%s %s%s %s",
  644.    me.name,
  645.    (IsToken(sptr) ? TOK_SPYFORWARD : MSG_SPYFORWARD),
  646.    s->who->name,
  647.    MergeLock(s->lock1, s->nick1),
  648.    MergeLockOpt(s->lock2, s->nick2),
  649.    s->chname ? s->chname : "*");
  650.  }
  651.  for (sc = SpyChList; sc; sc = sc->next)
  652.  {
  653.   sendto_one(sptr, ":%s %s ADD2 %s %s%s %s",
  654.    me.name,
  655.    (IsToken(sptr) ? TOK_SPYCHFORWARD : MSG_SPYCHFORWARD),
  656.    sc->who->name,
  657.    MergeLock(sc->lock, sc->channel),
  658.    sc->sendto ? sc->sendto : "*");
  659.  }
  660.  return 0;
  661. }
  662. // ==================================================================
  663. DLLFUNC char *spy_on_privmsg(aClient *cptr, aClient *sptr, aClient *acptr, char *text, int notice)
  664. {
  665.  SpyStruct *s;
  666.  aChannel *chptr;
  667.  char  *nick1, *nick2;
  668.  if (!MyClient(sptr))
  669.   return text;
  670.  /* First do some sorting */
  671.  if (smycmp(sptr->name, acptr->name) > 0)
  672.  {
  673.       nick1 = acptr->name;
  674.       nick2 = sptr->name;
  675.  }
  676.  else
  677.  {
  678.   nick1 = sptr->name;
  679.   nick2 = acptr->name;
  680.  }
  681.  for (s = SpyList; s; s = s->next)
  682.  {
  683.   if (
  684.    /* spy every messages sent and received by one client */
  685.    (
  686.     !s->nick2 &&
  687.     (!strcasecmp(s->nick1, sptr->name) || !strcasecmp(s->nick1, acptr->name))
  688.    ) ||
  689.    /* spy messages between two specific users */
  690.    (
  691.     !strcasecmp(s->nick1, nick1) && !strcasecmp(s->nick2, nick2)
  692.    )
  693.      )
  694.   {
  695.    if (s->chname)
  696.      spy_send_channel(&me, s->chname, notice,
  697.       sptr->name, acptr->name, text);
  698.     else
  699.      spy_send_client(s->who, notice,
  700.       sptr->name, acptr->name, text);
  701.   }
  702.  }
  703.  return text;
  704. }
  705. DLLFUNC char *spy_on_chanmsg(aClient *cptr, aClient *sptr, aChannel *chptr, char *text, int notice)
  706. {
  707.  SpyChStruct *sc;
  708.  if (!MyClient(sptr))
  709.   return text;
  710.  for (sc = SpyChList; sc; sc = sc->next)
  711.  {
  712.   if (!strcasecmp(chptr->chname, sc->channel))
  713.   {
  714.    if (sc->sendto)
  715.     spych_send_channel(&me, sc->sendto, notice,
  716.      sptr->name, chptr->chname, text);
  717.    else
  718.     spy_send_client(sc->who, notice,
  719.      sptr->name, chptr->chname, text);
  720.   }
  721.  }
  722.  return text;
  723. }
  724. // ==================================================================
  725. // m_spy: Adds, removes or lists nicknames in spy list
  726. // ==================================================================
  727. DLLFUNC int m_spy(aClient *cptr, aClient *sptr, int parc, char *parv[])
  728. {
  729.  SpyStruct *s;
  730.  char  *tmp = NULL, *cmd;
  731.  char  *nick1, *nick2, *channel;
  732.  u_int  lock1, lock2;
  733.         if (!MyClient(cptr) || !IsOper(cptr) || !IsSAdmin(cptr))
  734.  {
  735.          sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
  736.   return -1;
  737.  }
  738.  cmd = IsParam(1) ? parv[1] : NULL;
  739.         if (!cmd)
  740.  {
  741.   display_text(cptr, SpyHelp);
  742.   return -1;
  743.  }
  744.  /* ADD */
  745.  if (!strcasecmp(cmd, "add"))
  746.  {
  747.   if (!spy_paramcheck(cptr, parc, parv, &nick1, &nick2, &channel, &lock1, &lock2))
  748.   {
  749.    display_text(cptr, SpyHelp);
  750.    return -1;
  751.   }
  752.   if (!nick1 || IsParam(5))
  753.   {
  754.    display_text(cptr, SpyHelp);
  755.    return -1;
  756.   }
  757.   if (nick2 && !strcasecmp(nick1, nick2))
  758.   {
  759.        sendto_one(sptr, ":%s NOTICE %s :*** %s %s: Nicks cannot be the same",
  760.                me.name, sptr->name,
  761.     nick1, nick2);
  762.    return -1;
  763.   }
  764.   if (channel && *channel != '#')
  765.   {
  766.        sendto_one(sptr, ":%s NOTICE %s :*** %s: Invalid channel name",
  767.                me.name, sptr->name, channel);
  768.    return -1;
  769.   }
  770.   if (nick2 && (smycmp(nick1, nick2) > 0))
  771.   {
  772.    tmp = nick1;
  773.    nick1 = nick2;
  774.    nick2 = tmp;
  775.   }
  776.   if ((nick2 && FindSpyItem2(sptr, nick1, nick2)) || (!nick2 && FindSpyItem1(sptr, nick1)))
  777.   {
  778.        sendto_one(sptr, ":%s NOTICE %s :*** %s %s: Already on your private spy list",
  779.                me.name, sptr->name,
  780.     nick1, nick2 ? nick2 : "<irc>");
  781.    return -1;
  782.   }
  783.   AddSpyItem(sptr, nick1, nick2, channel, lock1, lock2);
  784.       sendto_one(sptr, ":%s NOTICE %s :*** %s %s: Added to your private spy list",
  785.               me.name, sptr->name,
  786.    nick1, nick2 ? nick2 : "<irc>");
  787.   SpyForward5(&me, "ADD", sptr->name, nick1, nick2, channel, lock1, lock2);
  788.   sendto_snomask(SNO_SPY, "*** [\2m_spy\2] %s used /SPY ADD %s%s" "%s" "%s%s" "%s" "%s",
  789.    sptr->name, MergeLock(lock1, nick1),
  790.    nick2 ? " " : "", MergeLockEmp(lock2, nick2),
  791.    channel ? " " : "", channel ? channel : "");
  792.  }
  793.  /* DEL */
  794.  else if (!strcasecmp(cmd, "del"))
  795.  {
  796.   if (!spy_paramcheck(cptr, parc, parv, &nick1, &nick2, &channel, &lock1, &lock2))
  797.   {
  798.    display_text(cptr, SpyHelp);
  799.    return -1;
  800.   }
  801.   if (!nick1 || channel || IsParam(4))
  802.   {
  803.    display_text(cptr, SpyHelp);
  804.    return -1;
  805.   }
  806.   if (nick2 && (smycmp(nick1, nick2) > 0))
  807.   {
  808.    tmp = nick1;
  809.    nick1 = nick2;
  810.    nick2 = tmp;
  811.   }
  812.   if ((nick2 && !(s = FindSpyItem2(sptr, nick1, nick2))) || (!nick2 && !(s = FindSpyItem1(sptr, nick1))))
  813.   {
  814.        sendto_one(sptr, ":%s NOTICE %s :*** %s %s: Not yet on your private spy list",
  815.                me.name, sptr->name,
  816.     nick1, nick2 ? nick2 : "<irc>");
  817.    return -1;
  818.   }
  819.   SpyForward4(&me, "DEL", s->who->name, s->nick1, s->nick2, 0, 0);
  820.       sendto_one(sptr, ":%s NOTICE %s :*** %s %s: Deleted from your private spy list",
  821.               me.name, sptr->name,
  822.    nick1, nick2 ? nick2 : "<irc>");
  823.   sendto_snomask(SNO_SPY, "*** [\2m_spy\2] %s used /SPY DEL %s%s%s",
  824.    sptr->name, s->nick1, s->nick2 ? " " : "", s->nick2 ? s->nick2 : "");
  825.   DelSpyItem(s);
  826.  }
  827.  /* LIST */
  828.  else if (!strcasecmp(cmd, "list"))
  829.  {
  830.   enum ListType { LT_n1n2c, LT_n1n2, LT_n1c, LT_n1, LT_c, LT_none };
  831.   unsigned int found = 0, type = 0, show = 0, empty = 1;
  832.   if (!spy_paramcheck(cptr, parc, parv, &nick1, &nick2, &channel, &lock1, &lock2))
  833.   {
  834.    display_text(cptr, SpyHelp);
  835.    return -1;
  836.   }
  837.   if (channel)
  838.   {
  839.    if (nick2)
  840.     type = LT_n1n2c;
  841.    else if (nick1)
  842.     type = LT_n1c;
  843.    else
  844.     type = LT_c;
  845.   }
  846.   else if (nick2)
  847.    type = LT_n1n2;
  848.   else if (nick1)
  849.    type = LT_n1;
  850.   else
  851.    type = LT_none;
  852.   if (nick1 && nick2 && (smycmp(nick1, nick2) > 0))
  853.   {
  854.    tmp = nick1;
  855.    nick1 = nick2;
  856.    nick2 = tmp;
  857.   }
  858.   for (s = SpyList; s; s = s->next)
  859.    if (s->who == sptr)
  860.    {
  861.     empty = 0;
  862.     show = 0;
  863.     switch (type)
  864.     {
  865.      case LT_n1n2c:
  866.       if (
  867.        s->nick2 &&
  868.        s->chname &&
  869.        !strcasecmp(s->nick1, nick1) &&
  870.        !strcasecmp(s->nick2, nick2) &&
  871.        !strcasecmp(s->chname, channel)
  872.          )
  873.        show = 1;
  874.       break;
  875.      case LT_n1n2:
  876.       if (
  877.        s->nick2 &&
  878.        !strcasecmp(s->nick1, nick1) &&
  879.        !strcasecmp(s->nick2, nick2)
  880.          )
  881.        show = 1;
  882.       break;
  883.      case LT_n1c:
  884.       if (
  885.        s->chname &&
  886.        !strcasecmp(s->nick1, nick1) &&
  887.        !strcasecmp(s->chname, channel)
  888.          )
  889.        show = 1;
  890.       break;
  891.      case LT_n1:
  892.       if (!strcasecmp(s->nick1, nick1))
  893.        show = 1;
  894.       break;
  895.      case LT_c:
  896.       if (s->chname && !strcasecmp(s->chname, channel))
  897.        show = 1;
  898.       break;
  899.      default:
  900.       show = 1;
  901.     }
  902.     if (show)
  903.     {
  904.      found++;
  905.  
  906.          sendto_one(sptr, ":%s NOTICE %s :*** %s%s %s%s %s",
  907.                  me.name, sptr->name,
  908.       MergeLock(s->lock1, s->nick1),
  909.       MergeLockOpt(s->lock2, s->nick2),
  910.       s->chname ? s->chname : "<irc>");
  911.     }
  912.    }
  913.   if (!found)
  914.   {
  915.        sendto_one(sptr, ":%s NOTICE %s :*** %s",
  916.         me.name, sptr->name,
  917.     empty ? "Your spy list is empty" : "No matching entries");
  918.   }
  919.   else
  920.   {
  921.    sendto_one(sptr, ":%s NOTICE %s :*** " SPY_LINE,
  922.     me.name, sptr->name);
  923.    sendto_one(sptr, ":%s NOTICE %s :*** %d entr%s",
  924.     me.name, sptr->name,
  925.     found, found > 1 ? "ies" : "y");
  926.   }
  927.  }
  928.  /* CLEAR */
  929.  else if (!strcasecmp(cmd, "clear"))
  930.  {
  931.   ListStruct *next;
  932.   for (s = SpyList; s; s = (SpyStruct *) next)
  933.   {
  934.    next = (ListStruct *) s->next;
  935.    if (s->who == sptr)
  936.     DelSpyItem(s);
  937.   }
  938.       sendto_one(sptr, ":%s NOTICE %s :*** Your private spy list is now empty",
  939.               me.name, sptr->name);
  940.   SpyForward2(&me, "CLEAR", sptr->name);
  941.  }
  942.  /* <INVALID OPTION> */
  943.  else
  944.  {
  945.       sendto_one(sptr, ":%s NOTICE %s :*** Invalid option %s",
  946.               me.name, sptr->name, cmd);
  947.   return -1;
  948.  }
  949.  return 0;
  950. }
  951. // ==================================================================
  952. // m_spychannel: Adds, removes or lists channel names in channel
  953. //     spy list
  954. // ==================================================================
  955. DLLFUNC int m_spychannel(aClient *cptr, aClient *sptr, int parc, char *parv[])
  956. {
  957.  SpyChStruct *sc;
  958.  char  *cmd, *channel, *sendto;
  959.  u_int  lock;
  960.         if (!MyClient(cptr) || !IsOper(cptr) || !IsSAdmin(cptr))
  961.  {
  962.          sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
  963.   return -1;
  964.  }
  965.  cmd = IsParam(1) ? parv[1] : NULL;
  966.         if (!cmd)
  967.  {
  968.   display_text(cptr, SpyChHelp);
  969.   return -1;
  970.  }
  971.  /* ADD */
  972.  if (!strcasecmp(cmd, "add"))
  973.  {
  974.   if (!spych_paramcheck(cptr, parc, parv, &channel, &sendto, &lock))
  975.   {
  976.    display_text(cptr, SpyChHelp);
  977.    return -1;
  978.   }
  979.   if (*channel != '#')
  980.   {
  981.        sendto_one(sptr, ":%s NOTICE %s :*** %s: Invalid channel name",
  982.                me.name, sptr->name, channel);
  983.    return -1;
  984.   }
  985.   if (sendto && *sendto != '#')
  986.   {
  987.        sendto_one(sptr, ":%s NOTICE %s :*** %s: Invalid channel name",
  988.                me.name, sptr->name, sendto);
  989.    return -1;
  990.   }
  991.   if (FindSpyChItem(sptr, channel))
  992.   {
  993.        sendto_one(sptr, ":%s NOTICE %s :*** %s: Already on your channel spy list",
  994.                me.name, sptr->name, channel);
  995.    return -1;
  996.   }
  997.   if (sendto && !strcasecmp(channel, sendto))
  998.   {
  999.        sendto_one(sptr, ":%s NOTICE %s :*** %s %s: Source and target channels cannot be the same",
  1000.                me.name, sptr->name, channel, sendto);
  1001.    return -1;
  1002.   }
  1003.   AddSpyChItem(sptr, channel, sendto, lock);
  1004.       sendto_one(sptr, ":%s NOTICE %s :*** %s: Added to your channel spy list",
  1005.               me.name, sptr->name, channel);
  1006.   SpyChForward4(&me, "ADD", sptr->name, channel, sendto, lock);
  1007.   sendto_snomask(SNO_SPY, "*** [\2m_spy\2] %s used /SPYCHANNEL ADD %s%s" "%s" "%s",
  1008.    sptr->name, MergeLock(lock, channel), sendto ? " " : "",
  1009.    sendto ? sendto : "");
  1010.  }
  1011.  /* DEL */
  1012.  else if (!strcasecmp(cmd, "del"))
  1013.  {
  1014.   if (!spych_paramcheck(cptr, parc, parv, &channel, &sendto, &lock))
  1015.   {
  1016.    display_text(cptr, SpyChHelp);
  1017.    return -1;
  1018.   }
  1019.   if (!(sc = FindSpyChItem(sptr, channel)))
  1020.   {
  1021.        sendto_one(sptr, ":%s NOTICE %s :*** %s: Not yet on your channel spy list",
  1022.                me.name, sptr->name, channel);
  1023.    return -1;
  1024.   }
  1025.   SpyChForward3(&me, "DEL", sc->who->name, sc->channel, 0);
  1026.       sendto_one(sptr, ":%s NOTICE %s :*** %s: Deleted from your channel spy list",
  1027.               me.name, sptr->name, channel);
  1028.   sendto_snomask(SNO_SPY, "*** [\2m_spy\2] %s used /SPYCHANNEL DEL %s",
  1029.    sptr->name, sc->channel);
  1030.   DelSpyChItem(sc);
  1031.  }
  1032.  /* LIST */
  1033.  else if (!strcasecmp(cmd, "list"))
  1034.  {
  1035.   unsigned int found = 0, empty = 1;
  1036.   sendto = NULL;
  1037.   channel = IsParam(2) ? parv[2] : NULL;
  1038.   if (channel)
  1039.    SplitLock(lock, channel);
  1040.   for (sc = SpyChList; sc; sc = sc->next)
  1041.    if (sc->who == sptr)
  1042.    {
  1043.     empty = 0;
  1044.     if (!channel || !strcasecmp(sc->channel, channel))
  1045.     {
  1046.      found++;
  1047.  
  1048.          sendto_one(sptr, ":%s NOTICE %s :*** %s%s %s",
  1049.                  me.name, sptr->name,
  1050.       MergeLock(sc->lock, sc->channel),
  1051.       sc->sendto ? sc->sendto : "<irc>");
  1052.     }
  1053.    }
  1054.   if (!found)
  1055.   {
  1056.        sendto_one(sptr, ":%s NOTICE %s :*** %s",
  1057.         me.name, sptr->name,
  1058.     empty ? "Your channel spy list is empty" : "No matching entries");
  1059.   }
  1060.   else
  1061.   {
  1062.    sendto_one(sptr, ":%s NOTICE %s :*** " SPY_LINE,
  1063.     me.name, sptr->name);
  1064.    sendto_one(sptr, ":%s NOTICE %s :*** %d entr%s",
  1065.     me.name, sptr->name,
  1066.     found, found > 1 ? "ies" : "y");
  1067.   }
  1068.  }
  1069.  /* CLEAR */
  1070.  else if (!strcasecmp(cmd, "clear"))
  1071.  {
  1072.   ListStruct *next;
  1073.   for (sc = SpyChList; sc; sc = (SpyChStruct *) next)
  1074.   {
  1075.    next = (ListStruct *) sc->next;
  1076.    if (sc->who == sptr)
  1077.     DelSpyChItem(sc);
  1078.   }
  1079.       sendto_one(sptr, ":%s NOTICE %s :*** Your channel spy list is now empty",
  1080.               me.name, sptr->name);
  1081.   SpyChForward2(&me, "CLEAR", sptr->name);
  1082.  }
  1083.  /* <INVALID OPTION> */
  1084.  else
  1085.  {
  1086.       sendto_one(sptr, ":%s NOTICE %s :*** Invalid option %s",
  1087.               me.name, sptr->name, cmd);
  1088.   return -1;
  1089.  }
  1090.  return 0;
  1091. }
  1092. // ==================================================================
  1093. // m_spyforward: Keeps SpyList updated on all servers
  1094. // ==================================================================
  1095. DLLFUNC int m_spyforward(aClient *cptr, aClient *sptr, int parc, char *parv[])
  1096. {
  1097.  SpyStruct *s;
  1098.  ListStruct  *next;
  1099.  aClient  *acptr;
  1100.  char  *tmp, *cmd, *who, *nick1, *nick2, *channel;
  1101.  u_int  lock1, lock2;
  1102.         if (IsClient(cptr))
  1103.  {
  1104.          sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
  1105.   return -1;
  1106.  }
  1107.  cmd = IsParam(1)  ? parv[1] : NULL;
  1108.  who = IsParam(2)  ? parv[2] : NULL;
  1109.  nick1 = IsParam(3)  ? parv[3] : NULL;
  1110.  nick2 = IsValidParam(4) ? parv[4] : NULL;
  1111.  channel = IsValidParam(5) ? parv[5] : NULL;
  1112.  /* sendto_realops("(\2m_spyforward\2) cptr=%s, sptr=%s, cmd=%s who=%s nick1=%s nick2=%s channel=%s",
  1113.   cptr->name, sptr->name,
  1114.   cmd ? cmd  : "(null)",
  1115.   who ? who  : "(null)",
  1116.   nick1 ? nick1  : "(null)",
  1117.   nick2 ? nick2  : "(null)",
  1118.   channel ? channel : "(null)"); */
  1119.         if (!cmd)
  1120.   return -1;
  1121.  if (nick1)
  1122.   SplitLock(lock1, nick1);
  1123.  if (nick2)
  1124.   SplitLock(lock2, nick2);
  1125.  /* ADD */
  1126.  if (!strcasecmp(cmd, "add"))
  1127.  {
  1128.   if (!nick1)
  1129.    return -1;
  1130.   if (nick2 && !strcasecmp(nick1, nick2))
  1131.    return -1;
  1132.   if (nick2 && (smycmp(nick1, nick2) > 0))
  1133.   {
  1134.    tmp = nick1;
  1135.    nick1 = nick2;
  1136.    nick2 = tmp;
  1137.   }
  1138.   if (!(acptr = find_person(who, NULL)))
  1139.    return -1;
  1140.   if ((nick2 && FindSpyItem2(acptr, nick1, nick2)) || (!nick2 && FindSpyItem1(acptr, nick1)))
  1141.    return -1;
  1142.   AddSpyItem(acptr, nick1, nick2, channel, lock1, lock2);
  1143.   SpyForward5(cptr, "ADD", acptr->name, nick1, nick2, channel, lock1, lock2);
  1144.   sendto_snomask(SNO_SPY, "*** [\2m_spy\2] %s used /SPY ADD %s%s" "%s" "%s%s" "%s" "%s",
  1145.    acptr->name, MergeLock(lock1, nick1),
  1146.    nick2 ? " " : "", MergeLockEmp(lock2, nick2),
  1147.    channel ? " " : "", channel ? channel : "");
  1148.  }
  1149.  /* ADD2 -- Like ADD, but without forwarding */
  1150.  if (!strcasecmp(cmd, "add2"))
  1151.  {
  1152.   if (!nick1)
  1153.    return -1;
  1154.   if (nick2 && !strcasecmp(nick1, nick2))
  1155.    return -1;
  1156.   if (nick2 && (smycmp(nick1, nick2) > 0))
  1157.   {
  1158.    tmp = nick1;
  1159.    nick1 = nick2;
  1160.    nick2 = tmp;
  1161.   }
  1162.   if (!(acptr = find_person(who, NULL)))
  1163.    return -1;
  1164.   if ((nick2 && FindSpyItem2(acptr, nick1, nick2)) || (!nick2 && FindSpyItem1(acptr, nick1)))
  1165.    return -1;
  1166.   AddSpyItem(acptr, nick1, nick2, channel, lock1, lock2);
  1167.  }
  1168.  /* DEL */
  1169.  else if (!strcasecmp(cmd, "del"))
  1170.  {
  1171.   if (!nick1)
  1172.    return -1;
  1173.   if (nick2 && (smycmp(nick1, nick2) > 0))
  1174.   {
  1175.    tmp = nick1;
  1176.    nick1 = nick2;
  1177.    nick2 = tmp;
  1178.   }
  1179.   if (!(acptr = find_person(who, NULL)))
  1180.    return -1;
  1181.   if ((nick2 && !(s = FindSpyItem2(acptr, nick1, nick2))) || (!nick2 && !(s = FindSpyItem1(acptr, nick1))))
  1182.    return -1;
  1183.   sendto_snomask(SNO_SPY, "*** [\2m_spy\2] %s used /SPY DEL %s%s%s",
  1184.    acptr->name, s->nick1, s->nick2 ? " " : "", s->nick2 ? s->nick2 : "");
  1185.   SpyForward4(cptr, "DEL", acptr->name, s->nick1, s->nick2, 0, 0);
  1186.   DelSpyItem(s);
  1187.  }
  1188.  /* CLEAR */
  1189.  else if (!strcasecmp(cmd, "clear"))
  1190.  {
  1191.   if (!who)
  1192.    return -1;
  1193.   if (!(acptr = find_person(who, NULL)))
  1194.    return -1;
  1195.   for (s = SpyList; s; s = (SpyStruct *) next)
  1196.   {
  1197.    next = (ListStruct *) s->next;
  1198.    if (s->who == acptr)
  1199.     DelSpyItem(s);
  1200.   }
  1201.   SpyForward2(cptr, "CLEAR", acptr->name);
  1202.  }
  1203.  /* CONNECT */
  1204.  else if (!strcasecmp(cmd, "connect"))
  1205.  {
  1206.   for (s = SpyList; s; s = s->next)
  1207.    /* act as a client who is just adding a spy entry */
  1208.    SpyForward5(&me, "ADD", s->who->name, s->nick1, s->nick2,
  1209.     s->chname, s->lock1, s->lock2);
  1210.  }
  1211.  /* <INVALID OPTION> */
  1212.  else
  1213.  {
  1214.   return -1;
  1215.  }
  1216.  return 0;
  1217. }
  1218. // ==================================================================
  1219. // m_spychforward: Keeps SpyChList updated on all servers
  1220. // ==================================================================
  1221. DLLFUNC int m_spychforward(aClient *cptr, aClient *sptr, int parc, char *parv[])
  1222. {
  1223.  SpyChStruct *sc;
  1224.  ListStruct  *next;
  1225.  aClient  *acptr;
  1226.  char  *cmd, *who, *channel, *sendto;
  1227.  u_int  lock;
  1228.         if (IsClient(cptr))
  1229.  {
  1230.          sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
  1231.   return -1;
  1232.  }
  1233.  cmd = IsParam(1)  ? parv[1] : NULL;
  1234.  who = IsParam(2)  ? parv[2] : NULL;
  1235.  channel = IsValidParam(3) ? parv[3] : NULL;
  1236.  sendto = IsValidParam(4) ? parv[4] : NULL;
  1237.  /* sendto_realops("(\2m_spychforward\2) cptr=%s, sptr=%s, cmd=%s who=%s channel=%s sendto=%s",
  1238.   cptr->name, sptr->name,
  1239.   cmd ? cmd  : "(null)",
  1240.   who ? who  : "(null)",
  1241.   channel ? channel : "(null)",
  1242.   sendto ? sendto : "(null)"); */
  1243.         if (!cmd)
  1244.   return -1;
  1245.  if (channel)
  1246.   SplitLock(lock, channel);
  1247.  /* ADD */
  1248.  if (!strcasecmp(cmd, "add"))
  1249.  {
  1250.   if (!channel)
  1251.    return -1;
  1252.   if (!(acptr = find_person(who, NULL)))
  1253.    return -1;
  1254.   if (FindSpyChItem(acptr, channel))
  1255.    return -1;
  1256.   AddSpyChItem(acptr, channel, sendto, lock);
  1257.   SpyChForward4(cptr, "ADD", acptr->name, channel, sendto, lock);
  1258.   sendto_snomask(SNO_SPY, "*** [\2m_spy\2] %s used /SPYCHANNEL ADD %s%s" "%s" "%s",
  1259.    acptr->name, MergeLock(lock, channel),
  1260.    sendto ? " " : "", sendto ? sendto : "");
  1261.  }
  1262.  /* ADD2 -- Like ADD, but without forwarding */
  1263.  if (!strcasecmp(cmd, "add2"))
  1264.  {
  1265.   if (!channel)
  1266.    return -1;
  1267.   if (!(acptr = find_person(who, NULL)))
  1268.    return -1;
  1269.   if (FindSpyChItem(acptr, channel))
  1270.    return -1;
  1271.   AddSpyChItem(acptr, channel, sendto, lock);
  1272.  }
  1273.  /* DEL */
  1274.  else if (!strcasecmp(cmd, "del"))
  1275.  {
  1276.   if (!channel)
  1277.    return -1;
  1278.   if (!(acptr = find_person(who, NULL)))
  1279.    return -1;
  1280.   if (!(sc = FindSpyChItem(acptr, channel)))
  1281.    return -1;
  1282.   sendto_snomask(SNO_SPY, "*** [\2m_spy\2] %s used /SPYCHANNEL DEL %s",
  1283.    acptr->name, sc->channel);
  1284.   SpyChForward3(cptr, "DEL", acptr->name, sc->channel, 0);
  1285.   DelSpyChItem(sc);
  1286.  }
  1287.  /* CLEAR */
  1288.  else if (!strcasecmp(cmd, "clear"))
  1289.  {
  1290.   if (!who)
  1291.    return -1;
  1292.   if (!(acptr = find_person(who, NULL)))
  1293.    return -1;
  1294.   for (sc = SpyChList; sc; sc = (SpyChStruct *) next)
  1295.   {
  1296.    next = (ListStruct *) sc->next;
  1297.    if (sc->who == acptr)
  1298.     DelSpyChItem(sc);
  1299.   }
  1300.   SpyChForward2(cptr, "CLEAR", acptr->name);
  1301.  }
  1302.  /* CONNECT */
  1303.  else if (!strcasecmp(cmd, "connect"))
  1304.  {
  1305.   for (sc = SpyChList; sc; sc = sc->next)
  1306.    /* act as a client who is just adding a channel spy entry */
  1307.    SpyChForward4(&me, "ADD", sc->who->name, sc->channel,
  1308.     sc->sendto, sc->lock);
  1309.  }
  1310.  /* <INVALID OPTION> */
  1311.  else
  1312.  {
  1313.   return -1;
  1314.  }
  1315.  return 0;
  1316. }
  1317. // ==================================================================
  1318. // m_spysend: Sends users' private messages to a client on the network
  1319. // Easier way?
  1320. // ==================================================================
  1321. DLLFUNC int m_spysend(aClient *cptr, aClient *sptr, int parc, char *parv[])
  1322. {
  1323.  aClient  *acptr;
  1324.  char  *from, *to, *cmd, *nick1, *nick2, *text;
  1325.  unsigned notice;
  1326.  if (!IsServer(sptr) || !IsParam(5))
  1327.   return -1;
  1328.  to = IsParam(1)  ? parv[1] : NULL;
  1329.  cmd = IsParam(2)  ? parv[2] : NULL;
  1330.  nick1 = IsParam(3)  ? parv[3] : NULL;
  1331.  nick2 = IsParam(4)  ? parv[4] : NULL;
  1332.  text = IsParam(5)  ? parv[5] : NULL;
  1333.  if (!text)
  1334.   return -1;
  1335.  notice = *cmd == 'N' ? 1 : 0;
  1336.  if (*to == '#')
  1337.   spy_send_channel(cptr, to, notice,
  1338.    nick1, nick2, text);
  1339.  else
  1340.  {
  1341.   if (!(acptr = find_person(to, NULL)))
  1342.    return -1;
  1343.   spy_send_client(acptr, notice,
  1344.    nick1, nick2, text);
  1345.  }
  1346.  return 0;
  1347. }
  1348. // ==================================================================
  1349. // m_spychsend: Sends users' channel messages to a client on the network
  1350. // Easier way?
  1351. // ==================================================================
  1352. DLLFUNC int m_spychsend(aClient *cptr, aClient *sptr, int parc, char *parv[])
  1353. {
  1354.  aClient  *acptr;
  1355.  char  *to, *cmd, *nick, *channel, *text;
  1356.  unsigned notice;
  1357.  if (!IsServer(sptr) || !IsParam(5))
  1358.   return -1;
  1359.  to = IsParam(1)  ? parv[1] : NULL;
  1360.  cmd = IsParam(2)  ? parv[2] : NULL;
  1361.  nick = IsParam(3)  ? parv[3] : NULL;
  1362.  channel = IsParam(4)  ? parv[4] : NULL;
  1363.  text = IsParam(5)  ? parv[5] : NULL;
  1364.  if (!text)
  1365.   return -1;
  1366.  notice = *cmd == 'N' ? 1 : 0;
  1367.  if (*to == '#')
  1368.   spy_send_channel(cptr, to, notice,
  1369.    nick, channel, text);
  1370.  else
  1371.  {
  1372.   if (!(acptr = find_person(to, NULL)))
  1373.    return -1;
  1374.   spy_send_client(acptr, notice,
  1375.    nick, channel, text);
  1376.  }
  1377.  return 0;
  1378. }
  1379. /*
  1380.  * m_spystats
  1381.  *
  1382.  * Displays SpyList statistics based on a given nickname. If you leave out
  1383.  * <nickname>, all SpyList entries will be displayed.
  1384.  *
  1385.  * :prefix SPYSTATS [<nickname>]
  1386.  * parv[0] - (sender)
  1387.  * parv[1] - channel|message
  1388.  * parv[2] - <nickname> (optional)
  1389.  *
  1390.  */
  1391. DLLFUNC int m_spystats(aClient *cptr, aClient *sptr, int parc, char *parv[])
  1392. {
  1393.  SpyStruct *s;
  1394.  SpyChStruct *sc;
  1395.  aClient  *acptr = NULL;
  1396.  unsigned long item = 0, count = 0, total = 0;
  1397.  unsigned long subcount = 0, subtotal = 0;
  1398.  char  *cmd;
  1399.         if (!MyClient(cptr) || !IsOper(cptr) || !IsSAdmin(cptr))
  1400.  {
  1401.          sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
  1402.   return -1;
  1403.  }
  1404.  if (!IsParam(1))
  1405.  {
  1406.       sendto_one(sptr, ":%s NOTICE %s :*** Usage: /spystats private|channel [<nickname>]",
  1407.        me.name, sptr->name);
  1408.   return 0;
  1409.  }
  1410.  cmd = parv[1];
  1411.  /* PRIVATE */
  1412.  if (!strcasecmp(cmd, "private"))
  1413.  {
  1414.   if (!SpyList)
  1415.   {
  1416.        sendto_one(sptr, ":%s NOTICE %s :*** Private spy list is empty",
  1417.         me.name, sptr->name);
  1418.    return 0;
  1419.   }
  1420.   if (IsParam(2) && !(acptr = find_person(parv[2], NULL)))
  1421.   {
  1422.        sendto_one(sptr, err_str(ERR_NOSUCHNICK),
  1423.     me.name, sptr->name, parv[2]);
  1424.        return -1;
  1425.   }
  1426.   for (s = SpyList; s; s = s->next)
  1427.   {
  1428.    item = sizeof(*s) + 1; /* 1 byte is the size of (lock1 + lock2) */
  1429.    item += sizeof(char) * (strlen(s->nick1) + 1);
  1430.    if (s->nick2)
  1431.     item += sizeof(char) * (strlen(s->nick2) + 1);
  1432.    if (s->chname)
  1433.     item += sizeof(char) * (strlen(s->chname) + 1);
  1434.    if (acptr && s->who == acptr)
  1435.    {
  1436.     subtotal += item;
  1437.     subcount++;
  1438.    }
  1439.    total += item;
  1440.    count++;
  1441.    if (!acptr || s->who == acptr)
  1442.         sendto_one(sptr, ":%s NOTICE %s :*** %s (%s%s): %s%s %s (mem: %ld)",
  1443.          me.name, sptr->name,
  1444.      s->who->name,
  1445.      MergeLock(s->lock1, s->nick1),
  1446.      MergeLockOpt(s->lock2, s->nick2),
  1447.      s->chname ? s->chname : "<irc>",
  1448.      item);
  1449.   }
  1450.   if (acptr)
  1451.   {
  1452.    sendto_one(sptr, ":%s NOTICE %s :*** " SPY_LINE,
  1453.     me.name, sptr->name);
  1454.        sendto_one(sptr, ":%s NOTICE %s :*** Sub total (%s): %ld entr%s (mem: %ld)",
  1455.         me.name, sptr->name,
  1456.     acptr->name,
  1457.     subcount, count > 1 ? "ies" : "y",
  1458.     subtotal);
  1459.   }
  1460.   sendto_one(sptr, ":%s NOTICE %s :*** " SPY_LINE,
  1461.    me.name, sptr->name);
  1462.   sendto_one(sptr, ":%s NOTICE %s :*** Total: %d entr%s (mem: %ld)",
  1463.    me.name, sptr->name,
  1464.    count, count > 1 ? "ies" : "y",
  1465.    total);
  1466.  }
  1467.  /* CHANNEL */
  1468.  else if (!strcasecmp(cmd, "channel"))
  1469.  {
  1470.   if (!SpyChList)
  1471.   {
  1472.        sendto_one(sptr, ":%s NOTICE %s :*** Channel spy list is empty",
  1473.         me.name, sptr->name);
  1474.    return 0;
  1475.   }
  1476.   if (IsParam(2) && !(acptr = find_person(parv[2], NULL)))
  1477.   {
  1478.        sendto_one(sptr, err_str(ERR_NOSUCHNICK),
  1479.     me.name, sptr->name, parv[2]);
  1480.        return -1;
  1481.   }
  1482.   for (sc = SpyChList; sc; sc = sc->next)
  1483.   {
  1484.    item = sizeof(*sc) + sizeof(sc->lock);
  1485.    item += sizeof(char) * (strlen(sc->channel) + 1);
  1486.    if (sc->sendto)
  1487.     item += sizeof(char) * (strlen(sc->sendto) + 1);
  1488.    if (acptr && sc->who == acptr)
  1489.    {
  1490.     subtotal += item;
  1491.     subcount++;
  1492.    }
  1493.    total += item;
  1494.    count++;
  1495.    if (!acptr || sc->who == acptr)
  1496.         sendto_one(sptr, ":%s NOTICE %s :*** %s (%s%s): %s (mem: %ld)",
  1497.          me.name, sptr->name,
  1498.      sc->who->name,
  1499.      MergeLock(sc->lock, sc->channel),
  1500.      sc->sendto ? sc->sendto : "<irc>",
  1501.      item);
  1502.   }
  1503.   if (acptr)
  1504.   {
  1505.    sendto_one(sptr, ":%s NOTICE %s :*** " SPY_LINE,
  1506.     me.name, sptr->name);
  1507.        sendto_one(sptr, ":%s NOTICE %s :*** Sub total (%s): %ld entr%s (mem: %ld)",
  1508.         me.name, sptr->name,
  1509.     acptr->name,
  1510.     subcount, count > 1 ? "ies" : "y",
  1511.     subtotal);
  1512.   }
  1513.   sendto_one(sptr, ":%s NOTICE %s :*** " SPY_LINE,
  1514.    me.name, sptr->name);
  1515.   sendto_one(sptr, ":%s NOTICE %s :*** Total: %d entr%s (mem: %ld)",
  1516.    me.name, sptr->name,
  1517.    count, count > 1 ? "ies" : "y",
  1518.    total);
  1519.  }
  1520.  /* <INVALID OPTION> */
  1521.  else
  1522.  {
  1523.       sendto_one(sptr, ":%s NOTICE %s :*** Invalid option %s",
  1524.               me.name, sptr->name, cmd);
  1525.   return -1;
  1526.  }
  1527.  
  1528.  return 0;
  1529. }
Advertisement
Add Comment
Please, Sign In to add comment