From: danieldg Date: Mon, 16 Nov 2009 17:59:06 +0000 (+0000) Subject: Use ServiceProvider for inter-module dependencies X-Git-Tag: v2.0.23~1246 X-Git-Url: https://git.netwichtig.de/gitweb/?a=commitdiff_plain;h=54fb0cd5aa7d090d5c3da5ab54988c86ba8a2e8e;p=user%2Fhenk%2Fcode%2Finspircd.git Use ServiceProvider for inter-module dependencies This will stop dependency chains from preventing module reloads when it is not actually needed; however, it removes some failsafes that will need to be reimplemented in order to avoid unmapped vtables. This deprecates Request as an inter-module signaling mechanism, although SQL still uses it. git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@12140 e03df62e-2008-0410-955e-edbf42e46eb7 --- diff --git a/include/base.h b/include/base.h index 8324d6347..e0b3d25e3 100644 --- a/include/base.h +++ b/include/base.h @@ -213,7 +213,7 @@ enum ServiceType { }; /** A structure defining something that a module can provide */ -class CoreExport providerbase : public classbase +class CoreExport ServiceProvider : public classbase { public: /** Module that is providing this service */ @@ -222,9 +222,9 @@ class CoreExport providerbase : public classbase const std::string name; /** Type of service (must match object type) */ const ServiceType service; - providerbase(Module* Creator, const std::string& Name, ServiceType Type) + ServiceProvider(Module* Creator, const std::string& Name, ServiceType Type) : creator(Creator), name(Name), service(Type) {} - virtual ~providerbase(); + virtual ~ServiceProvider(); }; diff --git a/include/ctables.h b/include/ctables.h index 991ad1cc2..9b433d6f9 100644 --- a/include/ctables.h +++ b/include/ctables.h @@ -85,7 +85,7 @@ struct RouteDescriptor /** A structure that defines a command. Every command available * in InspIRCd must be defined as derived from Command. */ -class CoreExport Command : public providerbase +class CoreExport Command : public ServiceProvider { public: /** User flags needed to execute the command or 0 @@ -144,7 +144,7 @@ class CoreExport Command : public providerbase * NICK, optionally PASS, and been resolved). */ Command(Module* me, const std::string &cmd, int minpara = 0, int maxpara = 0) : - providerbase(me, cmd, SERVICE_COMMAND), flags_needed(0), min_params(minpara), max_params(maxpara), + ServiceProvider(me, cmd, SERVICE_COMMAND), flags_needed(0), min_params(minpara), max_params(maxpara), use_count(0), total_bytes(0), disabled(false), works_before_reg(false), Penalty(1) { } diff --git a/include/extensible.h b/include/extensible.h index ae78c0a0d..d4c7a86d1 100644 --- a/include/extensible.h +++ b/include/extensible.h @@ -12,7 +12,7 @@ enum SerializeFormat /** Class represnting an extension of some object */ -class CoreExport ExtensionItem : public providerbase, public usecountbase +class CoreExport ExtensionItem : public ServiceProvider, public usecountbase { public: ExtensionItem(const std::string& key, Module* owner); diff --git a/include/inspircd.h b/include/inspircd.h index 52035ce49..96b05488a 100644 --- a/include/inspircd.h +++ b/include/inspircd.h @@ -594,15 +594,6 @@ class CoreExport InspIRCd */ bool AddResolver(Resolver* r, bool cached); - /** Register a service provided by a module */ - void AddService(providerbase&); - - inline void AddServices(providerbase** list, int count) - { - for(int i=0; i < count; i++) - AddService(*list[i]); - } - /** Add a command to this server's command parser * @param f A Command command handler object to add * @throw ModuleException Will throw ModuleExcption if the command already exists diff --git a/include/mode.h b/include/mode.h index f2b58a309..ce9d2ee2b 100644 --- a/include/mode.h +++ b/include/mode.h @@ -90,7 +90,7 @@ enum ParamSpec * mode is expected to have a parameter, then this is * equivalent to returning MODEACTION_DENY. */ -class CoreExport ModeHandler : public providerbase +class CoreExport ModeHandler : public ServiceProvider { protected: /** diff --git a/include/modules.h b/include/modules.h index 3efee83dc..d6625e7bf 100644 --- a/include/modules.h +++ b/include/modules.h @@ -258,6 +258,44 @@ class CoreExport Event : public classbase void Send(); }; +class CoreExport DataProvider : public ServiceProvider +{ + public: + DataProvider(Module* Creator, const std::string& Name) + : ServiceProvider(Creator, Name, SERVICE_DATA) {} +}; + +class CoreExport dynamic_reference_base : public interfacebase +{ + private: + std::string name; + protected: + DataProvider* value; + public: + ModuleRef creator; + dynamic_reference_base(Module* Creator, const std::string& Name); + ~dynamic_reference_base(); + inline void ClearCache() { value = NULL; } + inline const std::string& GetProvider() { return name; } + void SetProvider(const std::string& newname); + void lookup(); + operator bool(); +}; + +template +class dynamic_reference : public dynamic_reference_base +{ + public: + dynamic_reference(Module* Creator, const std::string& Name) + : dynamic_reference_base(Creator, Name) {} + inline T* operator->() + { + if (!value) + lookup(); + return static_cast(value); + } +}; + /** Priority types which can be used by Module::Prioritize() */ enum Priority { PRIORITY_FIRST, PRIORITY_DONTCARE, PRIORITY_LAST, PRIORITY_BEFORE, PRIORITY_AFTER }; @@ -1419,14 +1457,6 @@ class CoreExport ModuleManager */ std::string LastModuleError; - /** The feature names published by various modules - */ - featurelist Features; - - /** The interface names published by various modules - */ - interfacelist Interfaces; - /** Total number of modules loaded into the ircd */ int ModCount; @@ -1451,6 +1481,12 @@ class CoreExport ModuleManager */ IntModuleList EventHandlers[I_END]; + /** List of data services keyed by name */ + std::multimap DataProviders; + + /** List of all dynamic references that are currently active */ + std::vector ActiveDynrefs; + /** Simple, bog-standard, boring constructor. */ ModuleManager(); @@ -1566,116 +1602,24 @@ class CoreExport ModuleManager */ Module* Find(const std::string &name); - /** Publish a 'feature'. - * There are two ways for a module to find another module it depends on. - * Either by name, using InspIRCd::FindModule, or by feature, using this - * function. A feature is an arbitary string which identifies something this - * module can do. For example, if your module provides SSL support, but other - * modules provide SSL support too, all the modules supporting SSL should - * publish an identical 'SSL' feature. This way, any module requiring use - * of SSL functions can just look up the 'SSL' feature using FindFeature, - * then use the module pointer they are given. - * @param FeatureName The case sensitive feature name to make available - * @param Mod a pointer to your module class - * @returns True on success, false if the feature is already published by - * another module. - */ - bool PublishFeature(const std::string &FeatureName, Module* Mod); - - /** Publish a module to an 'interface'. - * Modules which implement the same interface (the same way of communicating - * with other modules) can publish themselves to an interface, using this - * method. When they do so, they become part of a list of related or - * compatible modules, and a third module may then query for that list - * and know that all modules within that list offer the same API. - * A prime example of this is the hashing modules, which all accept the - * same types of Request class. Consider this to be similar to PublishFeature, - * except for that multiple modules may publish the same 'feature'. - * @param InterfaceName The case sensitive interface name to make available - * @param Mod a pointer to your module class - * @returns True on success, false on failure (there are currently no failure - * cases) - */ - bool PublishInterface(const std::string &InterfaceName, Module* Mod); - - /** Return a pair saying how many other modules are currently using the - * interfaces provided by module m. - * @param m The module to count usage for - * @return A pair, where the first value is the number of uses of the interface, - * and the second value is the interface name being used. - */ - std::pair GetInterfaceInstanceCount(Module* m); - - /** Mark your module as using an interface. - * If you mark your module as using an interface, then that interface - * module may not unload until your module has unloaded first. - * This can be used to prevent crashes by ensuring code you depend on - * is always in memory while your module is active. - * @param InterfaceName The interface to use - */ - void UseInterface(const std::string &InterfaceName); - - /** Mark your module as finished with an interface. - * If you used UseInterface() above, you should use this method when - * your module is finished with the interface (usually in its destructor) - * to allow the modules which implement the given interface to be unloaded. - * @param InterfaceName The interface you are finished with using. - */ - void DoneWithInterface(const std::string &InterfaceName); - - /** Unpublish a 'feature'. - * When your module exits, it must call this method for every feature it - * is providing so that the feature table is cleaned up. - * @param FeatureName the feature to remove - */ - bool UnpublishFeature(const std::string &FeatureName); - - /** Unpublish your module from an interface - * When your module exits, it must call this method for every interface - * it is part of so that the interfaces table is cleaned up. Only when - * the last item is deleted from an interface does the interface get - * removed. - * @param InterfaceName the interface to be removed from - * @param Mod The module to remove from the interface list - */ - bool UnpublishInterface(const std::string &InterfaceName, Module* Mod); - - /** Find a 'feature'. - * There are two ways for a module to find another module it depends on. - * Either by name, using InspIRCd::FindModule, or by feature, using the - * InspIRCd::PublishFeature method. A feature is an arbitary string which - * identifies something this module can do. For example, if your module - * provides SSL support, but other modules provide SSL support too, all - * the modules supporting SSL should publish an identical 'SSL' feature. - * To find a module capable of providing the feature you want, simply - * call this method with the feature name you are looking for. - * @param FeatureName The feature name you wish to obtain the module for - * @returns A pointer to a valid module class on success, NULL on failure. - */ - Module* FindFeature(const std::string &FeatureName); - - /** Find an 'interface'. - * An interface is a list of modules which all implement the same API. - * @param InterfaceName The Interface you wish to obtain the module - * list of. - * @return A pointer to a deque of Module*, or NULL if the interface - * does not exist. - */ - modulelist* FindInterface(const std::string &InterfaceName); - - /** Determine if a module has published the named interface. - * This could be used in, for example, OnLoadModule to pick up other modules that can be used. - * @param mod The module to check. - * @param InterfaceName the interface you want to check for - * @return True if the module provides the interface, false otherwise. - */ - bool ModuleHasInterface(Module* mod, const std::string& InterfaceName); - - /** Given a pointer to a Module, return its filename - * @param m The module pointer to identify - * @return The module name or an empty string - */ - const std::string& GetModuleName(Module* m); + /** Register a service provided by a module */ + void AddService(ServiceProvider&); + + inline void AddServices(ServiceProvider** list, int count) + { + for(int i=0; i < count; i++) + AddService(*list[i]); + } + + /** Find a service by name. + * If multiple modules provide a given service, the first one loaded will be chosen. + */ + ServiceProvider* FindService(ServiceType Type, const std::string& name); + + template inline T* FindDataService(const std::string& name) + { + return static_cast(FindService(SERVICE_DATA, name)); + } /** Return a list of all modules matching the given filter * @param filter This int is a bitmask of flags set in Module::Flags, diff --git a/include/typedefs.h b/include/typedefs.h index c0a5ebbc1..a1c6e774d 100644 --- a/include/typedefs.h +++ b/include/typedefs.h @@ -123,18 +123,6 @@ typedef std::set CUList; */ typedef std::vector string_list; -/** Holds a list of 'published features' for modules. - */ -typedef std::map featurelist; - -/** Holds a list of modules which implement an interface - */ -typedef std::deque modulelist; - -/** Holds a list of all modules which implement interfaces, by interface name - */ -typedef std::map > interfacelist; - /** Contains an ident and host split into two strings */ typedef std::pair IdentHostPair; diff --git a/src/base.cpp b/src/base.cpp index 3ff3d5281..852738f82 100644 --- a/src/base.cpp +++ b/src/base.cpp @@ -77,11 +77,11 @@ usecountbase::~usecountbase() (void*)this, usecount); } -providerbase::~providerbase() +ServiceProvider::~ServiceProvider() { } -ExtensionItem::ExtensionItem(const std::string& Key, Module* mod) : providerbase(mod, Key, SERVICE_METADATA) +ExtensionItem::ExtensionItem(const std::string& Key, Module* mod) : ServiceProvider(mod, Key, SERVICE_METADATA) { } diff --git a/src/mode.cpp b/src/mode.cpp index 441ca520d..7d99277df 100644 --- a/src/mode.cpp +++ b/src/mode.cpp @@ -46,7 +46,7 @@ #include "modes/umode_s.h" ModeHandler::ModeHandler(Module* Creator, const std::string& Name, char modeletter, ParamSpec Params, ModeType type) - : providerbase(Creator, Name, type == MODETYPE_CHANNEL ? SERVICE_CMODE : SERVICE_UMODE), m_paramtype(TR_TEXT), + : ServiceProvider(Creator, Name, type == MODETYPE_CHANNEL ? SERVICE_CMODE : SERVICE_UMODE), m_paramtype(TR_TEXT), parameters_taken(Params), mode(modeletter), prefix(0), oper(false), list(false), m_type(type), count(0), levelrequired(HALFOP_VALUE) { diff --git a/src/modmanager_dynamic.cpp b/src/modmanager_dynamic.cpp index 156105ad8..bbbaf7b53 100644 --- a/src/modmanager_dynamic.cpp +++ b/src/modmanager_dynamic.cpp @@ -152,13 +152,6 @@ bool ModuleManager::CanUnload(Module* mod) ServerInstance->Logs->Log("MODULE", DEFAULT, LastModuleError); return false; } - std::pair intercount = GetInterfaceInstanceCount(mod); - if (intercount.first > 0) - { - LastModuleError = "Failed to unload module " + mod->ModuleSourceFile + ", being used by " + ConvToStr(intercount.first) + " other(s) via interface '" + intercount.second + "'"; - ServerInstance->Logs->Log("MODULE", DEFAULT, LastModuleError); - return false; - } return true; } @@ -192,6 +185,14 @@ void ModuleManager::DoSafeUnload(Module* mod) if (mh && mh->creator == mod) ServerInstance->Modes->DelMode(mh); } + for(std::multimap::iterator i = DataProviders.begin(); i != DataProviders.end(); ) + { + std::multimap::iterator curr = i++; + if (curr->second->creator == mod) + DataProviders.erase(curr); + } + for(unsigned int i = 0; i < ServerInstance->Modules->ActiveDynrefs.size(); i++) + ServerInstance->Modules->ActiveDynrefs[i]->ClearCache(); /* Tidy up any dangling resolvers */ ServerInstance->Res->CleanResolvers(mod); diff --git a/src/modules.cpp b/src/modules.cpp index d86dc6270..f4751ad11 100644 --- a/src/modules.cpp +++ b/src/modules.cpp @@ -322,178 +322,117 @@ std::string& ModuleManager::LastError() return LastModuleError; } -bool ModuleManager::PublishFeature(const std::string &FeatureName, Module* Mod) -{ - if (Features.find(FeatureName) == Features.end()) - { - Features[FeatureName] = Mod; - return true; - } - return false; -} - -bool ModuleManager::UnpublishFeature(const std::string &FeatureName) +CmdResult InspIRCd::CallCommandHandler(const std::string &commandname, const std::vector& parameters, User* user) { - featurelist::iterator iter = Features.find(FeatureName); - - if (iter == Features.end()) - return false; - - Features.erase(iter); - return true; + return this->Parser->CallHandler(commandname, parameters, user); } -Module* ModuleManager::FindFeature(const std::string &FeatureName) +bool InspIRCd::IsValidModuleCommand(const std::string &commandname, int pcnt, User* user) { - featurelist::iterator iter = Features.find(FeatureName); - - if (iter == Features.end()) - return NULL; - - return iter->second; + return this->Parser->IsValidCommand(commandname, pcnt, user); } -bool ModuleManager::PublishInterface(const std::string &InterfaceName, Module* Mod) +void InspIRCd::AddCommand(Command *f) { - interfacelist::iterator iter = Interfaces.find(InterfaceName); - - if (iter == Interfaces.end()) - { - modulelist ml; - ml.push_back(Mod); - Interfaces[InterfaceName] = std::make_pair(0, ml); - } - else + if (!this->Parser->AddCommand(f)) { - iter->second.second.push_back(Mod); + throw ModuleException("Command "+std::string(f->name)+" already exists."); } - return true; } -bool ModuleManager::UnpublishInterface(const std::string &InterfaceName, Module* Mod) +void ModuleManager::AddService(ServiceProvider& item) { - interfacelist::iterator iter = Interfaces.find(InterfaceName); - - if (iter == Interfaces.end()) - return false; - - for (modulelist::iterator x = iter->second.second.begin(); x != iter->second.second.end(); x++) + switch (item.service) { - if (*x == Mod) + case SERVICE_COMMAND: + if (!ServerInstance->Parser->AddCommand(static_cast(&item))) + throw ModuleException("Command "+std::string(item.name)+" already exists."); + return; + case SERVICE_CMODE: + case SERVICE_UMODE: + if (!ServerInstance->Modes->AddMode(static_cast(&item))) + throw ModuleException("Mode "+std::string(item.name)+" already exists."); + return; + case SERVICE_METADATA: + ServerInstance->Extensions.Register(static_cast(&item)); + return; + case SERVICE_DATA: + case SERVICE_IOHOOK: { - iter->second.second.erase(x); - if (iter->second.second.empty()) - Interfaces.erase(InterfaceName); - return true; + DataProviders.insert(std::make_pair(item.name, &item)); + std::string::size_type slash = item.name.find('/'); + if (slash != std::string::npos) + { + DataProviders.insert(std::make_pair(item.name.substr(0, slash), &item)); + DataProviders.insert(std::make_pair(item.name.substr(slash + 1), &item)); + } + return; } + default: + throw ModuleException("Cannot add unknown service type"); } - return false; } -modulelist* ModuleManager::FindInterface(const std::string &InterfaceName) +ServiceProvider* ModuleManager::FindService(ServiceType type, const std::string& name) { - interfacelist::iterator iter = Interfaces.find(InterfaceName); - if (iter == Interfaces.end()) - return NULL; - else - return &(iter->second.second); -} - -bool ModuleManager::ModuleHasInterface(Module* mod, const std::string& InterfaceName) -{ - interfacelist::iterator iter = Interfaces.find(InterfaceName); - if (iter == Interfaces.end()) - return false; - else + switch (type) { - modulelist& ml = iter->second.second; - modulelist::iterator mi = std::find(ml.begin(), ml.end(), mod); - return (mi != ml.end()); + case SERVICE_DATA: + case SERVICE_IOHOOK: + { + std::multimap::iterator i = DataProviders.find(name); + if (i != DataProviders.end() && i->second->service == type) + return i->second; + return NULL; + } + // TODO implement finding of the other types + default: + throw ModuleException("Cannot find unknown service type"); } } -void ModuleManager::UseInterface(const std::string &InterfaceName) -{ - interfacelist::iterator iter = Interfaces.find(InterfaceName); - if (iter != Interfaces.end()) - iter->second.first++; - -} - -void ModuleManager::DoneWithInterface(const std::string &InterfaceName) +dynamic_reference_base::dynamic_reference_base(Module* Creator, const std::string& Name) + : name(Name), value(NULL), creator(Creator) { - interfacelist::iterator iter = Interfaces.find(InterfaceName); - if (iter != Interfaces.end()) - iter->second.first--; + ServerInstance->Modules->ActiveDynrefs.push_back(this); } -std::pair ModuleManager::GetInterfaceInstanceCount(Module* m) +dynamic_reference_base::~dynamic_reference_base() { - for (interfacelist::iterator iter = Interfaces.begin(); iter != Interfaces.end(); iter++) + for(unsigned int i = 0; i < ServerInstance->Modules->ActiveDynrefs.size(); i++) { - for (modulelist::iterator x = iter->second.second.begin(); x != iter->second.second.end(); x++) + if (ServerInstance->Modules->ActiveDynrefs[i] == this) { - if (*x == m) - { - return std::make_pair(iter->second.first, iter->first); - } + unsigned int last = ServerInstance->Modules->ActiveDynrefs.size() - 1; + if (i != last) + ServerInstance->Modules->ActiveDynrefs[i] = ServerInstance->Modules->ActiveDynrefs[last]; + ServerInstance->Modules->ActiveDynrefs.erase(ServerInstance->Modules->ActiveDynrefs.begin() + last); + return; } } - return std::make_pair(0, ""); -} - -const std::string& ModuleManager::GetModuleName(Module* m) -{ - static std::string nothing; - - for (std::map::iterator n = Modules.begin(); n != Modules.end(); ++n) - { - if (n->second == m) - return n->first; - } - - return nothing; -} - -CmdResult InspIRCd::CallCommandHandler(const std::string &commandname, const std::vector& parameters, User* user) -{ - return this->Parser->CallHandler(commandname, parameters, user); } -bool InspIRCd::IsValidModuleCommand(const std::string &commandname, int pcnt, User* user) +void dynamic_reference_base::SetProvider(const std::string& newname) { - return this->Parser->IsValidCommand(commandname, pcnt, user); + name = newname; + ClearCache(); } -void InspIRCd::AddCommand(Command *f) +void dynamic_reference_base::lookup() { - if (!this->Parser->AddCommand(f)) - { - throw ModuleException("Command "+std::string(f->name)+" already exists."); - } + if (!*this) + throw ModuleException("Dynamic reference to '" + name + "' failed to resolve"); } -void InspIRCd::AddService(providerbase& item) +dynamic_reference_base::operator bool() { - switch (item.service) + if (!value) { - case SERVICE_COMMAND: - if (!Parser->AddCommand(static_cast(&item))) - throw ModuleException("Command "+std::string(item.name)+" already exists."); - return; - case SERVICE_CMODE: - case SERVICE_UMODE: - if (!Modes->AddMode(static_cast(&item))) - throw ModuleException("Mode "+std::string(item.name)+" already exists."); - return; - case SERVICE_METADATA: - Extensions.Register(static_cast(&item)); - return; - case SERVICE_DATA: - case SERVICE_IOHOOK: - default: - throw ModuleException("Cannot add unknown service type"); + std::multimap::iterator i = ServerInstance->Modules->DataProviders.find(name); + if (i != ServerInstance->Modules->DataProviders.end()) + value = static_cast(i->second); } + return value; } void InspIRCd::SendMode(const std::vector& parameters, User *user) diff --git a/src/modules/extra/m_mssql.cpp b/src/modules/extra/m_mssql.cpp index 455a4fa47..13f25d4fc 100644 --- a/src/modules/extra/m_mssql.cpp +++ b/src/modules/extra/m_mssql.cpp @@ -636,29 +636,23 @@ class ModuleMsSQL : public Module private: unsigned long currid; QueryThread* queryDispatcher; + ServiceProvider sqlserv; public: ModuleMsSQL() - : currid(0) + : currid(0), sqlserv(this, "SQL/mssql", SERVICE_DATA) { LoggingMutex = new Mutex(); ResultsMutex = new Mutex(); - ServerInstance->Modules->UseInterface("SQLutils"); - - if (!ServerInstance->Modules->PublishFeature("SQL", this)) - { - throw ModuleException("m_mssql: Unable to publish feature 'SQL'"); - } - ReadConf(); queryDispatcher = new QueryThread(this); ServerInstance->Threads->Start(queryDispatcher); - ServerInstance->Modules->PublishInterface("SQL", this); Implementation eventlist[] = { I_OnRehash }; ServerInstance->Modules->Attach(eventlist, this, 1); + ServerInstance->Modules->AddService(sqlserv); } virtual ~ModuleMsSQL() @@ -668,10 +662,6 @@ class ModuleMsSQL : public Module ClearQueue(); ClearAllConnections(); - ServerInstance->Modules->UnpublishInterface("SQL", this); - ServerInstance->Modules->UnpublishFeature("SQL"); - ServerInstance->Modules->DoneWithInterface("SQLutils"); - delete LoggingMutex; delete ResultsMutex; } diff --git a/src/modules/extra/m_mysql.cpp b/src/modules/extra/m_mysql.cpp index 358f5e992..c294befdc 100644 --- a/src/modules/extra/m_mysql.cpp +++ b/src/modules/extra/m_mysql.cpp @@ -93,6 +93,7 @@ class ModuleSQL : public Module Mutex ResultsMutex; Mutex LoggingMutex; Mutex ConnMutex; + ServiceProvider sqlserv; ModuleSQL(); ~ModuleSQL(); @@ -666,8 +667,6 @@ ConnMap::iterator GetCharId(char id) return Connections.end(); } -class ModuleSQL; - class DispatcherThread : public SocketThread { private: @@ -679,24 +678,13 @@ class DispatcherThread : public SocketThread virtual void OnNotify(); }; -ModuleSQL::ModuleSQL() : rehashing(false) +ModuleSQL::ModuleSQL() : rehashing(false), sqlserv(this, "SQL/mysql", SERVICE_DATA) { - ServerInstance->Modules->UseInterface("SQLutils"); - currid = 0; Dispatcher = new DispatcherThread(this); ServerInstance->Threads->Start(Dispatcher); - if (!ServerInstance->Modules->PublishFeature("SQL", this)) - { - Dispatcher->join(); - delete Dispatcher; - ServerInstance->Modules->DoneWithInterface("SQLutils"); - throw ModuleException("m_mysql: Unable to publish feature 'SQL'"); - } - - ServerInstance->Modules->PublishInterface("SQL", this); Implementation eventlist[] = { I_OnRehash }; ServerInstance->Modules->Attach(eventlist, this, 1); } @@ -705,9 +693,6 @@ ModuleSQL::~ModuleSQL() { delete Dispatcher; ClearAllConnections(); - ServerInstance->Modules->UnpublishInterface("SQL", this); - ServerInstance->Modules->UnpublishFeature("SQL"); - ServerInstance->Modules->DoneWithInterface("SQLutils"); } unsigned long ModuleSQL::NewID() diff --git a/src/modules/extra/m_pgsql.cpp b/src/modules/extra/m_pgsql.cpp index f362125cb..4fb3d3ab6 100644 --- a/src/modules/extra/m_pgsql.cpp +++ b/src/modules/extra/m_pgsql.cpp @@ -763,25 +763,18 @@ class ModulePgSQL : public Module unsigned long currid; char* sqlsuccess; ReconnectTimer* retimer; - + ServiceProvider sqlserv; public: ModulePgSQL() - : currid(0) + : currid(0), sqlserv(this, "SQL/pgsql", SERVICE_DATA) { - ServerInstance->Modules->UseInterface("SQLutils"); - sqlsuccess = new char[strlen(SQLSUCCESS)+1]; strlcpy(sqlsuccess, SQLSUCCESS, strlen(SQLSUCCESS)); - if (!ServerInstance->Modules->PublishFeature("SQL", this)) - { - throw ModuleException("BUG: PgSQL Unable to publish feature 'SQL'"); - } - ReadConf(); - ServerInstance->Modules->PublishInterface("SQL", this); + ServerInstance->Modules->AddService(sqlserv); Implementation eventlist[] = { I_OnUnloadModule, I_OnRehash }; ServerInstance->Modules->Attach(eventlist, this, 2); } @@ -792,9 +785,6 @@ class ModulePgSQL : public Module ServerInstance->Timers->DelTimer(retimer); ClearAllConnections(); delete[] sqlsuccess; - ServerInstance->Modules->UnpublishInterface("SQL", this); - ServerInstance->Modules->UnpublishFeature("SQL"); - ServerInstance->Modules->DoneWithInterface("SQLutils"); } diff --git a/src/modules/extra/m_regex_pcre.cpp b/src/modules/extra/m_regex_pcre.cpp index 9e8aff159..c286162e8 100644 --- a/src/modules/extra/m_regex_pcre.cpp +++ b/src/modules/extra/m_regex_pcre.cpp @@ -67,35 +67,27 @@ public: } }; -class ModuleRegexPCRE : public Module +class PCREFactory : public RegexFactory { -public: - ModuleRegexPCRE() { - ServerInstance->Modules->PublishInterface("RegularExpression", this); - } - - virtual Version GetVersion() + public: + PCREFactory(Module* m) : RegexFactory(m, "regex/pcre") {} + Regex* Create(const std::string& expr) { - return Version("Regex Provider Module for PCRE", VF_COMMON | VF_VENDOR); + return new PCRERegex(expr); } +}; - virtual ~ModuleRegexPCRE() - { - ServerInstance->Modules->UnpublishInterface("RegularExpression", this); +class ModuleRegexPCRE : public Module +{ +public: + PCREFactory ref; + ModuleRegexPCRE() : ref(this) { + ServerInstance->Modules->AddService(ref); } - void OnRequest(Request& request) + Version GetVersion() { - if (strcmp("REGEX-NAME", request.id) == 0) - { - static_cast(request).result = "pcre"; - } - else if (strcmp("REGEX", request.id) == 0) - { - RegexFactoryRequest& rfr = (RegexFactoryRequest&)request; - std::string rx = rfr.GetRegex(); - rfr.result = new PCRERegex(rx); - } + return Version("Regex Provider Module for PCRE", VF_OPTCOMMON | VF_VENDOR); } }; diff --git a/src/modules/extra/m_regex_posix.cpp b/src/modules/extra/m_regex_posix.cpp index ea016ae64..837f2ac1f 100644 --- a/src/modules/extra/m_regex_posix.cpp +++ b/src/modules/extra/m_regex_posix.cpp @@ -71,46 +71,37 @@ public: } }; -class ModuleRegexPOSIX : public Module +class PosixFactory : public RegexFactory { -private: + public: bool extended; + PosixFactory(Module* m) : RegexFactory(m, "regex/posix") {} + Regex* Create(const std::string& expr) + { + return new POSIXRegex(expr, extended); + } +}; + +class ModuleRegexPOSIX : public Module +{ + PosixFactory ref; public: - ModuleRegexPOSIX() { - ServerInstance->Modules->PublishInterface("RegularExpression", this); + ModuleRegexPOSIX() : ref(this) { + ServerInstance->Modules->AddService(ref); Implementation eventlist[] = { I_OnRehash }; ServerInstance->Modules->Attach(eventlist, this, 1); OnRehash(NULL); } - virtual Version GetVersion() + Version GetVersion() { return Version("Regex Provider Module for POSIX Regular Expressions", VF_COMMON | VF_VENDOR); } - virtual ~ModuleRegexPOSIX() - { - ServerInstance->Modules->UnpublishInterface("RegularExpression", this); - } - - virtual void OnRehash(User* u) + void OnRehash(User* u) { ConfigReader Conf; - extended = Conf.ReadFlag("posix", "extended", 0); - } - - void OnRequest(Request& request) - { - if (strcmp("REGEX-NAME", request.id) == 0) - { - static_cast(request).result = "posix"; - } - else if (strcmp("REGEX", request.id) == 0) - { - RegexFactoryRequest& rfr = (RegexFactoryRequest&)request; - std::string rx = rfr.GetRegex(); - rfr.result = new POSIXRegex(rx, extended); - } + ref.extended = Conf.ReadFlag("posix", "extended", 0); } }; diff --git a/src/modules/extra/m_regex_tre.cpp b/src/modules/extra/m_regex_tre.cpp index 01c6ebf4a..5a208ec8a 100644 --- a/src/modules/extra/m_regex_tre.cpp +++ b/src/modules/extra/m_regex_tre.cpp @@ -73,35 +73,30 @@ public: } }; +class TREFactory : public RegexFactory { + public: + TREFactory(Module* m) : RegexFactory(m, "regex/tre") {} + Regex* Create(const std::string& expr) + { + return new TRERegex(expr); + } +}; + class ModuleRegexTRE : public Module { + TREFactory trf; public: - ModuleRegexTRE() { - ServerInstance->Modules->PublishInterface("RegularExpression", this); + ModuleRegexTRE() : trf(this) { + ServerInstance->Modules->AddService(trf); } - virtual Version GetVersion() + Version GetVersion() { return Version("Regex Provider Module for TRE Regular Expressions", VF_COMMON | VF_VENDOR); } - virtual ~ModuleRegexTRE() + ~ModuleRegexTRE() { - ServerInstance->Modules->UnpublishInterface("RegularExpression", this); - } - - void OnRequest(Request& request) - { - if (strcmp("REGEX-NAME", request.id) == 0) - { - static_cast(request).result = "tre"; - } - else if (strcmp("REGEX", request.id) == 0) - { - RegexFactoryRequest& rfr = (RegexFactoryRequest&)request; - std::string rx = rfr.GetRegex(); - rfr.result = new TRERegex(rx); - } } }; diff --git a/src/modules/extra/m_sqlite3.cpp b/src/modules/extra/m_sqlite3.cpp index e5693b61f..58a33c510 100644 --- a/src/modules/extra/m_sqlite3.cpp +++ b/src/modules/extra/m_sqlite3.cpp @@ -446,21 +446,15 @@ class ModuleSQLite3 : public Module private: ConnMap connections; unsigned long currid; + ServiceProvider sqlserv; public: ModuleSQLite3() - : currid(0) + : currid(0), sqlserv(this, "SQL/sqlite", SERVICE_DATA) { - ServerInstance->Modules->UseInterface("SQLutils"); - - if (!ServerInstance->Modules->PublishFeature("SQL", this)) - { - throw ModuleException("m_sqlite3: Unable to publish feature 'SQL'"); - } ReadConf(); - ServerInstance->Modules->PublishInterface("SQL", this); Implementation eventlist[] = { I_OnRehash }; ServerInstance->Modules->Attach(eventlist, this, 1); } @@ -469,10 +463,6 @@ class ModuleSQLite3 : public Module { ClearQueue(); ClearAllConnections(); - - ServerInstance->Modules->UnpublishInterface("SQL", this); - ServerInstance->Modules->UnpublishFeature("SQL"); - ServerInstance->Modules->DoneWithInterface("SQLutils"); } void ClearQueue() diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp index 8ec787465..7ba611547 100644 --- a/src/modules/extra/m_ssl_gnutls.cpp +++ b/src/modules/extra/m_ssl_gnutls.cpp @@ -137,13 +137,12 @@ class ModuleSSLGnuTLS : public Module CommandStartTLS starttls; GenericCap capHandler; + ServiceProvider iohook; public: ModuleSSLGnuTLS() - : starttls(this), capHandler(this, "tls") + : starttls(this), capHandler(this, "tls"), iohook(this, "ssl/gnutls", SERVICE_IOHOOK) { - ServerInstance->Modules->PublishInterface("BufferedSocketHook", this); - sessions = new issl_session[ServerInstance->SE->GetMaxFds()]; gnutls_global_init(); // This must be called once in the program @@ -160,6 +159,7 @@ class ModuleSSLGnuTLS : public Module I_OnEvent, I_OnHookIO }; ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation)); + ServerInstance->Modules->AddService(iohook); ServerInstance->AddCommand(&starttls); } @@ -286,7 +286,6 @@ class ModuleSSLGnuTLS : public Module gnutls_dh_params_deinit(dh_params); gnutls_certificate_free_credentials(x509_cred); gnutls_global_deinit(); - ServerInstance->Modules->UnpublishInterface("BufferedSocketHook", this); delete[] sessions; } diff --git a/src/modules/extra/m_ssl_openssl.cpp b/src/modules/extra/m_ssl_openssl.cpp index 03c460be2..7524c0d07 100644 --- a/src/modules/extra/m_ssl_openssl.cpp +++ b/src/modules/extra/m_ssl_openssl.cpp @@ -97,11 +97,11 @@ class ModuleSSLOpenSSL : public Module std::string dhfile; std::string sslports; + ServiceProvider iohook; public: - ModuleSSLOpenSSL() + ModuleSSLOpenSSL() : iohook(this, "ssl/openssl", SERVICE_IOHOOK) { - ServerInstance->Modules->PublishInterface("BufferedSocketHook", this); sessions = new issl_session[ServerInstance->SE->GetMaxFds()]; @@ -128,6 +128,7 @@ class ModuleSSLOpenSSL : public Module OnModuleRehash(NULL,"ssl"); Implementation eventlist[] = { I_On005Numeric, I_OnRehash, I_OnModuleRehash, I_OnHookIO, I_OnUserConnect }; ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation)); + ServerInstance->Modules->AddService(iohook); } void OnHookIO(StreamSocket* user, ListenSocket* lsb) @@ -241,7 +242,6 @@ class ModuleSSLOpenSSL : public Module { SSL_CTX_free(ctx); SSL_CTX_free(clictx); - ServerInstance->Modules->UnpublishInterface("BufferedSocketHook", this); delete[] sessions; } diff --git a/src/modules/extra/m_ziplink.cpp b/src/modules/extra/m_ziplink.cpp index 2aeb4b9e6..2ac358769 100644 --- a/src/modules/extra/m_ziplink.cpp +++ b/src/modules/extra/m_ziplink.cpp @@ -56,8 +56,6 @@ class ModuleZLib : public Module ModuleZLib() { - ServerInstance->Modules->PublishInterface("BufferedSocketHook", this); - sessions = new izip_session[ServerInstance->SE->GetMaxFds()]; for (int i = 0; i < ServerInstance->SE->GetMaxFds(); i++) sessions[i].status = IZIP_CLOSED; @@ -74,7 +72,6 @@ class ModuleZLib : public Module ~ModuleZLib() { - ServerInstance->Modules->UnpublishInterface("BufferedSocketHook", this); delete[] sessions; delete[] net_buffer; } diff --git a/src/modules/m_chanfilter.cpp b/src/modules/m_chanfilter.cpp index a466978e3..5bb5a91b0 100644 --- a/src/modules/m_chanfilter.cpp +++ b/src/modules/m_chanfilter.cpp @@ -72,7 +72,6 @@ class ModuleChanFilter : public Module ServerInstance->Modules->Attach(eventlist, this, 4); OnRehash(NULL); - ServerInstance->Modules->PublishInterface("ChannelBanList", this); } virtual void OnRehash(User* user) @@ -141,7 +140,6 @@ class ModuleChanFilter : public Module virtual ~ModuleChanFilter() { - ServerInstance->Modules->UnpublishInterface("ChannelBanList", this); } }; diff --git a/src/modules/m_cloaking.cpp b/src/modules/m_cloaking.cpp index 0a4e58edf..c4cbbef21 100644 --- a/src/modules/m_cloaking.cpp +++ b/src/modules/m_cloaking.cpp @@ -116,29 +116,21 @@ class ModuleCloaking : public Module std::string key; unsigned int compatkey[4]; const char* xtab[4]; - Module* HashProvider; + dynamic_reference Hash; public: - ModuleCloaking() : cu(this) + ModuleCloaking() : cu(this), Hash(this, "hash/md5") { - /* Attempt to locate the md5 service provider, bail if we can't find it */ - HashProvider = ServerInstance->Modules->Find("m_md5.so"); - if (!HashProvider) - throw ModuleException("Can't find m_md5.so. Please load m_md5.so before m_cloaking.so."); - OnRehash(NULL); /* Register it with the core */ if (!ServerInstance->Modes->AddMode(&cu)) throw ModuleException("Could not add new modes!"); - ServerInstance->Modules->UseInterface("HashRequest"); ServerInstance->Extensions.Register(&cu.ext); Implementation eventlist[] = { I_OnRehash, I_OnCheckBan, I_OnUserConnect }; ServerInstance->Modules->Attach(eventlist, this, 3); - - CloakExistingUsers(); } /** This function takes a domain name string and returns just the last two domain parts, @@ -195,8 +187,7 @@ class ModuleCloaking : public Module /* Send the Hash module a different hex table for each octet group's Hash sum */ for (int k = 0; k < 4; k++) { - HashRequestIV hash(this, HashProvider, compatkey, xtab[(compatkey[k]+i[k]) % 4], octet[k]); - rv.append(hash.result.substr(0,6)); + rv.append(Hash->sumIV(compatkey, xtab[(compatkey[k]+i[k]) % 4], octet[k]).substr(0,6)); if (k < 3) rv.append("."); } @@ -217,16 +208,14 @@ class ModuleCloaking : public Module item += *input; if (item.length() > 7) { - HashRequestIV hash(this, HashProvider, compatkey, xtab[(compatkey[1]+rounds) % 4], item); - hashies.push_back(hash.result.substr(0,8)); + hashies.push_back(Hash->sumIV(compatkey, xtab[(compatkey[1]+rounds) % 4], item).substr(0,8)); item.clear(); } rounds++; } if (!item.empty()) { - HashRequestIV hash(this, HashProvider, compatkey, xtab[(compatkey[1]+rounds) % 4], item); - hashies.push_back(hash.result.substr(0,8)); + hashies.push_back(Hash->sumIV(compatkey, xtab[(compatkey[1]+rounds) % 4], item).substr(0,8)); } /* Stick them all together */ return irc::stringjoiner(":", hashies, 0, hashies.size() - 1).GetJoined(); @@ -301,8 +290,7 @@ class ModuleCloaking : public Module input.append(1, 0); // null does not terminate a C++ string input.append(item); - HashRequest hash(this, HashProvider, input); - std::string rv = hash.binresult.substr(0,6); + std::string rv = Hash->sum(input).substr(0,6); for(int i=0; i < 6; i++) { // this discards 3 bits per byte. We have an @@ -313,26 +301,18 @@ class ModuleCloaking : public Module return rv; } - void CloakExistingUsers() - { - std::string* cloak; - for (std::vector::iterator u = ServerInstance->Users->local_users.begin(); u != ServerInstance->Users->local_users.end(); u++) - { - cloak = cu.ext.get(*u); - if (!cloak) - { - OnUserConnect(*u); - } - } - } - ModResult OnCheckBan(User* user, Channel* chan, const std::string& mask) { - char cmask[MAXBUF]; + LocalUser* lu = IS_LOCAL(user); + if (!lu) + return MOD_RES_PASSTHRU; + + OnUserConnect(lu); std::string* cloak = cu.ext.get(user); /* Check if they have a cloaked host, but are not using it */ if (cloak && *cloak != user->dhost) { + char cmask[MAXBUF]; snprintf(cmask, MAXBUF, "%s!%s@%s", user->nick.c_str(), user->ident.c_str(), cloak->c_str()); if (InspIRCd::Match(cmask,mask)) return MOD_RES_DENY; @@ -348,7 +328,6 @@ class ModuleCloaking : public Module ~ModuleCloaking() { - ServerInstance->Modules->DoneWithInterface("HashRequest"); } Version GetVersion() @@ -455,11 +434,8 @@ class ModuleCloaking : public Module { std::string tail = LastTwoDomainParts(dest->host); - /** Reset the Hash module, and send it our IV and hex table */ - HashRequestIV hash(this, HashProvider, compatkey, xtab[(dest->host[0]) % 4], dest->host); - /* Generate a cloak using specialized Hash */ - chost = prefix + "-" + hash.result.substr(0,8) + tail; + chost = prefix + "-" + Hash->sumIV(compatkey, xtab[(dest->host[0]) % 4], dest->host).substr(0,8) + tail; /* Fix by brain - if the cloaked host is > the max length of a host (64 bytes * according to the DNS RFC) then they get cloaked as an IP. diff --git a/src/modules/m_exemptchanops.cpp b/src/modules/m_exemptchanops.cpp index 9e6b735ed..8b3fbf074 100644 --- a/src/modules/m_exemptchanops.cpp +++ b/src/modules/m_exemptchanops.cpp @@ -73,7 +73,6 @@ class ModuleExemptChanOps : public Module ServerInstance->Modules->Attach(eventlist, this, 4); OnRehash(NULL); - ServerInstance->Modules->PublishInterface("ChannelBanList", this); } virtual Version GetVersion() @@ -120,11 +119,6 @@ class ModuleExemptChanOps : public Module return MOD_RES_PASSTHRU; } - - virtual ~ModuleExemptChanOps() - { - ServerInstance->Modules->UnpublishInterface("ChannelBanList", this); - } }; MODULE_INIT(ModuleExemptChanOps) diff --git a/src/modules/m_filter.cpp b/src/modules/m_filter.cpp index 0220a3a44..55ef734ba 100644 --- a/src/modules/m_filter.cpp +++ b/src/modules/m_filter.cpp @@ -17,8 +17,7 @@ /* $ModDesc: Text (spam) filtering */ -static std::string RegexEngine = ""; -static Module* rxengine = NULL; +class ModuleFilter; enum FilterFlags { @@ -90,19 +89,16 @@ class FilterResult { } - virtual ~FilterResult() + ~FilterResult() { } }; -class FilterBase; - class CommandFilter : public Command { - FilterBase* Base; public: - CommandFilter(FilterBase* f) - : Command(reinterpret_cast(f), "FILTER", 1, 5), Base(f) + CommandFilter(Module* f) + : Command(f, "FILTER", 1, 5) { flags_needed = 'o'; this->syntax = " [] :"; @@ -120,33 +116,48 @@ class CommandFilter : public Command } }; -class FilterBase : public Module +class ImplFilter : public FilterResult { + public: + Regex* regex; + + ImplFilter(ModuleFilter* mymodule, const std::string &rea, const std::string &act, long glinetime, const std::string &pat, const std::string &flgs); +}; + + +class ModuleFilter : public Module +{ + public: CommandFilter filtcommand; + dynamic_reference RegexEngine; + + std::vector filters; + const char *error; + int erroffset; int flags; -protected: + std::vector exemptfromfilter; // List of channel names excluded from filtering. - public: - FilterBase(); - virtual ~FilterBase(); - virtual ModResult OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list); - virtual FilterResult* FilterMatch(User* user, const std::string &text, int flags) = 0; - virtual bool DeleteFilter(const std::string &freeform) = 0; - virtual void SyncFilters(Module* proto, void* opaque) = 0; - virtual void SendFilter(Module* proto, void* opaque, FilterResult* iter); - virtual std::pair AddFilter(const std::string &freeform, const std::string &type, const std::string &reason, long duration, const std::string &flags) = 0; - virtual ModResult OnUserPreNotice(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list); - virtual void OnRehash(User* user); - virtual Version GetVersion(); + + ModuleFilter(); + + ~ModuleFilter(); + ModResult OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list); + FilterResult* FilterMatch(User* user, const std::string &text, int flags); + bool DeleteFilter(const std::string &freeform); + void SyncFilters(Module* proto, void* opaque); + void SendFilter(Module* proto, void* opaque, FilterResult* iter); + std::pair AddFilter(const std::string &freeform, const std::string &type, const std::string &reason, long duration, const std::string &flags); + ModResult OnUserPreNotice(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list); + void OnRehash(User* user); + Version GetVersion(); std::string EncodeFilter(FilterResult* filter); FilterResult DecodeFilter(const std::string &data); - virtual void OnSyncNetwork(Module* proto, void* opaque); - virtual void OnDecodeMetaData(Extensible* target, const std::string &extname, const std::string &extdata); - virtual ModResult OnStats(char symbol, User* user, string_list &results) = 0; - virtual ModResult OnPreCommand(std::string &command, std::vector ¶meters, User *user, bool validated, const std::string &original_line); + void OnSyncNetwork(Module* proto, void* opaque); + void OnDecodeMetaData(Extensible* target, const std::string &extname, const std::string &extdata); + ModResult OnStats(char symbol, User* user, string_list &results); + ModResult OnPreCommand(std::string &command, std::vector ¶meters, User *user, bool validated, const std::string &original_line); bool AppliesToMe(User* user, FilterResult* filter, int flags); - void OnLoadModule(Module* mod); - virtual void ReadFilters(ConfigReader &MyConf) = 0; + void ReadFilters(ConfigReader &MyConf); }; CmdResult CommandFilter::Handle(const std::vector ¶meters, User *user) @@ -154,7 +165,7 @@ CmdResult CommandFilter::Handle(const std::vector ¶meters, User if (parameters.size() == 1) { /* Deleting a filter */ - if (Base->DeleteFilter(parameters[0])) + if (static_cast(*creator).DeleteFilter(parameters[0])) { user->WriteServ("NOTICE %s :*** Removed filter '%s'", user->nick.c_str(), parameters[0].c_str()); ServerInstance->SNO->WriteToSnoMask(IS_LOCAL(user) ? 'a' : 'A', std::string("FILTER: ")+user->nick+" removed filter '"+parameters[0]+"'"); @@ -201,7 +212,7 @@ CmdResult CommandFilter::Handle(const std::vector ¶meters, User { reason = parameters[3]; } - std::pair result = Base->AddFilter(freeform, type, reason, duration, flags); + std::pair result = static_cast(*creator).AddFilter(freeform, type, reason, duration, flags); if (result.first) { user->WriteServ("NOTICE %s :*** Added filter '%s', type '%s'%s%s, flags '%s', reason: '%s'", user->nick.c_str(), freeform.c_str(), @@ -227,7 +238,7 @@ CmdResult CommandFilter::Handle(const std::vector ¶meters, User } } -bool FilterBase::AppliesToMe(User* user, FilterResult* filter, int iflags) +bool ModuleFilter::AppliesToMe(User* user, FilterResult* filter, int iflags) { if ((filter->flag_no_opers) && IS_OPER(user)) return false; @@ -242,20 +253,19 @@ bool FilterBase::AppliesToMe(User* user, FilterResult* filter, int iflags) return true; } -FilterBase::FilterBase() : filtcommand(this) +ModuleFilter::ModuleFilter() : filtcommand(this), RegexEngine(this, "regex") { - ServerInstance->Modules->UseInterface("RegularExpression"); ServerInstance->AddCommand(&filtcommand); - Implementation eventlist[] = { I_OnPreCommand, I_OnStats, I_OnSyncNetwork, I_OnDecodeMetaData, I_OnUserPreMessage, I_OnUserPreNotice, I_OnRehash, I_OnLoadModule }; - ServerInstance->Modules->Attach(eventlist, this, 8); + Implementation eventlist[] = { I_OnPreCommand, I_OnStats, I_OnSyncNetwork, I_OnDecodeMetaData, I_OnUserPreMessage, I_OnUserPreNotice, I_OnRehash }; + ServerInstance->Modules->Attach(eventlist, this, 7); + OnRehash(NULL); } -FilterBase::~FilterBase() +ModuleFilter::~ModuleFilter() { - ServerInstance->Modules->DoneWithInterface("RegularExpression"); } -ModResult FilterBase::OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list) +ModResult ModuleFilter::OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list) { if (!IS_LOCAL(user)) return MOD_RES_PASSTHRU; @@ -264,7 +274,7 @@ ModResult FilterBase::OnUserPreMessage(User* user,void* dest,int target_type, st return OnUserPreNotice(user,dest,target_type,text,status,exempt_list); } -ModResult FilterBase::OnUserPreNotice(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list) +ModResult ModuleFilter::OnUserPreNotice(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list) { /* Leave ulines alone */ if ((ServerInstance->ULine(user->server)) || (!IS_LOCAL(user))) @@ -325,7 +335,7 @@ ModResult FilterBase::OnUserPreNotice(User* user,void* dest,int target_type, std return MOD_RES_PASSTHRU; } -ModResult FilterBase::OnPreCommand(std::string &command, std::vector ¶meters, User *user, bool validated, const std::string &original_line) +ModResult ModuleFilter::OnPreCommand(std::string &command, std::vector ¶meters, User *user, bool validated, const std::string &original_line) { flags = 0; if (validated && IS_LOCAL(user)) @@ -415,7 +425,7 @@ ModResult FilterBase::OnPreCommand(std::string &command, std::vector().swap(exemptfromfilter); @@ -426,62 +436,28 @@ void FilterBase::OnRehash(User* user) exemptfromfilter.push_back(chan); } } - std::string newrxengine = MyConf.ReadValue("filteropts", "engine", 0); - if (!RegexEngine.empty()) - { - if (RegexEngine == newrxengine) - return; - - ServerInstance->SNO->WriteGlobalSno('a', "Dumping all filters due to regex engine change (was '%s', now '%s')", RegexEngine.c_str(), newrxengine.c_str()); - //ServerInstance->XLines->DelAll("R"); - } - rxengine = NULL; + std::string newrxengine = "regex/" + MyConf.ReadValue("filteropts", "engine", 0); + if (RegexEngine.GetProvider() == newrxengine) + return; - RegexEngine = newrxengine; - modulelist* ml = ServerInstance->Modules->FindInterface("RegularExpression"); - if (ml) - { - for (modulelist::iterator i = ml->begin(); i != ml->end(); ++i) - { - if (RegexNameRequest(this, *i).result == newrxengine) - { - ServerInstance->SNO->WriteGlobalSno('a', "Filter now using engine '%s'", RegexEngine.c_str()); - rxengine = *i; - } - } - } - if (!rxengine) - { - ServerInstance->SNO->WriteGlobalSno('a', "WARNING: Regex engine '%s' is not loaded - Filter functionality disabled until this is corrected.", RegexEngine.c_str()); - } -} + //ServerInstance->SNO->WriteGlobalSno('a', "Dumping all filters due to regex engine change (was '%s', now '%s')", RegexEngine.GetProvider().c_str(), newrxengine.c_str()); + //ServerInstance->XLines->DelAll("R"); -void FilterBase::OnLoadModule(Module* mod) -{ - if (ServerInstance->Modules->ModuleHasInterface(mod, "RegularExpression")) + RegexEngine.SetProvider(newrxengine); + if (!RegexEngine) { - std::string rxname = RegexNameRequest(this, mod).result; - if (rxname == RegexEngine) - { - rxengine = mod; - /* Force a rehash to make sure that any filters that couldnt be applied from the conf - * on startup or on load are applied right now. - */ - ConfigReader Config; - ServerInstance->SNO->WriteGlobalSno('a', "Found and activated regex module '%s' for m_filter.so.", RegexEngine.c_str()); - ReadFilters(Config); - } + ServerInstance->SNO->WriteGlobalSno('a', "WARNING: Regex engine '%s' is not loaded - Filter functionality disabled until this is corrected.", RegexEngine.GetProvider().c_str()); } + ReadFilters(MyConf); } - -Version FilterBase::GetVersion() +Version ModuleFilter::GetVersion() { return Version("Text (spam) filtering", VF_VENDOR | VF_COMMON); } -std::string FilterBase::EncodeFilter(FilterResult* filter) +std::string ModuleFilter::EncodeFilter(FilterResult* filter) { std::ostringstream stream; std::string x = filter->freeform; @@ -495,7 +471,7 @@ std::string FilterBase::EncodeFilter(FilterResult* filter) return stream.str(); } -FilterResult FilterBase::DecodeFilter(const std::string &data) +FilterResult ModuleFilter::DecodeFilter(const std::string &data) { FilterResult res; irc::tokenstream tokens(data); @@ -516,17 +492,17 @@ FilterResult FilterBase::DecodeFilter(const std::string &data) return res; } -void FilterBase::OnSyncNetwork(Module* proto, void* opaque) +void ModuleFilter::OnSyncNetwork(Module* proto, void* opaque) { this->SyncFilters(proto, opaque); } -void FilterBase::SendFilter(Module* proto, void* opaque, FilterResult* iter) +void ModuleFilter::SendFilter(Module* proto, void* opaque, FilterResult* iter) { proto->ProtoSendMetaData(opaque, NULL, "filter", EncodeFilter(iter)); } -void FilterBase::OnDecodeMetaData(Extensible* target, const std::string &extname, const std::string &extdata) +void ModuleFilter::OnDecodeMetaData(Extensible* target, const std::string &extname, const std::string &extdata) { if ((target == NULL) && (extname == "filter")) { @@ -535,163 +511,127 @@ void FilterBase::OnDecodeMetaData(Extensible* target, const std::string &extname } } -class ImplFilter : public FilterResult +ImplFilter::ImplFilter(ModuleFilter* mymodule, const std::string &rea, const std::string &act, long glinetime, const std::string &pat, const std::string &flgs) + : FilterResult(pat, rea, act, glinetime, flgs) { - public: - Regex* regex; + if (!mymodule->RegexEngine) + throw ModuleException("Regex module implementing '"+mymodule->RegexEngine.GetProvider()+"' is not loaded!"); + regex = mymodule->RegexEngine->Create(pat); +} - ImplFilter(Module* mymodule, const std::string &rea, const std::string &act, long glinetime, const std::string &pat, const std::string &flgs) - : FilterResult(pat, rea, act, glinetime, flgs) +FilterResult* ModuleFilter::FilterMatch(User* user, const std::string &text, int flgs) +{ + for (std::vector::iterator index = filters.begin(); index != filters.end(); index++) { - if (!rxengine) - throw ModuleException("Regex module implementing '"+RegexEngine+"' is not loaded!"); - - regex = RegexFactoryRequest(mymodule, rxengine, pat).Create(); - } + /* Skip ones that dont apply to us */ + if (!AppliesToMe(user, dynamic_cast(&(*index)), flgs)) + continue; - ImplFilter() - { + //ServerInstance->Logs->Log("m_filter", DEBUG, "Match '%s' against '%s'", text.c_str(), index->freeform.c_str()); + if (index->regex->Matches(text)) + { + //ServerInstance->Logs->Log("m_filter", DEBUG, "MATCH"); + ImplFilter fr = *index; + if (index != filters.begin()) + { + /* Move to head of list for efficiency */ + filters.erase(index); + filters.insert(filters.begin(), fr); + } + return &*filters.begin(); + } + //ServerInstance->Logs->Log("m_filter", DEBUG, "NO MATCH"); } -}; + return NULL; +} -class ModuleFilter : public FilterBase +bool ModuleFilter::DeleteFilter(const std::string &freeform) { - std::vector filters; - const char *error; - int erroffset; - ImplFilter fr; - - public: - ModuleFilter() + for (std::vector::iterator i = filters.begin(); i != filters.end(); i++) { - OnRehash(NULL); + if (i->freeform == freeform) + { + delete i->regex; + filters.erase(i); + return true; + } } + return false; +} - virtual ~ModuleFilter() +void ModuleFilter::SyncFilters(Module* proto, void* opaque) +{ + for (std::vector::iterator i = filters.begin(); i != filters.end(); i++) { + this->SendFilter(proto, opaque, &(*i)); } +} - virtual FilterResult* FilterMatch(User* user, const std::string &text, int flgs) +std::pair ModuleFilter::AddFilter(const std::string &freeform, const std::string &type, const std::string &reason, long duration, const std::string &flgs) +{ + for (std::vector::iterator i = filters.begin(); i != filters.end(); i++) { - for (std::vector::iterator index = filters.begin(); index != filters.end(); index++) + if (i->freeform == freeform) { - /* Skip ones that dont apply to us */ - if (!FilterBase::AppliesToMe(user, dynamic_cast(&(*index)), flgs)) - continue; - - //ServerInstance->Logs->Log("m_filter", DEBUG, "Match '%s' against '%s'", text.c_str(), index->freeform.c_str()); - if (index->regex->Matches(text)) - { - //ServerInstance->Logs->Log("m_filter", DEBUG, "MATCH"); - fr = *index; - if (index != filters.begin()) - { - /* Move to head of list for efficiency */ - filters.erase(index); - filters.insert(filters.begin(), fr); - } - return &fr; - } - //ServerInstance->Logs->Log("m_filter", DEBUG, "NO MATCH"); + return std::make_pair(false, "Filter already exists"); } - return NULL; } - virtual bool DeleteFilter(const std::string &freeform) + try { - for (std::vector::iterator i = filters.begin(); i != filters.end(); i++) - { - if (i->freeform == freeform) - { - delete i->regex; - filters.erase(i); - return true; - } - } - return false; + filters.push_back(ImplFilter(this, reason, type, duration, freeform, flgs)); } - - virtual void SyncFilters(Module* proto, void* opaque) + catch (ModuleException &e) { - for (std::vector::iterator i = filters.begin(); i != filters.end(); i++) - { - this->SendFilter(proto, opaque, &(*i)); - } + ServerInstance->Logs->Log("m_filter", DEFAULT, "Error in regular expression '%s': %s", freeform.c_str(), e.GetReason()); + return std::make_pair(false, e.GetReason()); } + return std::make_pair(true, ""); +} - virtual std::pair AddFilter(const std::string &freeform, const std::string &type, const std::string &reason, long duration, const std::string &flgs) +void ModuleFilter::ReadFilters(ConfigReader &MyConf) +{ + for (int index = 0; index < MyConf.Enumerate("keyword"); index++) { - for (std::vector::iterator i = filters.begin(); i != filters.end(); i++) - { - if (i->freeform == freeform) - { - return std::make_pair(false, "Filter already exists"); - } - } + this->DeleteFilter(MyConf.ReadValue("keyword", "pattern", index)); + + std::string pattern = MyConf.ReadValue("keyword", "pattern", index); + std::string reason = MyConf.ReadValue("keyword", "reason", index); + std::string action = MyConf.ReadValue("keyword", "action", index); + std::string flgs = MyConf.ReadValue("keyword", "flags", index); + long gline_time = ServerInstance->Duration(MyConf.ReadValue("keyword", "duration", index)); + if (action.empty()) + action = "none"; + if (flgs.empty()) + flgs = "*"; try { - filters.push_back(ImplFilter(this, reason, type, duration, freeform, flgs)); + filters.push_back(ImplFilter(this, reason, action, gline_time, pattern, flgs)); + ServerInstance->Logs->Log("m_filter", DEFAULT, "Regular expression %s loaded.", pattern.c_str()); } catch (ModuleException &e) { - ServerInstance->Logs->Log("m_filter", DEFAULT, "Error in regular expression '%s': %s", freeform.c_str(), e.GetReason()); - return std::make_pair(false, e.GetReason()); + ServerInstance->Logs->Log("m_filter", DEFAULT, "Error in regular expression '%s': %s", pattern.c_str(), e.GetReason()); } - return std::make_pair(true, ""); - } - - virtual void OnRehash(User* user) - { - ConfigReader MyConf; - FilterBase::OnRehash(user); - ReadFilters(MyConf); } +} - void ReadFilters(ConfigReader &MyConf) +ModResult ModuleFilter::OnStats(char symbol, User* user, string_list &results) +{ + if (symbol == 's') { - for (int index = 0; index < MyConf.Enumerate("keyword"); index++) + std::string sn = ServerInstance->Config->ServerName; + for (std::vector::iterator i = filters.begin(); i != filters.end(); i++) { - this->DeleteFilter(MyConf.ReadValue("keyword", "pattern", index)); - - std::string pattern = MyConf.ReadValue("keyword", "pattern", index); - std::string reason = MyConf.ReadValue("keyword", "reason", index); - std::string action = MyConf.ReadValue("keyword", "action", index); - std::string flgs = MyConf.ReadValue("keyword", "flags", index); - long gline_time = ServerInstance->Duration(MyConf.ReadValue("keyword", "duration", index)); - if (action.empty()) - action = "none"; - if (flgs.empty()) - flgs = "*"; - - try - { - filters.push_back(ImplFilter(this, reason, action, gline_time, pattern, flgs)); - ServerInstance->Logs->Log("m_filter", DEFAULT, "Regular expression %s loaded.", pattern.c_str()); - } - catch (ModuleException &e) - { - ServerInstance->Logs->Log("m_filter", DEFAULT, "Error in regular expression '%s': %s", pattern.c_str(), e.GetReason()); - } + results.push_back(sn+" 223 "+user->nick+" :"+RegexEngine.GetProvider()+":"+i->freeform+" "+i->flags+" "+i->action+" "+ConvToStr(i->gline_time)+" :"+i->reason); } - } - - virtual ModResult OnStats(char symbol, User* user, string_list &results) - { - if (symbol == 's') + for (std::vector::iterator i = exemptfromfilter.begin(); i != exemptfromfilter.end(); ++i) { - std::string sn = ServerInstance->Config->ServerName; - for (std::vector::iterator i = filters.begin(); i != filters.end(); i++) - { - results.push_back(sn+" 223 "+user->nick+" :"+RegexEngine+":"+i->freeform+" "+i->flags+" "+i->action+" "+ConvToStr(i->gline_time)+" :"+i->reason); - } - for (std::vector::iterator i = exemptfromfilter.begin(); i != exemptfromfilter.end(); ++i) - { - results.push_back(sn+" 223 "+user->nick+" :EXEMPT "+(*i)); - } + results.push_back(sn+" 223 "+user->nick+" :EXEMPT "+(*i)); } - return MOD_RES_PASSTHRU; } -}; + return MOD_RES_PASSTHRU; +} MODULE_INIT(ModuleFilter) diff --git a/src/modules/m_hash.h b/src/modules/m_hash.h index 08a24eb85..385fff95e 100644 --- a/src/modules/m_hash.h +++ b/src/modules/m_hash.h @@ -19,75 +19,31 @@ #define SHA256_DIGEST_SIZE (256 / 8) #define SHA256_BLOCK_SIZE (512 / 8) -/** Query a hash algorithm's name - * - * Example: - * \code - * cout << "Using hash algorithm: " << HashNameRequest(this, HashModule).response; - * \endcode - */ -struct HashNameRequest : public Request +class HashProvider : public DataProvider { - std::string response; - HashNameRequest(Module* Me, Module* Target) : Request(Me, Target, "NAME") + public: + HashProvider(Module* mod, const std::string& Name) : DataProvider(mod, Name) {} + virtual std::string sum(const std::string& data) = 0; + inline std::string hexsum(const std::string& data) { - Send(); + return BinToHex(sum(data)); } -}; -/** Send this class to the hashing module to HashSUM a std::string. - * - * Example: - * \code - * // Get the Hash sum of the string 'doodads'. - * std::string result = HashRequest(this, HashModule, "doodads").result; - * \endcode - */ -struct HashRequest : public Request -{ - const std::string data; - std::string binresult; - /** Initialize HashSumRequest for sending. - * @param Me A pointer to the sending module - * @param Target A pointer to the hashing module - * @param data The data to be hashed + /** Allows the IVs for the hash to be specified. As the choice of initial IV is + * important for the security of a hash, this should not be used except to + * maintain backwards compatability. This also allows you to change the hex + * sequence from its default of "0123456789abcdef", which does not improve the + * strength of the output, but helps confuse those attempting to implement it. + * + * Only m_md5 implements this request; only m_cloaking should use it. + * + * Example: + * \code + * unsigned int iv[] = { 0xFFFFFFFF, 0x00000000, 0xAAAAAAAA, 0xCCCCCCCC }; + * std::string result = Hash.sumIV(iv, "0123456789abcdef", "data"); + * \endcode */ - HashRequest(Module* Me, Module* Target, const std::string &sdata) - : Request(Me, Target, "HASH"), data(sdata) - { - Send(); - } - inline std::string hex() - { - return BinToHex(binresult); - } -}; - -/** Allows the IVs for the hash to be specified. As the choice of initial IV is - * important for the security of a hash, this should not be used except to - * maintain backwards compatability. This also allows you to change the hex - * sequence from its default of "0123456789abcdef", which does not improve the - * strength of the output, but helps confuse those attempting to implement it. - * - * Only m_md5 implements this request; only m_cloaking should use it. - * - * Example: - * \code - * unsigned int iv[] = { 0xFFFFFFFF, 0x00000000, 0xAAAAAAAA, 0xCCCCCCCC }; - * std::string result = HashRequestIV(this, HashModule, iv, "0123456789abcdef", "data").result; - * \endcode - */ -struct HashRequestIV : public Request -{ - unsigned int* iv; - const char* map; - std::string result; - const std::string data; - HashRequestIV(Module* Me, Module* Target, unsigned int* IV, const char* HexMap, const std::string &sdata) - : Request(Me, Target, "HASH-IV"), iv(IV), map(HexMap), data(sdata) - { - Send(); - } + virtual std::string sumIV(unsigned int* IV, const char* HexMap, const std::string &sdata) = 0; }; #endif diff --git a/src/modules/m_md5.cpp b/src/modules/m_md5.cpp index 6ac9c3d87..6b74dae2e 100644 --- a/src/modules/m_md5.cpp +++ b/src/modules/m_md5.cpp @@ -47,7 +47,7 @@ class MD5Context word32 in[16]; }; -class ModuleMD5 : public Module +class MD5Provider : public HashProvider { void byteSwap(word32 *buf, unsigned words) { @@ -258,45 +258,36 @@ class ModuleMD5 : public Module } *dest++ = 0; } - public: - - ModuleMD5() + std::string sum(const std::string& data) { - ServerInstance->Modules->PublishInterface("HashRequest", this); + char res[16]; + MyMD5(res, (void*)data.data(), data.length(), NULL); + return std::string(res, 16); } - virtual ~ModuleMD5() + std::string sumIV(unsigned int* IV, const char* HexMap, const std::string &sdata) { - ServerInstance->Modules->UnpublishInterface("HashRequest", this); + char res[33]; + GenHash(sdata.data(), res, HexMap, IV, sdata.length()); + return res; } + MD5Provider(Module* parent) : HashProvider(parent, "hash/md5") {} +}; - void OnRequest(Request& request) +class ModuleMD5 : public Module +{ + MD5Provider md5; + public: + ModuleMD5() : md5(this) { - if (strcmp("HASH", request.id) == 0) - { - char res[16]; - HashRequest& req = static_cast(request); - MyMD5(res, (void*)req.data.data(), req.data.length(), NULL); - req.binresult.assign(res, 16); - } - else if (strcmp("HASH-IV", request.id) == 0) - { - char res[33]; - HashRequestIV& req = static_cast(request); - GenHash(req.data.data(), res, req.map, req.iv, req.data.length()); - req.result = res; - } - else if (strcmp("NAME", request.id) == 0) - { - static_cast(request).response = "md5"; - } + ServerInstance->Modules->AddService(md5); } Version GetVersion() { - return Version("Allows for MD5 encrypted oper passwords",VF_VENDOR); + return Version("Implements MD5 hashing",VF_VENDOR); } }; diff --git a/src/modules/m_password_hash.cpp b/src/modules/m_password_hash.cpp index 617983ec4..f064e9cf0 100644 --- a/src/modules/m_password_hash.cpp +++ b/src/modules/m_password_hash.cpp @@ -16,47 +16,36 @@ #include "inspircd.h" #include "m_hash.h" -typedef std::map hashymodules; - /* Handle /MKPASSWD */ class CommandMkpasswd : public Command { - hashymodules &hashers; - std::deque &names; public: - CommandMkpasswd(Module* Creator, hashymodules &h, std::deque &n) : Command(Creator, "MKPASSWD", 2), hashers(h), names(n) + CommandMkpasswd(Module* Creator) : Command(Creator, "MKPASSWD", 2) { syntax = " "; Penalty = 5; } - void MakeHash(User* user, const char* algo, const char* stuff) + void MakeHash(User* user, const std::string& algo, const std::string& stuff) { - /* Lets see if they gave us an algorithm which has been implemented */ - hashymodules::iterator x = hashers.find(algo); - if (x != hashers.end()) + HashProvider* hp = ServerInstance->Modules->FindDataService("hash/" + algo); + if (hp) { - HashRequest hash(creator, x->second, stuff); /* Now attempt to generate a hash */ user->WriteServ("NOTICE %s :%s hashed password for %s is %s", - user->nick.c_str(), algo, stuff, hash.hex().c_str()); - } - else if (names.empty()) - { - /* same idea as bug #569 */ - user->WriteServ("NOTICE %s :No hash provider modules are loaded", user->nick.c_str()); + user->nick.c_str(), algo.c_str(), stuff.c_str(), hp->hexsum(stuff).c_str()); } else { /* I dont do flying, bob. */ - user->WriteServ("NOTICE %s :Unknown hash type, valid hash types are: %s", user->nick.c_str(), irc::stringjoiner(", ", names, 0, names.size() - 1).GetJoined().c_str() ); + user->WriteServ("NOTICE %s :Unknown hash type", user->nick.c_str()); } } CmdResult Handle (const std::vector& parameters, User *user) { - MakeHash(user, parameters[0].c_str(), parameters[1].c_str()); + MakeHash(user, parameters[0], parameters[1]); return CMD_SUCCESS; } @@ -64,84 +53,31 @@ class CommandMkpasswd : public Command class ModuleOperHash : public Module { - CommandMkpasswd cmd; - hashymodules hashers; /* List of modules which implement HashRequest */ - std::deque names; /* Module names which implement HashRequest */ - - bool diduseiface; /* If we've called UseInterface yet. */ public: - ModuleOperHash() - : cmd(this, hashers, names) + ModuleOperHash() : cmd(this) { - diduseiface = false; - /* Read the config file first */ -// Conf = NULL; OnRehash(NULL); - /* Find all modules which implement the interface 'HashRequest' */ - modulelist* ml = ServerInstance->Modules->FindInterface("HashRequest"); - - /* Did we find any modules? */ - if (ml) - { - /* Yes, enumerate them all to find out the hashing algorithm name */ - for (modulelist::iterator m = ml->begin(); m != ml->end(); m++) - { - /* Make a request to it for its name, its implementing - * HashRequest so we know its safe to do this - */ - std::string name = HashNameRequest(this, *m).response; - /* Build a map of them */ - hashers[name.c_str()] = *m; - names.push_back(name); - } - /* UseInterface doesn't do anything if there are no providers, so we'll have to call it later if a module gets loaded later on. */ - ServerInstance->Modules->UseInterface("HashRequest"); - diduseiface = true; - } - ServerInstance->AddCommand(&cmd); - Implementation eventlist[] = { I_OnPassCompare, I_OnLoadModule }; - ServerInstance->Modules->Attach(eventlist, this, 2); - } - - virtual ~ModuleOperHash() - { - if (diduseiface) ServerInstance->Modules->DoneWithInterface("HashRequest"); - } - - - virtual void OnLoadModule(Module* mod) - { - if (ServerInstance->Modules->ModuleHasInterface(mod, "HashRequest")) - { - std::string sname = HashNameRequest(this, mod).response; - hashers[sname.c_str()] = mod; - names.push_back(sname); - if (!diduseiface) - { - ServerInstance->Modules->UseInterface("HashRequest"); - diduseiface = true; - } - } + Implementation eventlist[] = { I_OnPassCompare }; + ServerInstance->Modules->Attach(eventlist, this, 1); } virtual ModResult OnPassCompare(Extensible* ex, const std::string &data, const std::string &input, const std::string &hashtype) { - /* First, lets see what hash theyre using on this oper */ - hashymodules::iterator x = hashers.find(hashtype.c_str()); + HashProvider* hp = ServerInstance->Modules->FindDataService("hash/" + hashtype); - /* Is this a valid hash name? (case insensitive) */ - if (x != hashers.end()) + /* Is this a valid hash name? */ + if (hp) { /* Compare the hash in the config to the generated hash */ - if (!strcasecmp(data.c_str(), HashRequest(this, x->second, input).hex().c_str())) + if (data == hp->hexsum(input)) return MOD_RES_ALLOW; - /* No match, and must be hashed, forbid */ else + /* No match, and must be hashed, forbid */ return MOD_RES_DENY; } diff --git a/src/modules/m_regex.h b/src/modules/m_regex.h index 969c4920b..613ec2700 100644 --- a/src/modules/m_regex.h +++ b/src/modules/m_regex.h @@ -40,38 +40,12 @@ public: } }; -class RegexFactoryRequest : public Request +class RegexFactory : public DataProvider { -private: - std::string regex; + public: + RegexFactory(Module* Creator, const std::string& Name) : DataProvider(Creator, Name) {} -public: - Regex* result; - - RegexFactoryRequest(Module* Me, Module* Target, const std::string& rx) : Request(Me, Target, "REGEX"), regex(rx), result(NULL) - { - } - - const std::string& GetRegex() const - { - return regex; - } - - Regex* Create() - { - Send(); - return this->result; - } -}; - -class RegexNameRequest : public Request -{ -public: - std::string result; - RegexNameRequest(Module* Me, Module* Target) : Request(Me, Target, "REGEX-NAME") - { - Send(); - } + virtual Regex* Create(const std::string& expr) = 0; }; #endif diff --git a/src/modules/m_regex_glob.cpp b/src/modules/m_regex_glob.cpp index 42cc0abd1..75d77a267 100644 --- a/src/modules/m_regex_glob.cpp +++ b/src/modules/m_regex_glob.cpp @@ -33,35 +33,28 @@ public: } }; -class ModuleRegexGlob : public Module +class GlobFactory : public RegexFactory { -public: - ModuleRegexGlob() { - ServerInstance->Modules->PublishInterface("RegularExpression", this); - } - - virtual Version GetVersion() + public: + Regex* Create(const std::string& expr) { - return Version("Regex module using plain wildcard matching.", VF_OPTCOMMON | VF_VENDOR); + return new GlobRegex(expr); } - virtual ~ModuleRegexGlob() - { - ServerInstance->Modules->UnpublishInterface("RegularExpression", this); + GlobFactory(Module* m) : RegexFactory(m, "regex/glob") {} +}; + +class ModuleRegexGlob : public Module +{ + GlobFactory gf; +public: + ModuleRegexGlob() : gf(this) { + ServerInstance->Modules->AddService(gf); } - void OnRequest(Request& request) + Version GetVersion() { - if (strcmp("REGEX-NAME", request.id) == 0) - { - static_cast(request).result = "glob"; - } - else if (strcmp("REGEX", request.id) == 0) - { - RegexFactoryRequest& rfr = (RegexFactoryRequest&)request; - std::string rx = rfr.GetRegex(); - rfr.result = new GlobRegex(rx); - } + return Version("Regex module using plain wildcard matching.", VF_OPTCOMMON | VF_VENDOR); } }; diff --git a/src/modules/m_ripemd160.cpp b/src/modules/m_ripemd160.cpp index 03a7f9895..6bd9a059a 100644 --- a/src/modules/m_ripemd160.cpp +++ b/src/modules/m_ripemd160.cpp @@ -149,7 +149,7 @@ typedef uint32_t dword; } -class ModuleRIPEMD160 : public Module +class RIProv : public HashProvider { void MDinit(dword *MDbuf, unsigned int* key) @@ -436,36 +436,33 @@ class ModuleRIPEMD160 : public Module return (byte *)hashcode; } - - public: - - ModuleRIPEMD160() +public: + std::string sum(const std::string& data) { - ServerInstance->Modules->PublishInterface("HashRequest", this); + char* rv = (char*)RMD((byte*)data.data(), data.length(), NULL); + return std::string(rv, RMDsize / 8); } - virtual ~ModuleRIPEMD160() + std::string sumIV(unsigned int* IV, const char* HexMap, const std::string &sdata) { - ServerInstance->Modules->UnpublishInterface("HashRequest", this); + return ""; } - void OnRequest(Request& request) + RIProv(Module* m) : HashProvider(m, "hash/ripemd160") {} +}; + +class ModuleRIPEMD160 : public Module +{ + public: + RIProv mr; + ModuleRIPEMD160() : mr(this) { - if (strcmp("HASH", request.id) == 0) - { - HashRequest& req = static_cast(request); - char* data = (char*)RMD((byte*)req.data.data(), req.data.length(), NULL); - req.binresult.assign(data, RMDsize / 8); - } - else if (strcmp("NAME", request.id) == 0) - { - static_cast(request).response = "ripemd160"; - } + ServerInstance->Modules->AddService(mr); } - virtual Version GetVersion() + Version GetVersion() { - return Version("Allows for RIPEMD-160 encrypted oper passwords", VF_VENDOR); + return Version("Provides RIPEMD-160 hashing", VF_VENDOR); } }; diff --git a/src/modules/m_rline.cpp b/src/modules/m_rline.cpp index 87a95a1ff..5d7415fb5 100644 --- a/src/modules/m_rline.cpp +++ b/src/modules/m_rline.cpp @@ -15,8 +15,6 @@ #include "m_regex.h" #include "xline.h" -static Module* rxengine = NULL; -static Module* mymodule = NULL; /* Needed to let RLine send request! */ static bool ZlineOnMatch = false; static std::vector background_zlines; @@ -34,21 +32,15 @@ class RLine : public XLine * @param regex Pattern to match with * @ */ - RLine(time_t s_time, long d, std::string src, std::string re, std::string regexs) + RLine(time_t s_time, long d, std::string src, std::string re, std::string regexs, dynamic_reference& rxfactory) : XLine(s_time, d, src, re, "R") { matchtext = regexs; - if (!rxengine) - { - ServerInstance->SNO->WriteToSnoMask('a', "Cannot create regexes until engine is set to a loaded provider!"); - throw ModuleException("Regex engine not set or loaded!"); - } - /* This can throw on failure, but if it does we DONT catch it here, we catch it and display it * where the object is created, we might not ALWAYS want it to output stuff to snomask x all the time */ - regex = RegexFactoryRequest(mymodule, rxengine, regexs).Create(); + regex = rxfactory->Create(regexs); } /** Destructor @@ -102,15 +94,22 @@ class RLine : public XLine class RLineFactory : public XLineFactory { public: - RLineFactory() : XLineFactory("R") + dynamic_reference& rxfactory; + RLineFactory(dynamic_reference& rx) : XLineFactory("R"), rxfactory(rx) { } - + /** Generate a RLine */ XLine* Generate(time_t set_time, long duration, std::string source, std::string reason, std::string xline_specific_mask) { - return new RLine(set_time, duration, source, reason, xline_specific_mask); + if (!rxfactory) + { + ServerInstance->SNO->WriteToSnoMask('a', "Cannot create regexes until engine is set to a loaded provider!"); + throw ModuleException("Regex engine not set or loaded!"); + } + + return new RLine(set_time, duration, source, reason, xline_specific_mask, rxfactory); } ~RLineFactory() @@ -124,9 +123,10 @@ class RLineFactory : public XLineFactory class CommandRLine : public Command { std::string rxengine; + RLineFactory& factory; public: - CommandRLine(Module* Creator) : Command(Creator,"RLINE", 1, 3) + CommandRLine(Module* Creator, RLineFactory& rlf) : Command(Creator,"RLINE", 1, 3), factory(rlf) { flags_needed = 'o'; this->syntax = " [] :"; } @@ -139,11 +139,11 @@ class CommandRLine : public Command // Adding - XXX todo make this respect tag perhaps.. long duration = ServerInstance->Duration(parameters[1]); - RLine *r = NULL; + XLine *r = NULL; try { - r = new RLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), parameters[0].c_str()); + r = factory.Generate(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), parameters[0].c_str()); } catch (ModuleException &e) { @@ -197,30 +197,26 @@ class CommandRLine : public Command class ModuleRLine : public Module { private: - CommandRLine r; + dynamic_reference rxfactory; RLineFactory f; + CommandRLine r; bool MatchOnNickChange; std::string RegexEngine; public: - ModuleRLine() : r(this) + ModuleRLine() : rxfactory(this, "regex"), f(rxfactory), r(this, f) { - mymodule = this; OnRehash(NULL); - ServerInstance->Modules->UseInterface("RegularExpression"); - ServerInstance->AddCommand(&r); ServerInstance->XLines->RegisterFactory(&f); - Implementation eventlist[] = { I_OnUserConnect, I_OnRehash, I_OnUserPostNick, I_OnLoadModule, I_OnStats, I_OnBackgroundTimer }; - ServerInstance->Modules->Attach(eventlist, this, 6); - + Implementation eventlist[] = { I_OnUserConnect, I_OnRehash, I_OnUserPostNick, I_OnStats, I_OnBackgroundTimer }; + ServerInstance->Modules->Attach(eventlist, this, 5); } virtual ~ModuleRLine() { - ServerInstance->Modules->DoneWithInterface("RegularExpression"); ServerInstance->XLines->DelAll("R"); ServerInstance->XLines->UnregisterFactory(&f); } @@ -253,29 +249,8 @@ class ModuleRLine : public Module ZlineOnMatch = Conf.ReadFlag("rline", "zlineonmatch", 0); std::string newrxengine = Conf.ReadValue("rline", "engine", 0); - if (!RegexEngine.empty()) - { - if (RegexEngine == newrxengine) - return; - - ServerInstance->SNO->WriteToSnoMask('x', "Dumping all R-Lines due to regex engine change (was '%s', now '%s')", RegexEngine.c_str(), newrxengine.c_str()); - ServerInstance->XLines->DelAll("R"); - } - rxengine = 0; - RegexEngine = newrxengine; - modulelist* ml = ServerInstance->Modules->FindInterface("RegularExpression"); - if (ml) - { - for (modulelist::iterator i = ml->begin(); i != ml->end(); ++i) - { - if (RegexNameRequest(this, *i).result == newrxengine) - { - ServerInstance->SNO->WriteToSnoMask('a', "R-Line now using engine '%s'", RegexEngine.c_str()); - rxengine = *i; - } - } - } - if (!rxengine) + rxfactory.SetProvider("regex/" + newrxengine); + if (!rxfactory) { ServerInstance->SNO->WriteToSnoMask('a', "WARNING: Regex engine '%s' is not loaded - R-Line functionality disabled until this is corrected.", RegexEngine.c_str()); } @@ -290,19 +265,6 @@ class ModuleRLine : public Module return MOD_RES_DENY; } - virtual void OnLoadModule(Module* mod) - { - if (ServerInstance->Modules->ModuleHasInterface(mod, "RegularExpression")) - { - std::string rxname = RegexNameRequest(this, mod).result; - if (rxname == RegexEngine) - { - ServerInstance->SNO->WriteToSnoMask('a', "R-Line now using engine '%s'", RegexEngine.c_str()); - rxengine = mod; - } - } - } - virtual void OnUserPostNick(User *user, const std::string &oldnick) { if (!IS_LOCAL(user)) diff --git a/src/modules/m_sasl.cpp b/src/modules/m_sasl.cpp index 298544edc..07f6bb0ed 100644 --- a/src/modules/m_sasl.cpp +++ b/src/modules/m_sasl.cpp @@ -229,8 +229,8 @@ class ModuleSASL : public Module Implementation eventlist[] = { I_OnEvent, I_OnUserRegister }; ServerInstance->Modules->Attach(eventlist, this, 2); - providerbase* providelist[] = { &auth, &sasl, &authExt }; - ServerInstance->AddServices(providelist, 3); + ServiceProvider* providelist[] = { &auth, &sasl, &authExt }; + ServerInstance->Modules->AddServices(providelist, 3); if (!ServerInstance->Modules->Find("m_services_account.so") || !ServerInstance->Modules->Find("m_cap.so")) ServerInstance->Logs->Log("m_sasl", DEFAULT, "WARNING: m_services_account.so and m_cap.so are not loaded! m_sasl.so will NOT function correctly until these two modules are loaded!"); diff --git a/src/modules/m_sha256.cpp b/src/modules/m_sha256.cpp index 7856b296b..8c2b00eea 100644 --- a/src/modules/m_sha256.cpp +++ b/src/modules/m_sha256.cpp @@ -132,7 +132,7 @@ uint32_t sha256_k[64] = 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 }; -class ModuleSHA256 : public Module +class HashSHA256 : public HashProvider { void SHA256Init(SHA256Context *ctx, const unsigned int* ikey) { @@ -245,35 +245,33 @@ class ModuleSHA256 : public Module } public: - ModuleSHA256() + std::string sum(const std::string& data) { - ServerInstance->Modules->PublishInterface("HashRequest", this); + unsigned char bytes[SHA256_DIGEST_SIZE]; + SHA256(data.data(), bytes, data.length()); + return std::string((char*)bytes, SHA256_DIGEST_SIZE); } - virtual ~ModuleSHA256() + std::string sumIV(unsigned int* IV, const char* HexMap, const std::string &sdata) { - ServerInstance->Modules->UnpublishInterface("HashRequest", this); + return ""; } + HashSHA256(Module* parent) : HashProvider(parent, "hash/sha256") {} +}; - void OnRequest(Request& request) +class ModuleSHA256 : public Module +{ + HashSHA256 sha; + public: + ModuleSHA256() : sha(this) { - if (strcmp("HASH", request.id) == 0) - { - unsigned char bytes[SHA256_DIGEST_SIZE]; - HashRequest& req = static_cast(request); - SHA256(req.data.data(), bytes, req.data.length()); - req.binresult.assign((char*)bytes, SHA256_DIGEST_SIZE); - } - else if (strcmp("NAME", request.id) == 0) - { - static_cast(request).response = "sha256"; - } + ServerInstance->Modules->AddService(sha); } Version GetVersion() { - return Version("Allows for SHA-256 encrypted oper passwords", VF_VENDOR); + return Version("Implements SHA-256 hashing", VF_VENDOR); } }; diff --git a/src/modules/m_spanningtree/compat.cpp b/src/modules/m_spanningtree/compat.cpp index b35879cd9..dd577fca7 100644 --- a/src/modules/m_spanningtree/compat.cpp +++ b/src/modules/m_spanningtree/compat.cpp @@ -26,6 +26,7 @@ static const char* const forge_common_1201[] = { "m_saquit.so", "m_setident.so", "m_swhois.so", + "m_regex_pcre.so" }; static std::string wide_newline("\r\n"); diff --git a/src/modules/m_spanningtree/hmac.cpp b/src/modules/m_spanningtree/hmac.cpp index b5a5fa228..790358d36 100644 --- a/src/modules/m_spanningtree/hmac.cpp +++ b/src/modules/m_spanningtree/hmac.cpp @@ -55,16 +55,13 @@ std::string TreeSocket::MakePass(const std::string &password, const std::string * Note: If m_sha256.so is not loaded, we MUST fall back to plaintext with no * HMAC challenge/response. */ - Module* sha256 = ServerInstance->Modules->Find("m_sha256.so"); + HashProvider* sha256 = ServerInstance->Modules->FindDataService("hash/sha256"); if (Utils->ChallengeResponse && sha256 && !challenge.empty()) { - /* XXX: This is how HMAC is supposed to be done: + /* This is how HMAC is supposed to be done: * * sha256( (pass xor 0x5c) + sha256((pass xor 0x36) + m) ) * - * Note that we are encoding the hex hash, not the binary - * output of the hash which is slightly different to standard. - * * 5c and 36 were chosen as part of the HMAC standard, because they * flip the bits in a way likely to strengthen the function. */ @@ -72,17 +69,28 @@ std::string TreeSocket::MakePass(const std::string &password, const std::string for (size_t n = 0; n < password.length(); n++) { - hmac1 += static_cast(password[n] ^ 0x5C); - hmac2 += static_cast(password[n] ^ 0x36); + hmac1.push_back(static_cast(password[n] ^ 0x5C)); + hmac2.push_back(static_cast(password[n] ^ 0x36)); } - hmac2 += challenge; - hmac2 = HashRequest(Utils->Creator, sha256, hmac2).hex(); + if (proto_version >= 1202) + { + hmac2.append(challenge); + std::string hmac = sha256->hexsum(hmac1 + sha256->sum(hmac2)); + + return "AUTH:" + hmac; + } + else + { + // version 1.2 used a weaker HMAC, using hex output in the intermediate step + hmac2.append(challenge); + hmac2 = sha256->hexsum(hmac2); - std::string hmac = hmac1 + hmac2; - hmac = HashRequest(Utils->Creator, sha256, hmac).hex(); + std::string hmac = hmac1 + hmac2; + hmac = sha256->hexsum(hmac); - return "HMAC-SHA256:"+ hmac; + return "HMAC-SHA256:"+ hmac; + } } else if (!challenge.empty() && !sha256) ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Not authenticating to server using SHA256/HMAC because we don't have m_sha256 loaded!"); diff --git a/src/modules/m_spanningtree/main.cpp b/src/modules/m_spanningtree/main.cpp index fe2cfe9b6..0ed9b28ac 100644 --- a/src/modules/m_spanningtree/main.cpp +++ b/src/modules/m_spanningtree/main.cpp @@ -33,7 +33,6 @@ ModuleSpanningTree::ModuleSpanningTree() : max_local(0), max_global(0) { - ServerInstance->Modules->UseInterface("BufferedSocketHook"); Utils = new SpanningTreeUtilities(this); command_rconnect = new CommandRConnect(this, Utils); ServerInstance->AddCommand(command_rconnect); @@ -781,30 +780,16 @@ void ModuleSpanningTree::OnRehash(User* user) void ModuleSpanningTree::OnLoadModule(Module* mod) { - this->RedoConfig(mod); + // TODO notify other servers? } void ModuleSpanningTree::OnUnloadModule(Module* mod) { - this->RedoConfig(mod); + // TODO notify other servers? } void ModuleSpanningTree::RedoConfig(Module* mod) { - /* If m_sha256.so is loaded (we use this for HMAC) or any module implementing a BufferedSocket interface is loaded, - * then we need to re-read our config again taking this into account. - */ - modulelist* ml = ServerInstance->Modules->FindInterface("BufferedSocketHook"); - bool IsBufferSocketModule = false; - - /* Did we find any modules? */ - if (ml && std::find(ml->begin(), ml->end(), mod) != ml->end()) - IsBufferSocketModule = true; - - if (mod->ModuleSourceFile == "m_sha256.so" || IsBufferSocketModule) - { - Utils->ReadConfiguration(); - } } // note: the protocol does not allow direct umode +o except @@ -955,7 +940,6 @@ CullResult ModuleSpanningTree::cull() { Utils->cull(); ServerInstance->Timers->DelTimer(RefreshTimer); - ServerInstance->Modules->DoneWithInterface("BufferedSocketHook"); return this->Module::cull(); } diff --git a/src/modules/m_spanningtree/treesocket1.cpp b/src/modules/m_spanningtree/treesocket1.cpp index e41b53583..abed5fc25 100644 --- a/src/modules/m_spanningtree/treesocket1.cpp +++ b/src/modules/m_spanningtree/treesocket1.cpp @@ -40,26 +40,14 @@ TreeSocket::TreeSocket(SpanningTreeUtilities* Util, const std::string& shost, in LinkState = CONNECTING; if (!hook.empty()) { - modulelist* ml = ServerInstance->Modules->FindInterface("BufferedSocketHook"); - if (ml) + ServiceProvider* prov = ServerInstance->Modules->FindService(SERVICE_IOHOOK, hook); + if (!prov) { - for(modulelist::iterator i = ml->begin(); i != ml->end(); ++i) - { - std::string name = (**i).ModuleSourceFile; - int a = name.rfind('_'); - int b = name.rfind('.'); - name = name.substr(a+1, b-a-1); - if (name == hook) - { - AddIOHook(*i); - goto found; - } - } + SetError("Could not find hook '" + hook + "' for connection to " + ServerName); + return; } - SetError("Could not find hook '" + hook + "' for connection to " + ServerName); - return; + AddIOHook(prov->creator); } -found: DoConnect(shost, iport, maxtime, bindto); Utils->timeoutlist[this] = std::pair(ServerName, maxtime); SendCapabilities(1); diff --git a/src/modules/m_sqlauth.cpp b/src/modules/m_sqlauth.cpp index 3a4461480..9b8a27ab7 100644 --- a/src/modules/m_sqlauth.cpp +++ b/src/modules/m_sqlauth.cpp @@ -35,16 +35,14 @@ class ModuleSQLAuth : public Module public: ModuleSQLAuth() : sqlAuthed("sqlauth", this) { - ServerInstance->Modules->UseInterface("SQLutils"); - ServerInstance->Modules->UseInterface("SQL"); - SQLutils = ServerInstance->Modules->Find("m_sqlutils.so"); if (!SQLutils) throw ModuleException("Can't find m_sqlutils.so. Please load m_sqlutils.so before m_sqlauth.so."); - SQLprovider = ServerInstance->Modules->FindFeature("SQL"); - if (!SQLprovider) + ServiceProvider* prov = ServerInstance->Modules->FindService(SERVICE_DATA, "SQL"); + if (!prov) throw ModuleException("Can't find an SQL provider module. Please load one before attempting to load m_sqlauth."); + SQLprovider = prov->creator; OnRehash(NULL); Implementation eventlist[] = { I_OnUserDisconnect, I_OnCheckReady, I_OnRehash, I_OnUserRegister }; @@ -53,11 +51,8 @@ public: virtual ~ModuleSQLAuth() { - ServerInstance->Modules->DoneWithInterface("SQL"); - ServerInstance->Modules->DoneWithInterface("SQLutils"); } - void OnRehash(User* user) { ConfigReader Conf; @@ -105,19 +100,13 @@ public: SearchAndReplace(thisquery, std::string("$server"), std::string(user->server)); SearchAndReplace(thisquery, std::string("$uuid"), user->uuid); - Module* HashMod = ServerInstance->Modules->Find("m_md5.so"); - - if (HashMod) - { - SearchAndReplace(thisquery, std::string("$md5pass"), HashRequest(this, HashMod, user->password).hex()); - } - - HashMod = ServerInstance->Modules->Find("m_sha256.so"); + HashProvider* md5 = ServerInstance->Modules->FindDataService("hash/md5"); + if (md5) + SearchAndReplace(thisquery, std::string("$md5pass"), md5->hexsum(user->password)); - if (HashMod) - { - SearchAndReplace(thisquery, std::string("$sha256pass"), HashRequest(this, HashMod, user->password).hex()); - } + HashProvider* sha256 = ServerInstance->Modules->FindDataService("hash/sha256"); + if (sha256) + SearchAndReplace(thisquery, std::string("$sha256pass"), sha256->hexsum(user->password)); /* Build the query */ SQLrequest req = SQLrequest(this, SQLprovider, databaseid, SQLquery(thisquery)); diff --git a/src/modules/m_sqllog.cpp b/src/modules/m_sqllog.cpp index 8ff12a8d9..29fa320db 100644 --- a/src/modules/m_sqllog.cpp +++ b/src/modules/m_sqllog.cpp @@ -156,15 +156,15 @@ class ModuleSQLLog : public Module public: ModuleSQLLog() - { - ServerInstance->Modules->UseInterface("SQLutils"); - ServerInstance->Modules->UseInterface("SQL"); - + { Module* SQLutils = ServerInstance->Modules->Find("m_sqlutils.so"); if (!SQLutils) throw ModuleException("Can't find m_sqlutils.so. Please load m_sqlutils.so before m_sqlauth.so."); - SQLModule = ServerInstance->Modules->FindFeature("SQL"); + ServiceProvider* prov = ServerInstance->Modules->FindService(SERVICE_DATA, "SQL"); + if (!prov) + throw ModuleException("Can't find an SQL provider module. Please load one before attempting to load m_sqlauth."); + SQLModule = prov->creator; OnRehash(NULL); MyMod = this; @@ -175,13 +175,6 @@ class ModuleSQLLog : public Module ServerInstance->Modules->Attach(eventlist, this, 8); } - virtual ~ModuleSQLLog() - { - ServerInstance->Modules->DoneWithInterface("SQL"); - ServerInstance->Modules->DoneWithInterface("SQLutils"); - } - - void ReadConfig() { ConfigReader Conf; diff --git a/src/modules/m_sqloper.cpp b/src/modules/m_sqloper.cpp index a6da1ddaa..3ee47953b 100644 --- a/src/modules/m_sqloper.cpp +++ b/src/modules/m_sqloper.cpp @@ -27,50 +27,22 @@ class ModuleSQLOper : public Module LocalStringExt saved_pass; Module* SQLutils; std::string databaseid; - irc::string hashtype; - hashymodules hashers; - bool diduseiface; + std::string hashtype; parameterlist names; public: ModuleSQLOper() : saved_user("sqloper_user", this), saved_pass("sqloper_pass", this) { - ServerInstance->Modules->UseInterface("SQLutils"); - ServerInstance->Modules->UseInterface("SQL"); - ServerInstance->Modules->UseInterface("HashRequest"); - OnRehash(NULL); - diduseiface = false; - - /* Find all modules which implement the interface 'HashRequest' */ - modulelist* ml = ServerInstance->Modules->FindInterface("HashRequest"); - - /* Did we find any modules? */ - if (ml) - { - /* Yes, enumerate them all to find out the hashing algorithm name */ - for (modulelist::iterator m = ml->begin(); m != ml->end(); m++) - { - /* Make a request to it for its name, its implementing - * HashRequest so we know its safe to do this - */ - std::string name = HashNameRequest(this, *m).response; - /* Build a map of them */ - hashers[name.c_str()] = *m; - names.push_back(name); - } - /* UseInterface doesn't do anything if there are no providers, so we'll have to call it later if a module gets loaded later on. */ - diduseiface = true; - ServerInstance->Modules->UseInterface("HashRequest"); - } - SQLutils = ServerInstance->Modules->Find("m_sqlutils.so"); if (!SQLutils) throw ModuleException("Can't find m_sqlutils.so. Please load m_sqlutils.so before m_sqloper.so."); Implementation eventlist[] = { I_OnRehash, I_OnPreCommand, I_OnLoadModule }; - ServerInstance->Modules->Attach(eventlist, this, 4); + ServerInstance->Modules->Attach(eventlist, this, 3); + ServerInstance->Modules->AddService(saved_user); + ServerInstance->Modules->AddService(saved_pass); } bool OneOfMatches(const char* host, const char* ip, const char* hostlist) @@ -87,36 +59,12 @@ public: return false; } - virtual void OnLoadModule(Module* mod) - { - if (ServerInstance->Modules->ModuleHasInterface(mod, "HashRequest")) - { - std::string sname = HashNameRequest(this, mod).response; - hashers[sname.c_str()] = mod; - names.push_back(sname); - if (!diduseiface) - { - ServerInstance->Modules->UseInterface("HashRequest"); - diduseiface = true; - } - } - } - - virtual ~ModuleSQLOper() - { - ServerInstance->Modules->DoneWithInterface("SQL"); - ServerInstance->Modules->DoneWithInterface("SQLutils"); - if (diduseiface) - ServerInstance->Modules->DoneWithInterface("HashRequest"); - } - - virtual void OnRehash(User* user) { ConfigReader Conf; databaseid = Conf.ReadValue("sqloper", "dbid", 0); /* Database ID of a database configured for the service provider module */ - hashtype = assign(Conf.ReadValue("sqloper", "hash", 0)); + hashtype = Conf.ReadValue("sqloper", "hash", 0); } virtual ModResult OnPreCommand(std::string &command, std::vector ¶meters, User *user, bool validated, const std::string &original_line) @@ -138,18 +86,14 @@ public: bool LookupOper(User* user, const std::string &username, const std::string &password) { - Module* target; - - target = ServerInstance->Modules->FindFeature("SQL"); - - if (target) + ServiceProvider* prov = ServerInstance->Modules->FindService(SERVICE_DATA, "SQL"); + if (prov) { - hashymodules::iterator x = hashers.find(hashtype); - if (x == hashers.end()) - return false; + Module* target = prov->creator; + HashProvider* hash = ServerInstance->Modules->FindDataService("hash/" + hashtype); /* Make an MD5 hash of the password for using in the query */ - std::string md5_pass_hash = HashRequest(this, x->second, password).hex(); + std::string md5_pass_hash = hash ? hash->hexsum(password) : password; /* We generate our own sum here because some database providers (e.g. SQLite) dont have a builtin md5/sha256 function, * also hashing it in the module and only passing a remote query containing a hash is more secure. diff --git a/src/modules/m_sqlutils.cpp b/src/modules/m_sqlutils.cpp index db5a990e1..a65f6c24a 100644 --- a/src/modules/m_sqlutils.cpp +++ b/src/modules/m_sqlutils.cpp @@ -33,14 +33,12 @@ private: public: ModuleSQLutils() : idExt("sqlutils_list", this) { - ServerInstance->Modules->PublishInterface("SQLutils", this); Implementation eventlist[] = { I_OnChannelDelete, I_OnUnloadModule, I_OnUserDisconnect }; ServerInstance->Modules->Attach(eventlist, this, 3); } ~ModuleSQLutils() { - ServerInstance->Modules->UnpublishInterface("SQLutils", this); } diff --git a/src/modules/m_sslinfo.cpp b/src/modules/m_sslinfo.cpp index 7457ce296..b028a6eb2 100644 --- a/src/modules/m_sslinfo.cpp +++ b/src/modules/m_sslinfo.cpp @@ -129,12 +129,6 @@ class ModuleSSLInfo : public Module Implementation eventlist[] = { I_OnWhois, I_OnPreCommand }; ServerInstance->Modules->Attach(eventlist, this, 2); - ServerInstance->Modules->PublishInterface("SSLCertInfo", this); - } - - ~ModuleSSLInfo() - { - ServerInstance->Modules->UnpublishInterface("SSLCertInfo", this); } Version GetVersion() diff --git a/src/modules/m_testclient.cpp b/src/modules/m_testclient.cpp index c6abb0064..36027f41e 100644 --- a/src/modules/m_testclient.cpp +++ b/src/modules/m_testclient.cpp @@ -34,7 +34,10 @@ public: virtual void OnBackgroundTimer(time_t) { - Module* target = ServerInstance->Modules->FindFeature("SQL"); + ServiceProvider* prov = ServerInstance->Modules->FindService(SERVICE_DATA, "SQL"); + if (!prov) + return; + Module* target = prov->creator; if(target) {