]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - include/modules.h
Document ENCAP.
[user/henk/code/inspircd.git] / include / modules.h
index f6ac7fd613dd4e3b9b819748bf184dd0d8642139..a625a082c9cf96d54a8c3263be00767053adb72d 100644 (file)
@@ -2,7 +2,7 @@
  *       | Inspire Internet Relay Chat Daemon |
  *       +------------------------------------+
  *
- *  InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ *  InspIRCd: (C) 2002-2008 InspIRCd Development Team
  * See: http://www.inspircd.org/wiki/index.php/Credits
  *
  * This program is free but copyrighted software; see
 #ifndef __MODULES_H
 #define __MODULES_H
 
+#include "dynamic.h"
+#include "base.h"
+#include "ctables.h"
+#include "inspsocket.h"
+#include <string>
+#include <deque>
+#include <sstream>
+#include "timer.h"
+#include "mode.h"
+#include "dns.h"
+
 class XLine;
 
 /** Used with OnAccessCheck() method of modules
@@ -65,18 +76,6 @@ enum MessageType {
        MSG_NOTICE = 1
 };
 
-#include "globals.h"
-#include "dynamic.h"
-#include "base.h"
-#include "ctables.h"
-#include "inspsocket.h"
-#include <string>
-#include <deque>
-#include <sstream>
-#include "timer.h"
-#include "mode.h"
-#include "dns.h"
-
 /** 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
@@ -123,19 +122,23 @@ typedef std::map<std::string, std::pair<int, modulelist> > interfacelist;
  * loaded modules in a readable simple way, e.g.:
  * 'FOREACH_MOD(I_OnConnect,OnConnect(user));'
  */
-#define FOREACH_MOD(y,x) if (ServerInstance->Config->global_implementation[y] > 0) { \
-       for (int _i = 0; _i <= ServerInstance->Modules->GetCount(); _i++) { \
-       if (ServerInstance->Config->implement_lists[_i][y]) \
+#define FOREACH_MOD(y,x) do { \
+       EventHandlerIter safei; \
+       for (EventHandlerIter _i = ServerInstance->Modules->EventHandlers[y].begin(); _i != ServerInstance->Modules->EventHandlers[y].end(); ) \
+       { \
+               safei = _i; \
+               ++safei; \
                try \
                { \
-                       ServerInstance->Modules->modules[_i]->x ; \
+                       (*_i)->x ; \
                } \
                catch (CoreException& modexcept) \
                { \
-                       ServerInstance->Log(DEFAULT,"Exception caught: %s",modexcept.GetReason()); \
+                       ServerInstance->Logs->Log("MODULE",DEFAULT,"Exception caught: %s",modexcept.GetReason()); \
                } \
+               _i = safei; \
        } \
-  }
+} while (0);
 
 /**
  * This #define allows us to call a method in all
@@ -143,70 +146,82 @@ typedef std::map<std::string, std::pair<int, modulelist> > interfacelist;
  * an instance pointer to the macro. e.g.:
  * 'FOREACH_MOD_I(Instance, OnConnect, OnConnect(user));'
  */
-#define FOREACH_MOD_I(z,y,x) if (z->Config->global_implementation[y] > 0) { \
-       for (int _i = 0; _i <= z->Modules->GetCount(); _i++) { \
-               if (z->Config->implement_lists[_i][y]) \
+#define FOREACH_MOD_I(z,y,x) do { \
+       EventHandlerIter safei; \
+       for (EventHandlerIter _i = z->Modules->EventHandlers[y].begin(); _i != z->Modules->EventHandlers[y].end(); ) \
+       { \
+               safei = _i; \
+               ++safei; \
                try \
                { \
-                       z->Modules->modules[_i]->x ; \
+                       (*_i)->x ; \
                } \
                catch (CoreException& modexcept) \
                { \
-                       z->Log(DEFAULT,"Exception caught: %s",modexcept.GetReason()); \
+                       z->Logs->Log("MODULE",DEFAULT,"Exception caught: %s",modexcept.GetReason()); \
                } \
+               _i = safei; \
        } \
-}
+} 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.
  */
