]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - include/modules.h
Include VERSION/REVISION information in module version tag, so that we do no longer...
[user/henk/code/inspircd.git] / include / modules.h
index ca331e33481eb7e4bcdc9f190f17bb0cb3a0b436..86f77d2183d19914498e32218f7d42f72907b653 100644 (file)
@@ -2,8 +2,8 @@
  *       | Inspire Internet Relay Chat Daemon |
  *       +------------------------------------+
  *
- *  InspIRCd: (C) 2002-2008 InspIRCd Development Team
- * See: http://www.inspircd.org/wiki/index.php/Credits
+ *  InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
  *
  * This program is free but copyrighted software; see
  *         the file COPYING for details.
@@ -14,7 +14,6 @@
 #ifndef __MODULES_H
 #define __MODULES_H
 
-#include "globals.h"
 #include "dynamic.h"
 #include "base.h"
 #include "ctables.h"
@@ -42,7 +41,8 @@ enum AccessControlType {
        AC_HALFOP,              // a user is being halfopped
        AC_DEHALFOP,            // a user is being dehalfopped
        AC_INVITE,              // a user is being invited
-       AC_GENERAL_MODE         // a channel mode is being changed
+       AC_GENERAL_MODE,        // a channel mode is being changed
+       AC_GENERAL_UMODE        // a user mode is being changed
 };
 
 /** Used to define a set of behavior bits for a module
@@ -51,7 +51,8 @@ enum ModuleFlags {
        VF_STATIC = 1,          // module is static, cannot be /unloadmodule'd
        VF_VENDOR = 2,          // module is a vendor module (came in the original tarball, not 3rd party)
        VF_SERVICEPROVIDER = 4, // module provides a service to other modules (can be a dependency)
-       VF_COMMON = 8           // module needs to be common on all servers in a network to link
+       VF_COMMON = 8,          // module needs to be common on all servers in a network to link
+       VF_OPTCOMMON = 16       // module should be common on all servers for unsurprising behavior
 };
 
 /** Used with SendToMode()
@@ -77,18 +78,50 @@ enum MessageType {
        MSG_NOTICE = 1
 };
 
-/** If you change the module API, change this value.
- * If you have enabled ipv6, the sizes of structs is
- * different, and modules will be incompatible with
- * ipv4 servers, so this value will be ten times as
- * high on ipv6 servers.
+#define MOD_RES_ALLOW (ModResult(1))
+#define MOD_RES_PASSTHRU (ModResult(0))
+#define MOD_RES_DENY (ModResult(-1))
+
+/** Used to represent an allow/deny module result.
+ * Not constructed as an enum because it reverses the value logic of some functions;
+ * the compiler will inline accesses to have the same efficiency as integer operations.
  */
-#define NATIVE_API_VERSION 12000
-#ifdef IPV6
-#define API_VERSION (NATIVE_API_VERSION * 10)
-#else
-#define API_VERSION (NATIVE_API_VERSION * 1)
-#endif
+struct ModResult {
+       int res;
+       ModResult() : res(0) {}
+       explicit ModResult(int r) : res(r) {}
+       bool operator==(const ModResult& r) const
+       {
+               return res == r.res;
+       }
+       bool operator!=(const ModResult& r) const
+       {
+               return res != r.res;
+       }
+       bool operator!() const
+       {
+               return !res;
+       }
+       bool check(bool def) const
+       {
+               return (res == 1 || (res == 0 && def));
+       }
+       /**
+        * Merges two results, preferring ALLOW to DENY
+        */
+       ModResult operator+(const ModResult& r) const
+       {
+               if (res == r.res || r.res == 0)
+                       return *this;
+               if (res == 0)
+                       return r;
+               // they are different, and neither is passthru
+               return MOD_RES_ALLOW;
+       }
+};
+
+/** If you change the module API, change this value. */
+#define API_VERSION 13000
 
 class ServerConfig;
 
@@ -166,75 +199,65 @@ typedef std::map<std::string, std::pair<int, modulelist> > interfacelist;
 } while (0);
 
 /**
- * This define is similar to the one above but returns a result in MOD_RESULT.
- * The first module to return a nonzero result is the value to be accepted,
- * and any modules after are ignored.
+ * Custom module result handling loop. This is a paired macro, and should only
+ * be used with while_each_hook.
+ *
+ * See src/channels.cpp for an example of use.
  */
