/* ChanServ SENDPASS module.
 *
 * IRC Services is copyright (c) 1996-2007 Andrew Church.
 *     E-mail: <achurch@achurch.org>
 * Parts written by Andrew Kempe and others.
 * This program is free but copyrighted software; see the file COPYING for
 * details.
 */

#include "services.h"
#include "modules.h"
#include "conffile.h"
#include "commands.h"
#include "language.h"
#include "encrypt.h"
#include "modules/mail/mail.h"
#include "modules/nickserv/nickserv.h"

#include "chanserv.h"
#include "cs-local.h"

/*************************************************************************/
/*************************** Local variables *****************************/
/*************************************************************************/

static Module *module;
static Module *module_chanserv;
static Module *module_nickserv;
static Module *module_nickserv_mail_auth;
static Module *module_mail;

static time_t CSSendpassDelay = 0;

/*************************************************************************/

static void do_sendpass(User *u);

static Command commands[] = {
    { "SENDPASS", do_sendpass, NULL,              CHAN_HELP_SENDPASS, -1,-1 },
    { NULL }
};

/*************************************************************************/
/**************************** Command handler ****************************/
/*************************************************************************/

/* Handle the SENDPASS command. */

static void do_sendpass(User *u)
{
    char *chan = strtok(NULL, " ");
    char *s = strtok_remaining();
    NickInfo *ni;
    NickGroupInfo *ngi;
    ChannelInfo *ci;
    time_t now = time(NULL);
    char passbuf[PASSMAX];
    int res;

    if (!chan || s) {
	syntax_error(s_ChanServ, u, "SENDPASS", CHAN_SENDPASS_SYNTAX);
    } else if (!(ni = u->ni)) {
	notice_lang(s_ChanServ, u, NICK_NOT_REGISTERED);
    } else if (!(ngi = u->ngi) || ngi == NICKGROUPINFO_INVALID) {
	notice_lang(s_ChanServ, u, INTERNAL_ERROR);
    } else if (!(ci = get_channelinfo(chan))) {
	notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
    } else if (ngi->id != ci->founder) {
	notice_lang(s_ChanServ, u, CHAN_SENDPASS_FOUNDER_ONLY);
    } else if (!user_identified(u)) {
	notice_lang(s_ChanServ, u, CHAN_MUST_IDENTIFY_NICK,
		    s_NickServ, s_NickServ);
    } else if (!ngi->email) {
	notice_lang(s_ChanServ, u, CHAN_SENDPASS_NO_EMAIL);
    } else if (ci->last_sendpass
	       && now - ci->last_sendpass < CSSendpassDelay) {
	notice_lang(s_ChanServ, u, CHAN_SENDPASS_TOO_SOON,
		    maketime(ngi,CSSendpassDelay-(now-ci->last_sendpass),0));
    } else if ((res = decrypt(ci->founderpass,passbuf,sizeof(passbuf))) != 1) {
	if (res == 0) {
	    module_log("BUG: trapdoor algorithm in use (should have been"
		       " caught at load time)");
	}
	notice_lang(s_ChanServ, u, CHAN_SENDPASS_FAILED);
    } else {
	char subject[BUFSIZE], body[BUFSIZE];

	snprintf(subject, sizeof(subject),
		 getstring(ngi,CHAN_SENDPASS_MAIL_SUBJECT), ci->name);
	snprintf(body, sizeof(body), getstring(ngi,CHAN_SENDPASS_MAIL_BODY),
		 ci->name, passbuf, s_ChanServ, u->username, u->host);
	res = sendmail(ngi->email, subject, body);
	if (res == 0) {
	    ci->last_sendpass = now;
	    notice_lang(s_ChanServ, u, CHAN_SENDPASS_SENT,
			ci->name, ngi->email);
	} else if (res == 1) {
	    notice_lang(s_ChanServ, u, SENDMAIL_NO_RESOURCES);
	} else {
	    module_log("Valid SENDPASS for %s by %s!%s@%s failed",
		       ci->name, u->nick, u->username, u->host);
	    notice_lang(s_ChanServ, u, CHAN_SENDPASS_FAILED);
	}
    }
}

/*************************************************************************/
/***************************** Module stuff ******************************/
/*************************************************************************/

const int32 module_version = MODULE_VERSION_CODE;

ConfigDirective module_config[] = {
    { "CSSendpassDelay",  { { CD_TIME, 0, &CSSendpassDelay } } },
    { NULL }
};

/*************************************************************************/

static int do_reconfigure(int after_configure)
{
    if (after_configure) {
	Command *cmd;
	if ((cmd = lookup_cmd(module_chanserv, "SENDPASS")) != NULL)
	    cmd->help_param1 = s_NickServ;
	else
	    module_log("BUG: reconfigure: SENDPASS command entry not found");
    }
    return 0;
}

/*************************************************************************/

int init_module(Module *module_)
{
    char testbuf[PASSMAX], testbuf2[PASSMAX];
    Command *cmd;


    module = module_;

    if (encrypt("a", 1, testbuf, PASSMAX) < 0) {
	module_log("Couldn't encrypt string to test for trapdoor encryption");
	return 0;
    }
    if (decrypt(testbuf, testbuf2, sizeof(testbuf2)) == 0) {
	module_log("Trapdoor (one-way) encryption in use; SENDPASS cannot"
		   " be used");
	return 0;
    }

    module_chanserv = find_module("chanserv/main");
    if (!module_chanserv) {
	module_log("Main ChanServ module not loaded");
	exit_module(0);
	return 0;
    }
    use_module(module_chanserv);

    module_nickserv = find_module("nickserv/main");
    if (!module_nickserv) {
	module_log("Main NickServ module not loaded");
	exit_module(0);
	return 0;
    }
    use_module(module_nickserv);

    module_nickserv_mail_auth = find_module("nickserv/mail-auth");
    if (!module_nickserv_mail_auth) {
	module_log("NickServ AUTH module (mail-auth) required for SENDPASS");
	exit_module(0);
	return 0;
    }
    use_module(module_nickserv_mail_auth);

    module_mail = find_module("mail/main");
    if (!module_mail) {
	module_log("Mail module not loaded");
	exit_module(0);
	return 0;
    }
    use_module(module_mail);

    if (!register_commands(module_chanserv, commands)) {
	module_log("Unable to register commands");
	exit_module(0);
	return 0;
    }

    if (!add_callback(NULL, "reconfigure", do_reconfigure)) {
	module_log("Unable to add callbacks");
	exit_module(0);
	return 0;
    }

    if ((cmd = lookup_cmd(module_chanserv, "SENDPASS")) != NULL) {
	cmd->help_param1 = s_NickServ;
    } else {
	module_log("BUG: init: SENDPASS command entry not found");
	exit_module(0);
	return 0;
    }

    return 1;
}

/*************************************************************************/

int exit_module(int shutdown_unused)
{
#ifdef CLEAN_COMPILE
    shutdown_unused = shutdown_unused;
#endif

    remove_callback(NULL, "reconfigure", do_reconfigure);

    if (module_mail) {
	unuse_module(module_mail);
	module_mail = NULL;
    }
    if (module_nickserv_mail_auth) {
	unuse_module(module_nickserv_mail_auth);
	module_nickserv_mail_auth = NULL;
    }
    if (module_nickserv) {
	unuse_module(module_nickserv);
	module_nickserv = NULL;
    }
    if (module_chanserv) {
	unregister_commands(module_chanserv, commands);
	unuse_module(module_chanserv);
	module_chanserv = NULL;
    }

    return 1;
}

/*************************************************************************/


syntax highlighted by Code2HTML, v. 0.9.1