-#define FOREACH_RESULT(y,x) { if (ServerInstance->Config->global_implementation[y] > 0) { \
-                       MOD_RESULT = 0; \
-                       for (int _i = 0; _i <= ServerInstance->Modules->GetCount(); _i++) { \
-                       if (ServerInstance->Config->implement_lists[_i][y]) { \
-                               try \
-                               { \
-                                       int res = ServerInstance->Modules->modules[_i]->x ; \
-                                       if (res != 0) { \
-                                               MOD_RESULT = res; \
-                                               break; \
-                                       } \
-                               } \
-                               catch (CoreException& modexcept) \
-                               { \
-                                       ServerInstance->Log(DEFAULT,"Exception caught: %s",modexcept.GetReason()); \
-                               } \
+#define FOREACH_RESULT(y,x) \
+do { \
+       EventHandlerIter safei; \
+       MOD_RESULT = 0; \
+       for (EventHandlerIter _i = ServerInstance->Modules->EventHandlers[y].begin(); _i != ServerInstance->Modules->EventHandlers[y].end(); ) \
+       { \
+               safei = _i; \
+               ++safei; \
+               try \
+               { \
+                       int res = (*_i)->x ; \
+                       if (res != 0) { \
+                               MOD_RESULT = res; \
+                               break; \
                        } \
                } \
+               catch (CoreException& modexcept) \
+               { \
+                       ServerInstance->Logs->Log("MODULE",DEFAULT,"Exception caught: %s",modexcept.GetReason()); \
+               } \
+               _i = safei; \
        } \
- }
+} 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.
  */
-#define FOREACH_RESULT_I(z,y,x) { if (z->Config->global_implementation[y] > 0) { \
-                       MOD_RESULT = 0; \
-                       for (int _i = 0; _i <= z->Modules->GetCount(); _i++) { \
-                       if (z->Config->implement_lists[_i][y]) { \
-                               try \
-                               { \
-                                       int res = z->Modules->modules[_i]->x ; \
-                                       if (res != 0) { \
-                                               MOD_RESULT = res; \
-                                               break; \
-                                       } \
-                               } \
-                               catch (CoreException& modexcept) \
-                               { \
-                                       z->Log(DEBUG,"Exception caught: %s",modexcept.GetReason()); \
-                               } \
+#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);
 
 /** Represents a non-local user.
  * (in fact, any FD less than -1 does)
@@ -214,21 +229,17 @@ typedef std::map<std::string, std::pair<int, modulelist> > interfacelist;
 #define FD_MAGIC_NUMBER -42
 
 /* Useful macros */
-#ifdef WINDOWS
+
 /** Is a local user */
 #define IS_LOCAL(x) ((x->GetFd() > -1))
-#else
-/** Is a local user */
-#define IS_LOCAL(x) ((x->GetFd() > -1) && (x->GetFd() <= MAX_DESCRIPTORS))
-#endif
 /** Is a remote user */
 #define IS_REMOTE(x) (x->GetFd() < 0)
 /** Is a module created user */
 #define IS_MODULE_CREATED(x) (x->GetFd() == FD_MAGIC_NUMBER)
 /** Is an oper */
-#define IS_OPER(x) (*x->oper)
+#define IS_OPER(x) (!x->oper.empty())
 /** Is away */
-#define IS_AWAY(x) (*x->awaymsg)
+#define IS_AWAY(x) (!x->awaymsg.empty())
 
 /** Holds a module's Version information.
  *  The four members (set by the constructor only) indicate details as to the version number
@@ -240,13 +251,17 @@ typedef std::map<std::string, std::pair<int, modulelist> > interfacelist;
 class CoreExport Version : public classbase
 {
  public:
-        /** Version numbers, build number, flags and API version
-         */
-        const int Major, Minor, Revision, Build, Flags, API;
+       /** Version information.
+        */
+       std::string version;
+
+       /** Flags and API version
+        */
+       const int Flags, API;
 
-        /** Initialize version class
-         */
-        Version(int major, int minor, int revision, int build, int flags, int api_ver);
+       /** Initialize version class
+        */
+       Version(const std::string &sversion, int flags, int api_ver);
 };
 
 /** The ModuleMessage class is the base class of Request and Event
@@ -319,7 +334,7 @@ class CoreExport Request : public ModuleMessage
         * sent the request to. It is up to your module to know what this data is and
         * how to deal with it.
         */
-       char* Send();
+       const char* Send();
 };
 
 
@@ -370,19 +385,26 @@ enum Priority { PRIORITY_FIRST, PRIORITY_DONTCARE, PRIORITY_LAST, PRIORITY_BEFOR
 
 /** Implementation-specific flags which may be set in Module::Implements()
  */
-enum Implementation {  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_OnCleanup, I_OnUserPostNick, I_OnAccessCheck, I_On005Numeric, I_OnKill, I_OnRemoteKill, I_OnLoadModule, I_OnUnloadModule,
-                       I_OnBackgroundTimer, I_OnPreCommand, I_OnCheckReady, I_OnUserRrgister, I_OnCheckInvite,
-                       I_OnCheckKey, I_OnCheckLimit, I_OnCheckBan, I_OnStats, I_OnChangeLocalUserHost, I_OnChangeLocalUserGecos, I_OnLocalTopicChange,
-                       I_OnPostLocalTopicChange, I_OnEvent, I_OnRequest, I_OnOperCompre, I_OnGlobalOper, I_OnPostConnect, I_OnAddBan, I_OnDelBan,
-                       I_OnRawSocketAccept, I_OnRawSocketClose, I_OnRawSocketWrite, I_OnRawSocketRead, I_OnChangeLocalUserGECOS, I_OnUserRegister,
-                       I_OnOperCompare, I_OnChannelDelete, I_OnPostOper, I_OnSyncOtherMetaData, I_OnSetAway, I_OnCancelAway, I_OnUserList,
-                       I_OnPostCommand, I_OnPostJoin, I_OnWhoisLine, I_OnBuildExemptList, I_OnRawSocketConnect, I_OnGarbageCollect, I_OnBufferFlushed,
-                       I_OnText };
+enum Implementation
+{
+       I_BEGIN,
+       I_OnUserConnect, I_OnUserQuit, I_OnUserDisconnect, I_OnUserJoin, I_OnUserPart, I_OnRehash, I_OnServerRaw, 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_END
+};
+
+class ConfigReader;
 
 /** Base class for all InspIRCd modules
  *  This class is the base class for InspIRCd modules. All modules must inherit from this class,
@@ -409,47 +431,16 @@ class CoreExport Module : public Extensible
         */
        virtual ~Module();
 
+       virtual void Prioritize()
+       {
+       }
+
        /** Returns the version number of a Module.
         * The method should return a Version object with its version information assigned via
         * Version::Version
         */
        virtual Version GetVersion();
 
-       /** The Implements function specifies which methods a module should receive events for.
-        * The char* parameter passed to this function contains a set of true or false values
-        * (1 or 0) which indicate wether each function is implemented. You must use the Iimplementation
-        * enum (documented elsewhere on this page) to mark functions as active. For example, to
-        * receive events for OnUserJoin():
-        *
-        * Implements[I_OnUserJoin] = 1;
-        *
-        * @param The implement list
-        */
-       virtual void Implements(char* Implements);
-
-       /** Used to set the 'priority' of a module (e.g. when it is called in relation to other modules.
-        * Some modules prefer to be called before other modules, due to their design. For example, a
-        * module which is expected to operate on complete information would expect to be placed last, so
-        * that any other modules which wish to adjust that information would execute before it, to be sure
-        * its information is correct. You can change your module's priority by returning one of:
-        *
-        * PRIORITY_FIRST - To place your module first in the list
-        * 
-        * PRIORITY_LAST - To place your module last in the list
-        *
-        * PRIORITY_DONTCARE - To leave your module as it is (this is the default value, if you do not implement this function)
-        *
-        * The result of InspIRCd::PriorityBefore() - To move your module before another named module
-        *
-        * The result of InspIRCd::PriorityLast() - To move your module after another named module
-        *
-        * For a good working example of this method call, please see src/modules/m_spanningtree.cpp
-        * and src/modules/m_hostchange.so which make use of it. It is highly recommended that unless
-        * your module has a real need to reorder its priority, it should not implement this function,
-        * as many modules changing their priorities can make the system redundant.
-        */
-       virtual Priority Prioritize();
-
        /** Called when a user connects.
         * The details of the connecting user are available to you in the parameter User *user
         * @param user The user who is connecting
@@ -474,6 +465,12 @@ class CoreExport Module : public Extensible
         */
        virtual void OnUserDisconnect(User* user);
 
+       /** Called whenever a channel is about to be deleted
+        * @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);
+
        /** Called whenever a channel is deleted, either by QUIT, KICK or PART.
         * @param chan The channel being deleted
         */
@@ -486,8 +483,10 @@ class CoreExport Module : public Extensible
         * @param channel The channel being joined
         * @param silent Change this to true if you want to conceal the JOIN command from the other users
         * 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.
         */
-       virtual void OnUserJoin(User* user, Channel* channel, bool &silent);
+       virtual void OnUserJoin(User* user, Channel* channel, bool sync, bool &silent);
 
        /** Called after a user joins a channel
         * Identical to OnUserJoin, but called immediately afterwards, when any linking module has
@@ -502,11 +501,11 @@ class CoreExport Module : public Extensible
         * and the details of the channel they have left is available in the variable Channel *channel
         * @param user The user who is parting
         * @param channel The channel being parted
-        * @param partmessage The part message, or an empty string
+        * @param partmessage The part message, or an empty string (may be modified)
         * @param silent Change this to true if you want to conceal the PART command from the other users
         * of the channel (useful for modules such as auditorium)
         */
-       virtual void OnUserPart(User* user, Channel* channel, const std::string &partmessage, bool &silent);
+       virtual void OnUserPart(User* user, Channel* channel, std::string &partmessage, bool &silent);
 
        /** Called on rehash.
         * This method is called prior to a /REHASH or when a SIGHUP is received from the operating
@@ -532,6 +531,15 @@ class CoreExport Module : public Extensible
         */
        virtual void OnServerRaw(std::string &raw, bool inbound, 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 int 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
         * output to be sent to the user by the core. If you do this you must produce your own numerics,
@@ -549,9 +557,10 @@ class CoreExport Module : public Extensible
         * @param cname The channel name being joined. For new channels this is valid where chan is not.
         * @param privs A string containing the users privilages when joining the channel. For new channels this will contain "@".
         * You may alter this string to alter the user's modes on the channel.
+        * @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);
+       virtual int 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
@@ -590,9 +599,10 @@ class CoreExport Module : public Extensible
         * can be gauranteed to already have processed the oper-up, for example m_spanningtree has sent
         * out the OPERTYPE, etc.
         * @param user The user who is opering up
+        * @param opername The name of the oper that the user is opering up to. Only valid locally. Empty string otherwise.
         * @param opertype The opers type name
         */
-       virtual void OnPostOper(User* user, const std::string &opertype);
+       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
@@ -621,9 +631,10 @@ class CoreExport Module : public Extensible
         * @param source The user who is issuing the INVITE
         * @param dest The user being invited
         * @param channel The channel the user is being invited to
-        * @return 1 to deny the invite, 0 to allow
+        * @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);
+       virtual int 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,
@@ -631,8 +642,9 @@ class CoreExport Module : public Extensible
         * @param source The user who is issuing the INVITE
         * @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)
         */