-#define FOREACH_RESULT(y,x) \
+#define DO_EACH_HOOK(z,n,v,args) \
 do { \
-       EventHandlerIter safei; \
-       MOD_RESULT = 0; \
-       for (EventHandlerIter _i = ServerInstance->Modules->EventHandlers[y].begin(); _i != ServerInstance->Modules->EventHandlers[y].end(); ) \
+       EventHandlerIter iter_ ## n = z->Modules->EventHandlers[I_ ## n].begin(); \
+       while (iter_ ## n != z->Modules->EventHandlers[I_ ## n].end()) \
        { \
-               safei = _i; \
-               ++safei; \
+               Module* mod_ ## n = *iter_ ## n; \
+               iter_ ## n ++; \
                try \
                { \
-                       int res = (*_i)->x ; \
-                       if (res != 0) { \
-                               MOD_RESULT = res; \
-                               break; \
-                       } \
+                       v = (mod_ ## n)->n args;
+
+#define WHILE_EACH_HOOK(z,n) \
                } \
-               catch (CoreException& modexcept) \
+               catch (CoreException& except_ ## n) \
                { \
-                       ServerInstance->Logs->Log("MODULE",DEFAULT,"Exception caught: %s",modexcept.GetReason()); \
+                       z->Logs->Log("MODULE",DEFAULT,"Exception caught: %s", (except_ ## n).GetReason()); \
+                       (void) mod_ ## n; /* catch mismatched pairs */ \
                } \
-               _i = safei; \
        } \
-} while(0);
-
+} while(0)
 
 /**
- * This define is similar to the one above but returns a result in MOD_RESULT.
- * The first module to return a nonzero result is the value to be accepted,
- * and any modules after are ignored.
+ * Module result iterator
+ * Runs the given hook until some module returns a useful result.
+ *
+ * Example: ModResult result;
+ * FIRST_MOD_RESULT(ServerInstance, OnUserPreNick, result, (user, newnick))
  */
-#define FOREACH_RESULT_I(z,y,x) \
-do { \
-       EventHandlerIter safei; \
-       MOD_RESULT = 0; \
-       for (EventHandlerIter _i = z->Modules->EventHandlers[y].begin(); _i != z->Modules->EventHandlers[y].end(); ) \
+#define FIRST_MOD_RESULT(z,n,v,args) do { \
+       v = MOD_RES_PASSTHRU; \
+       DO_EACH_HOOK(z,n,v,args) \
        { \
-               safei = _i; \
-               ++safei; \
-               try \
-               { \
-                       int res = (*_i)->x ; \
-                       if (res != 0) { \
-                               MOD_RESULT = res; \
-                               break; \
-                       } \
-               } \
-               catch (CoreException& modexcept) \
-               { \
-                       z->Logs->Log("MODULE",DEBUG,"Exception caught: %s",modexcept.GetReason()); \
-               } \
-               _i = safei; \
+               if (v != MOD_RES_PASSTHRU) \
+                       break; \
        } \
-} while (0);
+       WHILE_EACH_HOOK(z,n); \
+} while (0)
 
 /** Represents a non-local user.
  * (in fact, any FD less than -1 does)
  */
 #define FD_MAGIC_NUMBER -42
+/** Represents a fake user (i.e. a server)
+ */
+#define FD_FAKEUSER_NUMBER -7
 
 /* Useful macros */
 
 /** Is a local user */
-#define IS_LOCAL(x) ((x->GetFd() > -1))
+#define IS_LOCAL(x) (x->GetFd() > -1)
 /** Is a remote user */
 #define IS_REMOTE(x) (x->GetFd() < 0)
+/** Is a fake user */
+#define IS_FAKE(x) (x->GetFd() == FD_FAKEUSER_NUMBER)
 /** Is a module created user */
 #define IS_MODULE_CREATED(x) (x->GetFd() == FD_MAGIC_NUMBER)
 /** Is an oper */
@@ -252,13 +275,18 @@ do { \
 class CoreExport Version : public classbase
 {
  public:
-        /** Version numbers, build number, flags and API version
-         */
-        const int Major, Minor, Revision, Build, Flags, API;
+       /** Version information.
+        */
+       const std::string version;
 
-        /** Initialize version class
-         */
-        Version(int major, int minor, int revision, int build, int flags, int api_ver);
+       /** Flags and API version
+        */
+       const int Flags, API;
+
+       /** Initialize version class
+        */
+       Version(const std::string &customver, int flags,
+               int api_ver = API_VERSION, const std::string& src_rev = VERSION " r" REVISION);
 };
 
 /** The ModuleMessage class is the base class of Request and Event
@@ -284,11 +312,11 @@ class CoreExport Request : public ModuleMessage
        /** This member holds a pointer to arbitary data set by the emitter of the message
         */
        char* data;
-       /** This should be a null-terminated string identifying the type of request,
-        * all modules should define this and use it to determine the nature of the
-        * request before they attempt to cast the Request in any way.
-        */
-       const char* id;
+       /** This should be a null-terminated string identifying the type of request,
+        * all modules should define this and use it to determine the nature of the
+        * request before they attempt to cast the Request in any way.
+        */
+       const char* id;
        /** This is a pointer to the sender of the message, which can be used to
         * directly trigger events, or to create a reply.
         */
@@ -298,26 +326,26 @@ class CoreExport Request : public ModuleMessage
        Module* dest;
  public:
        /** Create a new Request
-        * This is for the 'old' way of casting whatever the data is
-        * to char* and hoping you get the right thing at the other end.
-        * This is slowly being depreciated in favor of the 'new' way.
+        * This is for the 'old' way of casting whatever the data is
+        * to char* and hoping you get the right thing at the other end.
+        * This is slowly being depreciated in favor of the 'new' way.
         */
        Request(char* anydata, Module* src, Module* dst);
-       /** Create a new Request
-        * This is for the 'new' way of defining a subclass
-        * of Request and defining it in a common header,
+       /** Create a new Request
+        * This is for the 'new' way of defining a subclass
+        * of Request and defining it in a common header,
         * passing an object of your Request subclass through
-        * as a Request* and using the ID string to determine
-        * what to cast it back to and the other end. This is
-        * much safer as there are no casts not confirmed by
-        * the ID string, and all casts are child->parent and
-        * can be checked at runtime with dynamic_cast<>()
-        */
-       Request(Module* src, Module* dst, const char* idstr);
+        * as a Request* and using the ID string to determine
+        * what to cast it back to and the other end. This is
+        * much safer as there are no casts not confirmed by
+        * the ID string, and all casts are child->parent and
+        * can be checked at runtime with dynamic_cast<>()
+        */
+       Request(Module* src, Module* dst, const char* idstr);
        /** Fetch the Request data
         */
        char* GetData();
-       /** Fetch the ID string
+       /** Fetch the ID string
         */
        const char* GetId();
        /** Fetch the request source
@@ -385,19 +413,23 @@ enum Priority { PRIORITY_FIRST, PRIORITY_DONTCARE, PRIORITY_LAST, PRIORITY_BEFOR
 enum Implementation
 {
        I_BEGIN,
-       I_OnUserConnect, I_OnUserQuit, I_OnUserDisconnect, I_OnUserJoin, I_OnUserPart, I_OnRehash, I_OnServerRaw, 
-       I_OnUserPreJoin, I_OnUserPreKick, I_OnUserKick, I_OnOper, I_OnInfo, I_OnWhois, I_OnUserPreInvite,
-       I_OnUserInvite, I_OnUserPreMessage, I_OnUserPreNotice, I_OnUserPreNick, I_OnUserMessage, I_OnUserNotice, I_OnMode,
-       I_OnGetServerDescription, I_OnSyncUser, I_OnSyncChannel, I_OnSyncChannelMetaData, I_OnSyncUserMetaData,
-       I_OnDecodeMetaData, I_ProtoSendMode, I_ProtoSendMetaData, I_OnWallops, I_OnChangeHost, I_OnChangeName, I_OnAddLine,
-       I_OnDelLine, I_OnExpireLine, I_OnCleanup, I_OnUserPostNick, I_OnAccessCheck, I_On005Numeric, I_OnKill, I_OnRemoteKill, I_OnLoadModule, I_OnUnloadModule,
-       I_OnBackgroundTimer, I_OnPreCommand, I_OnCheckReady, I_OnCheckInvite, I_OnRawMode,
-       I_OnCheckKey, I_OnCheckLimit, I_OnCheckBan, I_OnStats, I_OnChangeLocalUserHost, I_OnChangeLocalUserGecos, I_OnLocalTopicChange,
-       I_OnPostLocalTopicChange, I_OnEvent, I_OnRequest, I_OnGlobalOper, I_OnPostConnect, I_OnAddBan, I_OnDelBan,
-       I_OnRawSocketAccept, I_OnRawSocketClose, I_OnRawSocketWrite, I_OnRawSocketRead, I_OnChangeLocalUserGECOS, I_OnUserRegister,
-       I_OnChannelPreDelete, I_OnChannelDelete, I_OnPostOper, I_OnSyncOtherMetaData, I_OnSetAway, I_OnUserList,
-       I_OnPostCommand, I_OnPostJoin, I_OnWhoisLine, I_OnBuildExemptList, I_OnRawSocketConnect, I_OnGarbageCollect, I_OnBufferFlushed,
-       I_OnText, I_OnPassCompare, I_OnRunTestSuite, I_OnNamesListItem, I_OnNumeric, I_OnHookUserIO,
+       I_OnUserConnect, I_OnUserQuit, I_OnUserDisconnect, I_OnUserJoin, I_OnUserPart, I_OnRehash,
+       I_OnSendSnotice, I_OnUserPreJoin, I_OnUserPreKick, I_OnUserKick, I_OnOper, I_OnInfo, I_OnWhois,
+       I_OnUserPreInvite, I_OnUserInvite, I_OnUserPreMessage, I_OnUserPreNotice, I_OnUserPreNick,
+       I_OnUserMessage, I_OnUserNotice, I_OnMode, I_OnGetServerDescription, I_OnSyncUser,
+       I_OnSyncChannel, I_OnDecodeMetaData, I_OnWallops,
+       I_OnChangeHost, I_OnChangeName, I_OnAddLine, I_OnDelLine, I_OnExpireLine, I_OnCleanup,
+       I_OnUserPostNick, I_OnAccessCheck, I_On005Numeric, I_OnKill, I_OnRemoteKill, I_OnLoadModule,
+       I_OnUnloadModule, I_OnBackgroundTimer, I_OnPreCommand, I_OnCheckReady, I_OnCheckInvite,
+       I_OnRawMode, I_OnCheckKey, I_OnCheckLimit, I_OnCheckBan, I_OnCheckExtBan, I_OnCheckStringExtBan,
+       I_OnStats, I_OnChangeLocalUserHost, I_OnChangeLocalUserGecos, I_OnLocalTopicChange,
+       I_OnPostLocalTopicChange, I_OnEvent, I_OnRequest, I_OnGlobalOper, I_OnPostConnect, I_OnAddBan,
+       I_OnDelBan, I_OnRawSocketAccept, I_OnRawSocketClose, I_OnRawSocketWrite, I_OnRawSocketRead,
+       I_OnChangeLocalUserGECOS, I_OnUserRegister, I_OnChannelPreDelete, I_OnChannelDelete,
+       I_OnPostOper, I_OnSyncNetwork, I_OnSetAway, I_OnUserList, I_OnPostCommand, I_OnPostJoin,
+       I_OnWhoisLine, I_OnBuildExemptList, I_OnRawSocketConnect, I_OnGarbageCollect, I_OnBufferFlushed,
+       I_OnText, I_OnPassCompare, I_OnRunTestSuite, I_OnNamesListItem, I_OnNumeric, I_OnHookIO,
+       I_OnHostCycle, I_OnPreRehash, I_OnModuleRehash, I_OnSendWhoLine, I_OnChangeIdent,
        I_END
 };
 
@@ -415,6 +447,9 @@ class CoreExport Module : public Extensible
         */
        InspIRCd* ServerInstance;
  public:
+       /** File that this module was loaded from
+        */
+       std::string ModuleSourceFile;
 
        /** Default constructor.
         * Creates a module class.
@@ -466,7 +501,7 @@ class CoreExport Module : public Extensible
         * @param chan The channel being deleted
         * @return An integer specifying whether or not the channel may be deleted. 0 for yes, 1 for no.
         */
-       virtual int OnChannelPreDelete(Channel *chan);
+       virtual ModResult OnChannelPreDelete(Channel *chan);
 
        /** Called whenever a channel is deleted, either by QUIT, KICK or PART.
         * @param chan The channel being deleted
@@ -482,8 +517,9 @@ class CoreExport Module : public Extensible
         * of the channel (useful for modules such as auditorium)
         * @param sync This is set to true if the JOIN is the result of a network sync and the remote user is being introduced
         * to a channel due to the network sync.
+        * @param created This is true if the join created the channel
         */
-       virtual void OnUserJoin(User* user, Channel* channel, bool sync, bool &silent);
+       virtual void OnUserJoin(User* user, Channel* channel, bool sync, bool &silent, bool created);
 
        /** Called after a user joins a channel
         * Identical to OnUserJoin, but called immediately afterwards, when any linking module has
@@ -506,27 +542,42 @@ class CoreExport Module : public Extensible
 
        /** Called on rehash.
         * This method is called prior to a /REHASH or when a SIGHUP is received from the operating
-        * system. You should use it to reload any files so that your module keeps in step with the
-        * rest of the application. If a parameter is given, the core has done nothing. The module
-        * receiving the event can decide if this parameter has any relevence to it.
-        * @param user The user performing the rehash, if any -- if this is server initiated, the
-        * value of this variable will be NULL.
-        * @param parameter The (optional) parameter given to REHASH from the user.
-        */
-       virtual void OnRehash(User* user, const std::string &parameter);
-
-       /** Called when a raw command is transmitted or received.
-        * This method is the lowest level of handler available to a module. It will be called with raw
-        * data which is passing through a connected socket. If you wish, you may munge this data by changing
-        * the string parameter "raw". If you do this, after your function exits it will immediately be
-        * cut down to 510 characters plus a carriage return and linefeed. For INBOUND messages only (where
-        * inbound is set to true) the value of user will be the User of the connection sending the
-        * data. This is not possible for outbound data because the data may be being routed to multiple targets.
-        * @param raw The raw string in RFC1459 format
-        * @param inbound A flag to indicate wether the data is coming into the daemon or going out to the user
-        * @param user The user record sending the text, when inbound == true.
-        */
-       virtual void OnServerRaw(std::string &raw, bool inbound, User* user);
+        * system. This is called in all cases -- including when this server will not execute the
+        * rehash because it is directed at a remote server.
+        *
+        * @param user The user performing the rehash, if any. If this is server initiated, the value of
+        * this variable will be NULL.
+        * @param parameter The (optional) parameter given to REHASH from the user. Empty when server
+        * initiated.
+        */
+       virtual void OnPreRehash(User* user, const std::string &parameter);
+
+       /** Called on rehash.
+        * This method is called when a user initiates a module-specific rehash. This can be used to do
+        * expensive operations (such as reloading SSL certificates) that are not executed on a normal
+        * rehash for efficiency. A rehash of this type does not reload the core configuration.
+        *
+        * @param user The user performing the rehash.
+        * @param parameter The parameter given to REHASH
+        */
+       virtual void OnModuleRehash(User* user, const std::string &parameter);
+
+       /** Called on rehash.
+        * This method is called after a rehash has completed. You should use it to reload any module
+        * configuration from the main configuration file.
+        * @param user The user that performed the rehash, if it was initiated by a user and that user
+        * is still connected.
+        */
+       virtual void OnRehash(User* user);
+
+       /** Called whenever a snotice is about to be sent to a snomask.
+        * snomask and type may both be modified; the message may not.
+        * @param snomask The snomask the message is going to (e.g. 'A')
+        * @param type The textual description the snomask will go to (e.g. 'OPER')
+        * @param message The text message to be sent via snotice
+        * @return 1 to block the snotice from being sent entirely, 0 else.
+        */
+       virtual ModResult OnSendSnotice(char &snomask, std::string &type, const std::string &message);
 
        /** Called whenever a user is about to join a channel, before any processing is done.
         * Returning a value of 1 from this function stops the process immediately, causing no
@@ -548,8 +599,8 @@ class CoreExport Module : public Extensible
         * @param keygiven The key given to join the channel, or an empty string if none was provided
         * @return 1 To prevent the join, 0 to allow it.
         */
-       virtual int OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string &privs, const std::string &keygiven);
-       
+       virtual ModResult OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string &privs, const std::string &keygiven);
+
        /** Called whenever a user is about to be kicked.
         * Returning a value of 1 from this function stops the process immediately, causing no
         * output to be sent to the user by the core. If you do this you must produce your own numerics,
@@ -560,7 +611,7 @@ class CoreExport Module : public Extensible
         * @param reason The kick reason
         * @return 1 to prevent the kick, 0 to continue normally, -1 to explicitly allow the kick regardless of normal operation
         */
-       virtual int OnUserPreKick(User* source, User* user, Channel* chan, const std::string &reason);
+       virtual ModResult OnUserPreKick(User* source, User* user, Channel* chan, const std::string &reason);
 
        /** Called whenever a user is kicked.
         * If this method is called, the kick is already underway and cannot be prevented, so
@@ -591,7 +642,7 @@ class CoreExport Module : public Extensible
         * @param opertype The opers type name
         */
        virtual void OnPostOper(User* user, const std::string &opername, const std::string &opertype);
-       
+
        /** Called whenever a user types /INFO.
         * The User will contain the information of the user who typed the command. Modules may use this
         * method to output their own credits in /INFO (which is the ircd's version of an about box).
@@ -603,7 +654,7 @@ class CoreExport Module : public Extensible
         * @param user The user issuing /INFO
         */
        virtual void OnInfo(User* user);
-       
+
        /** Called whenever a /WHOIS is performed on a local user.
         * The source parameter contains the details of the user who issued the WHOIS command, and
         * the dest parameter contains the information of the user they are whoising.
@@ -611,7 +662,7 @@ class CoreExport Module : public Extensible
         * @param dest The user who is being WHOISed
         */
        virtual void OnWhois(User* source, User* dest);
-       
+
        /** Called whenever a user is about to invite another user into a channel, before any processing is done.
         * Returning 1 from this function stops the process immediately, causing no
         * output to be sent to the user by the core. If you do this you must produce your own numerics,
@@ -620,10 +671,10 @@ class CoreExport Module : public Extensible
         * @param dest The user being invited
         * @param channel The channel the user is being invited to
         * @param timeout The time the invite will expire (0 == never)
-        * @return 1 to deny the invite, 0 to allow
+        * @return 1 to deny the invite, 0 to check whether or not the user has permission to invite, -1 to explicitly allow the invite
         */
-       virtual int OnUserPreInvite(User* source,User* dest,Channel* channel, time_t timeout);
-       
+       virtual ModResult OnUserPreInvite(User* source,User* dest,Channel* channel, time_t timeout);
+
        /** Called after a user has been successfully invited to a channel.
         * You cannot prevent the invite from occuring using this function, to do that,
         * use OnUserPreInvite instead.
@@ -633,7 +684,7 @@ class CoreExport Module : public Extensible
         * @param timeout The time the invite will expire (0 == never)
         */
        virtual void OnUserInvite(User* source,User* dest,Channel* channel, time_t timeout);
-       
+
        /** Called whenever a user is about to PRIVMSG A user or a channel, before any processing is done.
         * Returning any nonzero value from this function stops the process immediately, causing no
         * output to be sent to the user by the core. If you do this you must produce your own numerics,
@@ -648,9 +699,9 @@ class CoreExport Module : public Extensible
         * @param status The status being used, e.g. PRIVMSG @#chan has status== '@', 0 to send to everyone.
         * @param exempt_list A list of users not to send to. For channel messages, this will usually contain just the sender.
         * It will be ignored for private messages.
-        * @return 1 to deny the NOTICE, 0 to allow it
+        * @return 1 to deny the message, 0 to allow it
         */
-       virtual int OnUserPreMessage(User* user,void* dest,int target_type, std::string &text,char status, CUList &exempt_list);
+       virtual ModResult OnUserPreMessage(User* user,void* dest,int target_type, std::string &text,char status, CUList &exempt_list);
 
        /** Called whenever a user is about to NOTICE A user or a channel, before any processing is done.
         * Returning any nonzero value from this function stops the process immediately, causing no
@@ -671,7 +722,7 @@ class CoreExport Module : public Extensible
         * It will be ignored for private notices.
         * @return 1 to deny the NOTICE, 0 to allow it
         */
-       virtual int OnUserPreNotice(User* user,void* dest,int target_type, std::string &text,char status, CUList &exempt_list);
+       virtual ModResult OnUserPreNotice(User* user,void* dest,int target_type, std::string &text,char status, CUList &exempt_list);
 
        /** Called whenever the server wants to build the exemption list for a channel, but is not directly doing a PRIVMSG or NOTICE.
         * For example, the spanningtree protocol will call this event when passing a privmsg on (but not processing it directly).
@@ -683,7 +734,7 @@ class CoreExport Module : public Extensible
         * @param text The original message text causing the exempt list to be built
         */
        virtual void OnBuildExemptList(MessageType message_type, Channel* chan, User* sender, char status, CUList &exempt_list, const std::string &text);
-       
+
        /** Called before any nickchange, local or remote. This can be used to implement Q-lines etc.
         * Please note that although you can see remote nickchanges through this function, you should
         * NOT make any changes to the User if the user is a remote user as this may cause a desnyc.
@@ -694,7 +745,7 @@ class CoreExport Module : public Extensible
         * @param newnick Their new nickname
         * @return 1 to deny the change, 0 to allow
         */
-       virtual int OnUserPreNick(User* user, const std::string &newnick);
+       virtual ModResult OnUserPreNick(User* user, const std::string &newnick);
 
        /** Called after any PRIVMSG sent from a user.
         * The dest variable contains a User* if target_type is TYPE_USER and a Channel*
@@ -740,8 +791,9 @@ class CoreExport Module : public Extensible
         * @param dest The target of the modes (User* or Channel*)
         * @param target_type The type of target (TYPE_USER or TYPE_CHANNEL)
         * @param text The actual modes and their parameters if any
+        * @param translate The translation types of the mode parameters
         */
-       virtual void OnMode(User* user, void* dest, int target_type, const std::string &text);
+       virtual void OnMode(User* user, void* dest, int target_type, const std::vector<std::string> &text, const std::vector<TranslateType> &translate);
 
        /** Allows modules to alter or create server descriptions
         * Whenever a module requires a server description, for example for display in
@@ -772,9 +824,7 @@ class CoreExport Module : public Extensible
         * the linking protocol. This currently is m_spanningtree.so. A pointer to this module
         * is given in Module* proto, so that you may call its methods such as ProtoSendMode
         * (see below). This function will be called for every user visible on your side
-        * of the burst, allowing you to for example set modes, etc. Do not use this call to
-        * synchronize data which you have stored using class Extensible -- There is a specialist
-        * function OnSyncUserMetaData and OnSyncChannelMetaData for this!
+        * of the burst, allowing you to for example set modes, etc.
         *
         * For a good example of how to use this function, please see src/modules/m_chanprotect.cpp
         *
@@ -784,36 +834,6 @@ class CoreExport Module : public Extensible
         */
        virtual void OnSyncChannel(Channel* chan, Module* proto, void* opaque);
 
-       /* Allows modules to syncronize metadata related to channels over the network during a netburst.
-        * Whenever the linking module wants to send out data, but doesnt know what the data
-        * represents (e.g. it is Extensible metadata, added to a User or Channel by a module) then
-        * this method is called.You should use the ProtoSendMetaData function after you've
-        * correctly decided how the data should be represented, to send the metadata on its way if it belongs
-        * to your module. For a good example of how to use this method, see src/modules/m_swhois.cpp.
-        * @param chan The channel whos metadata is being syncronized
-        * @param proto A pointer to the module handling network protocol
-        * @param opaque An opaque pointer set by the protocol module, should not be modified!
-        * @param extname The extensions name which is being searched for
-        * @param displayable If this value is true, the data is going to be displayed to a user,
-        * and not sent across the network. Use this to determine wether or not to show sensitive data.
-        */
-       virtual void OnSyncChannelMetaData(Channel* chan, Module* proto,void* opaque, const std::string &extname, bool displayable = false);
-
-       /* Allows modules to syncronize metadata related to users over the network during a netburst.
-        * Whenever the linking module wants to send out data, but doesnt know what the data
-        * represents (e.g. it is Extensible metadata, added to a User or Channel by a module) then
-        * this method is called. You should use the ProtoSendMetaData function after you've
-        * correctly decided how the data should be represented, to send the metadata on its way if
-        * if it belongs to your module.
-        * @param user The user whos metadata is being syncronized
-        * @param proto A pointer to the module handling network protocol
-        * @param opaque An opaque pointer set by the protocol module, should not be modified!
-        * @param extname The extensions name which is being searched for
-        * @param displayable If this value is true, the data is going to be displayed to a user,
-        * and not sent across the network. Use this to determine wether or not to show sensitive data.
-        */
-       virtual void OnSyncUserMetaData(User* user, Module* proto,void* opaque, const std::string &extname, bool displayable = false);
-
        /* Allows modules to syncronize metadata not related to users or channels, over the network during a netburst.
         * Whenever the linking module wants to send out data, but doesnt know what the data
         * represents (e.g. it is Extensible metadata, added to a User or Channel by a module) then
@@ -825,7 +845,7 @@ class CoreExport Module : public Extensible
         * @param displayable If this value is true, the data is going to be displayed to a user,
         * and not sent across the network. Use this to determine wether or not to show sensitive data.
         */
-       virtual void OnSyncOtherMetaData(Module* proto, void* opaque, bool displayable = false);
+       virtual void OnSyncNetwork(Module* proto, void* opaque);
 
        /** Allows module data, sent via ProtoSendMetaData, to be decoded again by a receiving module.
         * Please see src/modules/m_swhois.cpp for a working example of how to use this method call.
@@ -834,7 +854,7 @@ class CoreExport Module : public Extensible
         * @param extname The extension name which is being sent
         * @param extdata The extension data, encoded at the other end by an identical module through OnSyncChannelMetaData or OnSyncUserMetaData
         */
-       virtual void OnDecodeMetaData(int target_type, void* target, const std::string &extname, const std::string &extdata);
+       virtual void OnDecodeMetaData(Extensible* target, const std::string &extname, const std::string &extdata);
 
        /** Implemented by modules which provide the ability to link servers.
         * These modules will implement this method, which allows transparent sending of servermodes
@@ -848,8 +868,9 @@ class CoreExport Module : public Extensible
         * @param target_type The type of item to decode data for, TYPE_USER or TYPE_CHANNEL
         * @param target The Channel* or User* that modes should be sent for
         * @param modeline The modes and parameters to be sent
+        * @param translate The translation types of the mode parameters
         */
-       virtual void ProtoSendMode(void* opaque, int target_type, void* target, const std::string &modeline);
+       virtual void ProtoSendMode(void* opaque, TargetTypeFlags target_type, void* target, const std::vector<std::string> &modeline, const std::vector<TranslateType> &translate);
 
        /** Implemented by modules which provide the ability to link servers.
         * These modules will implement this method, which allows metadata (extra data added to
@@ -865,8 +886,15 @@ class CoreExport Module : public Extensible
         * @param extname The extension name to send metadata for
         * @param extdata Encoded data for this extension name, which will be encoded at the oppsite end by an identical module using OnDecodeMetaData
         */
-       virtual void ProtoSendMetaData(void* opaque, int target_type, void* target, const std::string &extname, const std::string &extdata);
-       
+       virtual void ProtoSendMetaData(void* opaque, Extensible* target, const std::string &extname, const std::string &extdata);
+
+       /**
+        * Implemented by all modules that implement ProtoSendMetaData.
+        * Translates the item into a string format suitable for sending to other servers.
+        * Currently, this just translates nicks to their UID and channels to their name
+        */
+       virtual std::string ProtoTranslate(Extensible* item);
+
        /** Called after every WALLOPS command.
         * @param user The user sending the WALLOPS
         * @param text The content of the WALLOPS message
@@ -887,6 +915,13 @@ class CoreExport Module : public Extensible
         */
        virtual void OnChangeName(User* user, const std::string &gecos);
 
+       /** Called whenever a user's IDENT is changed.
+        * This event triggers after the name has been set.
+        * @param user The user who's IDENT is being changed
+        * @param gecos The new IDENT being set on the user
+        */
+       virtual void OnChangeIdent(User* user, const std::string &ident);
+
        /** Called whenever an xline is added by a local user.
         * This method is triggered after the line is added.
         * @param source The sender of the line or NULL for local server
@@ -934,15 +969,15 @@ class CoreExport Module : public Extensible
         * before opping a user, deopping a user, kicking a user, etc.
         * There are several values for access_type which indicate for what reason access is being checked.
         * These are:<br><br>
-        * AC_KICK (0) - A user is being kicked<br>
-        * AC_DEOP (1) - a user is being deopped<br>
-        * AC_OP (2) - a user is being opped<br>
-        * AC_VOICE (3) - a user is being voiced<br>
-        * AC_DEVOICE (4) - a user is being devoiced<br>
-        * AC_HALFOP (5) - a user is being halfopped<br>
-        * AC_DEHALFOP (6) - a user is being dehalfopped<br>
-        * AC_INVITE () - a user is being invited<br>
-        * AC_GENERAL_MODE (8) - a user channel mode is being changed<br><br>
+        * AC_KICK - A user is being kicked<br>
+        * AC_DEOP - a user is being deopped<br>
+        * AC_OP - a user is being opped<br>
+        * AC_VOICE - a user is being voiced<br>
+        * AC_DEVOICE - a user is being devoiced<br>
+        * AC_HALFOP - a user is being halfopped<br>
+        * AC_DEHALFOP - a user is being dehalfopped<br>
+        * AC_INVITE - a user is being invited<br>
+        * AC_GENERAL_MODE - a user channel mode is being changed<br><br>
         * Upon returning from your function you must return either ACR_DEFAULT, to indicate the module wishes
         * to do nothing, or ACR_DENY where approprate to deny the action, and ACR_ALLOW where appropriate to allow
         * the action. Please note that in the case of some access checks (such as AC_GENERAL_MODE) access may be
@@ -954,7 +989,7 @@ class CoreExport Module : public Extensible
         * @param channel The channel which is being checked
         * @param access_type See above
         */
-       virtual int OnAccessCheck(User* source,User* dest,Channel* channel,int access_type);
+       virtual ModResult OnAccessCheck(User* source,User* dest,Channel* channel,int access_type);
 
        /** Called when a 005 numeric is about to be output.
         * The module should modify the 005 numeric if needed to indicate its features.
@@ -975,7 +1010,7 @@ class CoreExport Module : public Extensible
         * @param reason The kill reason
         * @return 1 to prevent the kill, 0 to allow
         */
-       virtual int OnKill(User* source, User* dest, const std::string &reason);
+       virtual ModResult OnKill(User* source, User* dest, const std::string &reason);
 
        /** Called when an oper wants to disconnect a remote user via KILL
         * @param source The user sending the KILL
@@ -1038,7 +1073,7 @@ class CoreExport Module : public Extensible
         * @param original_line The entire original line as passed to the parser from the user
         * @return 1 to block the command, 0 to allow
         */
-       virtual int OnPreCommand(std::string &command, std::vector<std::string>& parameters, User *user, bool validated, const std::string &original_line);
+       virtual ModResult OnPreCommand(std::string &command, std::vector<std::string>& parameters, User *user, bool validated, const std::string &original_line);
 
        /** Called after any command has been executed.
         * This event occurs for all registered commands, wether they are registered in the core,
@@ -1064,7 +1099,7 @@ class CoreExport Module : public Extensible
         * @param user The user to check
         * @return true to indicate readiness, false if otherwise
         */
-       virtual bool OnCheckReady(User* user);
+       virtual ModResult OnCheckReady(User* user);
 
        /** Called whenever a user is about to register their connection (e.g. before the user
         * is sent the MOTD etc). Modules can use this method if they are performing a function
@@ -1075,7 +1110,7 @@ class CoreExport Module : public Extensible
         * @param user The user registering
         * @return 1 to indicate user quit, 0 to continue
         */
-       virtual int OnUserRegister(User* user);
+       virtual ModResult OnUserRegister(User* user);
 
        /** Called whenever a user joins a channel, to determine if invite checks should go ahead or not.
         * This method will always be called for each join, wether or not the channel is actually +i, and
@@ -1085,7 +1120,7 @@ class CoreExport Module : public Extensible
         * @param chan The channel being joined
         * @return 1 to explicitly allow the join, 0 to proceed as normal
         */
-       virtual int OnCheckInvite(User* user, Channel* chan);
+       virtual ModResult OnCheckInvite(User* user, Channel* chan);
 
        /** Called whenever a mode character is processed.
         * Return 1 from this function to block the mode character from being processed entirely.
@@ -1099,7 +1134,7 @@ class CoreExport Module : public Extensible
         * to skip all permission checking. Please note that for remote mode changes, your return value
         * will be ignored!
         */
-       virtual int OnRawMode(User* user, Channel* chan, const char mode, const std::string &param, bool adding, int pcnt, bool servermode = true);
+       virtual ModResult OnRawMode(User* user, Channel* chan, const char mode, const std::string &param, bool adding, int pcnt);
 
        /** Called whenever a user joins a channel, to determine if key checks should go ahead or not.
         * This method will always be called for each join, wether or not the channel is actually +k, and
@@ -1110,7 +1145,7 @@ class CoreExport Module : public Extensible
         * @param chan The channel being joined
         * @return 1 to explicitly allow the join, 0 to proceed as normal
         */
-       virtual int OnCheckKey(User* user, Channel* chan, const std::string &keygiven);
+       virtual ModResult OnCheckKey(User* user, Channel* chan, const std::string &keygiven);
 
        /** Called whenever a user joins a channel, to determine if channel limit checks should go ahead or not.
         * This method will always be called for each join, wether or not the channel is actually +l, and
@@ -1120,7 +1155,7 @@ class CoreExport Module : public Extensible
         * @param chan The channel being joined
         * @return 1 to explicitly allow the join, 0 to proceed as normal
         */
-       virtual int OnCheckLimit(User* user, Channel* chan);
+       virtual ModResult OnCheckLimit(User* user, Channel* chan);
 
        /** Called whenever a user joins a channel, to determine if banlist checks should go ahead or not.
         * This method will always be called for each join, wether or not the user actually matches a channel ban, and
@@ -1131,7 +1166,22 @@ class CoreExport Module : public Extensible
         * @return 1 to explicitly allow the join, 0 to proceed as normal. Return -1 to explicitly deny the
         * join to the channel.
         */
-       virtual int OnCheckBan(User* user, Channel* chan);
+       virtual ModResult OnCheckBan(User* user, Channel* chan);
+
+       /* Called whenever checking whether or not a user is matched by an applicable extended bantype.
+        * NOTE: may also trigger extra OnCheckStringExtBan events!
+        * @param u The user to check
+        * @param c The channel the user is on
+        * @param type The type of extended ban to check for.
+        * @returns 1 = exempt, 0 = no match, -1 = banned
+        */
+       virtual ModResult OnCheckExtBan(User *u, Channel *c, char type);
+
+       /** Called whenever checking whether or not a string is extbanned. NOTE: one OnCheckExtBan will also trigger a number of
+        * OnCheckStringExtBan events for seperate host/IP comnbinations.
+        * @returns 1 = exempt, 0 = no match, -1 = banned
+        */
+       virtual ModResult OnCheckStringExtBan(const std::string &s, Channel *c, char type);
 
        /** Called on all /STATS commands
         * This method is triggered for all /STATS use, including stats symbols handled by the core.
@@ -1142,7 +1192,7 @@ class CoreExport Module : public Extensible
         * work when remote STATS queries are received.
         * @return 1 to block the /STATS from being processed by the core, 0 to allow it
         */
-       virtual int OnStats(char symbol, User* user, string_list &results);
+       virtual ModResult OnStats(char symbol, User* user, string_list &results);
 
        /** Called whenever a change of a local users displayed host is attempted.
         * Return 1 to deny the host change, or 0 to allow it.
@@ -1150,7 +1200,7 @@ class CoreExport Module : public Extensible
         * @param newhost The new hostname
         * @return 1 to deny the host change, 0 to allow
         */
-       virtual int OnChangeLocalUserHost(User* user, const std::string &newhost);
+       virtual ModResult OnChangeLocalUserHost(User* user, const std::string &newhost);
 
        /** Called whenever a change of a local users GECOS (fullname field) is attempted.
         * return 1 to deny the name change, or 0 to allow it.
@@ -1158,16 +1208,16 @@ class CoreExport Module : public Extensible
         * @param newhost The new GECOS
         * @return 1 to deny the GECOS change, 0 to allow
         */
-       virtual int OnChangeLocalUserGECOS(User* user, const std::string &newhost); 
+       virtual ModResult OnChangeLocalUserGECOS(User* user, const std::string &newhost);
 
        /** Called whenever a topic is changed by a local user.
-        * Return 1 to deny the topic change, or 0 to allow it.
+        * Return 1 to deny the topic change, 0 to check details on the change, -1 to let it through with no checks
         * @param user The user changing the topic
         * @param chan The channels who's topic is being changed
         * @param topic The actual topic text
         * @param 1 to block the topic change, 0 to allow
         */
-       virtual int OnLocalTopicChange(User* user, Channel* chan, const std::string &topic);
+       virtual ModResult OnLocalTopicChange(User* user, Channel* chan, const std::string &topic);
 
        /** Called whenever a local topic has been changed.
         * To block topic changes you must use OnLocalTopicChange instead.
@@ -1204,7 +1254,7 @@ class CoreExport Module : public Extensible
         * @param hashtype The hash value from the config
         * @return 0 to do nothing (pass on to next module/default), 1 == password is OK, -1 == password is not OK
         */
-       virtual int OnPassCompare(Extensible* ex, const std::string &password, const std::string &input, const std::string& hashtype);
+       virtual ModResult OnPassCompare(Extensible* ex, const std::string &password, const std::string &input, const std::string& hashtype);
 
        /** Called whenever a user is given usermode +o, anywhere on the network.
         * You cannot override this and prevent it from happening as it is already happened and
@@ -1229,7 +1279,7 @@ class CoreExport Module : public Extensible
         * @param banmask The ban mask being added
         * @return 1 to block the ban, 0 to continue as normal
         */
-       virtual int OnAddBan(User* source, Channel* channel,const std::string &banmask);
+       virtual ModResult OnAddBan(User* source, Channel* channel,const std::string &banmask);
 
        /** Called whenever a ban is removed from a channel's list.
         * Return a non-zero value to 'eat' the mode change and prevent the ban from being removed.
@@ -1238,9 +1288,13 @@ class CoreExport Module : public Extensible
         * @param banmask The ban mask being deleted
         * @return 1 to block the unban, 0 to continue as normal
         */
-       virtual int OnDelBan(User* source, Channel* channel,const std::string &banmask);
+       virtual ModResult OnDelBan(User* source, Channel* channel,const std::string &banmask);
 
-       virtual void OnHookUserIO(User* user, const std::string &targetip);
+       /** Called to install an I/O hook on an event handler
+        * @param user The item to possibly install the I/O hook on
+        * @param via The port that <user> connected on
+        */
+       virtual void OnHookIO(EventHandler* user, ListenSocketBase* via);
 
        /** Called immediately after any  connection is accepted. This is intended for raw socket
         * processing (e.g. modules which wrap the tcp connection within another library) and provides
@@ -1248,10 +1302,11 @@ class CoreExport Module : public Extensible
         * There are no return values from this call as all modules get an opportunity if required to
         * process the connection.
         * @param fd The file descriptor returned from accept()
-        * @param ip The IP address of the connecting user
+        * @param client The client IP address and port
+        * @param server The server IP address and port
         * @param localport The local port number the user connected to
         */
-       virtual void OnRawSocketAccept(int fd, const std::string &ip, int localport);
+       virtual void OnRawSocketAccept(int fd, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server);
 
        /** Called immediately before any write() operation on a user's socket in the core. Because
         * this event is a low level event no user information is associated with it. It is intended
@@ -1302,7 +1357,7 @@ class CoreExport Module : public Extensible
         * @param awaymsg The away message of the user, or empty if returning from away
         * @return nonzero if the away message should be blocked - should ONLY be nonzero for LOCAL users (IS_LOCAL) (no output is returned by core)
         */
-       virtual int OnSetAway(User* user, const std::string &awaymsg);
+       virtual ModResult OnSetAway(User* user, const std::string &awaymsg);
 
        /** Called whenever a NAMES list is requested.
         * You can produce the nameslist yourself, overriding the current list,
@@ -1317,7 +1372,7 @@ class CoreExport Module : public Extensible
         * Returning -1 allows the names list, but bypasses any checks which check for
         * channel membership before sending the names list.
         */
-       virtual int OnUserList(User* user, Channel* Ptr, CUList* &userlist);
+       virtual ModResult OnUserList(User* user, Channel* Ptr, CUList* &userlist);
 
        /** Called whenever a line of WHOIS output is sent to a user.
         * You may change the numeric and the text of the output by changing
@@ -1330,7 +1385,7 @@ class CoreExport Module : public Extensible
         * @return nonzero to drop the line completely so that the user does not
         * receive it, or zero to allow the line to be sent.
         */
-       virtual int OnWhoisLine(User* user, User* dest, int &numeric, std::string &text);
+       virtual ModResult OnWhoisLine(User* user, User* dest, int &numeric, std::string &text);
 
        /** Called at intervals for modules to garbage-collect any hashes etc.
         * Certain data types such as hash_map 'leak' buckets, which must be
@@ -1359,7 +1414,21 @@ class CoreExport Module : public Extensible
         */
        virtual void OnNamesListItem(User* issuer, User* user, Channel* channel, std::string &prefixes, std::string &nick);
 
-       virtual int OnNumeric(User* user, unsigned int numeric, const std::string &text);
+       virtual ModResult OnNumeric(User* user, unsigned int numeric, const std::string &text);
+
+       /** Called for every time the user's host or ident changes, to indicate wether or not the 'Changing host'
+        * message should be sent, if enabled. Certain modules such as auditorium may opt to hide this message
+        * even if it is enabled.
+        */
+       virtual ModResult OnHostCycle(User* user);
+
+       /** Called whenever a result from /WHO is about to be returned
+        * @param source The user running the /WHO query
+        * @param user The user that this line of the query is about
+        * @param channel The channel being queried (or NULL if not a channel query)
+        * @param line The raw line to send; modifiable, if empty no line will be returned.
+        */
+       virtual void OnSendWhoLine(User* source, User* user, Channel* channel, std::string& line);
 };
 
 
@@ -1380,35 +1449,16 @@ class CoreExport ConfigReader : public classbase
 {
   protected:
        InspIRCd* ServerInstance;
-       /** The contents of the configuration file
-        * This protected member should never be accessed by a module (and cannot be accessed unless the
-        * core is changed). It will contain a pointer to the configuration file data with unneeded data
-        * (such as comments) stripped from it.
-        */
-       ConfigDataHash* data;
-       /** Used to store errors
-        */
-       std::ostringstream* errorlog;
-       /** If we're using our own config data hash or not
-        */
-       bool privatehash;
-       /** True if an error occured reading the config file
-        */
-       bool readerror;
        /** Error code
         */
        long error;
-       
+
   public:
        /** Default constructor.
         * This constructor initialises the ConfigReader class to read the inspircd.conf file
         * as specified when running ./configure.
         */
        ConfigReader(InspIRCd* Instance);
-       /** Overloaded constructor.
-        * This constructor initialises the ConfigReader class to read a user-specified config file
-        */
-       ConfigReader(InspIRCd* Instance, const std::string &filename);
        /** Default destructor.
         * This method destroys the ConfigReader class.
         */
@@ -1472,18 +1522,6 @@ class CoreExport ConfigReader : public classbase
         * multiple instance tag.
         */
        int Enumerate(const std::string &tag);
-       /** Returns true if a config file is valid.
-        * This method is partially implemented and will only return false if the config
-        * file does not exist or could not be opened.
-        */
-       bool Verify();
-       /** Dumps the list of errors in a config file to an output location. If bail is true,
-        * then the program will abort. If bail is false and user points to a valid user
-        * record, the error report will be spooled to the given user by means of NOTICE.
-        * if bool is false AND user is false, the error report will be spooled to all opers
-        * by means of a NOTICE to all opers.
-        */
-       void DumpErrors(bool bail,User* user);
 
        /** Returns the number of items within a tag.
         * For example if the tag was &lt;test tag="blah" data="foo"&gt; then this
@@ -1553,7 +1591,7 @@ class CoreExport FileReader : public classbase
         * This function will return false if the file could not be opened.
         */
        bool Exists();
+
        /** Retrieve one line from the file.
         * This method retrieves one line from the text file. If an empty non-NULL string is returned,
         * the index was out of bounds, or the line had no data on it.
@@ -1584,17 +1622,6 @@ typedef std::vector<Module*> IntModuleList;
  */
 typedef IntModuleList::iterator EventHandlerIter;
 
-/** Module priority states
- */
-enum PriorityState
-{
-       PRIO_DONTCARE,
-       PRIO_FIRST,
-       PRIO_LAST,
-       PRIO_AFTER,
-       PRIO_BEFORE
-};
-
 /** ModuleManager takes care of all things module-related
  * in the core.
  */
@@ -1604,19 +1631,19 @@ class CoreExport ModuleManager : public classbase
        /** Holds a string describing the last module error to occur
         */
        std::string LastModuleError;
-       /** The feature names published by various modules
+
+       /** 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; 
-       
+       int ModCount;
+
        /** Our pointer to the main insp instance
         */
        InspIRCd* Instance;
@@ -1626,6 +1653,11 @@ class CoreExport ModuleManager : public classbase
         */
        std::map<std::string, std::pair<ircd_module*, Module*> > Modules;
 
+       enum {
+               PRIO_STATE_FIRST,
+               PRIO_STATE_AGAIN,
+               PRIO_STATE_LAST
+       } prioritizationState;
  public:
 
        /** Event handler hooks.
@@ -1639,7 +1671,7 @@ class CoreExport ModuleManager : public classbase
 
        /** Destructor
         */
-       ~ModuleManager(); 
+       ~ModuleManager();
 
        /** Change the priority of one event in a module.
         * Each module event has a list of modules which are attached to that event type.
@@ -1651,28 +1683,28 @@ class CoreExport ModuleManager : public classbase
         * @param i The event to change the priority of
         * @param s The state you wish to use for this event. Use one of
         * PRIO_FIRST to set the event to be first called, PRIO_LAST to
-        * set it to be the last called, or PRIO_BEFORE and PRIO_AFTER
+        * set it to be the last called, or PRIO_BEFORE and PRIORITY_AFTER
         * to set it to be before or after one or more other modules.
-        * @param modules If PRIO_BEFORE or PRIO_AFTER is set in parameter 's',
-        * then this contains a list of one or more modules your module must be 
+        * @param modules If PRIO_BEFORE or PRIORITY_AFTER is set in parameter 's',
+        * then this contains a list of one or more modules your module must be
         * placed before or after. Your module will be placed before the highest
         * priority module in this list for PRIO_BEFORE, or after the lowest
-        * priority module in this list for PRIO_AFTER.
-        * @param sz The number of modules being passed for PRIO_BEFORE and PRIO_AFTER.
+        * priority module in this list for PRIORITY_AFTER.
+        * @param sz The number of modules being passed for PRIO_BEFORE and PRIORITY_AFTER.
         * Defaults to 1, as most of the time you will only want to prioritize your module
         * to be before or after one other module.
         */
-       bool SetPriority(Module* mod, Implementation i, PriorityState s, Module** modules = NULL, size_t sz = 1);
+       bool SetPriority(Module* mod, Implementation i, Priority s, Module** modules = NULL, size_t sz = 1);
 
        /** Change the priority of all events in a module.
         * @param mod The module to set the priority of
         * @param s The priority of all events in the module.
         * Note that with this method, it is not possible to effectively use
-        * PRIO_BEFORE or PRIO_AFTER, you should use the more fine tuned
+        * PRIO_BEFORE or PRIORITY_AFTER, you should use the more fine tuned
         * SetPriority method for this, where you may specify other modules to
         * be prioritized against.
         */
-       bool SetPriority(Module* mod, PriorityState s);
+       bool SetPriority(Module* mod, Priority s);
 
        /** Attach an event to a module.
         * You may later detatch the event with ModuleManager::Detach().
@@ -1702,7 +1734,7 @@ class CoreExport ModuleManager : public classbase
         * @param mod Module to detach from
         */
        void DetachAll(Module* mod);
+
        /** Returns text describing the last module error
         * @return The last error message to occur
         */
@@ -1719,11 +1751,11 @@ class CoreExport ModuleManager : public classbase
         * @return True if the module was unloaded
         */
        bool Unload(const char* filename);
-       
+
        /** Called by the InspIRCd constructor to load all modules from the config file.
         */
        void LoadAll();
-       
+
        /** Get the total number of currently loaded modules
         * @return The number of loaded modules
         */
@@ -1731,14 +1763,14 @@ class CoreExport ModuleManager : public classbase
        {
                return this->ModCount;
        }
-       
+
        /** Find a module by name, and return a Module* to it.
         * This is preferred over iterating the module lists yourself.
         * @param name The module name to look up
         * @return A pointer to the module, or NULL if the module cannot be found
         */
        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