/* Sky-Dancer */

#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

static long UMODE_GIZLE = 0;
Umode *UmodeGizle = NULL;

ModuleInfo *hidewhois_modinfo = NULL;
extern void sendto_one(aClient *to, char *pattern, ...);
static Cmdoverride		*O_Whois, *O_SvsMode, *O_Svs2Mode, *O_PrivMsg;
static Hook *H_Oper = NULL;

DLLFUNC int Func_OvrWhois(Cmdoverride *ovrr, aClient *cptr, aClient *sptr, int parc, char *parv[]);
DLLFUNC int Func_OvrPrivMsg(Cmdoverride *ovrr, aClient *cptr, aClient *sptr, int parc, char *parv[]);
DLLFUNC int Func_OvrSvsMode(Cmdoverride *ovrr, aClient *cptr, aClient *sptr, int parc, char *parv[]);
DLLFUNC int Func_OvrSvs2Mode(Cmdoverride *ovrr, aClient *cptr, aClient *sptr, int parc, char *parv[]);

static int WebTV_Kontrol_Et(aClient *, char *);
static int KontrolEt(aClient *, aClient *, char *);

#define HasUmodeQ(x)		((x)->umodes & UMODE_GIZLE)
#define HasOFlagHH(x)		((x)->oflag & OFLAG_HIDEWHOIS)
#define SetUmodeQ(x)		((x)->umodes |= UMODE_GIZLE)
#define ClearUmodeQ(x)		((x)->umodes &= ~UMODE_GIZLE)

#define MSG_WHOIS "WHOIS"
#define MSG_PRIVMSG "PRIVMSG"
#define MSG_SVSMODE "SVSMODE"
#define MSG_SVS2MODE "SVS2MODE"
#define MOD_Q 'Q'

int umode_allow_sky(aClient *sptr, int what);
static int Func_Oper(aClient *sptr, int what);

ModuleHeader MOD_HEADER(hidewhois) = {
	"hidewhois",
	"Operatorler icin Whois Gizleme Modu (QBilisim)",
	"Operatorler icin Whois Gizleme Modu (QBilisim)",
	"3.2-b8-1",
NULL 
};

DLLFUNC int MOD_INIT(hidewhois)(ModuleInfo *modinfo) {
	hidewhois_modinfo = modinfo;
	UmodeGizle = UmodeAdd(modinfo->handle, MOD_Q, UMODE_GLOBAL, umode_allow_sky, &UMODE_GIZLE);
	if (!UmodeGizle) {
		config_error("hidewhois: Kullanici Modu Eklenemedi 'Q': %s", ModuleGetErrorStr(modinfo->handle));
	return MOD_FAILED;
	}
	H_Oper = HookAddEx(modinfo->handle, HOOKTYPE_LOCAL_OPER, Func_Oper);
	if (!H_Oper) {
		config_error("hidewhois: Oper Hook Eklenemedi: %s", ModuleGetErrorStr(modinfo->handle));
	return MOD_FAILED;
	}
return MOD_SUCCESS;
}

DLLFUNC int MOD_LOAD(hidewhois)(int module_load) {
	O_Whois = CmdoverrideAdd(hidewhois_modinfo->handle, MSG_WHOIS, Func_OvrWhois);
	O_PrivMsg = CmdoverrideAdd(hidewhois_modinfo->handle, MSG_PRIVMSG, Func_OvrPrivMsg);
	O_SvsMode = CmdoverrideAdd(hidewhois_modinfo->handle, MSG_SVSMODE, Func_OvrSvsMode);
	O_Svs2Mode = CmdoverrideAdd(hidewhois_modinfo->handle, MSG_SVS2MODE, Func_OvrSvs2Mode);
	if (!O_Whois || !O_SvsMode || !O_Svs2Mode || !O_PrivMsg) {
		sendto_realops("hidewhois: Override Eklenemedi: %s", ModuleGetErrorStr(hidewhois_modinfo->handle));
		return MOD_FAILED;
	}
return MOD_SUCCESS;
}

DLLFUNC int MOD_UNLOAD(hidewhois)(int module_unload) {
	if (H_Oper) {
		HookDel(H_Oper);
		H_Oper = NULL;
	}
	if (UmodeGizle) {
		UmodeDel(UmodeGizle);
		UmodeGizle = NULL;
	}
	if (O_Whois && CommandExists(MSG_WHOIS)) {
		CmdoverrideDel(O_Whois);
		O_Whois = NULL;
	}
	if (O_SvsMode && CommandExists(MSG_SVSMODE)) {
		CmdoverrideDel(O_SvsMode);
		O_SvsMode = NULL;
	}
	if (O_PrivMsg && CommandExists(MSG_PRIVMSG)) {
		CmdoverrideDel(O_PrivMsg);
		O_PrivMsg = NULL;
	}
	if (O_Svs2Mode && CommandExists(MSG_SVS2MODE)) {
		CmdoverrideDel(O_Svs2Mode);
		O_Svs2Mode = NULL;
	}
return MOD_SUCCESS;
}

int umode_allow_sky(aClient *sptr, int what) {
	if (!IsAnOper(sptr))
		return 0;
	if (what == MODE_ADD) {
		if (MyClient(sptr))
			return 1;
	}
return 1;
}

static int Func_Oper(aClient *sptr, int what) {
	long Sky;
	if (what == 1) {
		if (!HasUmodeQ(sptr)) {
			Sky = sptr->umodes;
			SetUmodeQ(sptr);
			send_umode_out(sptr, sptr, Sky);
		}
	}
return 1;
}