-       virtual void OnUserInvite(User* source,User* dest,Channel* channel);
+       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
@@ -894,18 +906,18 @@ class CoreExport Module : public Extensible
         */
        virtual void OnAddLine(User* source, XLine* line);
 
-       /** Called whenever an xline is deleted.
+       /** Called whenever an xline is deleted MANUALLY. See OnExpireLine for expiry.
         * This method is triggered after the line is deleted.
         * @param source The user removing the line or NULL for local server
         * @param line the line being deleted
         */
        virtual void OnDelLine(User* source, XLine* line);
 
-       /** Called whenever a zline is deleted.
+       /** Called whenever an xline expires.
         * This method is triggered after the line is deleted.
-        * @param source The user removing the line
-        * @param hostmask The hostmask to delete
+        * @param line The line being deleted.
         */
+       virtual void OnExpireLine(XLine *line);
 
        /** Called before your module is unloaded to clean up Extensibles.
         * This method is called once for every user and channel on the network,
@@ -1034,10 +1046,11 @@ class CoreExport Module : public Extensible
         * @param pcnt The nuimber of parameters passed to the command
         * @param user the user issuing the command
         * @param validated True if the command has passed all checks, e.g. it is recognised, has enough parameters, the user has permission to execute it, etc.
+        * You should only change the parameter list and command string if validated == false (e.g. before the command lookup occurs).
         * @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(const std::string &command, const char** parameters, int pcnt, User *user, bool validated, const std::string &original_line);
+       virtual int 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,
@@ -1051,7 +1064,7 @@ class CoreExport Module : public Extensible
         * @param result The return code given by the command handler, one of CMD_SUCCESS or CMD_FAILURE
         * @param original_line The entire original line as passed to the parser from the user
         */
