]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Use ServiceProvider for inter-module dependencies
authordanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>
Mon, 16 Nov 2009 17:59:06 +0000 (17:59 +0000)
committerdanieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7>
Mon, 16 Nov 2009 17:59:06 +0000 (17:59 +0000)
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

44 files changed:
include/base.h
include/ctables.h
include/extensible.h
include/inspircd.h
include/mode.h
include/modules.h
include/typedefs.h
src/base.cpp
src/mode.cpp
src/modmanager_dynamic.cpp
src/modules.cpp
src/modules/extra/m_mssql.cpp
src/modules/extra/m_mysql.cpp
src/modules/extra/m_pgsql.cpp
src/modules/extra/m_regex_pcre.cpp
src/modules/extra/m_regex_posix.cpp
src/modules/extra/m_regex_tre.cpp
src/modules/extra/m_sqlite3.cpp
src/modules/extra/m_ssl_gnutls.cpp
src/modules/extra/m_ssl_openssl.cpp
src/modules/extra/m_ziplink.cpp
src/modules/m_chanfilter.cpp
src/modules/m_cloaking.cpp
src/modules/m_exemptchanops.cpp
src/modules/m_filter.cpp
src/modules/m_hash.h
src/modules/m_md5.cpp
src/modules/m_password_hash.cpp
src/modules/m_regex.h
src/modules/m_regex_glob.cpp
src/modules/m_ripemd160.cpp
src/modules/m_rline.cpp
src/modules/m_sasl.cpp
src/modules/m_sha256.cpp
src/modules/m_spanningtree/compat.cpp
src/modules/m_spanningtree/hmac.cpp
src/modules/m_spanningtree/main.cpp
src/modules/m_spanningtree/treesocket1.cpp
src/modules/m_sqlauth.cpp
src/modules/m_sqllog.cpp
src/modules/m_sqloper.cpp
src/modules/m_sqlutils.cpp
src/modules/m_sslinfo.cpp
src/modules/m_testclient.cpp

index 8324d63472c628c225a2957f5ebcdd8021c2b3af..e0b3d25e3d1799d4ebff7f2f8cf47394890f596b 100644 (file)
@@ -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();
 };
 
 
index 991ad1cc2927742b66e3a39324050235c35019d9..9b433d6f94630e1ce2ca9a65d3d23dff1d2466e8 100644 (file)
@@ -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)
        {
        }
index ae78c0a0d0151a70774cba1a8c48a9e0ece1b53a..d4c7a86d1f9c627a192f960036d701f7d6e67d0f 100644 (file)
@@ -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);
index 52035ce492975ecc3a76f1e5370a7d05a39fef95..96b05488a60b9580b5bd8e72bb084101cd0cac1b 100644 (file)
@@ -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
index f2b58a309207d46a3106598dd7eda0f656879a0a..ce9d2ee2bd0cecf93e462d6eb4a3b02b359d3176 100644 (file)
@@ -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:
        /**
index 3efee83dc4251efe2e0dc09464baf35834179e4d..d6625e7bfe191f92bcc139004f12dbb073a89085 100644 (file)
@@ -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<typename T>
+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<T*>(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<std::string, ServiceProvider*> DataProviders;
+
+       /** List of all dynamic references that are currently active */
+       std::vector<dynamic_reference_base*> 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<int,std::string> 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<typename T> inline T* FindDataService(const std::string& name)
+       {
+               return static_cast<T*>(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,
index c0a5ebbc1fc128a2b06b60645c84b38ddca15eca..a1c6e774d7f63468b9bdc9151a1e097d461675da 100644 (file)
@@ -123,18 +123,6 @@ typedef std::set<User*> CUList;
  */
 typedef std::vector<std::string> string_list;
 
-/** Holds a list of 'published features' for modules.
- */
-typedef std::map<std::string,Module*> featurelist;
-
-/** Holds a list of modules which implement an interface
- */
-typedef std::deque<Module*> modulelist;
-
-/** Holds a list of all modules which implement interfaces, by interface name
- */
-typedef std::map<std::string, std::pair<int, modulelist> > interfacelist;
-
 /** Contains an ident and host split into two strings
  */
 typedef std::pair<std::string, std::string> IdentHostPair;
index 3ff3d5281334a2b71871295bde327c451a8431b4..852738f82eb551848bfcbd282e3d570bec7a7541 100644 (file)
@@ -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)
 {
 }
 
index 441ca520df6b04ab46cd165ec9668b683121bf91..7d99277df1702b506ba8695899d3218d6d01c661 100644 (file)
@@ -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)
 {
index 156105ad8db041a6801efe430dbc2a05f3ac3522..bbbaf7b532a0dfdb41949d60658039470f44d3ca 100644 (file)
@@ -152,13 +152,6 @@ bool ModuleManager::CanUnload(Module* mod)
                ServerInstance->Logs->Log("MODULE", DEFAULT, LastModuleError);
                return false;
        }
