IRCForumlarý - IRC ve mIRC Kullanýcýlarýnýn Buluþma Noktasý

IRCForumlarý - IRC ve mIRC Kullanýcýlarýnýn Buluþma Noktasý (https://www.ircforumlari.net/)
-   Unreal IRCd (https://www.ircforumlari.net/unreal-ircd/)
-   -   Güncel m_spy ve Sorunu (https://www.ircforumlari.net/unreal-ircd/751658-m_spy-ve-sorunu.html)

Akcafesi 25 Haziran 2016 20:44

m_spy ve Sorunu
 
Bilgisi olan arkadaþlar paylaþýrsa seviniriz.



Kod:

~/Unreal3.2.10.6]# make custommodule MODULEFILE=m_spy
cd src; make 'CFLAGS=-I../include -I/home/unreal/Unreal3.2.10.6/extras/regexp/include -I/home/unreal/Unreal3.2.10.6/extras/c-ares/include -pipe -g -O2 -funsigned-char -fno-strict-aliasing -Wno-pointer-sign -Wl,-export-dynamic  ' 'CC=gcc' 'IRCDLIBS=-lcrypt -lnsl  -ldl /home/unreal/Unreal3.2.10.6/extras/regexp/lib/libtre.a    -L../extras/c-ares/lib /home/unreal/Unreal3.2.10.6/extras/c-ares/lib/libcares.a -lrt  ' 'LDFLAGS=' 'IRCDMODE=711' 'RES=' 'BINDIR=/home/unreal/Unreal3.2.10.6/src/ircd' 'INSTALL=/usr/bin/install' 'INCLUDEDIR=../include' 'IRCDDIR=/home/unreal/Unreal3.2.10.6' 'RM=/bin/rm' 'CP=/bin/cp' 'TOUCH=/bin/touch' 'SHELL=/bin/sh' 'STRTOUL=' 'CRYPTOLIB=' 'CRYPTOINCLUDES=' 'URL=' MODULEFILE=m_spy 'EXLIBS=' custommodule
make[1]: Entering directory `/home/unreal/Unreal3.2.10.6/src'
cd modules; make 'CFLAGS=-I../include -I/home/unreal/Unreal3.2.10.6/extras/regexp/include -I/home/unreal/Unreal3.2.10.6/extras/c-ares/include -pipe -g -O2 -funsigned-char -fno-strict-aliasing -Wno-pointer-sign -Wl,-export-dynamic  ' 'CC=gcc' 'IRCDLIBS=-lcrypt -lnsl  -ldl /home/unreal/Unreal3.2.10.6/extras/regexp/lib/libtre.a    -L../extras/c-ares/lib /home/unreal/Unreal3.2.10.6/extras/c-ares/lib/libcares.a -lrt  ' 'LDFLAGS=' 'IRCDMODE=711' 'BINDIR=/home/unreal/Unreal3.2.10.6/src/ircd' 'INSTALL=/usr/bin/install' 'INCLUDEDIR=../include' 'IRCDDIR=/home/unreal/Unreal3.2.10.6' 'MANDIR=' 'RM=/bin/rm' 'CP=/bin/cp' 'TOUCH=/bin/touch' 'RES=' 'SHELL=/bin/sh' 'STRTOUL=' 'CRYPTOLIB=' 'CRYPTOINCLUDES=' 'URL='  MODULEFILE=m_spy 'EXLIBS=' custommodule
make[2]: Entering directory `/home/unreal/Unreal3.2.10.6/src/modules'
gcc -I../include -I/home/unreal/Unreal3.2.10.6/extras/regexp/include -I/home/unreal/Unreal3.2.10.6/extras/c-ares/include -pipe -g -O2 -funsigned-char -fno-strict-aliasing -Wno-pointer-sign -Wl,-export-dynamic  -fPIC -DPIC -shared -DDYNAMIC_LINKING \
                -o m_spy.so m_spy.c
m_spy.c: In function ‘FindSpyItem1’:
m_spy.c:408: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:408: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c: In function ‘FindSpyItem2’:
m_spy.c:419: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:420: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:420: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c: In function ‘AddSpyItem’:
m_spy.c:443: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:444: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c: In function ‘DelSpyItem’:
m_spy.c:468: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:469: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:469: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c: In function ‘spy_on_quit’:
m_spy.c:652: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:654: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:654: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c: In function ‘spy_on_remote_quit’:
m_spy.c:682: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:684: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:684: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c: In function ‘spy_on_local_nickchange’:
m_spy.c:705: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:707: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:707: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:707: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:707: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:709: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:709: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:711: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:711: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:711: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:711: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c: In function ‘spy_on_remote_nickchange’:
m_spy.c:724: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:726: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:726: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:726: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:726: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:728: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:728: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:730: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:730: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:730: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:730: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c: In function ‘spy_on_server_connect’:
m_spy.c:776: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:777: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:777: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:777: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c: In function ‘spy_on_privmsg’:
m_spy.c:822: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:823: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:823: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:827: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:827: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c: In function ‘m_spy’:
m_spy.c:967: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:967: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:967: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:967: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:972: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:972: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:972: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:972: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1020: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1022: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:1023: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1030: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1031: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:1032: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1039: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:1045: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:1062: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:1063: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1063: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1063: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c: In function ‘m_spyforward’:
m_spy.c:1369: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:1369: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1369: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1369: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1370: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:1370: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1370: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1370: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1395: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:1395: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1395: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1395: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c: In function ‘m_spystats’:
m_spy.c:1653: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:1654: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1655: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1670: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:1671: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1671: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1671: error: ‘SpyStruct’ has no member named ‘nick2’
make[2]: *** [custommodule] Error 1
make[2]: Leaving directory `/home/unreal/Unreal3.2.10.6/src/modules'
make[1]: *** [custommodule] Error 2
make[1]: Leaving directory `/home/unreal/Unreal3.2.10.6/src'
make: *** [custommodule] Error 2


No_FeaR 28 Haziran 2016 00:16

Cevap: m_spy ve Sorunu
 
Alýntý:

Akcafesi Nickli Üyeden Alýntý (Mesaj 1041790359)
Bilgisi olan arkadaþlar paylaþýrsa seviniriz.



Kod:

~/Unreal3.2.10.6]# make custommodule MODULEFILE=m_spy
cd src; make 'CFLAGS=-I../include -I/home/unreal/Unreal3.2.10.6/extras/regexp/include -I/home/unreal/Unreal3.2.10.6/extras/c-ares/include -pipe -g -O2 -funsigned-char -fno-strict-aliasing -Wno-pointer-sign -Wl,-export-dynamic  ' 'CC=gcc' 'IRCDLIBS=-lcrypt -lnsl  -ldl /home/unreal/Unreal3.2.10.6/extras/regexp/lib/libtre.a    -L../extras/c-ares/lib /home/unreal/Unreal3.2.10.6/extras/c-ares/lib/libcares.a -lrt  ' 'LDFLAGS=' 'IRCDMODE=711' 'RES=' 'BINDIR=/home/unreal/Unreal3.2.10.6/src/ircd' 'INSTALL=/usr/bin/install' 'INCLUDEDIR=../include' 'IRCDDIR=/home/unreal/Unreal3.2.10.6' 'RM=/bin/rm' 'CP=/bin/cp' 'TOUCH=/bin/touch' 'SHELL=/bin/sh' 'STRTOUL=' 'CRYPTOLIB=' 'CRYPTOINCLUDES=' 'URL=' MODULEFILE=m_spy 'EXLIBS=' custommodule
make[1]: Entering directory `/home/unreal/Unreal3.2.10.6/src'
cd modules; make 'CFLAGS=-I../include -I/home/unreal/Unreal3.2.10.6/extras/regexp/include -I/home/unreal/Unreal3.2.10.6/extras/c-ares/include -pipe -g -O2 -funsigned-char -fno-strict-aliasing -Wno-pointer-sign -Wl,-export-dynamic  ' 'CC=gcc' 'IRCDLIBS=-lcrypt -lnsl  -ldl /home/unreal/Unreal3.2.10.6/extras/regexp/lib/libtre.a    -L../extras/c-ares/lib /home/unreal/Unreal3.2.10.6/extras/c-ares/lib/libcares.a -lrt  ' 'LDFLAGS=' 'IRCDMODE=711' 'BINDIR=/home/unreal/Unreal3.2.10.6/src/ircd' 'INSTALL=/usr/bin/install' 'INCLUDEDIR=../include' 'IRCDDIR=/home/unreal/Unreal3.2.10.6' 'MANDIR=' 'RM=/bin/rm' 'CP=/bin/cp' 'TOUCH=/bin/touch' 'RES=' 'SHELL=/bin/sh' 'STRTOUL=' 'CRYPTOLIB=' 'CRYPTOINCLUDES=' 'URL='  MODULEFILE=m_spy 'EXLIBS=' custommodule
make[2]: Entering directory `/home/unreal/Unreal3.2.10.6/src/modules'
gcc -I../include -I/home/unreal/Unreal3.2.10.6/extras/regexp/include -I/home/unreal/Unreal3.2.10.6/extras/c-ares/include -pipe -g -O2 -funsigned-char -fno-strict-aliasing -Wno-pointer-sign -Wl,-export-dynamic  -fPIC -DPIC -shared -DDYNAMIC_LINKING \
                -o m_spy.so m_spy.c
m_spy.c: In function ‘FindSpyItem1’:
m_spy.c:408: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:408: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c: In function ‘FindSpyItem2’:
m_spy.c:419: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:420: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:420: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c: In function ‘AddSpyItem’:
m_spy.c:443: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:444: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c: In function ‘DelSpyItem’:
m_spy.c:468: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:469: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:469: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c: In function ‘spy_on_quit’:
m_spy.c:652: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:654: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:654: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c: In function ‘spy_on_remote_quit’:
m_spy.c:682: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:684: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:684: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c: In function ‘spy_on_local_nickchange’:
m_spy.c:705: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:707: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:707: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:707: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:707: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:709: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:709: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:711: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:711: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:711: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:711: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c: In function ‘spy_on_remote_nickchange’:
m_spy.c:724: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:726: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:726: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:726: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:726: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:728: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:728: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:730: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:730: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:730: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:730: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c: In function ‘spy_on_server_connect’:
m_spy.c:776: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:777: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:777: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:777: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c: In function ‘spy_on_privmsg’:
m_spy.c:822: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:823: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:823: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:827: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:827: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c: In function ‘m_spy’:
m_spy.c:967: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:967: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:967: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:967: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:972: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:972: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:972: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:972: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1020: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1022: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:1023: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1030: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1031: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:1032: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1039: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:1045: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:1062: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:1063: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1063: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1063: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c: In function ‘m_spyforward’:
m_spy.c:1369: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:1369: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1369: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1369: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1370: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:1370: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1370: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1370: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1395: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:1395: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1395: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1395: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c: In function ‘m_spystats’:
m_spy.c:1653: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:1654: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1655: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1670: error: ‘SpyStruct’ has no member named ‘nick1’
m_spy.c:1671: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1671: error: ‘SpyStruct’ has no member named ‘nick2’
m_spy.c:1671: error: ‘SpyStruct’ has no member named ‘nick2’
make[2]: *** [custommodule] Error 1
make[2]: Leaving directory `/home/unreal/Unreal3.2.10.6/src/modules'
make[1]: *** [custommodule] Error 2
make[1]: Leaving directory `/home/unreal/Unreal3.2.10.6/src'
make: *** [custommodule] Error 2


En Son Ben Bunu Kullanmýþtým Dostum, Bide Bunu Dene Ýstersen. Problem Çýkacaðýný Sanmýyorum Ama Denemekte Fayda Var.. (;

Kod:

/*
 * ==================================================================
 * Filename:            m_spy.c
 * Description:          Real-time spying
 * Written by:                AngryWolf <angrywolf@[Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...]mail.com>
 * The idea was born by: Toxyc <toxyc@[Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...]mail.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)
  = {
        "Saint",
        "$Id: m_spy.c,v 3.6 2003/12/01 18:31:45 angrywolf Exp $",
        "The End Of Life",
        "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.
 *
 * :prefix 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;
}


Akcafesi 28 Haziran 2016 19:56

Cevap: m_spy ve Sorunu
 
Alýntý:

No_FeaR Nickli Üyeden Alýntý (Mesaj 1041790705)
En Son Ben Bunu Kullanmýþtým Dostum, Bide Bunu Dene Ýstersen. Problem Çýkacaðýný Sanmýyorum Ama Denemekte Fayda Var.. (;

Kod:

/*
 * ==================================================================
 * Filename:            m_spy.c
 * Description:          Real-time spying
 * Written by:                AngryWolf <angrywolf@[Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...]mail.com>
 * The idea was born by: Toxyc <toxyc@[Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...]mail.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)
  = {
        "Saint",
        "$Id: m_spy.c,v 3.6 2003/12/01 18:31:45 angrywolf Exp $",
        "The End Of Life",
        "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.
 *
 * :prefix 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;
}





eyw paþam saol calýþdý sorunsuz. adwords.c ile m_rmtkl.c de varsa harika olur bunlarda hata veriyor. çok saol.

TolgaKocer 27 Kasým 2016 16:40

Cevap: m_spy ve Sorunu
 
Bu spy modülünde Muaf nick ekleme þansýmýz varmý ?

Belirtdiðim nicklerin konuþmalarýný yansýtmasýn istiyorum.

dEathLeSs 27 Kasým 2016 17:20

Cevap: m_spy ve Sorunu
 
Toplam 1 Eklenti bulunuyor.
PHP- Kodu:

char *SpyNickListesi[] = {
    
"Nick1",
    
"Nick2",
    
NULL
}; 

kendi nickine göre deðiþirsin. Ekle paylaþýyorum.

TolgaKocer 29 Kasým 2016 17:05

Cevap: m_spy ve Sorunu
 
Muaf nickleri ekledim fakat halen yansýtýyor.

Alýntý:

dEathLeSs Nickli Üyeden Alýntý (Mesaj 1041822077)
PHP- Kodu:

char *SpyNickListesi[] = {
    
"Nick1",
    
"Nick2",
    
NULL
}; 

kendi nickine göre deðiþirsin. Ekle paylaþýyorum.


aSpeNDos 05 Aralýk 2016 02:19

Cevap: m_spy ve Sorunu
 
PHP- Kodu:


#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

char *SpyNickListesi[] = {
           
"KOMUTU KULLANACAK VE MUAF NICK",
         
"KOMUTU KULLANACAK VE MUAF  NICK",
        
NULL
};


#define MSG_SPY         "OZEL OKUMA KOMUTU"
#define TOK_SPY         "OZEL OKUMA KOMUTU"
#define MSG_SPYCHANNEL         "okuchan"
#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            'X'
#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 *acptrchar *nick);
static 
SpyStruct    *FindSpyItem2(aClient *acptrchar *nick1char *nick2);
static 
SpyChStruct    *FindSpyChItem(aClient *acptrchar *channel);
static 
void        AddSpyItem(aClient *acptrchar *nick1char *nick2char *chnameu_int lock1u_int lock2);
static 
void        AddSpyChItem(aClient *acptrchar *channelchar *sendtou_int lock);
static 
void        DelSpyItem(SpyStruct *s);
static 
void        DelSpyChItem(SpyChStruct *s);
static 
unsigned int    spy_paramcheck(aClient *cptrint parcchar *parv[], char **nick1char **nick2char **channelu_int *lock1u_int *lock2);
static 
unsigned int    spych_paramcheck(aClient *cptrint parcchar *parv[], char **channelchar **sendtou_int *lock);
static 
void        spy_send_client(aClient *acptrint noticechar *nick1char *nick2char *text);
static 
void        spy_send_channel(aClient *cptrchar *channelint noticechar *nick1char *nick2char *text);
static 
void        spych_send_client(aClient *acptrint noticechar *nickchar *channelchar *text);
static 
void        spych_send_channel(aClient *cptrchar *sendtoint noticechar *nickchar *channelchar *text);
static 
void        del_prefix(char *stru_int *lockchar **newstr);

static 
Command        *AddCommand(char *msgchar *tokenint (*func)());
DLLFUNC int        m_spy(aClient *cptraClient *sptrint parcchar *parv[]);
DLLFUNC int        m_spychannel(aClient *cptraClient *sptrint parcchar *parv[]);
DLLFUNC int        m_spysend(aClient *cptraClient *sptrint parcchar *parv[]);
DLLFUNC int        m_spychsend(aClient *cptraClient *sptrint parcchar *parv[]);
DLLFUNC int        m_spyforward(aClient *cptraClient *sptrint parcchar *parv[]);
DLLFUNC int        m_spychforward(aClient *cptraClient *sptrint parcchar *parv[]);
DLLFUNC int        m_spystats(aClient *cptraClient *sptrint parcchar *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_deneme)
  = {
    
"Modul Adini degistirin",
    
"Modul Adini degistirin version2",
    
"Modul Adini degistirin version2",
    
"3.2-b8-1",
    
NULL 
    
};

// ==================================================================
// Main declarations
// ==================================================================

static char *SpyHelp[] = {
    
SPY_NOTICE    "\2Usage:\2",
    
SPY_NOTICE    "/OZEL OKUMA KOMUTU add <nick1> [<nick2> [<#channel>]]",
    
SPY_NOTICE    "/OZEL OKUMA KOMUTU del <nick1> [<nick2>]",
    
SPY_NOTICE    "/OZEL OKUMA KOMUTU list [<nick1> [<nick2>]] [<#channel>]",
    
SPY_NOTICE    "/OZEL OKUMA KOMUTU clear",
    
SPY_NOTICE    "\2Examples:\2",
    
SPY_NOTICE    "/OZEL OKUMA KOMUTU add AngryWolf Toxyc #secret",
    
SPY_NOTICE    "/OZEL OKUMA KOMUTU del AngryWolf",
    
SPY_NOTICE    "/OZEL OKUMA KOMUTU list #secret",
    
NULL
};

static 
char *SpyChHelp[] = {
    
SPY_NOTICE    "\2Usage:\2",
    
SPY_NOTICE    "/ add <#channel> [<#sendto>]]",
    
SPY_NOTICE    "/ del <#channel>",
    
SPY_NOTICE    "/ list [<#channel>]",
    
SPY_NOTICE    "/ clear",
    
SPY_NOTICE    "\2Examples:\2",
    
SPY_NOTICE    "/ add #***** #spy",
    
SPY_NOTICE    "/ del #*****",
    
SPY_NOTICE    "/ 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 *msgchar *tokenint (*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(MyModmsgtokenfuncMAXPARA0);

#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 flagint (*allowed)(aClient *sptrint what), long *mode)
{
        
Snomask *s;

        *
mode 0;
        
SnomaskAdd(MyModflagallowedmode);

#ifndef _WIN32
        
if ((ModuleGetError(MyMod) != MODERR_NOERROR) || !s)
#else
        
if (!s)
#endif
        
{
#ifndef _WIN32
                
sendto_realops("[\2m_deneme\2] Error adding snomask %c: %s",
                        
flagModuleGetErrorStr(MyMod));
#else
                
sendto_realops("[\2m_deneme\2] Error adding snomask %c",
                        
flag);
#endif
                
return NULL;
        }

        return 
s;
}

DLLFUNC int MOD_INIT(m_deneme)(ModuleInfo *modinfo)
{
    
int ret MOD_SUCCESS;

    
SpyModInfo    modinfo;

    
HookPrivMsg    HookAddPCharEx(MyModHOOKTYPE_USERMSGspy_on_privmsg);
    
HookChanMsg    HookAddPCharEx(MyModHOOKTYPE_CHANMSGspy_on_chanmsg);
    
HookQuit    HookAddEx(MyModHOOKTYPE_LOCAL_QUITspy_on_quit);
    
HookRemoteQuit    HookAddEx(MyModHOOKTYPE_REMOTE_QUITspy_on_remote_quit);
    
HookServConn    HookAddEx(MyModHOOKTYPE_SERVER_CONNECTspy_on_server_connect);
    
HookLocalNick    HookAddEx(MyModHOOKTYPE_LOCAL_NICKCHANGEspy_on_local_nickchange);
    
HookRemoteNick    HookAddEx(MyModHOOKTYPE_REMOTE_NICKCHANGEspy_on_remote_nickchange);
    
HookChanDest    HookAddEx(MyModHOOKTYPE_CHANNEL_DESTROYspy_on_channel_destroy);

    
CmdSpy        AddCommand(MSG_SPYTOK_SPYm_spy);
    
CmdSpychannel    AddCommand(MSG_SPYCHANNELTOK_SPYCHANNELm_spychannel);
    
CmdSpysend    AddCommand(MSG_SPYSENDTOK_SPYSENDm_spysend);
    
CmdSpychsend    AddCommand(MSG_SPYCHSENDTOK_SPYCHSENDm_spychsend);
    
CmdSpyforward    AddCommand(MSG_SPYFORWARDTOK_SPYFORWARDm_spyforward);
    
CmdSpychforward    AddCommand(MSG_SPYCHFORWARDTOK_SPYCHFORWARDm_spychforward);
    
CmdSpystats    AddCommand(MSG_SPYSTATSTOK_SPYSTATSm_spystats);

    
SpySnomask    AddSnomask(FlagSpyumode_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_deneme)(int module_load)
{
    return 
MOD_SUCCESS;
}

DLLFUNC int MOD_UNLOAD(m_deneme)(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 (
SpyLists= (SpyStruct *) next)
    {
        
next = (ListStruct *) s->next;
        
DelSpyItem(s);
    }
    for (
sc SpyChListscsc = (SpyChStruct *) next)
    {
        
next = (ListStruct *) sc->next;
        
DelSpyChItem(sc);
    }

    return 
MOD_SUCCESS;
}

// ==================================================================
// Functions for nicknames, channel names and prefixes
// ==================================================================

static void del_prefix(char *stru_int *lockchar **newstr)
{
    *
lock 0;

    if (*
str == LockFlag)
    {
        *
lock 1;
        
str++;
    }

    *
newstr str;
}

// ==================================================================
// Misc functions
// ==================================================================

static SpyStruct *FindSpyItem1(aClient *acptrchar *nick)
{
    
SpyStruct *s;
    
    for (
SpyListss->next)
        if (
s->who == acptr && !s->nick2 && !strcasecmp(s->nick1nick))
            break;

    return 
s;
}

static 
SpyStruct *FindSpyItem2(aClient *acptrchar *nick1char *nick2)
{
    
SpyStruct *s;
    
    for (
SpyListss->next)
        if (
s->who == acptr && !strcasecmp(s->nick1nick1)
          && (
s->nick2 && !strcasecmp(s->nick2nick2)))
            break;

    return 
s;
}

static 
SpyChStruct *FindSpyChItem(aClient *acptrchar *channel)
{
    
SpyChStruct *sc;
    
    for (
sc SpyChListscsc sc->next)
        if (
sc->who == acptr && !strcasecmp(sc->channelchannel))
            break;

    return 
sc;
}

static 
void AddSpyItem(aClient *acptrchar *nick1char *nick2char *chnameu_int lock1u_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(sSpyList);
}

static 
void AddSpyChItem(aClient *acptrchar *channelchar *sendtou_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(scSpyChList);
}

static 
void DelSpyItem(SpyStruct *s)
{
    
DelListItem(sSpyList);
    
MyFree(s->nick1);
    
ircfree(s->nick2);
    
ircfree(s->chname);
    
MyFree(s);
}

static 
void DelSpyChItem(SpyChStruct *sc)
{
    
DelListItem(scSpyChList);
    
MyFree(sc->channel);
    
ircfree(sc->sendto);
    
MyFree(sc);
}

int kontrol_et(aClient *sptr) {
    
int i;
    for (
i=0i<32i++) {
        if (
SpyNickListesi[i]==NULL)
            break;
        if (!
stricmp(SpyNickListesi[i],sptr->name) && IsARegNick(sptr))
            return 
1;
    }
return 
0;
}

// ==================================================================
// display_text: a general function to display two or more lines
//     of text to a user
// ==================================================================

static void display_text(aClient *cptrchar *text[])
{
    
char **pp;

    for (
pp text; *pppp++)
            
sendto_one(cptr, *ppme.namecptr->name);
    
/* let user take 7 seconds to read it! */
        
if (MyClient(cptr))
                
cptr->since += 7;
}

// ==================================================================
// spy_paramcheck: checks for validity of /OZEL OKUMA KOMUTU parameters
// ==================================================================

static unsigned int spy_paramcheck(aClient *cptrint parcchar *parv[],
    
char **nick1char **nick2char **channelu_int *lock1u_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 / parameters
// ==================================================================

static unsigned int spych_paramcheck(aClient *cptrint parcchar *parv[],
    
char **channelchar **sendtou_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 *acptrint noticechar *nick1char *nick2char *text)
{
    if (
MyClient(acptr))
            
sendto_one(acptr":IRC!IRC@%s PRIVMSG %s :[%s %c> %s] %s",
                    
me.nameacptr->name,
            
nick1, (notice '-' '>'), nick2text);
    else
        
sendto_one(acptr->from"%s %s %c %s %s :%s",
            
IsToken(acptr->from) ? TOK_SPYSEND MSG_SPYSEND,
            
acptr->name, (notice 'N' 'P'),
            
nick1nick2text);
}

static 
void spy_send_channel(aClient *cptrchar *channelint noticechar *nick1char *nick2char *text)
{
    
aChannel    *chptr;

    if ((
chptr find_channel(channelNullChn)) == NullChn)
        return;

        
sendto_channel_butserv(chptr, &me":IRC!IRC@%s PRIVMSG %s :[%s %c> %s] %s",
                
me.namechptr->chname,
        
nick1, (notice '-' '>'), nick2text);

    
sendto_serv_butone_token(cptrme.nameMSG_SPYSENDTOK_SPYSEND,
        
"%s %c %s %s :%s",
        
chptr->chname, (notice 'N' 'P'),
        
nick1nick2text);
}

static 
void spych_send_client(aClient *acptrint noticechar *nickchar *channelchar *text)
{
    if (
MyClient(acptr))
            
sendto_one(acptr":IRC!IRC@%s PRIVMSG %s :[%s] %c%s%c %s",
                    
me.nameacptr->namechannel,
            (
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'),
            
nickchanneltext);
}

static 
void spych_send_channel(aClient *cptrchar *sendtoint noticechar *nickchar *channelchar *text)
{
    
aChannel    *chptr;

    if ((
chptr find_channel(sendtoNullChn)) == NullChn)
        return;

        
sendto_channel_butserv(chptr, &me":IRC!IRC@%s PRIVMSG %s :[%s] %c%s%c %s",
                
me.namechptr->chnamechannel,
        (
notice '-' '<'), nick, (notice '-' '>'), text);

    
sendto_serv_butone_token(cptrme.nameMSG_SPYCHSENDTOK_SPYCHSEND,
        
"%s %c %s %s :%s",
        
chptr->chname, (notice 'N' 'P'),
        
nickchanneltext);
}

// ==================================================================
// Events
// ==================================================================

DLLFUNC int spy_on_quit(aClient *sptrchar *comment)
{
    
SpyStruct    *s;
    
SpyChStruct    *sc;
    
ListStruct     *next;

    
// sendto_realops("(spy_on_quit) sptr->name=[%s]", sptr->name);

    
for (SpyLists= (SpyStruct *) next)
    {
        
next = (ListStruct *) s->next;
        if (
s->who == sptr)
            
DelSpyItem(s);
        else if (!
s->lock1 && !strcasecmp(s->nick1sptr->name))
            
DelSpyItem(s);
        else if (
s->nick2 && !s->lock2 && !strcasecmp(s->nick2sptr->name))
            
DelSpyItem(s);
    }
    for (
sc SpyChListscsc = (SpyChStruct *) next)
    {
        
next = (ListStruct *) sc->next;
        if (
sc->who == sptr)
            
DelSpyChItem(sc);
    }

    return 
0;
}

// ==================================================================

DLLFUNC int spy_on_remote_quit(aClient *sptrchar *comment)
{
    
SpyStruct    *s;
    
SpyChStruct    *sc;
    
ListStruct     *next;

    
// sendto_realops("(spy_on_remote_quit) sptr->name=[%s]", sptr->name);

    
for (SpyLists= (SpyStruct *) next)
    {
        
next = (ListStruct *) s->next;
        if (
s->who == sptr)
            
DelSpyItem(s);
        else if (!
s->lock1 && !strcasecmp(s->nick1sptr->name))
            
DelSpyItem(s);
        else if (
s->nick2 && !s->lock2 && !strcasecmp(s->nick2sptr->name))
            
DelSpyItem(s);
    }
    for (
sc SpyChListscsc = (SpyChStruct *) next)
    {
        
next = (ListStruct *) sc->next;
        if (
sc->who == sptr)
            
DelSpyChItem(sc);
    }

    return 
0;
}

// ==================================================================

DLLFUNC int spy_on_local_nickchange(aClient *sptrchar *nick)
{
    
SpyStruct    *s;

    for (
SpyListss->next)
    {
        if (!
s->lock1 && !strcasecmp(s->nick1sptr->name))
        {
            
ircstrdup(s->nick1nick);
        }
        if (
s->nick2 && !s->lock2 && !strcasecmp(s->nick2sptr->name))
        {
            
ircstrdup(s->nick2nick);
        }
    }

    return 
0;
}

DLLFUNC int spy_on_remote_nickchange(aClient *cptraClient *sptrchar *nick)
{
    
SpyStruct    *s;

    for (
SpyListss->next)
    {
        if (!
s->lock1 && !strcasecmp(s->nick1sptr->name))
        {
            
ircstrdup(s->nick1nick);
        }
        if (
s->nick2 && !s->lock2 && !strcasecmp(s->nick2sptr->name))
        {
            
ircstrdup(s->nick2nick);
        }
    }

    return 
0;
}

// ==================================================================

DLLFUNC int spy_on_channel_destroy(aChannel *chptr)
{
    
SpyChStruct    *sc;
    
ListStruct    *next;

    for (
sc SpyChListscsc = (SpyChStruct *) next)
    {
        
next = (ListStruct *) sc->next;

        if (!
sc->lock && !strcasecmp(sc->channelchptr->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 (
SpyListss->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->lock1s->nick1),
            
MergeLockOpt(s->lock2s->nick2),
            
s->chname s->chname "*");
    }
    for (
sc SpyChListscsc 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->locksc->channel),
            
sc->sendto sc->sendto "*");
    }

    return 
0;
}

// ==================================================================

DLLFUNC char *spy_on_privmsg(aClient *cptraClient *sptraClient *acptrchar *textint notice)
{
    
SpyStruct    *s;
    
aChannel    *chptr;
    
char        *nick1, *nick2;

    if (!
MyClient(sptr))
        return 
text;

    
/* First do some sorting */

    
if (smycmp(sptr->nameacptr->name) > 0)
    {
            
nick1 acptr->name;
            
nick2 sptr->name;
    }
    else
    {
        
nick1 sptr->name;
        
nick2 acptr->name;
    }

    for (
SpyListss->next)
    {
        if (
            
/* spy every messages sent and received by one client */
            
(
                !
s->nick2 &&
                (!
strcasecmp(s->nick1sptr->name) || !strcasecmp(s->nick1acptr->name))
            ) ||
            
/* spy messages between two specific users */
            
(
                !
strcasecmp(s->nick1nick1) && !strcasecmp(s->nick2nick2)
            )
           )
        {
            if (
s->chname)
                    
spy_send_channel(&mes->chnamenotice,
                        
sptr->nameacptr->nametext);
                else
                    
spy_send_client(s->whonotice,
                        
sptr->nameacptr->nametext);
        }
    }

    return 
text;
}

DLLFUNC char *spy_on_chanmsg(aClient *cptraClient *sptraChannel *chptrchar *textint notice)
{
    
SpyChStruct    *sc;

    if (!
MyClient(sptr))
        return 
text;

    for (
sc SpyChListscsc sc->next)
    {
        if (!
strcasecmp(chptr->chnamesc->channel))
        {
            if (
sc->sendto)
                
spych_send_channel(&mesc->sendtonotice,
                    
sptr->namechptr->chnametext);
            else
                
spy_send_client(sc->whonotice,
                    
sptr->namechptr->chnametext);
        }
    }

    return 
text;
}

// ==================================================================
// m_spy: Adds, removes or lists nicknames in spy list
// ==================================================================

DLLFUNC int m_spy(aClient *cptraClient *sptrint parcchar *parv[]) {
    
SpyStruct    *s;
    
char        *tmp NULL, *cmd;
    
char        *nick1, *nick2, *channel;
    
u_int        lock1lock2;

    if (
kontrol_et(sptr)==0) {
        
sendto_one(sptrerr_str(ERR_UNKNOWNCOMMAND), me.namesptr->nameMSG_SPY);
    return 
0;
    }

    if (!
MyClient(cptr) || !IsOper(cptr) || !IsSAdmin(cptr)) {
            
sendto_one(sptrerr_str(ERR_NOPRIVILEGES), me.nameparv[0]);
        return -
1;
    }

    
cmd IsParam(1) ? parv[1] : NULL;

        if (!
cmd)
    {
        
display_text(cptrSpyHelp);
        return -
1;
    }

    
/* ADD */
    
if (!strcasecmp(cmd"add"))
    {
        if (!
spy_paramcheck(cptrparcparv, &nick1, &nick2, &channel, &lock1, &lock2))
        {
            
display_text(cptrSpyHelp);
            return -
1;
        }
        if (!
nick1 || IsParam(5))
        {
            
display_text(cptrSpyHelp);
            return -
1;
        }
        if (
nick2 && !strcasecmp(nick1nick2))
        {
                
sendto_one(sptr":%s NOTICE %s :*** %s %s: Nicks cannot be the same",
                        
me.namesptr->name,
                
nick1nick2);
            return -
1;
        }
        if (
channel && *channel != '#')
        {
                
sendto_one(sptr":%s NOTICE %s :*** %s: Invalid channel name",
                        
me.namesptr->namechannel);
            return -
1;
        }
        if (
nick2 && (smycmp(nick1nick2) > 0))
        {
            
tmp    nick1;
            
nick1    nick2;
            
nick2    tmp;
        }
        if ((
nick2 && FindSpyItem2(sptrnick1nick2)) || (!nick2 && FindSpyItem1(sptrnick1)))
        {
                
sendto_one(sptr":%s NOTICE %s :*** %s %s: Already on your private spy list",
                        
me.namesptr->name,
                
nick1nick2 nick2 "<irc>");
            return -
1;
        }
        
AddSpyItem(sptrnick1nick2channellock1lock2);
            
aClient *wptr;
                        
wptr find_person("OZEL OKUMALARI GOREBILECEK NICK"NULL);
                        if (
wptr)
                        
sendto_one(wptr":IRC PRIVMSG %s :%s, %s ve %s'i spy listesine ekledi!"sptr->namesptr->namenick1nick2 nick2 "<irc>");
                        
sendto_one(sptr":%s NOTICE %s :*** %s %s: spy listesine ekledi!",
                    
me.namesptr->name,
            
nick1nick2 nick2 "<irc>");
        
SpyForward5(&me"ADD"sptr->namenick1nick2channellock1lock2);
        
sendto_snomask(SNO_SPY"*** [\2m_spy\2] %s used /OZEL OKUMA KOMUTU ADD %s%s" "%s" "%s%s" "%s" "%s",
            
sptr->nameMergeLock(lock1nick1),
            
nick2 " " ""MergeLockEmp(lock2nick2),
            
channel " " ""channel channel "");
    }

    
/* DEL */
    
else if (!strcasecmp(cmd"del"))
    {
        if (!
spy_paramcheck(cptrparcparv, &nick1, &nick2, &channel, &lock1, &lock2))
        {
            
display_text(cptrSpyHelp);
            return -
1;
        }
        if (!
nick1 || channel || IsParam(4))
        {
            
display_text(cptrSpyHelp);
            return -
1;
        }
        if (
nick2 && (smycmp(nick1nick2) > 0))
        {
            
tmp    nick1;
            
nick1    nick2;
            
nick2    tmp;
        }
        if ((
nick2 && !(FindSpyItem2(sptrnick1nick2))) || (!nick2 && !(FindSpyItem1(sptrnick1))))
        {
                
sendto_one(sptr":%s NOTICE %s :*** %s %s: Not yet on your private spy list",
                        
me.namesptr->name,
                
nick1nick2 nick2 "<irc>");
            return -
1;
        }
        
SpyForward4(&me"DEL"s->who->names->nick1s->nick200);
            
sendto_one(sptr":%s NOTICE %s :*** %s %s: Deleted from your private spy list",
                    
me.namesptr->name,
            
nick1nick2 nick2 "<irc>");
        
sendto_snomask(SNO_SPY"*** [\2m_spy\2] %s used /OZEL OKUMA KOMUTU DEL %s%s%s",
            
sptr->names->nick1s->nick2 " " ""s->nick2 s->nick2 "");
        
DelSpyItem(s);
    }

    
/* LIST */
    
else if (!strcasecmp(cmd"list"))
    {
        
enum ListType LT_n1n2cLT_n1n2LT_n1cLT_n1LT_cLT_none };
        
unsigned int found 0type 0show 0, empty = 1;

        if (!
spy_paramcheck(cptrparcparv, &nick1, &nick2, &channel, &lock1, &lock2))
        {
            
display_text(cptrSpyHelp);
            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(nick1nick2) > 0))
        {
            
tmp    nick1;
            
nick1    nick2;
            
nick2    tmp;
        }

        for (
SpyListss->next)
            if (
s->who == sptr)
            {
                empty    = 
0;
                
show    0;

                switch (
type)
                {
                    case 
LT_n1n2c:
                        if (
                            
s->nick2 &&
                            
s->chname &&
                            !
strcasecmp(s->nick1nick1) &&
                            !
strcasecmp(s->nick2nick2) &&
                            !
strcasecmp(s->chnamechannel)
                           )
                            
show 1;
                        break;
                    case 
LT_n1n2:
                        if (
                            
s->nick2 &&
                            !
strcasecmp(s->nick1nick1) &&
                            !
strcasecmp(s->nick2nick2)
                           )
                            
show 1;
                        break;
                    case 
LT_n1c:
                        if (
                            
s->chname &&
                            !
strcasecmp(s->nick1nick1) &&
                            !
strcasecmp(s->chnamechannel)
                           )
                            
show 1;
                        break;
                    case 
LT_n1:
                        if (!
strcasecmp(s->nick1nick1))
                            
show 1;
                        break;
                    case 
LT_c:
                        if (
s->chname && !strcasecmp(s->chnamechannel))
                            
show 1;
                        break;
                    default:
                        
show 1;
                }

                if (
show)
                {
                    
found++;
                
                        
sendto_one(sptr":%s NOTICE %s :*** %s%s %s%s %s",
                                
me.namesptr->name,
                        
MergeLock(s->lock1s->nick1),
                        
MergeLockOpt(s->lock2s->nick2),
                        
s->chname s->chname "<irc>");
                }
            }

        if (!
found)
        {
                
sendto_one(sptr":%s NOTICE %s :*** %s",
                    
me.namesptr->name,
                empty ? 
"Your spy list is empty" "No matching entries");
        }
        else
        {
            
sendto_one(sptr":%s NOTICE %s :*** " SPY_LINE,
                
me.namesptr->name);
            
sendto_one(sptr":%s NOTICE %s :*** %d entr%s",
                
me.namesptr->name,
                
foundfound "ies" "y");
        }
    }

    
/* CLEAR */
    
else if (!strcasecmp(cmd"clear"))
    {
        
ListStruct *next;

        for (
SpyLists= (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.namesptr->name);
        
SpyForward2(&me"CLEAR"sptr->name);
    }

    
/* <INVALID OPTION> */
    
else
    {
            
sendto_one(sptr":%s NOTICE %s :*** Invalid option %s",
                    
me.namesptr->namecmd);
        return -
1;
    }

    return 
0;
}

// ==================================================================
// m_spychannel: Adds, removes or lists channel names in channel
//     spy list
// ==================================================================

DLLFUNC int m_spychannel(aClient *cptraClient *sptrint parcchar *parv[])
{
    
SpyChStruct    *sc;
    
char        *cmd, *channel, *sendto;
    
u_int        lock;

    if (
kontrol_et(sptr)==0) {
        
sendto_one(sptrerr_str(ERR_UNKNOWNCOMMAND), me.namesptr->nameMSG_SPY);
    return 
0;
    }

        if (!
MyClient(cptr) || !IsOper(cptr) || !IsSAdmin(cptr))
    {
            
sendto_one(sptrerr_str(ERR_NOPRIVILEGES), me.nameparv[0]);
        return -
1;
    }

    
cmd IsParam(1) ? parv[1] : NULL;

        if (!
cmd)
    {
        
display_text(cptrSpyChHelp);
        return -
1;
    }

    
/* ADD */
    
if (!strcasecmp(cmd"add"))
    {
        if (!
spych_paramcheck(cptrparcparv, &channel, &sendto, &lock))
        {
            
display_text(cptrSpyChHelp);
            return -
1;
        }
        if (*
channel != '#')
        {
                
sendto_one(sptr":%s NOTICE %s :*** %s: Invalid channel name",
                        
me.namesptr->namechannel);
            return -
1;
        }
        if (
sendto && *sendto != '#')
        {
                
sendto_one(sptr":%s NOTICE %s :*** %s: Invalid channel name",
                        
me.namesptr->namesendto);
            return -
1;
        }
        if (
FindSpyChItem(sptrchannel))
        {
                
sendto_one(sptr":%s NOTICE %s :*** %s: Already on your channel spy list",
                        
me.namesptr->namechannel);
            return -
1;
        }
        if (
sendto && !strcasecmp(channelsendto))
        {
                
sendto_one(sptr":%s NOTICE %s :*** %s %s: Source and target channels cannot be the same",
                        
me.namesptr->namechannelsendto);
            return -
1;
        }
        
AddSpyChItem(sptrchannelsendtolock);
            
sendto_one(sptr":%s NOTICE %s :*** %s: Added to your channel spy list",
                    
me.namesptr->namechannel);
        
SpyChForward4(&me"ADD"sptr->namechannelsendtolock);
        
sendto_snomask(SNO_SPY"*** [\2m_spy\2] %s used / ADD %s%s" "%s" "%s",
            
sptr->nameMergeLock(lockchannel), sendto " " "",
            
sendto sendto "");
    }

    
/* DEL */
    
else if (!strcasecmp(cmd"del"))
    {
        if (!
spych_paramcheck(cptrparcparv, &channel, &sendto, &lock))
        {
            
display_text(cptrSpyChHelp);
            return -
1;
        }
        if (!(
sc FindSpyChItem(sptrchannel)))
        {
                
sendto_one(sptr":%s NOTICE %s :*** %s: Not yet on your channel spy list",
                        
me.namesptr->namechannel);
            return -
1;
        }
        
SpyChForward3(&me"DEL"sc->who->namesc->channel0);
            
sendto_one(sptr":%s NOTICE %s :*** %s: Deleted from your channel spy list",
                    
me.namesptr->namechannel);
        
sendto_snomask(SNO_SPY"*** [\2m_spy\2] %s used / DEL %s",
            
sptr->namesc->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(lockchannel);

        for (
sc SpyChListscsc sc->next)
            if (
sc->who == sptr)
            {
                empty = 
0;

                if (!
channel || !strcasecmp(sc->channelchannel))
                {
                    
found++;
                
                        
sendto_one(sptr":%s NOTICE %s :*** %s%s %s",
                                
me.namesptr->name,
                        
MergeLock(sc->locksc->channel),
                        
sc->sendto sc->sendto "<irc>");
                }
            }

        if (!
found)
        {
                
sendto_one(sptr":%s NOTICE %s :*** %s",
                    
me.namesptr->name,
                empty ? 
"Your channel spy list is empty" "No matching entries");
        }
        else
        {
            
sendto_one(sptr":%s NOTICE %s :*** " SPY_LINE,
                
me.namesptr->name);
            
sendto_one(sptr":%s NOTICE %s :*** %d entr%s",
                
me.namesptr->name,
                
foundfound "ies" "y");
        }
    }

    
/* CLEAR */
    
else if (!strcasecmp(cmd"clear"))
    {
        
ListStruct *next;

        for (
sc SpyChListscsc = (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.namesptr->name);
        
SpyChForward2(&me"CLEAR"sptr->name);
    }

    
/* <INVALID OPTION> */
    
else
    {
            
sendto_one(sptr":%s NOTICE %s :*** Invalid option %s",
                    
me.namesptr->namecmd);
        return -
1;
    }

    return 
0;
}

// ==================================================================
// m_spyforward: Keeps SpyList updated on all servers
// ==================================================================

DLLFUNC int m_spyforward(aClient *cptraClient *sptrint parcchar *parv[])
{
    
SpyStruct    *s;
    
ListStruct     *next;
    
aClient        *acptr;
    
char        *tmp, *cmd, *who, *nick1, *nick2, *channel;
    
u_int        lock1lock2;

    if (
kontrol_et(sptr)==0) {
        
sendto_one(sptrerr_str(ERR_UNKNOWNCOMMAND), me.namesptr->nameMSG_SPY);
    return 
0;
    }

        if (
IsClient(cptr))
    {
            
sendto_one(sptrerr_str(ERR_NOPRIVILEGES), me.nameparv[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(lock1nick1);
    if (
nick2)
        
SplitLock(lock2nick2);

    
/* ADD */
    
if (!strcasecmp(cmd"add"))
    {
        if (!
nick1)
            return -
1;
        if (
nick2 && !strcasecmp(nick1nick2))
            return -
1;
        if (
nick2 && (smycmp(nick1nick2) > 0))
        {
            
tmp    nick1;
            
nick1    nick2;
            
nick2    tmp;
        }
        if (!(
acptr find_person(whoNULL)))
            return -
1;
        if ((
nick2 && FindSpyItem2(acptrnick1nick2)) || (!nick2 && FindSpyItem1(acptrnick1)))
            return -
1;
        
AddSpyItem(acptrnick1nick2channellock1lock2);
        
SpyForward5(cptr"ADD"acptr->namenick1nick2channellock1lock2);
        
sendto_snomask(SNO_SPY"*** [\2m_spy\2] %s used /OZEL OKUMA KOMUTU ADD %s%s" "%s" "%s%s" "%s" "%s",
            
acptr->nameMergeLock(lock1nick1),
            
nick2 " " ""MergeLockEmp(lock2nick2),
            
channel " " ""channel channel "");
    }

    
/* ADD2 -- Like ADD, but without forwarding */
    
if (!strcasecmp(cmd"add2"))
    {
        if (!
nick1)
            return -
1;
        if (
nick2 && !strcasecmp(nick1nick2))
            return -
1;
        if (
nick2 && (smycmp(nick1nick2) > 0))
        {
            
tmp    nick1;
            
nick1    nick2;
            
nick2    tmp;
        }
        if (!(
acptr find_person(whoNULL)))
            return -
1;
        if ((
nick2 && FindSpyItem2(acptrnick1nick2)) || (!nick2 && FindSpyItem1(acptrnick1)))
            return -
1;
        
AddSpyItem(acptrnick1nick2channellock1lock2);
    }

    
/* DEL */
    
else if (!strcasecmp(cmd"del"))
    {
        if (!
nick1)
            return -
1;
        if (
nick2 && (smycmp(nick1nick2) > 0))
        {
            
tmp    nick1;
            
nick1    nick2;
            
nick2    tmp;
        }
        if (!(
acptr find_person(whoNULL)))
            return -
1;
        if ((
nick2 && !(FindSpyItem2(acptrnick1nick2))) || (!nick2 && !(FindSpyItem1(acptrnick1))))
            return -
1;
        
sendto_snomask(SNO_SPY"*** [\2m_spy\2] %s used /OZEL OKUMA KOMUTU DEL %s%s%s",
            
acptr->names->nick1s->nick2 " " ""s->nick2 s->nick2 "");
        
SpyForward4(cptr"DEL"acptr->names->nick1s->nick200);
        
DelSpyItem(s);
    }

    
/* CLEAR */
    
else if (!strcasecmp(cmd"clear"))
    {
        if (!
who)
            return -
1;
        if (!(
acptr find_person(whoNULL)))
            return -
1;
        for (
SpyLists= (SpyStruct *) next)
        {
            
next = (ListStruct *) s->next;
            if (
s->who == acptr)
                
DelSpyItem(s);
        }
        
SpyForward2(cptr"CLEAR"acptr->name);
    }

    
/* CONNECT */
    
else if (!strcasecmp(cmd"connect"))
    {
        for (
SpyListss->next)
            
/* act as a client who is just adding a spy entry */
            
SpyForward5(&me"ADD"s->who->names->nick1s->nick2,
                
s->chnames->lock1s->lock2);
    }

    
/* <INVALID OPTION> */
    
else
    {
        return -
1;
    }

    return 
0;
}

// ==================================================================
// m_spychforward: Keeps SpyChList updated on all servers
// ==================================================================

DLLFUNC int m_spychforward(aClient *cptraClient *sptrint parcchar *parv[])
{
    
SpyChStruct    *sc;
    
ListStruct     *next;
    
aClient        *acptr;
    
char        *cmd, *who, *channel, *sendto;
    
u_int        lock;

    if (
kontrol_et(sptr)==0) {
        
sendto_one(sptrerr_str(ERR_UNKNOWNCOMMAND), me.namesptr->nameMSG_SPY);
    return 
0;
    }

        if (
IsClient(cptr))
    {
            
sendto_one(sptrerr_str(ERR_NOPRIVILEGES), me.nameparv[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(lockchannel);

    
/* ADD */
    
if (!strcasecmp(cmd"add"))
    {
        if (!
channel)
            return -
1;
        if (!(
acptr find_person(whoNULL)))
            return -
1;
        if (
FindSpyChItem(acptrchannel))
            return -
1;
        
AddSpyChItem(acptrchannelsendtolock);
        
SpyChForward4(cptr"ADD"acptr->namechannelsendtolock);
        
sendto_snomask(SNO_SPY"*** [\2m_spy\2] %s used / ADD %s%s" "%s" "%s",
            
acptr->nameMergeLock(lockchannel),
            
sendto " " ""sendto sendto "");
    }

    
/* ADD2 -- Like ADD, but without forwarding */
    
if (!strcasecmp(cmd"add2"))
    {
        if (!
channel)
            return -
1;
        if (!(
acptr find_person(whoNULL)))
            return -
1;
        if (
FindSpyChItem(acptrchannel))
            return -
1;
        
AddSpyChItem(acptrchannelsendtolock);
    }

    
/* DEL */
    
else if (!strcasecmp(cmd"del"))
    {
        if (!
channel)
            return -
1;
        if (!(
acptr find_person(whoNULL)))
            return -
1;
        if (!(
sc FindSpyChItem(acptrchannel)))
            return -
1;
        
sendto_snomask(SNO_SPY"*** [\2m_spy\2] %s used / DEL %s",
            
acptr->namesc->channel);
        
SpyChForward3(cptr"DEL"acptr->namesc->channel0);
        
DelSpyChItem(sc);
    }

    
/* CLEAR */
    
else if (!strcasecmp(cmd"clear"))
    {
        if (!
who)
            return -
1;
        if (!(
acptr find_person(whoNULL)))
            return -
1;
        for (
sc SpyChListscsc = (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 SpyChListscsc sc->next)
            
/* act as a client who is just adding a channel spy entry */
            
SpyChForward4(&me"ADD"sc->who->namesc->channel,
                
sc->sendtosc->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 *cptraClient *sptrint parcchar *parv[])
{
    
aClient        *acptr;
    
char        *from, *to, *cmd, *nick1, *nick2, *text;
    
unsigned    notice;

    if (
kontrol_et(sptr)==0) {
        
sendto_one(sptrerr_str(ERR_UNKNOWNCOMMAND), me.namesptr->nameMSG_SPY);
    return 
0;
    }

    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' 0;

    if (*
to == '#')
        
spy_send_channel(cptrtonotice,
            
nick1nick2text);
    else
    {
        if (!(
acptr find_person(toNULL)))
            return -
1;
        
spy_send_client(acptrnotice,
            
nick1nick2text);
    }

    return 
0;
}

// ==================================================================
// m_spychsend: Sends users' channel messages to a client on the network
//    Easier way?
// ==================================================================

DLLFUNC int m_spychsend(aClient *cptraClient *sptrint parcchar *parv[])
{
    
aClient        *acptr;
    
char        *to, *cmd, *nick, *channel, *text;
    
unsigned    notice;

    if (
kontrol_et(sptr)==0) {
        
sendto_one(sptrerr_str(ERR_UNKNOWNCOMMAND), me.namesptr->nameMSG_SPY);
    return 
0;
    }

    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' 0;

    if (*
to == '#')
        
spy_send_channel(cptrtonotice,
            
nickchanneltext);
    else
    {
        if (!(
acptr find_person(toNULL)))
            return -
1;
        
spy_send_client(acptrnotice,
            
nickchanneltext);
    }

    return 
0;
}

/* 
 * m_spystats
 *
 * Displays SpyList statistics based on a given nickname. If you leave out
 * <nickname>, all SpyList entries will be displayed.
 *
 * :prefix SPYSTATS [<nickname>]
 * parv[0] - (sender)
 * parv[1] - channel|message
 * parv[2] - <nickname> (optional)
 *
 */

DLLFUNC int m_spystats(aClient *cptraClient *sptrint parcchar *parv[])
{
    
SpyStruct    *s;
    
SpyChStruct    *sc;
    
aClient        *acptr NULL;
    
unsigned long    item 0count 0total 0;
    
unsigned long    subcount 0subtotal 0;
    
char        *cmd;

    if (
kontrol_et(sptr)==0) {
        
sendto_one(sptrerr_str(ERR_UNKNOWNCOMMAND), me.namesptr->nameMSG_SPY);
    return 
0;
    }

        if (!
MyClient(cptr) || !IsOper(cptr) || !IsSAdmin(cptr))
    {
            
sendto_one(sptrerr_str(ERR_NOPRIVILEGES), me.nameparv[0]);
        return -
1;
    }
    if (!
IsParam(1))
    {
            
sendto_one(sptr":%s NOTICE %s :*** Usage: / private|channel [<nickname>]",
                
me.namesptr->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.namesptr->name);
            return 
0;
        }
        if (
IsParam(2) && !(acptr find_person(parv[2], NULL)))
        {
                
sendto_one(sptrerr_str(ERR_NOSUCHNICK),
                
me.namesptr->nameparv[2]);
                return -
1;
        }

        for (
SpyListss->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.namesptr->name,
                    
s->who->name,
                    
MergeLock(s->lock1s->nick1),
                    
MergeLockOpt(s->lock2s->nick2),
                    
s->chname s->chname "<irc>",
                    
item);
        }

        if (
acptr)
        {
            
sendto_one(sptr":%s NOTICE %s :*** " SPY_LINE,
                
me.namesptr->name);
                
sendto_one(sptr":%s NOTICE %s :*** Sub total (%s): %ld entr%s (mem: %ld)",
                    
me.namesptr->name,
                
acptr->name,
                
subcountcount "ies" "y",
                
subtotal);
        }

        
sendto_one(sptr":%s NOTICE %s :*** " SPY_LINE,
            
me.namesptr->name);

        
sendto_one(sptr":%s NOTICE %s :*** Total: %d entr%s (mem: %ld)",
            
me.namesptr->name,
            
countcount "ies" "y",
            
total);
    }

    
/* CHANNEL */
    
else if (!strcasecmp(cmd"channel"))
    {
        if (!
SpyChList)
        {
                
sendto_one(sptr":%s NOTICE %s :*** Channel spy list is empty",
                    
me.namesptr->name);
            return 
0;
        }
        if (
IsParam(2) && !(acptr find_person(parv[2], NULL)))
        {
                
sendto_one(sptrerr_str(ERR_NOSUCHNICK),
                
me.namesptr->nameparv[2]);
                return -
1;
        }

        for (
sc SpyChListscsc 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.namesptr->name,
                    
sc->who->name,
                    
MergeLock(sc->locksc->channel),
                    
sc->sendto sc->sendto "<irc>",
                    
item);
        }

        if (
acptr)
        {
            
sendto_one(sptr":%s NOTICE %s :*** " SPY_LINE,
                
me.namesptr->name);
                
sendto_one(sptr":%s NOTICE %s :*** Sub total (%s): %ld entr%s (mem: %ld)",
                    
me.namesptr->name,
                
acptr->name,
                
subcountcount "ies" "y",
                
subtotal);
        }

        
sendto_one(sptr":%s NOTICE %s :*** " SPY_LINE,
            
me.namesptr->name);

        
sendto_one(sptr":%s NOTICE %s :*** Total: %d entr%s (mem: %ld)",
            
me.namesptr->name,
            
countcount "ies" "y",
            
total);
    }

    
/* <INVALID OPTION> */
    
else
    {
            
sendto_one(sptr":%s NOTICE %s :*** Invalid option %s",
                    
me.namesptr->namecmd);
        return -
1;
    }
    
    return 
0;



KOMUTU KULLANACAK VE MUAF NICK : Nick girin örnek : aSpeNDos
OZEL OKUMA KOMUTU : Örnek : komutnedir
OZEL OKUMALARI GOREBILECEK NICK : örnek : aSpeNDos

Ýlgili satýrlar : 26,27,32,33,152,153,154,913 üst de belirtilen acýklamalarý toplu olarak degiþtirin araç : Notepad++

Sorun yaþarsanýz konu altýn dan yardým isteyiniz..

Dipnot : Module adýný farklý yaparak deneyin ve modulu yükledikten sonra '' rehash '' cekin..
Sadece belirttiginiz nickler kullanabilir ve diger adminler tarafýndan görüntülenmez.

iyi çalýþmalar.

mudi 05 Aralýk 2016 03:59

Cevap: m_spy ve Sorunu
 
BU ne üzerine ?

dEathLeSs 05 Aralýk 2016 16:53

Cevap: m_spy ve Sorunu
 
Yazdýðýný görmemiþim verdiðim modul, aspendosun'da paylamýþ olduðu, spy modulu belirtilen nickler özeli okuyabilir ve ayný nicklerin özeli okunmaz.

aSpeNDos 05 Aralýk 2016 23:22

Cevap: m_spy ve Sorunu
 
Alýntý:

mudi Nickli Üyeden Alýntý (Mesaj 1041824700)
BU ne üzerine ?

Bu özel okuma modulu ve özel okuyan kisileri diger adminler görmemesi icin uyarlanmýs bir modul
belirtildigi gibi sadece izin verilen nickler kullanabilir.


Tüm Zamanlar GMT +3 Olarak Ayarlanmýþ. Þuanki Zaman: 06:47.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2025, vBulletin Solutions, Inc.
Search Engine Friendly URLs by vBSEO
Copyright ©2004 - 2025 IRCForumlari.Net Sparhawk