-       virtual void OnPostCommand(const std::string &command, const char** parameters, int pcnt, User *user, CmdResult result, const std::string &original_line);
+       virtual void OnPostCommand(const std::string &command, const std::vector<std::string>& parameters, User *user, CmdResult result, const std::string &original_line);
 
        /** Called to check if a user who is connecting can now be allowed to register
         * If any modules return false for this function, the user is held in the waiting
@@ -1086,6 +1099,20 @@ class CoreExport Module : public Extensible
         */
        virtual int 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.
+        * @param user The user who is sending the mode
+        * @param chan The channel the mode is being sent to (or NULL if a usermode)
+        * @param mode The mode character being set
+        * @param param The parameter for the mode or an empty string
+        * @param adding true of the mode is being added, false if it is being removed
+        * @param pcnt The parameter count for the mode (0 or 1)
+        * @return ACR_DENY to deny the mode, ACR_DEFAULT to do standard mode checking, and ACR_ALLOW
+        * 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);
+
        /** 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
         * determines the outcome of an if statement around the whole section of key checking code.
@@ -1113,10 +1140,24 @@ class CoreExport Module : public Extensible
         * return 1 to explicitly allow the join to go ahead or 0 to ignore the event.
         * @param user The user joining the channel
         * @param chan The channel being joined
-        * @return 1 to explicitly allow the join, 0 to proceed as normal
+        * @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);
 
+       /* 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.
+        */
+       virtual int 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.
+        */
+       virtual int 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.
         * @param symbol the symbol provided to /STATS
