/***************************************************************************************/
/* Anope Module : vhost_fantasy.c : v1.3                                               */  
/* Trystan Scott Lee                                                                   */
/* trystan@nomadirc.net                                                                */ 
/*                                                                                     */
/* Adds !vhost with out the request system                                             */
/*                                                                                     */
/* This program is free software; you can redistribute it and/or modify it under the   */
/* terms of the GNU General Public License as published by the Free Software           */
/* Foundation; either version 1, or (at your option) any later version.                */
/*                                                                                     */
/*  This program is distributed in the hope that it will be useful, but WITHOUT ANY    */
/*  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A    */
/*  PARTICULAR PURPOSE.  See the GNU General Public License for more details.          */
/*                                                                                     */
/***************************************************************************************/

/*
  1.0 : first release
  1.1 : 
    - Added internal event of hook for EVENT_BOT_FANTASY_NO_ACCESS 
    - Added banned vhosts, you can add these to the config file like so 
    - frees memory of used varaibles on unload 
    - Now reloads the settings on EVENT_RELOAD 
  1.2 :
    - Added check for "vhost" and not just "!vhost"
    - fixed ban vhosts
  1.3 :
    - Fixed memory leaks that were copied from the Anope core
    - Added message that tells user to assign a botserv bot to the request channel.
    - Added !vhost help and VhostRequestHelp to show on this.
    - Fixed possible segfault if the request chan was removed and Anope did a reload
    - Fixed being able to set a channel name without #
*/


#include "module.h"

#define AUTHOR "Trystan"
#define VERSION "1.3"

int do_hs_fantasy(int argc, char **argv);
int do_reload(int argc, char **argv);
int vhost_fantasy(User *u, char *cur_buffer);
char *VhostRequestChan;
char *BannedVhosts;
char **BannedVhostsList;
int NumBannedVhosts;
int load_config(void);
int check_baned_vhost(char *vhost);
char *VhostRequestHelpMessage;

int AnopeInit(int argc, char **argv)
{
	EvtHook *hook;
	
    hook = createEventHook(EVENT_BOT_FANTASY, do_hs_fantasy);
    moduleAddEventHook(hook);

    hook = createEventHook(EVENT_BOT_FANTASY_NO_ACCESS, do_hs_fantasy);
    moduleAddEventHook(hook);

    hook = createEventHook(EVENT_RELOAD, do_reload);
    moduleAddEventHook(hook);

    moduleAddAuthor(AUTHOR);
    moduleAddVersion(VERSION);
    moduleSetType(THIRD);

    if (!load_config()) {
        return MOD_STOP;
    }

    if (!ircd->vhost) {
        alog("Vhosting not supported by IRCD");
        return MOD_STOP;
    }
	
    alog("vhost_fantasy loaded");
    return MOD_CONT;
}

void AnopeFini(void)
{
    int idx;

    if (VhostRequestChan) {
        free(VhostRequestChan);
    }

    if (NumBannedVhosts) {
     for (idx = 0; idx < NumBannedVhosts; idx++) {
        free(BannedVhostsList[idx]);
     }
    }
    alog("vhost_fantasy un-loaded");
}

int do_hs_fantasy(int argc, char **argv)
{
    User *u;
    char *vHost = NULL;
    char *vIdent = NULL;
    int status;

    if (argc != 4) {
        if (argc >= 3 && VhostRequestHelpMessage) {
                notice(s_HostServ, argv[1], VhostRequestHelpMessage);
        }
        return MOD_CONT;
    }

    if (!VhostRequestChan) {
        if (debug) {
            alog("[vhost_fantasy] RequestChan is not set");
        }
        return MOD_CONT;
    }

    if ((stricmp(argv[0], "vhost") == 0) || (stricmp(argv[0], "!vhost") == 0)) {
        u = finduser(argv[1]);
        if (!stricmp(VhostRequestChan,argv[2])) {
         if (u) {
            status = vhost_fantasy(u, argv[3]);
            if (status == MOD_CONT) {
                vHost = getvHost(u->nick);
                vIdent = getvIdent(u->nick);
                anope_cmd_vhost_on(u->nick, vIdent, vHost);
            } else {
              if (debug) {
                alog("[vhost_fantasy] vhost_fantasy() returned %d", status);
              }
            }
         } else {
          if (debug) {
            alog("[vhost_fantasy] could not find the user %s", argv[1]);
          }
         }
        } else {
         if (debug) {
            alog("[vhost_fantasy] %s is and channel called was %s", VhostRequestChan, argv[2]);
         }
        }
    } else {
        if (debug) {
            alog("[vhost_fantasy] fantasy commands was for %s", argv[0]);
        }
    }

    return MOD_CONT;
}

int do_reload(int argc, char **argv)
{
    int idx;

    if (VhostRequestChan) {
        free(VhostRequestChan);
    }

    if (NumBannedVhosts) {
     for (idx = 0; idx < NumBannedVhosts; idx++) {
        free(BannedVhostsList[idx]);
     }
    }

    load_config();

    if (!VhostRequestChan) {
        return MOD_STOP;
    }
    return MOD_CONT;
}

