]> 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 21e4760897f234045690980735f169f3c88b6287..86f77d2183d19914498e32218f7d42f72907b653 100644 (file)
@@ -41,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
@@ -50,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()
@@ -76,6 +78,48 @@ enum MessageType {
        MSG_NOTICE = 1
 };
 
+#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.
+ */
+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
 
@@ -155,83 +199,48 @@ 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(); ) \
-       { \
-               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; \
-       } \
-} while (0);
-
-#define FOREACH_RESULT_MAP(y,x,f) \
-do { \
-       EventHandlerIter safei; \
-       for (EventHandlerIter _i = ServerInstance->Modules->EventHandlers[y].begin(); _i != ServerInstance->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 MOD_RESULT = (*_i)->x ; \
-                       f; \
-               } \
-               catch (CoreException& modexcept) \
-               { \
-                       ServerInstance->Logs->Log("MODULE",DEFAULT,"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)
@@ -268,7 +277,7 @@ class CoreExport Version : public classbase
  public:
        /** Version information.
         */
-       std::string version;
+       const std::string version;
 
        /** Flags and API version
         */
@@ -276,7 +285,8 @@ class CoreExport Version : public classbase
 
        /** Initialize version class
         */
-       Version(const std::string &sversion, int flags, int api_ver);
+       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
@@ -403,20 +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_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_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_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_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_OnHostCycle,
-       I_OnPreRehash, I_OnModuleRehash,
+       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
 };
 
@@ -434,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.
@@ -485,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
@@ -501,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
@@ -560,7 +577,7 @@ class CoreExport Module : public Extensible
         * @param message The text message to be sent via snotice
         * @return 1 to block the snotice from being sent entirely, 0 else.
         */
-       virtual int OnSendSnotice(char &snomask, std::string &type, const std::string &message);
+       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
@@ -582,7 +599,7 @@ 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
@@ -594,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
@@ -656,7 +673,7 @@ class CoreExport Module : public Extensible
         * @param timeout The time the invite will expire (0 == never)
         * @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,
@@ -684,7 +701,7 @@ class CoreExport Module : public Extensible
         * It will be ignored for private messages.
         * @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
@@ -705,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).
@@ -728,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*
@@ -807,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
         *
@@ -819,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
@@ -860,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.
@@ -869,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
@@ -901,7 +886,14 @@ 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, TargetTypeFlags 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
@@ -923,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
@@ -990,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.
@@ -1011,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
@@ -1074,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,
@@ -1100,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
@@ -1111,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
@@ -1121,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.
@@ -1135,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
@@ -1146,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
@@ -1156,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
@@ -1167,7 +1166,7 @@ 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!
@@ -1176,13 +1175,13 @@ class CoreExport Module : public Extensible
         * @param type The type of extended ban to check for.
         * @returns 1 = exempt, 0 = no match, -1 = banned
         */
-       virtual int OnCheckExtBan(User *u, Channel *c, char type);
+       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 int OnCheckStringExtBan(const std::string &s, Channel *c, char type);
+       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.
@@ -1193,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.
@@ -1201,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.
@@ -1209,7 +1208,7 @@ 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, 0 to check details on the change, -1 to let it through with no checks
@@ -1218,7 +1217,7 @@ class CoreExport Module : public Extensible
         * @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.
@@ -1255,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
@@ -1280,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.
@@ -1289,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);
+       /** 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
@@ -1354,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,
@@ -1369,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
@@ -1382,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
@@ -1411,13 +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 bool OnHostCycle(User* user);
+       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);
 };