int Func_OvrWhois(Cmdoverride *ovrr, aClient *cptr, aClient *sptr, int parc, char *parv[]) {
	aClient *acptr;
	char *nick, *tmp;
	char *p = NULL;
	int cnt = 0;

	if (IsServer(sptr)) return 0;

	if (parc < 2) {
		sendto_one(sptr, err_str(ERR_NONICKNAMEGIVEN), me.name, parv[0]);
	return 0;
	}

	if (parc > 2) {
		if (hunt_server_token(cptr, sptr, MSG_WHOIS, TOK_WHOIS, "%s :%s", 1, parc, parv) != HUNTED_ISME)
			return 0;
		parv[1] = parv[2];
	}

	for (tmp = canonize(parv[1]); (nick = strtoken(&p, tmp, ",")); tmp = NULL) {
		unsigned char sky;
		if (++cnt > MAXTARGETS)
			break;
		sky = (index(nick, '?') || index(nick, '*'));
		if (sky)
			continue;
		if ((acptr = find_client(nick, NULL))) {
			if (IsServer(acptr))
				continue;
			if (IsMe(acptr))
				break;
			if (!IsPerson(acptr))
				continue;
			if (KontrolEt(sptr, acptr, "/whois") == 0)
				return 0;
		}
	}
return CallCmdoverride(O_Whois, cptr, sptr, parc, parv);
}

int Func_OvrSvsMode(Cmdoverride *ovrr, aClient *cptr, aClient *sptr, int parc, char *parv[]) {
	int i;
	char *m;
	aClient *acptr;

	if (!IsULine(sptr))
		return 0;

	if (parc < 3)
		return 0;

	for (m = parv[2]; *m; m++) {
		switch (*m) {
			case MOD_Q:
				return 0;
			break;
		}
	}
return CallCmdoverride(O_SvsMode, cptr, sptr, parc, parv);
}

int Func_OvrPrivMsg(Cmdoverride *ovrr, aClient *cptr, aClient *sptr, int parc, char *parv[]) {
	char *s;
	char *nick, *p, *ctcp, *p2, *pc;
	int  cansend = 0;
	int  prefix = 0;
	char pfixchan[CHANNELLEN + 4];
	int ret=0;
	char Sky[512];

	if (IsHandshake(sptr))
		return 0;

	if (parc < 2 || *parv[1] == '\0') {
		sendto_one(sptr, err_str(ERR_NORECIPIENT), me.name, parv[0], MSG_PRIVMSG);
		return -1;
	}

	if (parc < 3 || *parv[2] == '\0') {
		sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]);
		return -1;
	}

	strlcpy(Sky, parv[1], sizeof(Sky));

	for (p = NULL, nick = strtoken(&p, Sky, ","); nick; nick = strtoken(&p, NULL, ",")) {
		if (!strcasecmp(nick, "irc") && MyClient(sptr)) {
			ret = WebTV_Kontrol_Et(sptr, parv[2]);
			if (ret == 0) return 0;
		}
	}
return CallCmdoverride(O_PrivMsg, cptr, sptr, parc, parv);
}

// SvsMode override ile birleşim yapılabilir ?
int Func_OvrSvs2Mode(Cmdoverride *ovrr, aClient *cptr, aClient *sptr, int parc, char *parv[]) {
	int i;
	char *m;
	aClient *acptr;

	if (!IsULine(sptr))
		return 0;

	if (parc < 3)
		return 0;

	for (m = parv[2]; *m; m++) {
		switch (*m) {
			case MOD_Q:
				return 0;
			break;
		}
	}
return CallCmdoverride(O_Svs2Mode, cptr, sptr, parc, parv);
}

static int WebTV_Kontrol_Et(aClient *sptr, char *Msgg) {
	char *cmd = NULL, *s = NULL, *p=NULL, *nick=NULL;
	int i, n;
	static char *para[MAXPARA + 2];
	char maxbuff[1024];
	aClient *acptr;
	
	if (!Msgg || !*Msgg) {
		sendto_one(sptr, ":IRC %s %s :No command given", MSG_PRIVMSG, sptr->name);
		return 0;
	}

	memset(maxbuff,0,sizeof(maxbuff));
	strncpy(maxbuff,Msgg,strlen(Msgg));

	cmd = strtok(maxbuff, " ");
	if (!cmd)
		return 0;

	s = strtok(NULL, "");
	if (!s)
		return 0;

	for (p = NULL, nick = strtoken(&p, s, ","); nick; nick = strtoken(&p, NULL, ",")) {
		if ((acptr = find_client(nick, NULL))) {
			if (IsServer(acptr))
				continue;
			if (IsMe(acptr))
				break;
			if (!IsPerson(acptr))
				continue;
			if (KontrolEt(sptr, acptr, "\"webtv whois\"") == 0)
				return 0;
		}
	}
return 1;
}

static int KontrolEt(aClient *sptr, aClient *acptr, char *Tip) {
	aClient *acptr;
	
	if (IsNetAdmin(sptr)) return 1;
	if ((acptr != sptr) && (IsAnOper(acptr)) && (HasUmodeQ(acptr))) {
		sendto_one(sptr,
			":%s NOTICE %s :*** %s nickine ait whois bilgilerini, sadece servis adminleri gorebilmektedir.",
			me.name, sptr->name, acptr->name);
		sendto_one(acptr,
			":%s %s %s :*** %s (%s@%s) size %s uygulamayi denedi.",
			me.name, IsWebTV(acptr) ? "PRIVMSG" : "NOTICE", acptr->name, sptr->name,
			sptr->user->username, sptr->user->realhost, Tip);
	return 0;
	}
return 1;
}