int vhost_fantasy(User *u, char *cur_buffer)
{
    char *nick = u->nick;
    char *rawhostmask = cur_buffer;
    char *hostmask = smalloc(HOSTMAX);

    NickAlias *na;
    char *s;

    char *vIdent = NULL;

    if (!nick || !rawhostmask) {
        return MOD_STOP;
    }

    if (!stricmp(rawhostmask, "help")) {
        if (VhostRequestHelpMessage) {
                notice(s_HostServ, u->nick, VhostRequestHelpMessage);
        }
        free(hostmask);
        return MOD_STOP;
    }

    vIdent = myStrGetOnlyToken(rawhostmask, '@', 0);    /* Get the first substring, @ as delimiter */
    if (vIdent) {
        rawhostmask = myStrGetTokenRemainder(rawhostmask, '@', 1);      /* get the remaining string */
        if (!rawhostmask) {
            return MOD_STOP;
        }
        if (strlen(vIdent) > USERMAX - 1) {
            notice_lang(s_HostServ, u, HOST_SET_IDENTTOOLONG, USERMAX);
            return MOD_STOP;
        } else {
            for (s = vIdent; *s; s++) {
                if (!isvalidchar(*s)) {
                    notice_lang(s_HostServ, u, HOST_SET_IDENT_ERROR);
                    if (vIdent) {
                        free(vIdent);
                    }
                    return MOD_STOP;
                }
            }
        }
        if (!ircd->vident) {
            notice_lang(s_HostServ, u, HOST_NO_VIDENT);
            if (vIdent) {
                free(vIdent);
            }
            return MOD_STOP;
        }
    }
    if (strlen(rawhostmask) < HOSTMAX - 1) {
        snprintf(hostmask, HOSTMAX - 1, "%s", rawhostmask);
    } else {
        notice_lang(s_HostServ, u, HOST_SET_TOOLONG, HOSTMAX);
        if (vIdent) {
            free(vIdent);
        }
        return MOD_STOP;
    }

    if (!isValidHost(hostmask, 3)) {
        if (!stricmp(hostmask, "help")) {
            if (VhostRequestHelpMessage) {
                notice(s_HostServ, u->nick, VhostRequestHelpMessage);
            }
        } else {
           notice_lang(s_HostServ, u, HOST_SET_ERROR);
        }
        if (vIdent) {
            free(vIdent);
        }
        free(hostmask);
        return MOD_STOP;
    }

    if (!check_baned_vhost(hostmask)) {
        notice(s_HostServ, u->nick, "The vhost you have requested is not allowed please choose another");
        if (vIdent) {
            free(vIdent);
        }
        free(hostmask);
        return MOD_STOP;
    }

    if ((na = findnick(nick))) {
        if (na->status & NS_VERBOTEN) {
            notice_lang(s_HostServ, u, NICK_X_FORBIDDEN, nick);
            if (vIdent) {
                free(vIdent);
            }
            free(hostmask);
            return MOD_STOP;
        }
        if (vIdent && ircd->vident) {
            alog("vHost for user \002%s\002 set to \002%s@%s\002 by !vhost", nick, vIdent, hostmask);
        } else {
            alog("vHost for user \002%s\002 set to \002%s\002 by !vhost", nick, hostmask);
        }
        addHostCore(nick, vIdent, hostmask, u->nick, (int32) time(NULL));
        if (vIdent) {
            notice_lang(s_HostServ, u, HOST_IDENT_SET, nick, vIdent,
                        hostmask);
        } else {
            notice_lang(s_HostServ, u, HOST_SET, nick, hostmask);
        }
    } else {
        notice_lang(s_HostServ, u, HOST_NOREG, nick);
    }
    if (vIdent) {
      free(vIdent);
    }
    free(hostmask);
    return MOD_CONT;
}

int load_config(void)
{
	int i;
    char *s;
    ChannelInfo *ci;
	
    Directive confvalues[][1] = {
		{{"RequestChan", {{PARAM_STRING, PARAM_RELOAD, &VhostRequestChan}}}},
        {{"BannedVhosts", {{PARAM_STRING, PARAM_RELOAD, &BannedVhosts}}}},
        {{"VhostsRequestHelp", {{PARAM_STRING, PARAM_RELOAD, &VhostRequestHelpMessage}}}}
    };

	for (i = 0; i < 3; i++) {
    	moduleGetConfigDirective(confvalues[i]);
    }

    if (!VhostRequestChan) {
       alog("[vhost_fantasy] RequestChan not set in the config");
       return 0;
    }

    if (*VhostRequestChan != '#') {
        alog("[vhost_fantasy] RequestChan must start with a #");
        return 0;
    }

    NumBannedVhosts = 0;          /* always zero it, even if we have no setters */
    if (BannedVhosts) {
        s = strtok(BannedVhosts, " ");
        do {
            if (s) {
                NumBannedVhosts++;
                BannedVhostsList =
                    realloc(BannedVhostsList,
                            sizeof(char *) * NumBannedVhosts);
                BannedVhostsList[NumBannedVhosts - 1] = sstrdup(s);
            }
        } while ((s = strtok(NULL, " ")));
    }
    alog("[vhost_fantasy] Set config vars: RequestChan=%s", VhostRequestChan);
    alog("[vhost_fantasy] for help use !vhost help in %s", VhostRequestChan);
    ci = cs_findchan(VhostRequestChan);
    if (ci) {
        if (!ci->bi) {
            alog("[vhost_fantasy] %s does not have a botserv bot assigned, please assign a bot", VhostRequestChan);
        }
        if (ci->botflags & BS_FANTASY) {
            alog("[vhost_fantasy] fantasy commands are enabled for %s", VhostRequestChan);
        } else {
            alog("[vhost_fantasy] fantasy commands are disabled for %s", VhostRequestChan);
            alog("[vhost_fantasy] /bs set %s FANTASY on", VhostRequestChan);
        }
    } else {
        alog("[vhost_fantasy] %s is not a registered channel", VhostRequestChan);
        return 0;
    }

    return 1;
}


int check_baned_vhost(char *vhost)
{
    int idx;
	
    for (idx = 0; idx < NumBannedVhosts; idx++) {
        if (match_wild_nocase(BannedVhostsList[idx], vhost)) {
            return 0;
        }
    }
    return 1;
}


/* EOF */