-       std::pair<int,std::string> 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<std::string, ServiceProvider*>::iterator i = DataProviders.begin(); i != DataProviders.end(); )
+       {
+               std::multimap<std::string, ServiceProvider*>::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);
index d86dc62705ce6c33e500683c9fc5c1999c88024c..f4751ad112dc84cfac8cf3a56977972d1279dd9a 100644 (file)
@@ -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<std::string>& 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<Command*>(&item)))
+                               throw ModuleException("Command "+std::string(item.name)+" already exists.");
+                       return;
+               case SERVICE_CMODE:
+               case SERVICE_UMODE:
+                       if (!ServerInstance->Modes->AddMode(static_cast<ModeHandler*>(&item)))
+                               throw ModuleException("Mode "+std::string(item.name)+" already exists.");
+                       return;
+               case SERVICE_METADATA:
+                       ServerInstance->Extensions.Register(static_cast<ExtensionItem*>(&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<std::string, ServiceProvider*>::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<int,std::string> 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<std::string, Module*>::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<std::string>& 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<Command*>(&item)))
-                               throw ModuleException("Command "+std::string(item.name)+" already exists.");
-                       return;
-               case SERVICE_CMODE:
-               case SERVICE_UMODE:
-                       if (!Modes->AddMode(static_cast<ModeHandler*>(&item)))
-                               throw ModuleException("Mode "+std::string(item.name)+" already exists.");
-                       return;
-               case SERVICE_METADATA:
-                       Extensions.Register(static_cast<ExtensionItem*>(&item));
-                       return;
-               case SERVICE_DATA:
-               case SERVICE_IOHOOK:
-               default:
-                       throw ModuleException("Cannot add unknown service type");
+               std::multimap<std::string, ServiceProvider*>::iterator i = ServerInstance->Modules->DataProviders.find(name);
+               if (i != ServerInstance->Modules->DataProviders.end())
+                       value = static_cast<DataProvider*>(i->second);
        }
+       return value;
 }
 
 void InspIRCd::SendMode(const std::vector<std::string>& parameters, User *user)
index 455a4fa47cdaba4209c04c50235b29c66b189895..13f25d4fc2ef31f3eb54f52e4284f28b866b37b0 100644 (file)
@@ -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;
        }
index 358f5e992b76f8dffb71f74126dcb647516ebe0a..c294befdc09eeb24545cff49f2399008d6d415cf 100644 (file)
@@ -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()
index f362125cb7b3b75136816fe25a3d55753311b3b1..4fb3d3ab685dedcd4e87f31bc7981495cb28e1c3 100644 (file)
@@ -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");
        }
 
 
index 9e8aff159c81467959b935c67b6f5c73897b78be..c286162e8e25808bb07f721377f8e82a25e1020b 100644 (file)
@@ -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<RegexNameRequest&>(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);
        }
 };
 
index ea016ae64917004462fa71d2478f71b3ce3d5e6d..837f2ac1f7ddb5ca0d978a88d4e50281bbebe205 100644 (file)
@@ -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<RegexNameRequest&>(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);
        }
 };
 
index 01c6ebf4aa33ba624a6d7a060918769933debf55..5a208ec8ac0e05ba1eb4ce76e0f02610c2c7b89b 100644 (file)
@@ -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<RegexNameRequest&>(request).result = "tre";
-               }
-               else if (strcmp("REGEX", request.id) == 0)
-               {
-                       RegexFactoryRequest& rfr = (RegexFactoryRequest&)request;
-                       std::string rx = rfr.GetRegex();
-                       rfr.result = new TRERegex(rx);
-               }
        }
 };
 
index e5693b61f04d2ec188acbe7a93d69fccc554b421..58a33c510fa4c4e4e978734858fccab0ef57cd08 100644 (file)
@@ -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()
index 8ec787465a80598bf524c3b9c8189dfdedb6e132..7ba61154742ba88a5fa5c3498d58583c369a2385 100644 (file)
@@ -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;
        }
 
index 03c460be299ddc616a5e5b7855b098507deb26aa..7524c0d0799e07a0d18b08d34f04b3a625942768 100644 (file)
@@ -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;
        }
 
index 2aeb4b9e6d37c23c397c5a777d08d076bfea5adb..2ac358769c6d062b48a8f4ada61c072beb67caf2 100644 (file)
@@ -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;
        }