@@ -1145,7 +1186,7 @@ class CoreExport Module : public Extensible
        virtual int 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
@@ -1176,19 +1217,19 @@ class CoreExport Module : public Extensible
         * may be able to use for pre-determined purposes (e.g. the results of an SQL query, etc).
         * @param request The Request class being received
         */
-       virtual char* OnRequest(Request* request);
+       virtual const char* OnRequest(Request* request);
 
-       /** Called whenever an oper password is to be compared to what a user has input.
+       /** Called whenever a password check is to be made. Replaces the old OldOperCompare API.
         * The password field (from the config file) is in 'password' and is to be compared against
-        * 'input'. This method allows for encryption of oper passwords and much more besides.
-        * You should return a nonzero value if you want to allow the comparison or zero if you wish
-        * to do nothing.
-        * @param password The oper's password
-        * @param input The password entered
-        * @param tagnumber The tag number (from the configuration file) of this oper's tag
-        * @return 1 to match the passwords, 0 to do nothing. -1 to not match, and not continue.
+        * 'input'. This method allows for encryption of passwords (oper, connect:allow, die/restart, etc).
+        * You should return a nonzero value to override the normal comparison, or zero to pass it on.
+        * @param ex The object that's causing the authentication (User* for <oper> <connect:allow> etc, Server* for <link>).
+        * @param password The password from the configuration file (the password="" value).
+        * @param input The password entered by the user or whoever.
+        * @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 OnOperCompare(const std::string &password, const std::string &input, int tagnumber);
+       virtual int 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
@@ -1224,6 +1265,8 @@ class CoreExport Module : public Extensible
         */
        virtual int OnDelBan(User* source, Channel* channel,const std::string &banmask);
 
