]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - include/modules.h
Replace std::deque with std::vector in spanningtree and related modules
[user/henk/code/inspircd.git] / include / modules.h
index 33416a596ed17a964aa6bbb187af6ee04e735c0c..21e4760897f234045690980735f169f3c88b6287 100644 (file)
@@ -2,25 +2,30 @@
  *       | Inspire Internet Relay Chat Daemon |
  *       +------------------------------------+
  *
- *  InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
- *                    E-mail:
- *             <brain@chatspike.net>
- *               <Craig@chatspike.net>
- *     
- * Written by Craig Edwards, Craig McLure, and others.
+ *  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.
  *
  * ---------------------------------------------------
  */
 
-
 #ifndef __MODULES_H
 #define __MODULES_H
 
-/** log levels
- */
-enum DebugLevels { DEBUG, VERBOSE, DEFAULT, SPARSE, NONE };
+#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
  */
@@ -48,11 +53,15 @@ enum ModuleFlags {
        VF_COMMON = 8           // module needs to be common on all servers in a network to link
 };
 
+/** Used with SendToMode()
+ */
 enum WriteModeFlags {
        WM_AND = 1,
        WM_OR = 2
 };
 
+/** Used to represent an event type, for user, channel or server
+ */
 enum TargetTypeFlags {
        TYPE_USER = 1,
        TYPE_CHANNEL,
@@ -60,124 +69,225 @@ enum TargetTypeFlags {
        TYPE_OTHER
 };
 
-#include "globals.h"
-#include "dynamic.h"
-#include "base.h"
-#include "ctables.h"
-#include "inspsocket.h"
-#include <string>
-#include <deque>
-#include <sstream>
-#include <typeinfo>
-#include "timer.h"
-#include "mode.h"
+/** Used to represent wether a message was PRIVMSG or NOTICE
+ */
+enum MessageType {
+       MSG_PRIVMSG = 0,
+       MSG_NOTICE = 1
+};
+
+/** If you change the module API, change this value. */
+#define API_VERSION 13000
 
-class Server;
 class ServerConfig;
 
-// Forward-delacare module for ModuleMessage etc
+/* Forward-delacare module for ModuleMessage etc
+ */
 class Module;
+class InspIRCd;
 
-/** Low level definition of a FileReader classes file cache area
+/** Low level definition of a FileReader classes file cache area -
+ * a text file seperated into lines.
  */
 typedef std::deque<std::string> file_cache;
-typedef file_cache string_list;
 
-/** Holds a list of users in a channel
+/** A set of strings.
  */
-typedef std::deque<userrec*> chanuserlist;
-
+typedef file_cache string_list;
 
 /** Holds a list of 'published features' for modules.
  */
 typedef std::map<std::string,Module*> featurelist;
 
+/** Holds a list of modules which implement an interface
+ */
+typedef std::deque<Module*> modulelist;
+
+/** Holds a list of all modules which implement interfaces, by interface name
+ */
+typedef std::map<std::string, std::pair<int, modulelist> > interfacelist;
+
 /**
  * This #define allows us to call a method in all
  * loaded modules in a readable simple way, e.g.:
- * 'FOREACH_MOD(I_OnXonnwxr,OnConnect(user));'
+ * 'FOREACH_MOD(I_OnConnect,OnConnect(user));'
  */
-#define FOREACH_MOD(y,x) if (Config->global_implementation[y] > 0) { \
-       for (int _i = 0; _i <= MODCOUNT; _i++) { \
-       if (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 \
                { \
-                       modules[_i]->x ; \
+                       (*_i)->x ; \
                } \
-               catch (ModuleException& modexcept) \
+               catch (CoreException& modexcept) \
                { \
-                       log(DEBUG,"Module exception caught: %s",modexcept.GetReason()); \
+                       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.
+ * This #define allows us to call a method in all
+ * loaded modules in a readable simple way and pass
+ * an instance pointer to the macro. e.g.:
+ * 'FOREACH_MOD_I(Instance, OnConnect, OnConnect(user));'
+ */
+#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 \
+               { \
+                       (*_i)->x ; \
+               } \
+               catch (CoreException& modexcept) \
+               { \
+                       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 (Config->global_implementation[y] > 0) { \
-                       MOD_RESULT = 0; \
-                       for (int _i = 0; _i <= MODCOUNT; _i++) { \
-                       if (Config->implement_lists[_i][y]) {\
-                               try \
-                               { \
-                                       int res = modules[_i]->x ; \
-                                       if (res != 0) { \
-                                               MOD_RESULT = res; \
-                                               break; \
-                                       } \
-                               } \
-                               catch (ModuleException& modexcept) \
-                               { \
-                                       log(DEBUG,"Module exception cought: %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; \
        } \
- }
-
-#define FD_MAGIC_NUMBER -42
+} while(0);
 
-// useful macros
 
-#define IS_LOCAL(x) ((x->fd > -1) && (x->fd <= MAX_DESCRIPTORS))
-#define IS_REMOTE(x) (x->fd < 0)
-#define IS_MODULE_CREATED(x) (x->fd == FD_MAGIC_NUMBER)
+/**
+ * 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) \
+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(); ) \
+       { \
+               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; \
+       } \
+} while(0);
 
-/** Holds a module's Version information
+/** 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)
+/** 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 */
+#define IS_OPER(x) (!x->oper.empty())
+/** Is away */
+#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
  *  of a module. A class of type Version is returned by the GetVersion method of the Module class.
+ *  The flags and API values represent the module flags and API version of the module.
+ *  The API version of a module must match the API version of the core exactly for the module to
+ *  load successfully.
  */
-class Version : public classbase
+class CoreExport Version : public classbase
 {
  public:
-        const int Major, Minor, Revision, Build, Flags;
-        Version(int major, int minor, int revision, int build, int flags);
-};
+       /** Version information.
+        */
+       std::string version;
 
-/** Holds /ADMIN data
- *  This class contains the admin details of the local server. It is constructed by class Server,
- *  and has three read-only values, Name, Email and Nick that contain the specified values for the
- *  server where the module is running.
- */
-class Admin : public classbase
-{
- public:
-        const std::string Name, Email, Nick;
-        Admin(std::string name, std::string email, std::string nick);
+       /** Flags and API version
+        */
+       const int Flags, API;
+
+       /** Initialize version class
+        */
+       Version(const std::string &sversion, int flags, int api_ver);
 };
 
 /** The ModuleMessage class is the base class of Request and Event
  * This class is used to represent a basic data structure which is passed
  * between modules for safe inter-module communications.
  */
-class ModuleMessage : public classbase
+class CoreExport ModuleMessage : public Extensible
 {
  public:
-       /** This class is pure virtual and must be inherited.
+       /** Destructor
         */
-       virtual char* Send() = 0;
        virtual ~ModuleMessage() {};
 };
 
@@ -186,12 +296,17 @@ class ModuleMessage : public classbase
  * using the Send() method, which will call the given module's OnRequest
  * method with this class as its parameter.
  */
-class Request : public ModuleMessage
+class CoreExport Request : public ModuleMessage
 {
  protected:
        /** 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 is a pointer to the sender of the message, which can be used to
         * directly trigger events, or to create a reply.
         */
@@ -201,11 +316,28 @@ class 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.
         */
        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,
+        * 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);
        /** Fetch the Request data
         */
        char* GetData();
+       /** Fetch the ID string
+        */
+       const char* GetId();
        /** Fetch the request source
         */
        Module* GetSource();
@@ -217,7 +349,7 @@ class 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();
 };
 
 
@@ -226,7 +358,7 @@ class Request : public ModuleMessage
  * using the Send() method, which will trigger the OnEvent method in
  * all modules passing the object as its parameter.
  */
-class Event : public ModuleMessage
+class CoreExport Event : public ModuleMessage
 {
  protected:
        /** This member holds a pointer to arbitary data set by the emitter of the message
@@ -259,39 +391,7 @@ class Event : public ModuleMessage
         * The return result of an Event::Send() will always be NULL as
         * no replies are expected.
         */
-       char* Send();
-};
-
-/** This class can be used on its own to represent an exception, or derived to represent a module-specific exception.
- * When a module whishes to abort, e.g. within a constructor, it should throw an exception using ModuleException or
- * a class derived from ModuleException. If a module throws an exception during its constructor, the module will not
- * be loaded. If this happens, the error message returned by ModuleException::GetReason will be displayed to the user
- * attempting to load the module, or dumped to the console if the ircd is currently loading for the first time.
- */
-class ModuleException : public classbase
-{
- private:
-       /** Holds the error message to be displayed
-        */
-       std::string err;
- public:
-       /** Default constructor, just uses the error mesage 'Module threw an exception'.
-        */
-       ModuleException() : err("Module threw an exception") {}
-       /** This constructor can be used to specify an error message before throwing.
-        */
-       ModuleException(std::string message) : err(message) {}
-       /** This destructor solves world hunger, cancels the world debt, and causes the world to end.
-        * Actually no, it does nothing. Never mind.
-        */
-       virtual ~ModuleException() {};
-       /** Returns the reason for the exception.
-        * The module should probably put something informative here as the user will see this upon failure.
-        */
-       virtual const char* GetReason()
-       {
-               return err.c_str();
-       }
+       char* Send(InspIRCd* ServerInstance);
 };
 
 /** Priority types which can be returned from Module::Prioritize()
@@ -300,147 +400,167 @@ 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_OnAddGLine,
-                       I_OnAddZLine, I_OnAddQLine, I_OnAddKLine, I_OnAddELine, I_OnDelGLine, I_OnDelZLine, I_OnDelKLine, I_OnDelELine, I_OnDelQLine,
-                       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_OnRawMode, 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_OnGlobalConnect, 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 };
+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_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,
  *  its methods will be called when irc server events occur. class inherited from module must be
  *  instantiated by the ModuleFactory class (see relevent section) for the module to be initialised.
  */
-class Module : public Extensible
+class CoreExport Module : public Extensible
 {
+ protected:
+       /** Creator/owner pointer
+        */
+       InspIRCd* ServerInstance;
  public:
 
-       /** Default constructor
+       /** Default constructor.
         * Creates a module class.
-        * @param Me An instance of the Server class which can be saved for future use
+        * @param Me An instance of the InspIRCd class which will be saved into ServerInstance for your use
         * \exception ModuleException Throwing this class, or any class derived from ModuleException, causes loading of the module to abort.
         */
-       Module(Server* Me);
+       Module(InspIRCd* Me);
 
-       /** Default destructor
+       /** Default destructor.
         * destroys a module class
         */
        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 Server::PriorityBefore() - To move your module before another named module
-        *
-        * The result of Server::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 userrec *user
+        * The details of the connecting user are available to you in the parameter User *user
         * @param user The user who is connecting
         */
-       virtual void OnUserConnect(userrec* user);
+       virtual void OnUserConnect(User* user);
 
        /** Called when a user quits.
-        * The details of the exiting user are available to you in the parameter userrec *user
+        * The details of the exiting user are available to you in the parameter User *user
         * This event is only called when the user is fully registered when they quit. To catch
         * raw disconnections, use the OnUserDisconnect method.
         * @param user The user who is quitting
-        * @param message The user's quit message
+        * @param message The user's quit message (as seen by non-opers)
+        * @param oper_message The user's quit message (as seen by opers)
         */
-       virtual void OnUserQuit(userrec* user, const std::string &message);
+       virtual void OnUserQuit(User* user, const std::string &message, const std::string &oper_message);
 
        /** Called whenever a user's socket is closed.
-        * The details of the exiting user are available to you in the parameter userrec *user
+        * The details of the exiting user are available to you in the parameter User *user
         * This event is called for all users, registered or not, as a cleanup method for modules
         * which might assign resources to user, such as dns lookups, objects and sockets.
         * @param user The user who is disconnecting
         */
-       virtual void OnUserDisconnect(userrec* user);
+       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
         */
-       virtual void OnChannelDelete(chanrec* chan);
+       virtual void OnChannelDelete(Channel* chan);
 
        /** Called when a user joins a channel.
-        * The details of the joining user are available to you in the parameter userrec *user,
-        * and the details of the channel they have joined is available in the variable chanrec *channel
+        * The details of the joining user are available to you in the parameter User *user,
+        * and the details of the channel they have joined is available in the variable Channel *channel
+        * @param user The user who is joining
+        * @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 sync, bool &silent);
+
+       /** Called after a user joins a channel
+        * Identical to OnUserJoin, but called immediately afterwards, when any linking module has
+        * seen the join.
         * @param user The user who is joining
         * @param channel The channel being joined
         */
-       virtual void OnUserJoin(userrec* user, chanrec* channel);
+       virtual void OnPostJoin(User* user, Channel* channel);
 
        /** Called when a user parts a channel.
-        * The details of the leaving user are available to you in the parameter userrec *user,
-        * and the details of the channel they have left is available in the variable chanrec *channel
+        * The details of the leaving user are available to you in the parameter User *user,
+        * 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(userrec* user, chanrec* channel, const std::string &partmessage);
+       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
-        * 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 parameter The (optional) parameter given to REHASH from the user.
-        */
-       virtual void OnRehash(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 userrec 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, userrec* 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 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
@@ -451,15 +571,19 @@ class Module : public Extensible
         * IMPORTANT NOTE!
         *
         * If the user joins a NEW channel which does not exist yet, OnUserPreJoin will be called BEFORE the channel
-        * record is created. This will cause chanrec* chan to be NULL. There is very little you can do in form of
+        * record is created. This will cause Channel* chan to be NULL. There is very little you can do in form of
         * processing on the actual channel record at this point, however the channel NAME will still be passed in
         * char* cname, so that you could for example implement a channel blacklist or whitelist, etc.
         * @param user The user joining the channel
-        * @param cname The channel name being joined
+        * @param chan If the  channel is a new channel, this will be NULL, otherwise it will be a pointer to the channel being joined
+        * @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(userrec* user, chanrec* chan, const char* cname);
-       
+       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
         * output to be sent to the user by the core. If you do this you must produce your own numerics,
@@ -470,7 +594,7 @@ class 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(userrec* source, userrec* user, chanrec* chan, const std::string &reason);
+       virtual int 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
@@ -479,28 +603,31 @@ class Module : public Extensible
         * @param user The user being kicked
         * @param chan The channel the user is being kicked from
         * @param reason The kick reason
+        * @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 OnUserKick(userrec* source, userrec* user, chanrec* chan, const std::string &reason);
+       virtual void OnUserKick(User* source, User* user, Channel* chan, const std::string &reason, bool &silent);
 
        /** Called whenever a user opers locally.
-        * The userrec will contain the oper mode 'o' as this function is called after any modifications
+        * The User will contain the oper mode 'o' as this function is called after any modifications
         * are made to the user's structure by the core.
         * @param user The user who is opering up
         * @param opertype The opers type name
         */
-       virtual void OnOper(userrec* user, const std::string &opertype);
+       virtual void OnOper(User* user, const std::string &opertype);
 
        /** Called after a user opers locally.
         * This is identical to Module::OnOper(), except it is called after OnOper so that other modules
         * 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(userrec* 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 userrec will contain the information of the user who typed the command. Modules may use this
+        * 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).
         * It is purposefully not possible to modify any info that has already been output, or halt the list.
         * You must write a 371 numeric to the user, containing your info in the following format:
@@ -509,16 +636,16 @@ class Module : public Extensible
         *
         * @param user The user issuing /INFO
         */
-       virtual void OnInfo(userrec* user);
-       
+       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.
         * @param source The user issuing the WHOIS command
         * @param dest The user who is being WHOISed
         */
-       virtual void OnWhois(userrec* source, userrec* dest);
-       
+       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,
@@ -526,57 +653,74 @@ class 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(userrec* source,userrec* dest,chanrec* 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,
         * use OnUserPreInvite instead.
         * @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(userrec* source,userrec* dest,chanrec* 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
         * output to be sent to the user by the core. If you do this you must produce your own numerics,
         * notices etc. This is useful for modules which may want to filter or redirect messages.
         * target_type can be one of TYPE_USER or TYPE_CHANNEL. If the target_type value is a user,
-        * you must cast dest to a userrec* otherwise you must cast it to a chanrec*, this is the details
+        * you must cast dest to a User* otherwise you must cast it to a Channel*, this is the details
         * of where the message is destined to be sent.
         * @param user The user sending the message
-        * @param dest The target of the message (chanrec* or userrec*)
+        * @param dest The target of the message (Channel* or User*)
         * @param target_type The type of target (TYPE_USER or TYPE_CHANNEL)
         * @param text Changeable text being sent by the user
         * @param status The status being used, e.g. PRIVMSG @#chan has status== '@', 0 to send to everyone.
-        * @return 1 to deny the NOTICE, 0 to allow it
+        * @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 message, 0 to allow it
         */
-       virtual int OnUserPreMessage(userrec* user,void* dest,int target_type, std::string &text,char status);
+       virtual int 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
         * output to be sent to the user by the core. If you do this you must produce your own numerics,
         * notices etc. This is useful for modules which may want to filter or redirect messages.
         * target_type can be one of TYPE_USER or TYPE_CHANNEL. If the target_type value is a user,
-        * you must cast dest to a userrec* otherwise you must cast it to a chanrec*, this is the details
+        * you must cast dest to a User* otherwise you must cast it to a Channel*, this is the details
         * of where the message is destined to be sent.
         * You may alter the message text as you wish before relinquishing control to the next module
         * in the chain, and if no other modules block the text this altered form of the text will be sent out
         * to the user and possibly to other servers.
         * @param user The user sending the message
-        * @param dest The target of the message (chanrec* or userrec*)
+        * @param dest The target of the message (Channel* or User*)
         * @param target_type The type of target (TYPE_USER or TYPE_CHANNEL)
         * @param text Changeable text being sent by the user
         * @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 notices, this will usually contain just the sender.
+        * It will be ignored for private notices.
         * @return 1 to deny the NOTICE, 0 to allow it
         */
-       virtual int OnUserPreNotice(userrec* user,void* dest,int target_type, std::string &text,char status);
-       
+       virtual int 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).
+        * @param message_type The message type, either MSG_PRIVMSG or MSG_NOTICE
+        * @param chan The channel to build the exempt list of
+        * @param sender The original sender of the PRIVMSG or NOTICE
+        * @param status The status char to be used for the channel list
+        * @param exempt_list The exempt list to be populated
+        * @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 userrec if the user is a remote user as this may cause a desnyc.
+        * NOT make any changes to the User if the user is a remote user as this may cause a desnyc.
         * check user->server before taking any action (including returning nonzero from the method).
         * If your method returns nonzero, the nickchange is silently forbidden, and it is down to your
         * module to generate some meaninful output.
@@ -584,10 +728,10 @@ class Module : public Extensible
         * @param newnick Their new nickname
         * @return 1 to deny the change, 0 to allow
         */
-       virtual int OnUserPreNick(userrec* user, const std::string &newnick);
+       virtual int OnUserPreNick(User* user, const std::string &newnick);
 
        /** Called after any PRIVMSG sent from a user.
-        * The dest variable contains a userrec* if target_type is TYPE_USER and a chanrec*
+        * The dest variable contains a User* if target_type is TYPE_USER and a Channel*
         * if target_type is TYPE_CHANNEL.
         * @param user The user sending the message
         * @param dest The target of the message
@@ -595,10 +739,10 @@ class Module : public Extensible
         * @param text the text being sent by the user
         * @param status The status being used, e.g. PRIVMSG @#chan has status== '@', 0 to send to everyone.
         */
-       virtual void OnUserMessage(userrec* user, void* dest, int target_type, const std::string &text, char status);
+       virtual void OnUserMessage(User* user, void* dest, int target_type, const std::string &text, char status, const CUList &exempt_list);
 
        /** Called after any NOTICE sent from a user.
-        * The dest variable contains a userrec* if target_type is TYPE_USER and a chanrec*
+        * The dest variable contains a User* if target_type is TYPE_USER and a Channel*
         * if target_type is TYPE_CHANNEL.
         * @param user The user sending the message
         * @param dest The target of the message
@@ -606,18 +750,33 @@ class Module : public Extensible
         * @param text the text being sent by the user
         * @param status The status being used, e.g. NOTICE @#chan has status== '@', 0 to send to everyone.
         */
-       virtual void OnUserNotice(userrec* user, void* dest, int target_type, const std::string &text, char status);
+       virtual void OnUserNotice(User* user, void* dest, int target_type, const std::string &text, char status, const CUList &exempt_list);
+
+       /** Called immediately before any NOTICE or PRIVMSG sent from a user, local or remote.
+        * The dest variable contains a User* if target_type is TYPE_USER and a Channel*
+        * if target_type is TYPE_CHANNEL.
+        * The difference between this event and OnUserPreNotice/OnUserPreMessage is that delivery is gauranteed,
+        * the message has already been vetted. In the case of the other two methods, a later module may stop your
+        * message. This also differs from OnUserMessage which occurs AFTER the message has been sent.
+        * @param user The user sending the message
+        * @param dest The target of the message
+        * @param target_type The type of target (TYPE_USER or TYPE_CHANNEL)
+        * @param text the text being sent by the user
+        * @param status The status being used, e.g. NOTICE @#chan has status== '@', 0 to send to everyone.
+        */
+       virtual void OnText(User* user, void* dest, int target_type, const std::string &text, char status, CUList &exempt_list);
 
        /** Called after every MODE command sent from a user
-        * The dest variable contains a userrec* if target_type is TYPE_USER and a chanrec*
+        * The dest variable contains a User* if target_type is TYPE_USER and a Channel*
         * if target_type is TYPE_CHANNEL. The text variable contains the remainder of the
         * mode string after the target, e.g. "+wsi" or "+ooo nick1 nick2 nick3".
         * @param user The user sending the MODEs
-        * @param dest The target of the modes (userrec* or chanrec*)
+        * @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(userrec* 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
@@ -641,7 +800,7 @@ class Module : public Extensible
         * @param proto A pointer to the module handling network protocol
         * @param opaque An opaque pointer set by the protocol module, should not be modified!
         */
-       virtual void OnSyncUser(userrec* user, Module* proto, void* opaque);
+       virtual void OnSyncUser(User* user, Module* proto, void* opaque);
 
        /** Allows modules to synchronize data which relates to channels during a netburst.
         * When this function is called, it will be called from the module which implements
@@ -658,11 +817,11 @@ class Module : public Extensible
         * @param proto A pointer to the module handling network protocol
         * @param opaque An opaque pointer set by the protocol module, should not be modified!
         */
-       virtual void OnSyncChannel(chanrec* chan, Module* proto, void* opaque);
+       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 userrec or chanrec by a module) then
+        * 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.
@@ -670,12 +829,14 @@ class Module : public Extensible
         * @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(chanrec* chan, Module* proto,void* opaque, const std::string &extname);
+       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 userrec or chanrec by a module) then
+        * 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.
@@ -683,24 +844,28 @@ class Module : public Extensible
         * @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(userrec* user, Module* proto,void* opaque, const std::string &extname);
+       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 userrec or chanrec by a module) then
+        * 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 proto A pointer to the module handling network protocol
         * @param opaque An opaque pointer set by the protocol module, should not be modified!
+        * @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);
+       virtual void OnSyncOtherMetaData(Module* proto, void* opaque, bool displayable = false);
 
        /** 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.
         * @param target_type The type of item to decode data for, TYPE_USER or TYPE_CHANNEL
-        * @param target The chanrec* or userrec* that data should be added to
+        * @param target The Channel* or User* that data should be added to
         * @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
         */
@@ -716,10 +881,11 @@ class Module : public Extensible
         *
         * @param opaque An opaque pointer set by the protocol module, should not be modified!
         * @param target_type The type of item to decode data for, TYPE_USER or TYPE_CHANNEL
-        * @param target The chanrec* or userrec* that modes should be sent for
+        * @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
@@ -731,118 +897,58 @@ class Module : public Extensible
         * how to use this function.
         * @param opaque An opaque pointer set by the protocol module, should not be modified!
         * @param target_type The type of item to decode data for, TYPE_USER or TYPE_CHANNEL
-        * @param target The chanrec* or userrec* that metadata should be sent for
+        * @param target The Channel* or User* that metadata should be sent for
         * @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, TargetTypeFlags target_type, void* target, const std::string &extname, const std::string &extdata);
+
        /** Called after every WALLOPS command.
         * @param user The user sending the WALLOPS
         * @param text The content of the WALLOPS message
         */
-       virtual void OnWallops(userrec* user, const std::string &text);
+       virtual void OnWallops(User* user, const std::string &text);
 
        /** Called whenever a user's hostname is changed.
         * This event triggers after the host has been set.
         * @param user The user whos host is being changed
         * @param newhost The new hostname being set
         */
-       virtual void OnChangeHost(userrec* user, const std::string &newhost);
+       virtual void OnChangeHost(User* user, const std::string &newhost);
 
        /** Called whenever a user's GECOS (realname) is changed.
         * This event triggers after the name has been set.
         * @param user The user who's GECOS is being changed
         * @param gecos The new GECOS being set on the user
         */
-       virtual void OnChangeName(userrec* user, const std::string &gecos);
-
-       /** Called whenever a gline is added by a local user.
-        * This method is triggered after the line is added.
-        * @param duration The duration of the line in seconds
-        * @param source The sender of the line
-        * @param reason The reason text to be displayed
-        * @param hostmask The hostmask to add
-        */
-       virtual void OnAddGLine(long duration, userrec* source, const std::string &reason, const std::string &hostmask);
-
-       /** Called whenever a zline is added by a local user.
-        * This method is triggered after the line is added.
-        * @param duration The duration of the line in seconds
-        * @param source The sender of the line
-        * @param reason The reason text to be displayed
-        * @param ipmask The hostmask to add
-        */
-       virtual void OnAddZLine(long duration, userrec* source, const std::string &reason, const std::string &ipmask);
+       virtual void OnChangeName(User* user, const std::string &gecos);
 
-       /** Called whenever a kline is added by a local user.
+       /** Called whenever an xline is added by a local user.
         * This method is triggered after the line is added.
-        * @param duration The duration of the line in seconds
-        * @param source The sender of the line
-        * @param reason The reason text to be displayed
-        * @param hostmask The hostmask to add
+        * @param source The sender of the line or NULL for local server
+        * @param line The xline being added
         */
-       virtual void OnAddKLine(long duration, userrec* source, const std::string &reason, const std::string &hostmask);
+       virtual void OnAddLine(User* source, XLine* line);
 
-       /** Called whenever a qline is added by a local user.
-        * This method is triggered after the line is added.
-        * @param duration The duration of the line in seconds
-        * @param source The sender of the line
-        * @param reason The reason text to be displayed
-        * @param nickmask The hostmask to add
-        */
-       virtual void OnAddQLine(long duration, userrec* source, const std::string &reason, const std::string &nickmask);
-
-       /** Called whenever a eline is added by a local user.
-        * This method is triggered after the line is added.
-        * @param duration The duration of the line in seconds
-        * @param source The sender of the line
-        * @param reason The reason text to be displayed
-        * @param hostmask The hostmask to add
-        */
-       virtual void OnAddELine(long duration, userrec* source, const std::string &reason, const std::string &hostmask);
-
-       /** Called whenever a gline is deleted.
-        * This method is triggered after the line is deleted.
-        * @param source The user removing the line
-        * @param hostmask The hostmask to delete
-        */
-       virtual void OnDelGLine(userrec* source, const std::string &hostmask);
-
-       /** Called whenever a zline is deleted.
-        * This method is triggered after the line is deleted.
-        * @param source The user removing the line
-        * @param hostmask The hostmask to delete
-        */
-       virtual void OnDelZLine(userrec* source, const std::string &ipmask);
-
-       /** Called whenever a kline is deleted.
-        * This method is triggered after the line is deleted.
-        * @param source The user removing the line
-        * @param hostmask The hostmask to delete
-        */
-       virtual void OnDelKLine(userrec* source, const std::string &hostmask);
-       
-       /** Called whenever a qline 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
-        * @param hostmask The hostmask to delete
+        * @param source The user removing the line or NULL for local server
+        * @param line the line being deleted
         */
-       virtual void OnDelQLine(userrec* source, const std::string &nickmask);
+       virtual void OnDelLine(User* source, XLine* line);
 
-       /** Called whenever a eline 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 OnDelELine(userrec* source, const std::string &hostmask);
+       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,
         * so that when your module unloads it may clear up any remaining data
         * in the form of Extensibles added using Extensible::Extend().
         * If the target_type variable is TYPE_USER, then void* item refers to
-        * a userrec*, otherwise it refers to a chanrec*.
+        * a User*, otherwise it refers to a Channel*.
         * @param target_type The type of item being cleaned
         * @param item A pointer to the item's class
         */
@@ -850,29 +956,29 @@ class Module : public Extensible
 
        /** Called after any nickchange, local or remote. This can be used to track users after nickchanges
         * have been applied. Please note that although you can see remote nickchanges through this function, you should
-        * NOT make any changes to the userrec if the user is a remote user as this may cause a desnyc.
+        * NOT make any changes to the User if the user is a remote user as this may cause a desnyc.
         * check user->server before taking any action (including returning nonzero from the method).
         * Because this method is called after the nickchange is taken place, no return values are possible
         * to indicate forbidding of the nick change. Use OnUserPreNick for this.
         * @param user The user changing their nick
         * @param oldnick The old nickname of the user before the nickchange
         */
-       virtual void OnUserPostNick(userrec* user, const std::string &oldnick);
+       virtual void OnUserPostNick(User* user, const std::string &oldnick);
 
        /** Called before an action which requires a channel privilage check.
         * This function is called before many functions which check a users status on a channel, for example
         * 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
@@ -884,7 +990,7 @@ class Module : public Extensible
         * @param channel The channel which is being checked
         * @param access_type See above
         */
-       virtual int OnAccessCheck(userrec* source,userrec* dest,chanrec* channel,int access_type);
+       virtual int 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.
@@ -905,14 +1011,14 @@ class Module : public Extensible
         * @param reason The kill reason
         * @return 1 to prevent the kill, 0 to allow
         */
-       virtual int OnKill(userrec* source, userrec* dest, const std::string &reason);
+       virtual int 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
         * @param dest The user being killed
         * @param reason The kill reason
         */
-       virtual void OnRemoteKill(userrec* source, userrec* dest, const std::string &reason);
+       virtual void OnRemoteKill(User* source, User* dest, const std::string &reason, const std::string &operreason);
 
        /** Called whenever a module is loaded.
         * mod will contain a pointer to the module, and string will contain its name,
@@ -952,21 +1058,37 @@ class Module : public Extensible
 
        /** Called whenever any command is about to be executed.
         * This event occurs for all registered commands, wether they are registered in the core,
-        * or another module, but it will not occur for invalid commands (e.g. ones which do not
-        * exist within the command table). By returning 1 from this method you may prevent the
+        * or another module, and for invalid commands. Invalid commands may only be sent to this
+        * function when the value of validated is false. By returning 1 from this method you may prevent the
         * command being executed. If you do this, no output is created by the core, and it is
         * down to your module to produce any output neccessary.
         * Note that unless you return 1, you should not destroy any structures (e.g. by using
-        * Server::QuitUser) otherwise when the command's handler function executes after your
+        * InspIRCd::QuitUser) otherwise when the command's handler function executes after your
         * method returns, it will be passed an invalid pointer to the user object and crash!)
         * @param command The command being executed
         * @param parameters An array of array of characters containing the parameters for the command
         * @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, char **parameters, int pcnt, userrec *user, bool validated);
+       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,
+        * or another module, but it will not occur for invalid commands (e.g. ones which do not
+        * exist within the command table). The result code returned by the command handler is
+        * provided.
+        * @param command The command being executed
+        * @param parameters An array of array of characters containing the parameters for the command
+        * @param pcnt The nuimber of parameters passed to the command
+        * @param user the user issuing the command
+        * @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 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
@@ -978,7 +1100,7 @@ class Module : public Extensible
         * @param user The user to check
         * @return true to indicate readiness, false if otherwise
         */
-       virtual bool OnCheckReady(userrec* user);
+       virtual bool 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
@@ -987,22 +1109,9 @@ class Module : public Extensible
         * Note that you should NOT delete the user record here by causing a disconnection!
         * Use OnUserConnect for that instead.
         * @param user The user registering
+        * @return 1 to indicate user quit, 0 to continue
         */
-       virtual void OnUserRegister(userrec* user);
-
-       /** Called whenever a mode character is processed.
-        * Return 1 from this function to block the mode character from being processed entirely,
-        * so that you may perform your own code instead. Note that this method allows you to override
-        * modes defined by other modes, but this is NOT RECOMMENDED!
-        * @param user The user who is sending the mode
-        * @param chan The channel the mode is being sent to
-        * @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 1 to deny the mode, 0 to allow
-        */
-       virtual int OnRawMode(userrec* user, chanrec* chan, char mode, const std::string &param, bool adding, int pcnt);
+       virtual int 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
@@ -1012,7 +1121,21 @@ class Module : public Extensible
         * @param chan The channel being joined
         * @return 1 to explicitly allow the join, 0 to proceed as normal
         */
-       virtual int OnCheckInvite(userrec* user, chanrec* chan);
+       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
@@ -1023,7 +1146,7 @@ class Module : public Extensible
         * @param chan The channel being joined
         * @return 1 to explicitly allow the join, 0 to proceed as normal
         */
-       virtual int OnCheckKey(userrec* user, chanrec* chan, const std::string &keygiven);
+       virtual int 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
@@ -1033,7 +1156,7 @@ class Module : public Extensible
         * @param chan The channel being joined
         * @return 1 to explicitly allow the join, 0 to proceed as normal
         */
-       virtual int OnCheckLimit(userrec* user, chanrec* chan);
+       virtual int 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
@@ -1041,17 +1164,36 @@ class 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(userrec* user, chanrec* chan);
+       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.
+        * @returns 1 = exempt, 0 = no match, -1 = banned
+        */
+       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.
+        * @returns 1 = exempt, 0 = no match, -1 = banned
+        */
+       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
-        * @user the user issuing the /STATS command
+        * @param user the user issuing the /STATS command
+        * @param results A string_list to append results into. You should put all your results
+        * into this string_list, rather than displaying them directly, so that your handler will
+        * 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, userrec* user);
+       virtual int 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.
@@ -1059,7 +1201,7 @@ class Module : public Extensible
         * @param newhost The new hostname
         * @return 1 to deny the host change, 0 to allow
         */
-       virtual int OnChangeLocalUserHost(userrec* user, const std::string &newhost);
+       virtual int 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.
@@ -1067,16 +1209,16 @@ class Module : public Extensible
         * @param newhost The new GECOS
         * @return 1 to deny the GECOS change, 0 to allow
         */
-       virtual int OnChangeLocalUserGECOS(userrec* user, const std::string &newhost); 
+       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
         * @param 1 to block the topic change, 0 to allow
         */
-       virtual int OnLocalTopicChange(userrec* user, chanrec* chan, const std::string &topic);
+       virtual int 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.
@@ -1084,7 +1226,7 @@ class Module : public Extensible
         * @param chan The channels who's topic is being changed
         * @param topic The actual topic text
         */
-       virtual void OnPostLocalTopicChange(userrec* user, chanrec* chan, const std::string &topic);
+       virtual void OnPostLocalTopicChange(User* user, Channel* chan, const std::string &topic);
 
        /** Called whenever an Event class is sent to all module by another module.
         * Please see the documentation of Event::Send() for further information. The Event sent can
@@ -1101,18 +1243,19 @@ class 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
-        * @return 1 to match the passwords, 0 to do nothing
+        * '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);
+       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
@@ -1120,14 +1263,15 @@ class Module : public Extensible
         * servermodes out to reverse mode changes.
         * @param user The user who is opering
         */
-       virtual void OnGlobalOper(userrec* user);
+       virtual void OnGlobalOper(User* user);
 
-       /**  Called whenever a user connects, anywhere on the network.
+       /** Called after a user has fully connected and all modules have executed OnUserConnect
         * This event is informational only. You should not change any user information in this
         * event. To do so, use the OnUserConnect method to change the state of local users.
+        * This is called for both local and remote users.
         * @param user The user who is connecting
         */
-       virtual void OnGlobalConnect(userrec* user);
+       virtual void OnPostConnect(User* user);
 
        /** Called whenever a ban is added to a channel's list.
         * Return a non-zero value to 'eat' the mode change and prevent the ban from being added.
@@ -1136,7 +1280,7 @@ class Module : public Extensible
         * @param banmask The ban mask being added
         * @return 1 to block the ban, 0 to continue as normal
         */
-       virtual int OnAddBan(userrec* source, chanrec* channel,const std::string &banmask);
+       virtual int 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.
@@ -1145,7 +1289,9 @@ class Module : public Extensible
         * @param banmask The ban mask being deleted
         * @return 1 to block the unban, 0 to continue as normal
         */
-       virtual int OnDelBan(userrec* source, chanrec* channel,const std::string &banmask);
+       virtual int OnDelBan(User* source, Channel* channel,const std::string &banmask);
+
+       virtual void OnHookUserIO(User* user);
 
        /** 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
@@ -1153,10 +1299,11 @@ class 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
@@ -1168,7 +1315,7 @@ class Module : public Extensible
         * @param Number of characters to write
         * @return Number of characters actually written or 0 if you didn't handle the operation
         */
-       virtual int OnRawSocketWrite(int fd, char* buffer, int count);
+       virtual int OnRawSocketWrite(int fd, const char* buffer, int count);
 
        /** Called immediately before any socket is closed. When this event is called, shutdown()
         * has not yet been called on the socket.
@@ -1176,6 +1323,12 @@ class Module : public Extensible
         */
        virtual void OnRawSocketClose(int fd);
 
+       /** Called immediately upon connection of an outbound BufferedSocket which has been hooked
+        * by a module.
+        * @param fd The file descriptor of the socket immediately after connect()
+        */
+       virtual void OnRawSocketConnect(int fd);
+
        /** Called immediately before any read() operation on a client socket in the core.
         * This occurs AFTER the select() or poll() so there is always data waiting to be read
         * when this event occurs.
@@ -1193,712 +1346,569 @@ class 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 userrec::awaymsg.
-        */
-       virtual void OnSetAway(userrec* user);
-
-       /** Called when a user cancels their away state.
-        */
-       virtual void OnCancelAway(userrec* user);
+       /** 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 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,
+        * and if you do you must return 1. If you do not handle the names list,
+        * return 0.
+        * @param The user requesting the NAMES list
+        * @param Ptr The channel the NAMES list is requested for
+        * @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.
+        * 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);
+
+       /** 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
+        * the values numeric and text, but you cannot change the user the
+        * numeric is sent to. You may however change the user's User values.
+        * @param user The user the numeric is being sent to
+        * @param dest The user being WHOISed
+        * @param numeric The numeric of the line being sent
+        * @param text The text of the numeric, including any parameters
+        * @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);
+
+       /** Called at intervals for modules to garbage-collect any hashes etc.
+        * Certain data types such as hash_map 'leak' buckets, which must be
+        * tidied up and freed by copying into a new item every so often. This
+        * method is called when it is time to do that.
+        */
+       virtual void OnGarbageCollect();
+
+       /** Called whenever a user's write buffer has been completely sent.
+        * This is called when the user's write buffer is completely empty, and
+        * there are no more pending bytes to be written and no pending write events
+        * in the socket engine's queue. This may be used to refill the buffer with
+        * data which is being spooled in a controlled manner, e.g. LIST lines.
+        * @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);
 };
 
 
-/** Allows server output and query functions
- * This class contains methods which allow a module to query the state of the irc server, and produce
- * output to users and other servers. All modules should instantiate at least one copy of this class,
- * and use its member functions to perform their tasks.
+#define CONF_NO_ERROR          0x000000
+#define CONF_NOT_A_NUMBER      0x000010
+#define CONF_INT_NEGATIVE      0x000080
+#define CONF_VALUE_NOT_FOUND   0x000100
+#define CONF_FILE_NOT_FOUND    0x000200
+
+
+/** Allows reading of values from configuration files
+ * This class allows a module to read from either the main configuration file (inspircd.conf) or from
+ * a module-specified configuration file. It may either be instantiated with one parameter or none.
+ * Constructing the class using one parameter allows you to specify a path to your own configuration
+ * file, otherwise, inspircd.conf is read.
  */
-class Server : public Extensible
+class CoreExport ConfigReader : public classbase
 {
public:
-       /** Default constructor.
-        * Creates a Server object.
 protected:
+       InspIRCd* ServerInstance;
+       /** Error code
         */
-       Server();
+       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);
        /** Default destructor.
-        * Destroys a Server object.
+        * This method destroys the ConfigReader class.
         */
-       virtual ~Server();
+       ~ConfigReader();
 
-       /** Obtains a pointer to the server's ServerConfig object.
-        * The ServerConfig object contains most of the configuration data
-        * of the IRC server, as read from the config file by the core.
+       /** Retrieves a value from the config file.
+        * This method retrieves a value from the config file. Where multiple copies of the tag
+        * exist in the config file, index indicates which of the values to retrieve.
         */
-       ServerConfig* GetConfig();
-
-       /** 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
+       std::string ReadValue(const std::string &tag, const std::string &name, int index, bool allow_linefeeds = false);
+       /** Retrieves a value from the config file.
+        * This method retrieves a value from the config file. Where multiple copies of the tag
+        * exist in the config file, index indicates which of the values to retrieve. If the
+        * tag is not found the default value is returned instead.
         */
-       long PriorityBefore(const std::string &modulename);
+       std::string ReadValue(const std::string &tag, const std::string &name, const std::string &default_value, int index, bool allow_linefeeds = false);
 
-       /** 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
+       /** Retrieves a boolean value from the config file.
+        * This method retrieves a boolean value from the config file. Where multiple copies of the tag
+        * exist in the config file, index indicates which of the values to retrieve. The values "1", "yes"
+        * and "true" in the config file count as true to ReadFlag, and any other value counts as false.
         */
-       long PriorityAfter(const std::string &modulename);
-       
-       /** Sends text to all opers.
-        * This method sends a server notice to all opers with the usermode +s.
+       bool ReadFlag(const std::string &tag, const std::string &name, int index);
+       /** Retrieves a boolean value from the config file.
+        * This method retrieves a boolean value from the config file. Where multiple copies of the tag
+        * exist in the config file, index indicates which of the values to retrieve. The values "1", "yes"
+        * and "true" in the config file count as true to ReadFlag, and any other value counts as false.
+        * If the tag is not found, the default value is used instead.
         */
-       virtual void SendOpers(const std::string &s);
+       bool ReadFlag(const std::string &tag, const std::string &name, const std::string &default_value, int index);
 
-       /** Returns the version string of this server
+       /** Retrieves an integer value from the config file.
+        * This method retrieves an integer value from the config file. Where multiple copies of the tag
+        * exist in the config file, index indicates which of the values to retrieve. Any invalid integer
+        * values in the tag will cause the objects error value to be set, and any call to GetError() will
+        * return CONF_INVALID_NUMBER to be returned. need_positive is set if the number must be non-negative.
+        * If a negative number is placed into a tag which is specified positive, 0 will be returned and GetError()
+        * will return CONF_INT_NEGATIVE. Note that need_positive is not suitable to get an unsigned int - you
+        * should cast the result to achieve that effect.
         */
-       std::string GetVersion();
-
-       /** Publish a 'feature'.
-        * There are two ways for a module to find another module it depends on.
-        * Either by name, using Server::FindModule, or by feature, using this
-        * function. A feature is an arbitary string which identifies something this
-        * module can do. For example, if your module provides SSL support, but other
-        * modules provide SSL support too, all the modules supporting SSL should
-        * publish an identical 'SSL' feature. This way, any module requiring use
-        * of SSL functions can just look up the 'SSL' feature using FindFeature,
-        * then use the module pointer they are given.
-        * @param FeatureName The case sensitive feature name to make available
-        * @param Mod a pointer to your module class
-        * @returns True on success, false if the feature is already published by
-        * another module.
+       int ReadInteger(const std::string &tag, const std::string &name, int index, bool need_positive);
+       /** Retrieves an integer value from the config file.
+        * This method retrieves an integer value from the config file. Where multiple copies of the tag
+        * exist in the config file, index indicates which of the values to retrieve. Any invalid integer
+        * values in the tag will cause the objects error value to be set, and any call to GetError() will
+        * return CONF_INVALID_NUMBER to be returned. needs_unsigned is set if the number must be unsigned.
+        * If a signed number is placed into a tag which is specified unsigned, 0 will be returned and GetError()
+        * will return CONF_NOT_UNSIGNED. If the tag is not found, the default value is used instead.
         */
-       bool PublishFeature(const std::string &FeatureName, Module* Mod);
+       int ReadInteger(const std::string &tag, const std::string &name, const std::string &default_value, int index, bool need_positive);
 
-       /** Unpublish a 'feature'.
-        * When your module exits, it must call this method for every feature it
-        * is providing so that the feature table is cleaned up.
-        * @param FeatureName the feature to remove
+       /** Returns the last error to occur.
+        * Valid errors can be found by looking in modules.h. Any nonzero value indicates an error condition.
+        * A call to GetError() resets the error flag back to 0.
         */
-       bool UnpublishFeature(const std::string &FeatureName);
+       long GetError();
+       /** Counts the number of times a given tag appears in the config file.
+        * This method counts the number of times a tag appears in a config file, for use where
+        * there are several tags of the same kind, e.g. with opers and connect types. It can be
+        * used with the index value of ConfigReader::ReadValue to loop through all copies of a
+        * multiple instance tag.
+        */
+       int Enumerate(const std::string &tag);
 
-       /** Find a 'feature'.
-        * There are two ways for a module to find another module it depends on.
-        * Either by name, using Server::FindModule, or by feature, using the
-        * Server::PublishFeature method. A feature is an arbitary string which
-        * identifies something this module can do. For example, if your module
-        * provides SSL support, but other modules provide SSL support too, all
-        * the modules supporting SSL should publish an identical 'SSL' feature.
-        * To find a module capable of providing the feature you want, simply
-        * call this method with the feature name you are looking for.
-        * @param FeatureName The feature name you wish to obtain the module for
-        * @returns A pointer to a valid module class on success, NULL on failure.
+       /** Returns the number of items within a tag.
+        * For example if the tag was &lt;test tag="blah" data="foo"&gt; then this
+        * function would return 2. Spaces and newlines both qualify as valid seperators
+        * between values.
         */
-       Module* FindFeature(const std::string &FeatureName);
+       int EnumerateValues(const std::string &tag, int index);
+};
 
-       const std::string& GetModuleName(Module* m);
 
-       /** Writes a log string.
-        * This method writes a line of text to the log. If the level given is lower than the
-        * level given in the configuration, this command has no effect.
-        */
-       virtual void Log(int level, const std::string &s);
 
-       /** Sends a line of text down a TCP/IP socket.
-        * This method writes a line of text to an established socket, cutting it to 510 characters
-        * plus a carriage return and linefeed if required.
+/** Caches a text file into memory and can be used to retrieve lines from it.
+ * This class contains methods for read-only manipulation of a text file in memory.
+ * Either use the constructor type with one parameter to load a file into memory
+ * at construction, or use the LoadFile method to load a file.
+ */
+class CoreExport FileReader : public classbase
+{
+       InspIRCd* ServerInstance;
+       /** The file contents
         */
-       virtual void Send(int Socket, const std::string &s);
+       file_cache fc;
 
-       /** Sends text from the server to a socket.
-        * This method writes a line of text to an established socket, with the servername prepended
-        * as used by numerics (see RFC 1459)
+       /** Content size in bytes
         */
-       virtual void SendServ(int Socket, const std::string &s);
+       unsigned long contentsize;
 
-       /** Writes text to a channel, but from a server, including all.
-        * This can be used to send server notices to a group of users.
+       /** Calculate content size in bytes
         */
-       virtual void SendChannelServerNotice(const std::string &ServName, chanrec* Channel, const std::string &text);
+       void CalcSize();
 
-       /** Sends text from a user to a socket.
-        * This method writes a line of text to an established socket, with the given user's nick/ident
-        * /host combination prepended, as used in PRIVSG etc commands (see RFC 1459)
+ public:
+       /** Default constructor.
+        * This method does not load any file into memory, you must use the LoadFile method
+        * after constructing the class this way.
         */
-       virtual void SendFrom(int Socket, userrec* User, const std::string &s);
+       FileReader(InspIRCd* Instance);
 
-       /** Sends text from a user to another user.
-        * This method writes a line of text to a user, with a user's nick/ident
-        * /host combination prepended, as used in PRIVMSG etc commands (see RFC 1459)
-        * If you specify NULL as the source, then the data will originate from the
-        * local server, e.g. instead of:
-        *
-        * :user!ident@host TEXT
-        *
-        * The format will become:
-        *
-        * :localserver TEXT
-        *
-        * Which is useful for numerics and server notices to single users, etc.
+       /** Secondary constructor.
+        * This method initialises the class with a file loaded into it ready for GetLine and
+        * and other methods to be called. If the file could not be loaded, FileReader::FileSize
+        * returns 0.
         */
-       virtual void SendTo(userrec* Source, userrec* Dest, const std::string &s);
+       FileReader(InspIRCd* Instance, const std::string &filename);
 
-       /** Sends text from a user to a channel (mulicast).
-        * This method writes a line of text to a channel, with the given user's nick/ident
-        * /host combination prepended, as used in PRIVMSG etc commands (see RFC 1459). If the
-        * IncludeSender flag is set, then the text is also sent back to the user from which
-        * it originated, as seen in MODE (see RFC 1459).
+       /** Default destructor.
+        * This deletes the memory allocated to the file.
         */
-       virtual void SendChannel(userrec* User, chanrec* Channel, const std::string &s, bool IncludeSender);
+       ~FileReader();
 
-       /** Returns true if two users share a common channel.
-        * This method is used internally by the NICK and QUIT commands, and the Server::SendCommon
-        * method.
+       /** Used to load a file.
+        * This method loads a file into the class ready for GetLine and
+        * and other methods to be called. If the file could not be loaded, FileReader::FileSize
+        * returns 0.
         */
-       virtual bool CommonChannels(userrec* u1, userrec* u2);
+       void LoadFile(const std::string &filename);
 
-       /** Sends text from a user to one or more channels (mulicast).
-        * This method writes a line of text to all users which share a common channel with a given     
-        * user, with the user's nick/ident/host combination prepended, as used in PRIVMSG etc
-        * commands (see RFC 1459). If the IncludeSender flag is set, then the text is also sent
-        * back to the user from which it originated, as seen in NICK (see RFC 1459). Otherwise, it
-        * is only sent to the other recipients, as seen in QUIT.
+       /** Returns the whole content of the file as std::string
         */
-       virtual void SendCommon(userrec* User, const std::string &text, bool IncludeSender);
+       std::string Contents();
 
-       /** Sends a WALLOPS message.
-        * This method writes a WALLOPS message to all users with the +w flag, originating from the
-        * specified user.
+       /** Returns the entire size of the file as std::string
         */
-       virtual void SendWallops(userrec* User, const std::string &text);
+       unsigned long ContentSize();
 
-       /** Returns true if a nick is valid.
-        * Nicks for unregistered connections will return false.
+       /** Returns true if the file exists
+        * This function will return false if the file could not be opened.
         */
-       virtual bool IsNick(const std::string &nick);
+       bool Exists();
 
-       /** Returns a count of the number of users on a channel.
-        * This will NEVER be 0, as if the chanrec exists, it will have at least one user in the channel.
+       /** 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.
         */
-       virtual int CountUsers(chanrec* c);
+       std::string GetLine(int x);
 
-       /** Adds an InspTimer which will trigger at a future time
+       /** Returns the size of the file in lines.
+        * This method returns the number of lines in the read file. If it is 0, no lines have been
+        * read into memory, either because the file is empty or it does not exist, or cannot be
+        * opened due to permission problems.
         */
-       virtual void AddTimer(InspTimer* T);
+       int FileSize();
+};
 
-       /** Attempts to look up a nick and return a pointer to it.
-        * This function will return NULL if the nick does not exist.
-        */
-       virtual userrec* FindNick(const std::string &nick);
+/** A DLLFactory (designed to load shared objects) containing a
+ * 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;
 
-       /** Attempts to look up a nick using the file descriptor associated with that nick.
-        * This function will return NULL if the file descriptor is not associated with a valid user.
-        */
-       virtual userrec* FindDescriptor(int socket);
+/** A list of modules
+ */
+typedef std::vector<Module*> IntModuleList;
 
-       /** Attempts to look up a channel and return a pointer to it.
-        * This function will return NULL if the channel does not exist.
-        */
-       virtual chanrec* FindChannel(const std::string &channel);
+/** An event handler iterator
+ */
+typedef IntModuleList::iterator EventHandlerIter;
 
-       /** Attempts to look up a user's privilages on a channel.
-        * This function will return a string containing either @, %, +, or an empty string,
-        * representing the user's privilages upon the channel you specify.
+/** ModuleManager takes care of all things module-related
+ * in the core.
+ */
+class CoreExport ModuleManager : public classbase
+{
+ private:
+       /** Holds a string describing the last module error to occur
         */
-       virtual std::string ChanMode(userrec* User, chanrec* Chan);
+       std::string LastModuleError;
 
-       /** Returns the server name of the server where the module is loaded.
+       /** The feature names published by various modules
         */
-       virtual std::string GetServerName();
+       featurelist Features;
 
-       /** Returns the network name, global to all linked servers.
+       /** The interface names published by various modules
         */
-       virtual std::string GetNetworkName();
+       interfacelist Interfaces;
 
-       /** Returns the server description string of the local server
+       /** Total number of modules loaded into the ircd
         */
-       virtual std::string GetServerDescription();
+       int ModCount;
 
-       /** Returns the information of the server as returned by the /ADMIN command.
-        * See the Admin class for further information of the return value. The members
-        * Admin::Nick, Admin::Email and Admin::Name contain the information for the
-        * server where the module is loaded.
+       /** Our pointer to the main insp instance
         */
-       virtual Admin GetAdmin();
+       InspIRCd* Instance;
 
-       virtual bool AddMode(ModeHandler* mh, const unsigned char modechar);
-
-       virtual bool AddModeWatcher(ModeWatcher* mw);
+       /** List of loaded modules and shared object/dll handles
+        * keyed by module name
+        */
+       std::map<std::string, std::pair<ircd_module*, Module*> > Modules;
 
-       virtual bool DelModeWatcher(ModeWatcher* mw);
+       enum {
+               PRIO_STATE_FIRST,
+               PRIO_STATE_AGAIN,
+               PRIO_STATE_LAST
+       } prioritizationState;
+ public:
 
-       /** Adds a command to the command table.
-        * This allows modules to add extra commands into the command table. You must place a function within your
-        * module which is is of type handlerfunc:
-        * 
-        * typedef void (handlerfunc) (char**, int, userrec*);
-        * ...
-        * void handle_kill(char **parameters, int pcnt, userrec *user)
-        *
-        * When the command is typed, the parameters will be placed into the parameters array (similar to argv) and
-        * the parameter count will be placed into pcnt (similar to argv). There will never be any less parameters
-        * than the 'minparams' value you specified when creating the command. The *user parameter is the class of
-        * the user which caused the command to trigger, who will always have the flag you specified in 'flags' when
-        * creating the initial command. For example to create an oper only command create the commands with flags='o'.
-        * The source parameter is used for resource tracking, and should contain the name of your module (with file
-        * extension) e.g. "m_blarp.so". If you place the wrong identifier here, you can cause crashes if your module
-        * is unloaded.
-        */
-       virtual void AddCommand(command_t *f);
-        
-       /** Sends a servermode.
-        * you must format the parameters array with the target, modes and parameters for those modes.
-        *
-        * For example:
-        *
-        * char *modes[3];
-        *
-        * modes[0] = ChannelName;
-        *
-        * modes[1] = "+o";
-        *
-        * modes[2] = user->nick;
-        *
-        * Srv->SendMode(modes,3,user);
-        *
-        * The modes will originate from the server where the command was issued, however responses (e.g. numerics)
-        * will be sent to the user you provide as the third parameter.
-        * You must be sure to get the number of parameters correct in the pcnt parameter otherwise you could leave
-        * your server in an unstable state!
-        */
-
-       virtual void SendMode(char **parameters, int pcnt, userrec *user);
-       
-       /** Sends to all users matching a mode mask
-        * You must specify one or more usermodes as the first parameter. These can be RFC specified modes such as +i,
-        * or module provided modes, including ones provided by your own module.
-        * In the second parameter you must place a flag value which indicates wether the modes you have given will be
-        * logically ANDed or OR'ed. You may use one of either WM_AND or WM_OR.
-        * for example, if you were to use:
-        *
-        * Serv->SendToModeMask("xi", WM_OR, "m00");
-        *
-        * Then the text 'm00' will be sent to all users with EITHER mode x or i. Conversely if you used WM_AND, the
-        * user must have both modes set to receive the message.
-        */
-       virtual void SendToModeMask(const std::string &modes, int flags, const std::string &text);
-
-       /** Forces a user to join a channel.
-        * This is similar to svsjoin and can be used to implement redirection, etc.
-        * On success, the return value is a valid pointer to a chanrec* of the channel the user was joined to.
-        * On failure, the result is NULL.
-        */
-       virtual chanrec* JoinUserToChannel(userrec* user, const std::string &cname, const std::string &key);
-       
-       /** Forces a user to part a channel.
-        * This is similar to svspart and can be used to implement redirection, etc.
-        * Although the return value of this function is a pointer to a channel record, the returned data is
-        * undefined and should not be read or written to. This behaviour may be changed in a future version.
-        */
-       virtual chanrec* PartUserFromChannel(userrec* user, const std::string &cname, const std::string &reason);
-       
-       /** Forces a user nickchange.
-        * This command works similarly to SVSNICK, and can be used to implement Q-lines etc.
-        * If you specify an invalid nickname, the nick change will be dropped and the target user will receive
-        * the error numeric for it.
-        */
-       virtual void ChangeUserNick(userrec* user, const std::string &nickname);
-       
-       /** Forces a user to quit with the specified reason.
-        * To the user, it will appear as if they typed /QUIT themselves, except for the fact that this function
-        * may bypass the quit prefix specified in the config file.
-        *
-        * WARNING!
-        *
-        * Once you call this function, userrec* user will immediately become INVALID. You MUST NOT write to, or
-        * read from this pointer after calling the QuitUser method UNDER ANY CIRCUMSTANCES! The best course of
-        * action after calling this method is to immediately bail from your handler.
+       /** Event handler hooks.
+        * This needs to be public to be used by FOREACH_MOD and friends.
         */
-       virtual void QuitUser(userrec* user, const std::string &reason);
+       IntModuleList EventHandlers[I_END];
 
-       /** Makes a user kick another user, with the specified reason.
-        * If source is NULL, the server will peform the kick.
-        * @param The person or server (if NULL) performing the KICK
-        * @param target The person being kicked
-        * @param chan The channel to kick from
-        * @param reason The kick reason
-        */
-       virtual void KickUser(userrec* source, userrec* target, chanrec* chan, const std::string &reason);
-       
-       /**  Matches text against a glob pattern.
-        * Uses the ircd's internal matching function to match string against a globbing pattern, e.g. *!*@*.com
-        * Returns true if the literal successfully matches the pattern, false if otherwise.
-        */
-       virtual bool MatchText(const std::string &sliteral, const std::string &spattern);
-       
-       /** Calls the handler for a command, either implemented by the core or by another module.
-        * You can use this function to trigger other commands in the ircd, such as PRIVMSG, JOIN,
-        * KICK etc, or even as a method of callback. By defining command names that are untypeable
-        * for users on irc (e.g. those which contain a \r or \n) you may use them as callback identifiers.
-        * The first parameter to this method is the name of the command handler you wish to call, e.g.
-        * PRIVMSG. This will be a command handler previously registered by the core or wih AddCommand().
-        * The second parameter is an array of parameters, and the third parameter is a count of parameters
-        * in the array. If you do not pass enough parameters to meet the minimum needed by the handler, the
-        * functiom will silently ignore it. The final parameter is the user executing the command handler,
-        * used for privilage checks, etc.
-        * @return True if the command exists
-        */
-       virtual bool CallCommandHandler(const std::string &commandname, char** parameters, int pcnt, userrec* user);
-
-       /** This function returns true if the commandname exists, pcnt is equal to or greater than the number
-        * of paramters the command requires, the user specified is allowed to execute the command, AND
-        * if the command is implemented by a module (not the core). This has a few specific uses, usually
-        * within network protocols (see src/modules/m_spanningtree.cpp)
-        */
-       virtual bool IsValidModuleCommand(const std::string &commandname, int pcnt, userrec* user);
-       
-       /** Change displayed hostname of a user.
-        * You should always call this method to change a user's host rather than writing directly to the
-        * dhost member of userrec, as any change applied via this method will be propogated to any
-        * linked servers.
-        */     
-       virtual void ChangeHost(userrec* user, const std::string &host);
-       
-       /** Change GECOS (fullname) of a user.
-        * You should always call this method to change a user's GECOS rather than writing directly to the
-        * fullname member of userrec, as any change applied via this method will be propogated to any
-        * linked servers.
-        */     
-       virtual void ChangeGECOS(userrec* user, const std::string &gecos);
-       
-       /** Returns true if the servername you give is ulined.
-        * ULined servers have extra privilages. They are allowed to change nicknames on remote servers,
-        * change modes of clients which are on remote servers and set modes of channels where there are
-        * no channel operators for that channel on the ulined server, amongst other things.
-        */
-       virtual bool IsUlined(const std::string &server);
-       
-       /** Fetches the userlist of a channel. This function must be here and not a member of userrec or
-        * chanrec due to include constraints.
+       /** Simple, bog-standard, boring constructor.
         */
-       virtual chanuserlist GetUsers(chanrec* chan);
+       ModuleManager(InspIRCd* Ins);
 
-       /** Remove a user's connection to the irc server, but leave their client in existence in the
-        * user hash. When you call this function, the user's file descriptor will be replaced with the
-        * value of FD_MAGIC_NUMBER and their old file descriptor will be closed. This idle client will
-        * remain until it is restored with a valid file descriptor, or is removed from IRC by an operator
-        * After this call, the pointer to user will be invalid.
+       /** Destructor
         */
-       virtual bool UserToPseudo(userrec* user, const std::string &message);
+       ~ModuleManager();
 
-       /** This user takes one user, and switches their file descriptor with another user, so that one user
-        * "becomes" the other. The user in 'alive' is booted off the server with the given message. The user
-        * referred to by 'zombie' should have previously been locked with Server::UserToPseudo, otherwise
-        * stale sockets and file descriptor leaks can occur. After this call, the pointer to alive will be
-        * invalid, and the pointer to zombie will be equivalent in effect to the old pointer to alive.
+       /** 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 PRIORITY_AFTER
+        * to set it to be before or after one or more other modules.
+        * @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 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.
         */
-       virtual bool PseudoToUser(userrec* alive, userrec* zombie, const std::string &message);
+       bool SetPriority(Module* mod, Implementation i, Priority s, Module** modules = NULL, size_t sz = 1);
 
-       /** Adds a G-line
-        * The G-line is propogated to all of the servers in the mesh and enforced as soon as it is added.
-        * The duration must be in seconds, however you can use the Server::CalcDuration method to convert
-        * durations into the 1w2d3h3m6s format used by /GLINE etc. The source is an arbitary string used
-        * to indicate who or what sent the data, usually this is the nickname of a person, or a server
-        * name.
+       /** 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 PRIORITY_AFTER, you should use the more fine tuned
+        * SetPriority method for this, where you may specify other modules to
+        * be prioritized against.
         */
-       virtual void AddGLine(long duration, const std::string &source, const std::string &reason, const std::string &hostmask);
+       bool SetPriority(Module* mod, Priority s);
 
-       /** Adds a Q-line
-        * The Q-line is propogated to all of the servers in the mesh and enforced as soon as it is added.
-        * The duration must be in seconds, however you can use the Server::CalcDuration method to convert
-        * durations into the 1w2d3h3m6s format used by /GLINE etc. The source is an arbitary string used
-        * to indicate who or what sent the data, usually this is the nickname of a person, or a server
-        * name.
+       /** 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
         */
-       virtual void AddQLine(long duration, const std::string &source, const std::string &reason, const std::string &nickname);
+       bool Attach(Implementation i, Module* mod);
 
-       /** Adds a Z-line
-        * The Z-line is propogated to all of the servers in the mesh and enforced as soon as it is added.
-        * The duration must be in seconds, however you can use the Server::CalcDuration method to convert
-        * durations into the 1w2d3h3m6s format used by /GLINE etc. The source is an arbitary string used
-        * to indicate who or what sent the data, usually this is the nickname of a person, or a server
-        * name.
+       /** 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
         */
-       virtual void AddZLine(long duration, const std::string &source, const std::string &reason, const std::string &ipaddr);
+       bool Detach(Implementation i, Module* mod);
 
-       /** Adds a K-line
-        * The K-line is enforced as soon as it is added.
-        * The duration must be in seconds, however you can use the Server::CalcDuration method to convert
-        * durations into the 1w2d3h3m6s format used by /GLINE etc. The source is an arbitary string used
-        * to indicate who or what sent the data, usually this is the nickname of a person, or a server
-        * name.
+       /** Attach an array of events to a module
+        * @param i Event types (array) to attach
+        * @param mod Module to attach events to
         */
-       virtual void AddKLine(long duration, const std::string &source, const std::string &reason, const std::string &hostmask);
+       void Attach(Implementation* i, Module* mod, size_t sz);
 
-       /** Adds a E-line
-        * The E-line is enforced as soon as it is added.
-        * The duration must be in seconds, however you can use the Server::CalcDuration method to convert
-        * durations into the 1w2d3h3m6s format used by /GLINE etc. The source is an arbitary string used
-        * to indicate who or what sent the data, usually this is the nickname of a person, or a server
-        * name.
+       /** Detach all events from a module (used on unload)
+        * @param mod Module to detach from
         */
-       virtual void AddELine(long duration, const std::string &source, const std::string &reason, const std::string &hostmask);
+       void DetachAll(Module* mod);
 
-       /** Deletes a G-Line from all servers
+       /** Returns text describing the last module error
+        * @return The last error message to occur
         */
-       virtual bool DelGLine(const std::string &hostmask);
+       std::string& LastError();
 
-       /** Deletes a Q-Line from all servers
+       /** Load a given module file
+        * @param filename The file to load
+        * @return True if the module was found and loaded
         */
-       virtual bool DelQLine(const std::string &nickname);
+       bool Load(const char* filename);
 
-       /** Deletes a Z-Line from all servers
+       /** Unload a given module file
+        * @param filename The file to unload
+        * @return True if the module was unloaded
         */
-       virtual bool DelZLine(const std::string &ipaddr);
+       bool Unload(const char* filename);
 
-       /** Deletes a local K-Line
+       /** Called by the InspIRCd constructor to load all modules from the config file.
         */
-       virtual bool DelKLine(const std::string &hostmask);
+       void LoadAll();
 
-       /** Deletes a local E-Line
+       /** Get the total number of currently loaded modules
+        * @return The number of loaded modules
         */
-       virtual bool DelELine(const std::string &hostmask);
+       int GetCount()
+       {
+               return this->ModCount;
+       }
 
-       /** Calculates a duration
-        * This method will take a string containing a formatted duration (e.g. "1w2d") and return its value
-        * as a total number of seconds. This is the same function used internally by /GLINE etc to set
-        * the ban times.
+       /** 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
         */
-       virtual long CalcDuration(const std::string &duration);
+       Module* Find(const std::string &name);
 
-       /** Returns true if a nick!ident@host string is correctly formatted, false if otherwise.
+       /** Publish a 'feature'.
+        * There are two ways for a module to find another module it depends on.
+        * Either by name, using InspIRCd::FindModule, or by feature, using this
+        * function. A feature is an arbitary string which identifies something this
+        * module can do. For example, if your module provides SSL support, but other
+        * modules provide SSL support too, all the modules supporting SSL should
+        * publish an identical 'SSL' feature. This way, any module requiring use
+        * of SSL functions can just look up the 'SSL' feature using FindFeature,
+        * then use the module pointer they are given.
+        * @param FeatureName The case sensitive feature name to make available
+        * @param Mod a pointer to your module class
+        * @returns True on success, false if the feature is already published by
+        * another module.
         */
-       virtual bool IsValidMask(const std::string &mask);
+       bool PublishFeature(const std::string &FeatureName, Module* Mod);
 
-       /** This function finds a module by name.
-        * You must provide the filename of the module. If the module cannot be found (is not loaded)
-        * the function will return NULL.
+       /** Publish a module to an 'interface'.
+        * Modules which implement the same interface (the same way of communicating
+        * with other modules) can publish themselves to an interface, using this
+        * method. When they do so, they become part of a list of related or
+        * compatible modules, and a third module may then query for that list
+        * and know that all modules within that list offer the same API.
+        * A prime example of this is the hashing modules, which all accept the
+        * same types of Request class. Consider this to be similar to PublishFeature,
+        * except for that multiple modules may publish the same 'feature'.
+        * @param InterfaceName The case sensitive interface name to make available
+        * @param Mod a pointer to your module class
+        * @returns True on success, false on failure (there are currently no failure
+        * cases)
         */
-       virtual Module* FindModule(const std::string &name);
+       bool PublishInterface(const std::string &InterfaceName, Module* Mod);
 
-       /** Adds a class derived from InspSocket to the server's socket engine.
+       /** Return a pair saying how many other modules are currently using the
+        * interfaces provided by module m.
+        * @param m The module to count usage for
+        * @return A pair, where the first value is the number of uses of the interface,
+        * and the second value is the interface name being used.
         */
-       virtual void AddSocket(InspSocket* sock);
+       std::pair<int,std::string> GetInterfaceInstanceCount(Module* m);
 
-       /** Forcibly removes a class derived from InspSocket from the servers socket engine.
+       /** Mark your module as using an interface.
+        * If you mark your module as using an interface, then that interface
+        * module may not unload until your module has unloaded first.
+        * This can be used to prevent crashes by ensuring code you depend on
+        * is always in memory while your module is active.
+        * @param InterfaceName The interface to use
         */
-       virtual void RemoveSocket(InspSocket* sock);
+       void UseInterface(const std::string &InterfaceName);
 
-       /** Deletes a class derived from InspSocket from the server's socket engine.
+       /** Mark your module as finished with an interface.
+        * If you used UseInterface() above, you should use this method when
+        * your module is finished with the interface (usually in its destructor)
+        * to allow the modules which implement the given interface to be unloaded.
+        * @param InterfaceName The interface you are finished with using.
         */
-       virtual void DelSocket(InspSocket* sock);
+       void DoneWithInterface(const std::string &InterfaceName);
 
-       /** Causes the local server to rehash immediately.
-        * WARNING: Do not call this method from within your rehash method, for
-        * obvious reasons!
+       /** Unpublish a 'feature'.
+        * When your module exits, it must call this method for every feature it
+        * is providing so that the feature table is cleaned up.
+        * @param FeatureName the feature to remove
         */
-       virtual void RehashServer();
+       bool UnpublishFeature(const std::string &FeatureName);
 
-       /** This method returns the total number of channels on the network.
+       /** Unpublish your module from an interface
+        * When your module exits, it must call this method for every interface
+        * it is part of so that the interfaces table is cleaned up. Only when
+        * the last item is deleted from an interface does the interface get
+        * removed.
+        * @param InterfaceName the interface to be removed from
+        * @param Mod The module to remove from the interface list
         */
-       virtual long GetChannelCount();
+       bool UnpublishInterface(const std::string &InterfaceName, Module* Mod);
 
-       /** This method returns a channel whos index is greater than or equal to 0 and less than the number returned by Server::GetChannelCount().
-        * This is slower (by factors of dozens) than requesting a channel by name with Server::FindChannel(), however there are times when
-        * you wish to safely iterate the channel list, saving your position, with large amounts of time in between, which is what this function
-        * is useful for.
+       /** Find a 'feature'.
+        * There are two ways for a module to find another module it depends on.
+        * Either by name, using InspIRCd::FindModule, or by feature, using the
+        * InspIRCd::PublishFeature method. A feature is an arbitary string which
+        * identifies something this module can do. For example, if your module
+        * provides SSL support, but other modules provide SSL support too, all
+        * the modules supporting SSL should publish an identical 'SSL' feature.
+        * To find a module capable of providing the feature you want, simply
+        * call this method with the feature name you are looking for.
+        * @param FeatureName The feature name you wish to obtain the module for
+        * @returns A pointer to a valid module class on success, NULL on failure.
         */
-       virtual chanrec* GetChannelIndex(long index);
+       Module* FindFeature(const std::string &FeatureName);
 
-       /** Dumps text (in a stringstream) to a user. The stringstream should not contain linefeeds, as it will be split
-        * automatically by the function into safe amounts. The line prefix given is prepended onto each line (e.g. a servername
-        * and a numeric).
+       /** Find an 'interface'.
+        * An interface is a list of modules which all implement the same API.
+        * @param InterfaceName The Interface you wish to obtain the module
+        * list of.
+        * @return A pointer to a deque of Module*, or NULL if the interface
+        * does not exist.
         */
-       void DumpText(userrec* User, const std::string &LinePrefix, stringstream &TextStream);
-};
-
+       modulelist* FindInterface(const std::string &InterfaceName);
 
-#define CONF_NOT_A_NUMBER      0x000010
-#define CONF_NOT_UNSIGNED      0x000080
-#define CONF_VALUE_NOT_FOUND   0x000100
-#define CONF_FILE_NOT_FOUND    0x000200
-
-
-/** Allows reading of values from configuration files
- * This class allows a module to read from either the main configuration file (inspircd.conf) or from
- * a module-specified configuration file. It may either be instantiated with one parameter or none.
- * Constructing the class using one parameter allows you to specify a path to your own configuration
- * file, otherwise, inspircd.conf is read.
- */
-class ConfigReader : public classbase
-{
-  protected:
-       /** 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;
-       std::ostringstream* errorlog;;
-       /** Used to store errors
-        */
-       bool privatehash; // If we're using our own config data hash or not.
-       bool readerror;
-       long error;
-       
-  public:
-       /** Default constructor.
-        * This constructor initialises the ConfigReader class to read the inspircd.conf file
-        * as specified when running ./configure.
-        */
-       ConfigReader();                 // default constructor reads ircd.conf
-       /** Overloaded constructor.
-        * This constructor initialises the ConfigReader class to read a user-specified config file
-        */
-       ConfigReader(const std::string &filename);      // read a module-specific config
-       /** Default destructor.
-        * This method destroys the ConfigReader class.
-        */
-       ~ConfigReader();
-       /** Retrieves a value from the config file.
-        * This method retrieves a value from the config file. Where multiple copies of the tag
-        * exist in the config file, index indicates which of the values to retrieve.
+       /** 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.
         */
-       std::string ReadValue(const std::string &tag, const std::string &name, int index);
-       /** Retrieves a boolean value from the config file.
-        * This method retrieves a boolean value from the config file. Where multiple copies of the tag
-        * exist in the config file, index indicates which of the values to retrieve. The values "1", "yes"
-        * and "true" in the config file count as true to ReadFlag, and any other value counts as false.
-        */
-       bool ReadFlag(const std::string &tag, const std::string &name, int index);
-       /** Retrieves an integer value from the config file.
-        * This method retrieves an integer value from the config file. Where multiple copies of the tag
-        * exist in the config file, index indicates which of the values to retrieve. Any invalid integer
-        * values in the tag will cause the objects error value to be set, and any call to GetError() will
-        * return CONF_INVALID_NUMBER to be returned. needs_unsigned is set if the number must be unsigned.
-        * If a signed number is placed into a tag which is specified unsigned, 0 will be returned and GetError()
-        * will return CONF_NOT_UNSIGNED
-        */
-       long ReadInteger(const std::string &tag, const std::string &name, int index, bool needs_unsigned);
-       /** Returns the last error to occur.
-        * Valid errors can be found by looking in modules.h. Any nonzero value indicates an error condition.
-        * A call to GetError() resets the error flag back to 0.
-        */
-       long GetError();
-       /** Counts the number of times a given tag appears in the config file.
-        * This method counts the number of times a tag appears in a config file, for use where
-        * there are several tags of the same kind, e.g. with opers and connect types. It can be
-        * used with the index value of ConfigReader::ReadValue to loop through all copies of a
-        * 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,userrec* user);
+       bool ModuleHasInterface(Module* mod, const std::string& InterfaceName);
 
-       /** Returns the number of items within a tag.
-        * For example if the tag was &lt;test tag="blah" data="foo"&gt; then this
-        * function would return 2. Spaces and newlines both qualify as valid seperators
-        * between values.
+       /** Given a pointer to a Module, return its filename
+        * @param m The module pointer to identify
+        * @return The module name or an empty string
         */
-       int EnumerateValues(const std::string &tag, int index);
-};
-
-
+       const std::string& GetModuleName(Module* m);
 
-/** Caches a text file into memory and can be used to retrieve lines from it.
- * This class contains methods for read-only manipulation of a text file in memory.
- * Either use the constructor type with one parameter to load a file into memory
- * at construction, or use the LoadFile method to load a file.
- */
-class FileReader : public classbase
-{
-       /** The file contents
+       /** 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
         */
-       file_cache fc;
- public:
-        /** Default constructor.
-         * This method does not load any file into memory, you must use the LoadFile method
-         * after constructing the class this way.
-         */
-        FileReader();
-
-        /** Secondary constructor.
-         * This method initialises the class with a file loaded into it ready for GetLine and
-         * and other methods to be called. If the file could not be loaded, FileReader::FileSize
-         * returns 0.
-         */
-        FileReader(const std::string &filename);
-
-        /** Default destructor.
-         * This deletes the memory allocated to the file.
-         */
-        ~FileReader();
-
-        /** Used to load a file.
-         * This method loads a file into the class ready for GetLine and
-         * and other methods to be called. If the file could not be loaded, FileReader::FileSize
-         * returns 0.
-         */
-        void LoadFile(const std::string &filename);
-
-        /** Returns the whole content of the file as std::string
-         */
-        std::string Contents();
-
-        /** Returns the entire size of the file as std::string
-         */
-        unsigned long ContentSize();
-
-        /** Returns true if the file exists
-         * 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.
-         */
-        std::string GetLine(int x);
-
-        /** Returns the size of the file in lines.
-         * This method returns the number of lines in the read file. If it is 0, no lines have been
-         * read into memory, either because the file is empty or it does not exist, or cannot be
-         * opened due to permission problems.
-         */
-        int FileSize();
+       const std::vector<std::string> GetAllModuleNames(int filter);
 };
 
-
-/** Instantiates classes inherited from Module
- * This class creates a class inherited from type Module, using new. This is to allow for modules
- * to create many different variants of Module, dependent on architecture, configuration, etc.
- * In most cases, the simple class shown in the example module m_foobar.so will suffice for most
- * modules.
+/** 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.
  */
-class ModuleFactory : public classbase
-{
- public:
-       ModuleFactory() { }
-       virtual ~ModuleFactory() { }
-       /** Creates a new module.
-        * Your inherited class of ModuleFactory must return a pointer to your Module class
-        * using this method.
-        */
-       virtual Module * CreateModule(Server* Me) = 0;
-};
+#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; \
+       }
 
-typedef DLLFactory<ModuleFactory> ircd_module;
-typedef std::vector<Module*> ModuleList;
-typedef std::vector<ircd_module*> FactoryList;
+#else
+
+#define MODULE_INIT(y) \
+       extern "C" DllExport Module * init_module(InspIRCd* Me) \
+       { \
+               return new y(Me); \
+       }
+#endif
 
 #endif