/*
 * =================================================================
 * Filename:             operonlymap.c
 * Description:          Oper-only /map & /links.
 * Written by:           AngryWolf <angrywolf@flashmail.com>
 * Documentation:        operonlymap.txt (comes with the package)
 * =================================================================
 */

#include "config.h"
#include "struct.h"
#include "common.h"
#include "sys.h"
#include "numeric.h"
#include "msg.h"
#include "channel.h"
#include <time.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#include <io.h>
#endif
#include <fcntl.h>
#include "h.h"
#ifdef STRIPBADWORDS
#include "badwords.h"
#endif
#ifdef _WIN32
#include "version.h"
#endif

#define MyMod		ModOperOnlyMap->handle
#define DelOverride(x)	if (x) CmdoverrideDel(x); x = NULL
#define DelHook(x)      if (x) HookDel(x); x = NULL
#define ircstrdup(x,y)	if (x) MyFree(x); if (!y) x = NULL; else x = strdup(y)
#define ircfree(x)	if (x) MyFree(x); x = NULL

Cmdoverride		*AddOverride(char *msg, int (*cb)());
DLLFUNC int		override_map(Cmdoverride *, aClient *, aClient *, int, char *[]);
DLLFUNC int		override_links(Cmdoverride *, aClient *, aClient *, int, char *[]);
DLLFUNC int		cb_config_test(ConfigFile *, ConfigEntry *, int, int *);
DLLFUNC int		cb_config_run(ConfigFile *, ConfigEntry *, int);
DLLFUNC int		cb_config_rehash();
DLLFUNC int		cb_stats(aClient *sptr, char *stats);

Hook			*HookConfTest, *HookConfRun;
Hook			*HookConfRehash, *HookStats;
ModuleInfo		*ModOperOnlyMap;
Cmdoverride		*OvrMap, *OvrLinks;
char			*map_deny_message, *links_deny_message;

ModuleHeader MOD_HEADER(operonlymap)
  = {
	"operonlymap",
	"$Id: operonlymap.c,v 3.4 2003/11/29 19:35:20 angrywolf Exp $",
	"Oper-only /map & /links",
	"3.2-b8-1",
	NULL 
    };

static void InitConf()
{
	map_deny_message = NULL;
	links_deny_message = NULL;
}

static void FreeConf()
{
	ircfree(map_deny_message);
	ircfree(links_deny_message);
}

DLLFUNC int MOD_TEST(operonlymap)(ModuleInfo *modinfo)
{
	ModOperOnlyMap = modinfo;
	HookConfTest = HookAddEx(MyMod, HOOKTYPE_CONFIGTEST, cb_config_test);

	return MOD_SUCCESS;
}

DLLFUNC int MOD_INIT(operonlymap)(ModuleInfo *modinfo)
{
	ModOperOnlyMap = modinfo;
	InitConf();

	HookConfRun = HookAddEx(MyMod, HOOKTYPE_CONFIGRUN, cb_config_run);
	HookConfRehash = HookAddEx(MyMod, HOOKTYPE_REHASH, cb_config_rehash);
	HookStats = HookAddEx(MyMod, HOOKTYPE_STATS, cb_stats);

        return MOD_SUCCESS;
}

DLLFUNC int MOD_LOAD(operonlymap)(int module_load)
{
	int ret = MOD_SUCCESS;

	OvrMap = AddOverride("map", override_map);
	OvrLinks = AddOverride("links", override_links);

	if (!OvrMap || !OvrLinks)
		ret = MOD_FAILED;

	return ret;
}

DLLFUNC int MOD_UNLOAD(operonlymap)(int module_unload)
{
	FreeConf();

	DelOverride(OvrMap);
	DelOverride(OvrLinks);

	DelHook(HookStats);
	DelHook(HookConfRehash);
	DelHook(HookConfRun);
	DelHook(HookConfTest);

	return MOD_SUCCESS;
}

DLLFUNC int cb_config_rehash()
{
	FreeConf();
	InitConf();

	return 1;
}

DLLFUNC int cb_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
{
	int errors = 0;

	if (type != CONFIG_SET)
		return 0;

	if (!strcmp(ce->ce_varname, "map-deny-message"))
	{
		if (!ce->ce_vardata)
		{
			config_error("%s:%i: set::%s without contents",
					ce->ce_fileptr->cf_filename,
					ce->ce_varlinenum, ce->ce_varname);
			errors++;
		}

		*errs = errors;
		return errors ? -1 : 1;
	}
	else if (!strcmp(ce->ce_varname, "links-deny-message"))
	{
		if (!ce->ce_vardata)
		{
			config_error("%s:%i: set::%s without contents",
					ce->ce_fileptr->cf_filename,
					ce->ce_varlinenum, ce->ce_varname);
			errors++;
		}

		*errs = errors;
		return errors ? -1 : 1;
	}
	else
		return 0;
}

DLLFUNC int cb_config_run(ConfigFile *cf, ConfigEntry *ce, int type)
{
	if (type != CONFIG_SET)
		return 0;

	if (!strcmp(ce->ce_varname, "map-deny-message"))
	{
		ircstrdup(map_deny_message, ce->ce_vardata);
		return 1;		
	}
	else if (!strcmp(ce->ce_varname, "links-deny-message"))
	{
		ircstrdup(links_deny_message, ce->ce_vardata);
		return 1;		
	}

	return 0;
}

DLLFUNC int cb_stats(aClient *sptr, char *stats)
{
	if (*stats == 'S')
	{
		sendto_one(sptr, ":%s %i %s :map-deny-message: %s",
			me.name, RPL_TEXT, sptr->name, map_deny_message ? map_deny_message : "<none>");
		sendto_one(sptr, ":%s %i %s :links-deny-message: %s",
			me.name, RPL_TEXT, sptr->name, links_deny_message ? links_deny_message : "<none>");
	}
        return 0;
}

Cmdoverride *AddOverride(char *msg, int (*cb)())
{
	Cmdoverride *ovr = CmdoverrideAdd(MyMod, msg, cb);

#ifndef _WIN32
        if (ModuleGetError(MyMod) != MODERR_NOERROR || !ovr)
#else
        if (!ovr)
#endif
	{
#ifndef _WIN32
		config_error("Error replacing command %s when loading module %s: %s",
			msg, MOD_HEADER(operonlymap).name, ModuleGetErrorStr(MyMod));
#else
		config_error("Error replacing command %s when loading module %s",
			msg, MOD_HEADER(operonlymap).name);
#endif
		return NULL; /* just to be sure */
	}

	return ovr;
}

DLLFUNC int override_map(Cmdoverride *ovr, aClient *cptr, aClient *sptr, int parc, char *parv[])
{
	if (MyClient(sptr) && !IsAnOper(sptr))
	{
		if (map_deny_message)
			sendto_one(sptr, ":%s %s %s :%s",
				me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE",
				sptr->name, map_deny_message);
		sendto_one(sptr, rpl_str(RPL_MAPEND), me.name, parv[0]);
		return 0;
	}
	else
		CallCmdoverride(ovr, cptr, sptr, parc, parv);
}

DLLFUNC int override_links(Cmdoverride *ovr, aClient *cptr, aClient *sptr, int parc, char *parv[])
{
	if (MyClient(sptr) && !IsAnOper(sptr))
	{
		if (links_deny_message)
			sendto_one(sptr, ":%s %s %s :%s",
				me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE",
				sptr->name, links_deny_message);
		sendto_one(sptr, rpl_str(RPL_ENDOFLINKS), me.name, parv[0], "*");
		return 0;
	}
	else
		CallCmdoverride(ovr, cptr, sptr, parc, parv);
}