+       virtual void OnHookUserIO(User* user, const std::string &targetip);
+
        /** 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
         * no information relating to a user record as the connection has not been assigned yet.
@@ -1276,17 +1319,15 @@ class CoreExport Module : public Extensible
         */
        virtual int OnRawSocketRead(int fd, char* buffer, unsigned int count, int &readresult);
 
-       /** Called whenever a user sets away.
-        * This method has no parameter for the away message, as it is available in the
-        * user record as User::awaymsg.
+       /** Called whenever a user sets away or returns from being away.
+        * The away message is available as a parameter, but should not be modified.
+        * At this stage, it has already been copied into the user record.
+        * If awaymsg is empty, the user is returning from away.
         * @param user The user setting away
+        * @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 void OnSetAway(User* user);
-
-       /** Called when a user cancels their away state.
-        * @param user The user returning from away
-        */
-       virtual void OnCancelAway(User* user);
+       virtual int OnSetAway(User* user, const std::string &awaymsg);
 
        /** Called whenever a NAMES list is requested.
         * You can produce the nameslist yourself, overriding the current list,
@@ -1297,7 +1338,9 @@ class CoreExport Module : public Extensible
         * @param userlist The user list for the channel (you may change this pointer.
         * If you want to change the values, take a copy first, and change the copy, then
         * point the pointer at your copy)
-        * @return 1 to prevent the user list being sent to the client, 0 to allow it
+        * @return 1 to prevent the user list being sent to the client, 0 to allow it.
+        * 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);
 
@@ -1329,6 +1372,25 @@ class CoreExport Module : public Extensible
         * @param user The user who's buffer is now empty.
         */
        virtual void OnBufferFlushed(User* user);
+
+       /** Add test suite hooks here. These are used for testing functionality of a module
+        * via the --testsuite debugging parameter.
+        */
+       virtual void OnRunTestSuite();
+
+       /** Called for every item in a NAMES list, so that modules may reformat portions of it as they see fit.
+        * For example NAMESX, channel mode +u and +I, and UHNAMES. If the nick is set to an empty string by any
+        * module, then this will cause the nickname not to be displayed at all.
+        */
+       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);
+
+       /** 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);
 };
 
 
@@ -1538,17 +1600,31 @@ class CoreExport FileReader : public classbase
 };
 
 /** A DLLFactory (designed to load shared objects) containing a
- * handle to a module's init_module() function.
+ * handle to a module's init_module() function. Unfortunately,
+ * due to the design of shared object systems we must keep this
+ * hanging around, as if we remove this handle, we remove the
+ * shared object file from memory (!)
  */
 typedef DLLFactory<Module> ircd_module;
 
-/** A list of loaded Modules
+/** A list of modules
+ */
+typedef std::vector<Module*> IntModuleList;
+
+/** An event handler iterator
  */
-typedef std::vector<Module*> ModuleList;
+typedef IntModuleList::iterator EventHandlerIter;
 
-/** A list of loaded module handles (ircd_module)
+/** Module priority states
  */
