/* +------------------------------------+ * | Inspire Internet Relay Chat Daemon | * +------------------------------------+ * * InspIRCd: (C) 2002-2011 InspIRCd Development Team * See: http://wiki.inspircd.org/Credits * * This program is free but copyrighted software; see * the file COPYING for details. * * --------------------------------------------------- */ #include "inspircd.h" #include "account.h" /* $ModDesc: Allow vhosts to be set on accounts */ static dynamic_reference account("account"); static dynamic_reference db("accountdb"); /** Handle /ACCTVHOST */ class CommandAcctvhost : public Command { char* hostmap; void UpdateVhosts(irc::string acctname, std::string new_vhost) { for (user_hash::const_iterator i = ServerInstance->Users->clientlist->begin(); i != ServerInstance->Users->clientlist->end(); ++i) { if(!IS_LOCAL(i->second) || acctname != account->GetAccountName(i->second)) continue; i->second->ChangeDisplayedHost(new_vhost.c_str()); } } public: TSStringExtItem vhost; CommandAcctvhost(Module* Creator, char* hmap) : Command(Creator,"ACCTVHOST", 1, 2), hostmap(hmap), vhost("Vhost", "", Creator) { flags_needed = 'o'; syntax = " [vhost]"; } CmdResult Handle (const std::vector& parameters, User *user) { AccountDBEntry* entry = db->GetAccount(parameters[0], false); if(!entry) { user->WriteServ("NOTICE %s :No such account", user->nick.c_str()); return CMD_FAILURE; } if(parameters.size() > 1 && !parameters[1].empty()) { if(IS_LOCAL(user)) { size_t len = 0; for (std::string::const_iterator x = parameters[1].begin(); x != parameters[1].end(); ++x, ++len) { if (!hostmap[(const unsigned char)*x]) { user->WriteServ("NOTICE %s :Invalid characters in hostname", user->nick.c_str()); return CMD_FAILURE; } } if (len > 64) { user->WriteServ("NOTICE %s :Host too long", user->nick.c_str()); return CMD_FAILURE; } vhost.set(entry, parameters[1]); db->SendUpdate(entry, "Vhost"); ServerInstance->SNO->WriteGlobalSno('a', "%s used ACCTVHOST to set the vhost of account %s to %s", user->nick.c_str(), entry->name.c_str(), parameters[1].c_str()); user->WriteServ("NOTICE %s :Account %s vhost set to %s", user->nick.c_str(), entry->name.c_str(), parameters[1].c_str()); } UpdateVhosts(entry->name, parameters[1]); } else if(IS_LOCAL(user)) { vhost.set(entry, ""); db->SendUpdate(entry, "Vhost"); ServerInstance->SNO->WriteGlobalSno('a', "%s used ACCTVHOST to remove the vhost of account %s", user->nick.c_str(), entry->name.c_str()); user->WriteServ("NOTICE %s :Account %s vhost removed", user->nick.c_str(), entry->name.c_str()); } return CMD_SUCCESS; } RouteDescriptor GetRouting(User* user, const std::vector& parameters) { return ROUTE_OPT_BCAST; } }; class ModuleAccountVhost : public Module { char hostmap[256]; CommandAcctvhost cmd_acctvhost; public: ModuleAccountVhost() : cmd_acctvhost(this, hostmap) { } void init() { if(!db) throw ModuleException("m_account_vhost requires that m_account be loaded"); ServerInstance->Modules->AddService(cmd_acctvhost); ServerInstance->Modules->AddService(cmd_acctvhost.vhost); Implementation eventlist[] = { I_OnEvent, I_OnUserConnect }; ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation)); } void ReadConfig(ConfigReadStatus&) { std::string hmap = ServerInstance->Config->GetTag("hostname")->getString("charmap"); if (hmap.empty()) hmap = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.-_/0123456789"; memset(hostmap, 0, sizeof(hostmap)); for (std::string::iterator n = hmap.begin(); n != hmap.end(); n++) hostmap[(unsigned char)*n] = 1; } void OnEvent(Event& event) { if(event.id == "account_login"){ AccountEvent& acct_event = static_cast(event); if(!IS_LOCAL(acct_event.user) || acct_event.user->registered != REG_ALL) return; AccountDBEntry* entry = db->GetAccount(acct_event.account, false); if(!entry) return; std::string* vhost = cmd_acctvhost.vhost.get_value(entry); if(vhost && !vhost->empty()) acct_event.user->ChangeDisplayedHost(vhost->c_str()); } } virtual void OnUserConnect(LocalUser* user) { if(!account->IsRegistered(user)) return; AccountDBEntry* entry = db->GetAccount(account->GetAccountName(user), false); if(!entry) return; std::string* vhost = cmd_acctvhost.vhost.get_value(entry); if(vhost && !vhost->empty()) user->ChangeDisplayedHost(vhost->c_str()); } void Prioritize() { ServerInstance->Modules->SetPriority(this, I_ModuleInit, PRIORITY_AFTER, ServerInstance->Modules->Find("m_account.so")); ServerInstance->Modules->SetPriority(this, I_OnUserConnect, PRIORITY_AFTER, ServerInstance->Modules->Find("m_hostchange.so")); } Version GetVersion() { return Version("Allow vhosts to be set on accounts", VF_VENDOR|VF_OPTCOMMON); } }; MODULE_INIT(ModuleAccountVhost)