index a466978e381be02c9c1f8423e600b82190793a34..5bb5a91b03a59cc72c3fc7ca2ef3d076a988005b 100644 (file)
@@ -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);
        }
 };
 
index 0a4e58edfc6714e6ac6c40160ee0515512244be7..c4cbbef211e6476ab6ed19cfd2f8fe30f2176fdb 100644 (file)
@@ -116,29 +116,21 @@ class ModuleCloaking : public Module
        std::string key;
        unsigned int compatkey[4];
        const char* xtab[4];
-       Module* HashProvider;
+       dynamic_reference<HashProvider> 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<LocalUser*>::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.
index 9e6b735ed2caef39d6e67e8655b57a38e72a70e0..8b3fbf074a9f71ea9a7a794918197fcebd213a6a 100644 (file)
@@ -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)
index 0220a3a44eedeb1e4b7d3260f5c4b67a40623db4..55ef734ba8095059a3b7fd4c285e89a2fa90877b 100644 (file)
@@ -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<Module*>(f), "FILTER", 1, 5), Base(f)
+       CommandFilter(Module* f)
+               : Command(f, "FILTER", 1, 5)
        {
                flags_needed = 'o';
                this->syntax = "<filter-definition> <action> <flags> [<gline-duration>] :<reason>";
@@ -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<RegexFactory> RegexEngine;
+
+       std::vector<ImplFilter> filters;
+       const char *error;
+       int erroffset;
        int flags;
-protected:
+
        std::vector<std::string> 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<bool, std::string> 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<bool, std::string> 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<std::string> &parameters, 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<std::string> &parameters, 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<std::string> &parameters, User *user)