-typedef std::vector<ircd_module*> ModuleHandleList;
+enum PriorityState
+{
+       PRIO_DONTCARE,
+       PRIO_FIRST,
+       PRIO_LAST,
+       PRIO_AFTER,
+       PRIO_BEFORE
+};
 
 /** ModuleManager takes care of all things module-related
  * in the core.
@@ -1558,7 +1634,7 @@ class CoreExport ModuleManager : public classbase
  private:
        /** Holds a string describing the last module error to occur
         */
-       char MODERR[MAXBUF];
+       std::string LastModuleError;
  
        /** The feature names published by various modules
         */
@@ -1568,7 +1644,7 @@ class CoreExport ModuleManager : public classbase
         */
        interfacelist Interfaces;
  
-       /** Total number of modules loaded into the ircd, minus one
+       /** Total number of modules loaded into the ircd
         */
        int ModCount; 
        
@@ -1576,29 +1652,92 @@ class CoreExport ModuleManager : public classbase
         */
        InspIRCd* Instance;
 
- public:
-       /** A list of ircd_module* module handles
-        * Note that this list is always exactly 255 in size.
-        * The actual number of loaded modules is available from GetModuleCount()
+       /** List of loaded modules and shared object/dll handles
+        * keyed by module name
         */
-       ModuleHandleList handles;
-       /** A list of Module* module classes
-        * Note that this list is always exactly 255 in size.
-        * The actual number of loaded modules is available from GetModuleCount()
+       std::map<std::string, std::pair<ircd_module*, Module*> > Modules;
+
+ public:
+
+       /** Event handler hooks.
+        * This needs to be public to be used by FOREACH_MOD and friends.
         */
-       ModuleList modules;      
+       IntModuleList EventHandlers[I_END];
 
        /** Simple, bog-standard, boring constructor.
         */
        ModuleManager(InspIRCd* Ins);
 
+       /** Destructor
+        */
        ~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.
+        * If you wish to be called before or after other specific modules, you may use this
+        * method (usually within void Module::Prioritize()) to set your events priority.
+        * You may use this call in other methods too, however, this is not supported behaviour
+        * for a module.
+        * @param mod The module to change the priority of
+        * @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
+        * 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 
+        * 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.
+        * 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);
+
+       /** 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
+        * SetPriority method for this, where you may specify other modules to
+        * be prioritized against.
+        */
+       bool SetPriority(Module* mod, PriorityState s);
+
+       /** Attach an event to a module.
+        * You may later detatch the event with ModuleManager::Detach().
+        * If your module is unloaded, all events are automatically detatched.
+        * @param i Event type to attach
+        * @param mod Module to attach event to
+        * @return True if the event was attached
+        */
+       bool Attach(Implementation i, Module* mod);
+
+       /** Detatch an event from a module.
+        * This is not required when your module unloads, as the core will
+        * automatically detatch your module from all events it is attached to.
+        * @param i Event type to detach
+        * @param mod Module to detach event from
+        * @param Detach true if the event was detached
+        */
+       bool Detach(Implementation i, Module* mod);
+
+       /** Attach an array of events to a module
+        * @param i Event types (array) to attach
+        * @param mod Module to attach events to
+        */
+       void Attach(Implementation* i, Module* mod, size_t sz);
+
+       /** Detach all events from a module (used on unload)
+        * @param mod Module to detach from
+        */
+       void DetachAll(Module* mod);
  
        /** Returns text describing the last module error
         * @return The last error message to occur
         */
-       const char* LastError();
+       std::string& LastError();
 
        /** Load a given module file
         * @param filename The file to load
@@ -1631,66 +1770,6 @@ class CoreExport ModuleManager : public classbase
         */
        Module* Find(const std::string &name);
  
