/**
* -----------------------------------------------------------------------------
* Name : hs_nethost
* Author : Viper <Viper@Absurd-IRC.net>
* Date : 12/05/2008
* Last update : 29/05/2008
* Version : 2.1
* -----------------------------------------------------------------------------
* Tested : Anope-1.7.21 + UnrealIRCd 3.2.6
* Requires : Anope-1.7.21
* -----------------------------------------------------------------------------
* This module will automatically set a default vhost upon registration, supporting
* customization based upon the user's nickname.
*
* This module is based on a fork of hs_nethost 1.2 by Trystan Scott Lee when that
* module was no longer supported. Most code however has been rewritten to make use
* of the events system and allow for better customization of the NetworkHost.
* Credit also goes to the original author Certus, and Strike, the author of hs_autohost.
*
* This module is published under GPLv2.
* -----------------------------------------------------------------------------
* Translations: *** Does not currently apply ***
*
* - English and Dutch Languages provided and maintained by myself.
*
* -----------------------------------------------------------------------------
*
* Changelog:
*
* 2.1 Fixed segfault crash occuring when no vIdent is set.
*
* 2.0 Added support for more customizable network vhosts.
* Added windows support.
* Re-wrote most code and re-releasing module under my name.
* Module forked off hs_nethost 1.2 by Trystan.
*
* -----------------------------------------------------------------------------
**/
/**
* Configuration directives that should be copy-pasted to services.conf
# NetworkHost [REQUIRED by hs_nethost]
# Module: hs_nethost
#
# When set this vHost (and vIdent) will automatically be set for users
# when they register a new nick with NickServ.
# Note that no ident must be given.
#
# Some variables may be used for further customization:
# "$nick$" will be replaced by the nickname that was just registered and
# can be used multiple times in both the ident and host portion.
# $network$ will be replaced by the configured NetworkName.
#
# Note that only letters and numbers are allowed to be used in the NetworkHost.
#
# Some examples are:
#NetworkHost "$nick$@users.network.net"
#NetworkHost "$nick$.users.network.net"
#NetworkHost "$nick$@$nick$.users.network.net"
#NetworkHost "$nick$.users.$network$"
#NetworkHost "$nick$@$nick$.users.$network$"
NetworkHost "$nick$@users.$network$"
*
**/
/* ------------------------------------------------------------------------------- */
#include "module.h"
#include <stdlib.h>
/*------------------------------Configuration Block----------------------------*/
/**
* Undefining this will make you lose all support for hs_nethost!
*
* This module checks whether unsupported modules are enabled/loaded in anope and
* whether the anope version meets minimum requirements to load.
* If an incompatible module is found, hs_nethost will either unload or disable
* itself (ex: os_raw), or continue in unsupported mode (ex: ircd_init).
*
* These measures have been added to protect users against themselves and prevent
* the author of this module from being confronted with support queries about situations that
* would not occor during normal use (for example when using RAW).
*
* If you undef this directive, these checks will be disabled, however you WILL LOSE ALL SUPPORT!!!
* If you use the module in unsupported module ayways (because of a conflicting 3rd party module
* for example) this may also be desirable.
*
* To undefine this replace "#define" by "#undef" or simply comment the line out.
* Note that you may need to delete hs_nethost.o and .so (*nix) to force a recompile.
**/
#define SUPPORTED
/*-------------------------End of Configuration Block--------------------------*/
#define AUTHOR "Viper"
#define VERSION "2.1"
/* Language defines - not currently being used.. */
#define LANG_NUM_STRINGS 0
#define LANG_ 0
/* Constants */
char *rep_nick = "$nick$";
char *rep_network = "$network$";
char *rand_num = "$rand$";
/* Variables */
char *NetworkHost;
int Enabled;
int supported;
/* Functions */
int set_vhost(int argc, char **argv);
void vident_check(char *s);
void vhost_check(char *s);
char *str_replace(char *replace_target, char *replace_with, char *source);
int check_load(void);
void update_version(void);
int load_config(void);
int reload_config(int argc, char **argv);
void add_languages(void);
/* ------------------------------------------------------------------------------- */
/**
* Create the command, and tell anope about it.
* @param argc Argument count
* @param argv Argument list
* @return MOD_CONT to allow the module, MOD_STOP to stop it
**/
int AnopeInit(int argc, char **argv) {
EvtHook *hook;
Enabled = 1;
alog("[\002hs_nethost\002] Loading module...");
moduleAddAuthor(AUTHOR);
/* This one is not needed, but the modules site requires it... */
moduleAddVersion(VERSION);
#ifdef SUPPORTED
if (!moduleMinVersion(1,7,21,1341)) {
alog("[\002hs_nethost\002] Your version of Anope isn't supported. Please update to a newer release.");
return MOD_STOP;
}
supported = 1;
#else
supported = -1;
#endif
check_load();
if (!Enabled)
return MOD_STOP;
/* Hook to some events.. */
hook = createEventHook(EVENT_NICK_REGISTERED, set_vhost);
if (moduleAddEventHook(hook) != MOD_ERR_OK) {
alog("[\002hs_nethost\002] Can't hook to EVENT_NICK_REGISTERED event");
return MOD_STOP;
}
hook = createEventHook(EVENT_GROUP, set_vhost);
if (moduleAddEventHook(hook) != MOD_ERR_OK) {
alog("[\002hs_nethost\002] Can't hook to EVENT_GROUP event");
return MOD_STOP;
}
hook = createEventHook(EVENT_RELOAD, reload_config);
if (moduleAddEventHook(hook) != MOD_ERR_OK) {
alog("[\002hs_nethost\002] Can't hook to EVENT_RELOAD event");
return MOD_STOP;
}
if (!load_config()) {
alog("[\002hs_nethost\002] NetworkHost is not set in the config. (This is fatal)");
return MOD_STOP;
}
update_version();
alog("[\002hs_nethost\002] Module loaded successfully...");
return MOD_CONT;
}
void AnopeFini(void) {
alog("[\002hs_nethost\002] Unloading module...");
if (NetworkHost)
free(NetworkHost);
}
/* ------------------------------------------------------------------------------- */
int set_vhost(int argc, char **argv) {
srand(time(NULL));
int32 tmp_time = time(NULL);
NickAlias *na;
char *cust_host, *vIdent, *vHost;
char randcrap[7];
if (!Enabled)
return MOD_CONT;
if (argc != 1)
return MOD_CONT;
if (!NetworkHost)
return MOD_CONT;
if (!(na = findnick(argv[0])))
return MOD_CONT;
/* Create the customized host for the user.. */
cust_host = strdup(NetworkHost);
cust_host = str_replace(rep_nick, na->nick, cust_host);
cust_host = str_replace(rep_network, NetworkName, cust_host);
sprintf(randcrap, "%i", rand() % 1000000);
cust_host = str_replace(rand_num, randcrap, cust_host);
vIdent = myStrGetOnlyToken(cust_host, '@', 0);
if (!vIdent)
vHost = strdup(cust_host);
else
vHost = myStrGetTokenRemainder(cust_host, '@', 1);
/* Make sure ident and host are valid */
if (vIdent) vident_check(vIdent);
vhost_check(vHost);
/* Create the new vhost... */
alog("[hs_nethost] Automatically setting vhost for nick %s (%s).", na->nick, cust_host);
addHostCore(na->nick, vIdent, vHost, s_HostServ, tmp_time);
if (na->u) {
notice_lang(s_HostServ, na->u, HOST_SET, s_HostServ, cust_host);
/* Make sure the vhost is also set. */
if (nick_identified(na->u))
do_on_id(na->u);
}
free(cust_host);
free(vHost);
free(randcrap);
if (vIdent) free(vIdent);
return MOD_CONT;
}
/* ------------------------------------------------------------------------------- */
/**
* Replaces non-letters and non-numbers by _s.
**/
void vident_check(char *s) {
register int c;
while ((c = *s)) {
if (!isalnum(c))
*s = '_';
s++;
}
return;
}
/**
* Replaces non-letters and non-numbers by .s.
**/
void vhost_check(char *s) {
register int c;
while ((c = *s)) {
if (!isalnum(c))
*s = '.';
s++;
}
return;
}
/**
* This will replace all occurances of replace_target by replace_with in the source string.
* Returns pointer to the new string.
*
* Note that all passed strings should be terminated.
**/
char *str_replace(char *replace_target, char *replace_with, char *source) {
char *ret, *tmp;
int diff, length;
if (!replace_target || !replace_with || !source)
return NULL;
diff = strlen(replace_with) - strlen(replace_target);
ret = strdup(source);
while ((tmp = strstr(ret, replace_target))) {
length = strlen(ret);
if (diff > 0) {
ret = (char *) realloc(ret, sizeof(char) * (length + diff) + 1);
memmove(tmp + strlen(replace_with), tmp + strlen(replace_target),
sizeof(char) * (strlen(tmp) - strlen(replace_target)) +1);
}
memcpy(tmp, replace_with, strlen(replace_with));
if (diff < 0) {
memmove(tmp + strlen(replace_with), tmp + strlen(replace_target),
sizeof(char) * (strlen(tmp) - strlen(replace_target)) +1);
ret = (char *) realloc(ret, sizeof(char) * (length + diff) + 1);
}
/* Make sure the array is null terminated */
memset(ret + (length + diff), 0, 1);
}
return ret;
}
/* ------------------------------------------------------------------------------- */
int check_load(void) {
#ifdef SUPPORTED
if (!DisableRaw || findModule("os_raw")) {
alog("[\002hs_nethost\002] RAW has NOT been disabled! (This is fatal!)");
Enabled = 0;
return MOD_STOP;
}
if (supported) {
if (findModule("bs_logchanmon")) {
alog("[\002hs_nethost\002] This module is unsupported in combination with bs_logchanmon.");
supported = 0;
} else if (findModule("ircd_gameserv")) {
alog("[\002hs_nethost\002] This module is unsupported in combination with ircd_gameserv.");
supported = 0;
} else if (findModule("ircd_init")) {
alog("[\002hs_nethost\002] This module is unsupported in combination with ircd_init.");
supported = 0;
} else if (findModule("cs_join")) {
alog("[\002hs_nethost\002] This module is unsupported in combination with cs_join.");
supported = 0;
}
} else
alog("[\002hs_nethost\002] Module operating in unsupported mode!");
#endif
return MOD_CONT;
}
void update_version(void) {
Module *m;
char tmp[BUFSIZE];
if (mod_current_module)
m = mod_current_module;
else
m = findModule("hs_nethost");
snprintf(tmp, BUFSIZE, "%s [%s]", VERSION, (((Enabled))?((supported >= 0)?((supported == 0)?"u":"S"):"U"):"D"));
if (m->version)
free(m->version);
m->version = sstrdup(tmp);
}
/* ------------------------------------------------------------------------------- */
/**
* (Re)Load the configuration directives
**/
int load_config(void) {
int i;
Directive confvalues[][1] = {
{{"NetworkHost", {{PARAM_STRING, PARAM_RELOAD, &NetworkHost}}}},
};
if (NetworkHost) free(NetworkHost);
NetworkHost = NULL;
for (i = 0; i < 1; i++)
moduleGetConfigDirective(confvalues[i]);
if (NetworkHost) {
alog("[hs_nethost] NetworkHost set to %s", NetworkHost);
return 1;
} else {
alog("[hs_nethost] NetworkHost NOT Set, please set NetworkHost in the services.conf");
return 0;
}
}
/**
* Upon /os reload call the routines for reloading the configuration directives
**/
int reload_config(int argc, char **argv) {
if (!Enabled)
return MOD_CONT;
if (argc >= 1) {
if (!stricmp(argv[0], EVENT_START)) {
alog("[hs_nethost]: Reloading configuration directives...");
load_config();
}
}
if (check_load() != MOD_CONT) {
update_version();
}
return MOD_CONT;
}
/* ------------------------------------------------------------------------------- */
/**
* At this stage, this is not being used..
**/
void add_languages(void) {
char *langtable_en_us[] = {
"",
};
char *langtable_nl[] = {
"",
};
moduleInsertLanguage(LANG_EN_US, LANG_NUM_STRINGS, langtable_en_us);
moduleInsertLanguage(LANG_NL, LANG_NUM_STRINGS, langtable_nl);
}
/* EOF */