/* * ================================================================= * Filename: hideserver.c * Description: Hide certain or all servers from /map & /links. * Written by: AngryWolf * Documentation: hideserver.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 #include #include #include #include #ifdef _WIN32 #include #endif #include #include "h.h" #ifdef STRIPBADWORDS #include "badwords.h" #endif #ifdef _WIN32 #include "version.h" #endif extern void sendto_one(aClient *to, char *pattern, ...); extern char *my_itoa(int i); #define DelOverride(cmd, ovr) if (ovr && CommandExists(cmd)) CmdoverrideDel(ovr); ovr = 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, iFP cb); static int override_map(Cmdoverride *, aClient *, aClient *, int, char *[]); static int override_links(Cmdoverride *, aClient *, aClient *, int, char *[]); static int cb_test(ConfigFile *, ConfigEntry *, int, int *); static int cb_conf(ConfigFile *, ConfigEntry *, int); static int cb_rehash(); /* static int cb_stats(aClient *sptr, char *stats); */ Hook *HookConfTest, *HookConfRun; Hook *HookConfRehash; Cmdoverride *OvrMap, *OvrLinks; ConfigItem_ulines *HiddenServers; static struct { unsigned disable_map : 1; unsigned disable_links : 1; char *map_deny_message; char *links_deny_message; } Settings; #ifndef STATIC_LINKING static ModuleInfo *MyModInfo; #define MyMod MyModInfo->handle #define SAVE_MODINFO MyModInfo = modinfo; #else #define MyMod NULL #define SAVE_MODINFO #endif ModuleHeader MOD_HEADER(hideserver) = { "hideserver", "$Id: hideserver.c,v 4.8 2004/04/05 07:25:04 angrywolf Exp $", "Hide servers from /map & /links", "3.2-b8-1", NULL }; static void InitConf() { memset(&Settings, 0, sizeof Settings); } static void FreeConf() { ConfigItem_ulines *h; ListStruct *next; ircfree(Settings.map_deny_message); ircfree(Settings.links_deny_message); for (h = HiddenServers; h; h = (ConfigItem_ulines *) next) { next = (ListStruct *) h->next; DelListItem(h, HiddenServers); MyFree(h->servername); MyFree(h); } } DLLFUNC int MOD_TEST(hideserver)(ModuleInfo *modinfo) { SAVE_MODINFO HookConfTest = HookAddEx(modinfo->handle, HOOKTYPE_CONFIGTEST, cb_test); return MOD_SUCCESS; } DLLFUNC int MOD_INIT(hideserver)(ModuleInfo *modinfo) { SAVE_MODINFO HiddenServers = NULL; InitConf(); HookConfRun = HookAddEx(modinfo->handle, HOOKTYPE_CONFIGRUN, cb_conf); HookConfRehash = HookAddEx(modinfo->handle, HOOKTYPE_REHASH, cb_rehash); return MOD_SUCCESS; } DLLFUNC int MOD_LOAD(hideserver)(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(hideserver)(int module_unload) { FreeConf(); DelOverride("map", OvrMap); DelOverride("links", OvrLinks); DelHook(HookConfRehash); DelHook(HookConfRun); DelHook(HookConfTest); return MOD_SUCCESS; } static int cb_rehash() { FreeConf(); InitConf(); return 1; } static int cb_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs) { ConfigEntry *cep, *cepp; int errors = 0; if (type == CONFIG_MAIN) { if (!strcmp(ce->ce_varname, "hideserver")) { for (cep = ce->ce_entries; cep; cep = cep->ce_next) { if (!strcmp(cep->ce_varname, "hide")) { for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next) { if (!cepp->ce_varname) { config_error("%s:%i: blank hideserver::hide item", cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum); errors++; } } } else if (!cep->ce_varname) { config_error("%s:%i: blank %s item", cep->ce_fileptr->cf_filename, cep->ce_varlinenum, ce->ce_varname); errors++; continue; } else if (!cep->ce_vardata) { config_error("%s:%i: %s::%s without value", cep->ce_fileptr->cf_filename, cep->ce_varlinenum, ce->ce_varname, cep->ce_varname); errors++; continue; } else if (!strcmp(cep->ce_varname, "disable-map")) ; else if (!strcmp(cep->ce_varname, "disable-links")) ; else if (!strcmp(cep->ce_varname, "map-deny-message")) ; else if (!strcmp(cep->ce_varname, "links-deny-message")) ; else { config_error("%s:%i: unknown directive hideserver::%s", cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_varname); errors++; } } *errs = errors; return errors ? -1 : 1; } } return 0; } static int cb_conf(ConfigFile *cf, ConfigEntry *ce, int type) { ConfigEntry *cep, *cepp; ConfigItem_ulines *ca; if (type == CONFIG_MAIN) { if (!strcmp(ce->ce_varname, "hideserver")) { for (cep = ce->ce_entries; cep; cep = cep->ce_next) { if (!strcmp(cep->ce_varname, "disable-map")) Settings.disable_map = config_checkval(cep->ce_vardata, CFG_YESNO); else if (!strcmp(cep->ce_varname, "disable-links")) Settings.disable_links = config_checkval(cep->ce_vardata, CFG_YESNO); else if (!strcmp(cep->ce_varname, "map-deny-message")) { ircstrdup(Settings.map_deny_message, cep->ce_vardata); } else if (!strcmp(cep->ce_varname, "links-deny-message")) { ircstrdup(Settings.links_deny_message, cep->ce_vardata); } else if (!strcmp(cep->ce_varname, "hide")) { for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next) { if (!strcasecmp(cepp->ce_varname, me.name)) continue; ca = MyMallocEx(sizeof(ConfigItem_ulines)); ircstrdup(ca->servername, cepp->ce_varname); AddListItem(ca, HiddenServers); } } } return 1; } } return 0; } /* * static int cb_stats(aClient *sptr, char *stats) * { * if (*stats == 'S') * { * sendto_one(sptr, ":%s %i %s :disable-map: %d", * me.name, RPL_TEXT, sptr->name, Settings.disable_map); * sendto_one(sptr, ":%s %i %s :disable-links: %d", * me.name, RPL_TEXT, sptr->name, Settings.disable_links); * sendto_one(sptr, ":%s %i %s :map-deny-message: %s", * me.name, RPL_TEXT, sptr->name, Settings.map_deny_message ? Settings.map_deny_message : ""); * sendto_one(sptr, ":%s %i %s :links-deny-message: %s", * me.name, RPL_TEXT, sptr->name, Settings.links_deny_message ? Settings.links_deny_message : ""); * } * return 0; * } */ Cmdoverride *AddOverride(char *msg, iFP cb) { Cmdoverride *ovr = CmdoverrideAdd(MyMod, msg, cb); #ifndef STATIC_LINKING if (ModuleGetError(MyMod) != MODERR_NOERROR || !ovr) #else if (!ovr) #endif { #ifndef STATIC_LINKING config_error("Error replacing command %s when loading module %s: %s", msg, MOD_HEADER(hideserver).name, ModuleGetErrorStr(MyMod)); #else config_error("Error replacing command %s when loading module %s", msg, MOD_HEADER(hideserver).name); #endif return NULL; } return ovr; } ConfigItem_ulines *FindHiddenServer(char *servername) { ConfigItem_ulines *h; for (h = HiddenServers; h; h = (ConfigItem_ulines *) h->next) if (!strcasecmp(servername, h->servername)) break; return h; } /* * New /MAP format -Potvin * dump_map function. * Rewritten by AngryWolf */ void my_dump_map(aClient *cptr, aClient *server, int prompt_length, int length) { static char prompt[64]; char *p = &prompt[prompt_length]; int cnt = 0; aClient *acptr; Link *lp; *p = '\0'; if (prompt_length > 60) sendto_one(cptr, rpl_str(RPL_MAPMORE), me.name, cptr->name, prompt, server->name); else { sendto_one(cptr, rpl_str(RPL_MAP), me.name, cptr->name, prompt, length, server->name, server->serv->users, (server->serv->numeric ? (char *)my_itoa(server->serv-> numeric) : "")); cnt = 0; } if (prompt_length > 0) { p[-1] = ' '; if (p[-2] == '`') p[-2] = ' '; } if (prompt_length > 60) return; strcpy(p, "|-"); for (lp = Servers; lp; lp = lp->next) { acptr = lp->value.cptr; if (acptr->srvptr != server || !(acptr->flags & FLAGS_MAP)) continue; cnt++; } for (lp = Servers; lp; lp = lp->next) { acptr = lp->value.cptr; if (acptr->srvptr != server || !(acptr->flags & FLAGS_MAP)) continue; if (--cnt == 0) *p = '`'; my_dump_map(cptr, acptr, prompt_length + 2, length - 2); } if (prompt_length > 0) p[-1] = '-'; } /* ** New /MAP format. -Potvin ** m_map (NEW) ** Rewritten by AngryWolf ** ** parv[0] = sender prefix ** parv[1] = server mask **/ static int override_map(Cmdoverride *ovr, aClient *cptr, aClient *sptr, int parc, char *parv[]) { Link *lp; aClient *acptr, *uplink; u_int longest = strlen(me.name); int hide_ulines = (HIDE_ULINES && !IsAnOper(sptr)); if (!IsClient(sptr)) return CallCmdoverride(ovr, cptr, sptr, parc, parv); if (!IsAnOper(sptr) && Settings.disable_map) { if (Settings.map_deny_message) sendto_one(sptr, ":%s %s %s :%s", me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE", sptr->name, Settings.map_deny_message); else sendto_one(sptr, rpl_str(RPL_MAPEND), me.name, parv[0]); return 0; } if (parc < 2 || BadPtr(parv[1])) parv[1] = "*"; for (lp = Servers; lp; lp = lp->next) lp->value.cptr->flags &= ~FLAGS_MAP; me.flags |= FLAGS_MAP; for (lp = Servers; lp; lp = lp->next) { acptr = lp->value.cptr; if (IsMe(acptr) || _match(parv[1], acptr->name)) continue; for (uplink = acptr; uplink && uplink != &me; uplink = uplink->srvptr) { if (hide_ulines && IsULine(uplink)) break; if (!IsAnOper(sptr) && FindHiddenServer(uplink->name)) break; if (uplink->flags & FLAGS_MAP) break; uplink->flags |= FLAGS_MAP; if ((strlen(uplink->name) + uplink->hopcount * 2) > longest) longest = strlen(uplink->name) + uplink->hopcount * 2; } } if (longest > 60) longest = 60; longest += 2; my_dump_map(sptr, &me, 0, longest); sendto_one(sptr, rpl_str(RPL_MAPEND), me.name, parv[0]); return 0; } /* ** m_links ** parv[0] = sender prefix ** or ** parv[0] = sender prefix ** ** Recoded by Stskeeps ** Modified by AngryWolf */ static int override_links(Cmdoverride *ovr, aClient *cptr, aClient *sptr, int parc, char *parv[]) { Link *lp; aClient *acptr; if (!IsClient(sptr)) return CallCmdoverride(ovr, cptr, sptr, parc, parv); if (!IsAnOper(sptr) && Settings.disable_links) { if (Settings.links_deny_message) sendto_one(sptr, ":%s %s %s :%s", me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE", sptr->name, Settings.links_deny_message); else sendto_one(sptr, rpl_str(RPL_ENDOFLINKS), me.name, parv[0], "*"); return 0; } for (lp = Servers; lp; lp = lp->next) { acptr = lp->value.cptr; /* Some checks */ if (!IsAnOper(sptr)) { if (HIDE_ULINES && IsULine(acptr)) continue; if (FindHiddenServer(acptr->name)) continue; } sendto_one(sptr, rpl_str(RPL_LINKS), me.name, parv[0], acptr->name, acptr->serv->up, acptr->hopcount, (acptr->info[0] ? acptr->info : "(Unknown Location)")); } sendto_one(sptr, rpl_str(RPL_ENDOFLINKS), me.name, parv[0], "*"); return 0; }