-       /** Remove a module handle pointer
-        * @param j Index number of the module handle to remove
-        * @return True if a handle existed at the given index, false otherwise
-        */
-       bool EraseHandle(unsigned int j);
-
-       /** Remove a Module pointer
-        * @param j Index number of the Module to remove
-        * @return True if a handle existed at the given index, false otherwise
-        */
-       bool EraseModule(unsigned int j);
-
-       /** Move a given module to a specific slot in the list
-        * @param modulename The module name to relocate
-        * @param slot The slot to move the module into
-        */
-       void MoveTo(std::string modulename,int slot);
-
-       /** Moves the given module to the last slot in the list
-        * @param modulename The module name to relocate
-        */
-       void MoveToLast(std::string modulename);
-
-       /** Moves the given module to the first slot in the list
-        * @param modulename The module name to relocate
-        */
-       void MoveToFirst(std::string modulename);
-
-       /** Moves one module to be placed after another in the list
-        * @param modulename The module name to relocate
-        * @param after The module name to place the module after
-        */
-       void MoveAfter(std::string modulename, std::string after);
-
-       /** Moves one module to be placed before another in the list
-        * @param modulename The module name to relocate
-        * @param after The module name to place the module before
-        */
-       void MoveBefore(std::string modulename, std::string before);
-       
-       /** For use with Module::Prioritize().
-        * When the return value of this function is returned from
-        * Module::Prioritize(), this specifies that the module wishes
-        * to be ordered exactly BEFORE 'modulename'. For more information
-        * please see Module::Prioritize().
-        * @param modulename The module your module wants to be before in the call list
-        * @returns a priority ID which the core uses to relocate the module in the list
-        */
-       long PriorityBefore(const std::string &modulename);
-
-       /** For use with Module::Prioritize().
-        * When the return value of this function is returned from
-        * Module::Prioritize(), this specifies that the module wishes
-        * to be ordered exactly AFTER 'modulename'. For more information please
-        * see Module::Prioritize().
-        * @param modulename The module your module wants to be after in the call list
-        * @returns a priority ID which the core uses to relocate the module in the list
-        */
-       long PriorityAfter(const std::string &modulename);
-
        /** 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
@@ -1788,21 +1867,58 @@ class CoreExport ModuleManager : public classbase
         */
        modulelist* FindInterface(const std::string &InterfaceName);
 
+       /** Determine if a module has published the named interface.
+        * This could be used in, for example, OnLoadModule to pick up other modules that can be used.
+        * @param mod The module to check.
+        * @param InterfaceName the interface you want to check for
+        * @return True if the module provides the interface, false otherwise.
+        */
+       bool ModuleHasInterface(Module* mod, const std::string& InterfaceName);
+
        /** Given a pointer to a Module, return its filename
         * @param m The module pointer to identify
         * @return The module name or an empty string
         */
        const std::string& GetModuleName(Module* m);
+
+       /** Return a list of all modules matching the given filter
+        * @param filter This int is a bitmask of flags set in Module::Flags,
+        * such as VF_VENDOR or VF_STATIC. If you wish to receive a list of
+        * all modules with no filtering, set this to 0.
+        * @return The list of module names
+        */
+       const std::vector<std::string> GetAllModuleNames(int filter);
 };
 
 /** This definition is used as shorthand for the various classes
  * and functions needed to make a module loadable by the OS.
  * It defines the class factory and external init_module function.
  */
+#ifdef WINDOWS
+
+#define MODULE_INIT(y) \
+       extern "C" DllExport Module * init_module(InspIRCd* Me) \
+       { \
+               return new y(Me); \
+       } \
+       BOOLEAN WINAPI DllMain(HINSTANCE hDllHandle, DWORD nReason, LPVOID Reserved) \
+       { \
+               switch ( nReason ) \
+               { \
+                       case DLL_PROCESS_ATTACH: \
+                       case DLL_PROCESS_DETACH: \
+                               break; \
+               } \
+               return TRUE; \
+       }
+
+#else
+
 #define MODULE_INIT(y) \
        extern "C" DllExport Module * init_module(InspIRCd* Me) \
        { \
                return new y(Me); \
        }
+#endif
 
 #endif