@@ -154,7 +165,7 @@ CmdResult CommandFilter::Handle(const std::vector<std::string> &parameters, User
        if (parameters.size() == 1)
        {
                /* Deleting a filter */
-               if (Base->DeleteFilter(parameters[0]))
+               if (static_cast<ModuleFilter&>(*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<std::string> &parameters, User
                        {
                                reason = parameters[3];
                        }
-                       std::pair<bool, std::string> result = Base->AddFilter(freeform, type, reason, duration, flags);
+                       std::pair<bool, std::string> result = static_cast<ModuleFilter&>(*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<std::string> &parameters, 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<std::string> &parameters, User *user, bool validated, const std::string &original_line)
+ModResult ModuleFilter::OnPreCommand(std::string &command, std::vector<std::string> &parameters, 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<std::string
        return MOD_RES_PASSTHRU;
 }
 
-void FilterBase::OnRehash(User* user)
+void ModuleFilter::OnRehash(User* user)
 {
        ConfigReader MyConf;
        std::vector<std::string>().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<ImplFilter>::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<FilterResult*>(&(*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<ImplFilter> filters;
-       const char *error;
-       int erroffset;
-       ImplFilter fr;
-
- public:
-       ModuleFilter()
+       for (std::vector<ImplFilter>::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<ImplFilter>::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<bool, std::string> ModuleFilter::AddFilter(const std::string &freeform, const std::string &type, const std::string &reason, long duration, const std::string &flgs)
+{
+       for (std::vector<ImplFilter>::iterator i = filters.begin(); i != filters.end(); i++)
        {
-               for (std::vector<ImplFilter>::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<FilterResult*>(&(*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<ImplFilter>::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<ImplFilter>::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<bool, std::string> 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<ImplFilter>::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<ImplFilter>::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<std::string>::iterator i = exemptfromfilter.begin(); i != exemptfromfilter.end(); ++i)
                {
-                       std::string sn = ServerInstance->Config->ServerName;
-                       for (std::vector<ImplFilter>::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<std::string>::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)
index 08a24eb8548f99e1a18c25efbe06c1b430c57b20..385fff95edd317b6bcd600488b15a9d4bbc30592 100644 (file)
 #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
index 6ac9c3d87f78664a762f5a802b8aadb38c67cc9b..6b74dae2ee5f385ed72ddaa6e0ea8145e0d126e5 100644 (file)
@@ -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<HashRequest&>(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<HashRequestIV&>(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<HashNameRequest&>(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);
        }
 };
 
index 617983ec4df49a56422a8876ddb8969730687b62..f064e9cf0cafc0540542752606094229c9846858 100644 (file)
 #include "inspircd.h"
 #include "m_hash.h"
 
-typedef std::map<irc::string, Module*> hashymodules;
-
 /* Handle /MKPASSWD
  */
 class CommandMkpasswd : public Command
 {
-       hashymodules &hashers;
-       std::deque<std::string> &names;
  public:
-       CommandMkpasswd(Module* Creator, hashymodules &h, std::deque<std::string> &n) : Command(Creator, "MKPASSWD", 2), hashers(h), names(n)
+       CommandMkpasswd(Module* Creator) : Command(Creator, "MKPASSWD", 2)
        {
                syntax = "<hashtype> <any-text>";
                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<HashProvider>("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<std::string>& 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<std::string> 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<HashProvider>("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;
                }
 
index 969c4920bc1e328ed29b21b5e71f3b972154a7fc..613ec2700b1506657334d65f1025ac424c6ea0bc 100644 (file)
@@ -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
index 42cc0abd1d0d3e522f114f2871adfdbe4d0ce6a3..75d77a2674375703448688dd5077e8d0e2cbf69e 100644 (file)
@@ -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<RegexNameRequest&>(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);
        }
 };
 
index 03a7f9895cb719370266647b1c742badfdee24b1..6bd9a059a996431c21d04dc53a3de50a57a86586 100644 (file)
@@ -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<HashRequest&>(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<HashNameRequest&>(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);
        }
 
 };
index 87a95a1ff41faf07e77d04d8c4891fc40d3fd49f..5d7415fb52cdcc33dc0912d489ad4c962c96afa3 100644 (file)
@@ -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<ZLine *> 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<RegexFactory>& 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<RegexFactory>& rxfactory;
+       RLineFactory(dynamic_reference<RegexFactory>& 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 = "<regex> [<rline-duration>] :<reason>";
        }
@@ -139,11 +139,11 @@ class CommandRLine : public Command
                        // Adding - XXX todo make this respect <insane> 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<RegexFactory> 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))
index 298544edce84a228365acacaa03cc36efde7f3e2..07f6bb0ed1fbebbcbd3af66e05afeea4d7bfa0a4 100644 (file)
@@ -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!");
index 7856b296bcc3adbcc972748a3488c543b8696687..8c2b00eeaa387d53ee81a7fb02521ca3b1b96d35 100644 (file)
@@ -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<HashRequest&>(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<HashNameRequest&>(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);
        }
 };
 
index b35879cd99bd81074bcea4ed9b70d85cda81db7c..dd577fca7c2a1b7fe9a0f82205b8c2c74fe1c2f9 100644 (file)
@@ -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");
index b5a5fa2284ef133a1af6b6dc891bf947a546a13d..790358d364ffe66cd01b2aa602c8eed1696f6063 100644 (file)
@@ -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<HashProvider>("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<char>(password[n] ^ 0x5C);
-                       hmac2 += static_cast<char>(password[n] ^ 0x36);
+                       hmac1.push_back(static_cast<char>(password[n] ^ 0x5C));
+                       hmac2.push_back(static_cast<char>(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!");
index fe2cfe9b62f98a8e5a074d5acaa47d4de2d5ea25..0ed9b28ac7311b172f60c067aacddb5c44f3df3a 100644 (file)
@@ -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();
 }
 
index e41b53583ed105a0943a96c43261de61c84d6fa0..abed5fc2560fbc90d4f089492e157fda05c7ffce 100644 (file)
@@ -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<std::string, int>(ServerName, maxtime);
        SendCapabilities(1);
index 3a446148036a9c8ea30b63c3e9dfee22cc869d08..9b8a27ab769060c42ee100f52c2815b6be00e6c9 100644 (file)
@@ -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<HashProvider>("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<HashProvider>("hash/sha256");
+               if (sha256)
+                       SearchAndReplace(thisquery, std::string("$sha256pass"), sha256->hexsum(user->password));
 
                /* Build the query */
                SQLrequest req = SQLrequest(this, SQLprovider, databaseid, SQLquery(thisquery));
index 8ff12a8d9fce471294a8b085d00e24a72f65e51a..29fa320db6c0178838907020a5fb4972468788fa 100644 (file)
@@ -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;
index a6da1ddaafa7b30069f8921355bdfbe46841df16..3ee47953b4de4beeee066fad143ebc0a0292d96e 100644 (file)
@@ -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<std::string> &parameters, 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<HashProvider>("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.
index db5a990e17831384e2fa29585e89638de62fa2b8..a65f6c24a46f98a813ea1a283fc244e03b7b4015 100644 (file)
@@ -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);
        }
 
 
index 7457ce29652f7481e241eb49885c597f8a902791..b028a6eb24b52bc0b429264ba233fc80bca2e17b 100644 (file)
@@ -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()
index c6abb006449504b946e8afeb0e8370057d516929..36027f41e929bec01d6efbf8ddb9870d0dc945f6 100644 (file)
@@ -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)
                {