#include <deque>
#include <sstream>
#include <typeinfo>
+#include "timer.h"
class Server;
class ServerConfig;
#define FOREACH_MOD(y,x) if (Config->global_implementation[y] > 0) { \
for (int _i = 0; _i <= MODCOUNT; _i++) { \
if (Config->implement_lists[_i][y]) \
- modules[_i]->x ; \
+ try \
+ { \
+ modules[_i]->x ; \
+ } \
+ catch (ModuleException& modexcept) \
+ { \
+ log(DEBUG,"Module exception cought: %s",modexcept.GetReason()); \
+ } \
} \
}
MOD_RESULT = 0; \
for (int _i = 0; _i <= MODCOUNT; _i++) { \
if (Config->implement_lists[_i][y]) {\
- int res = modules[_i]->x ; \
- if (res != 0) { \
- MOD_RESULT = res; \
- break; \
+ try \
+ { \
+ int res = modules[_i]->x ; \
+ if (res != 0) { \
+ MOD_RESULT = res; \
+ break; \
+ } \
+ } \
+ catch (ModuleException& modexcept) \
+ { \
+ log(DEBUG,"Module exception cought: %s",modexcept.GetReason()); \
} \
} \
} \
class ModuleMessage : public classbase
{
public:
- /** This class is pure virtual and must be inherited.
- */
- virtual char* Send() = 0;
+ /** This class is pure virtual and must be inherited.
+ */
+ virtual char* Send() = 0;
virtual ~ModuleMessage() {};
};
class Request : public ModuleMessage
{
protected:
- /** This member holds a pointer to arbitary data set by the emitter of the message
- */
- char* data;
- /** This is a pointer to the sender of the message, which can be used to
- * directly trigger events, or to create a reply.
- */
- Module* source;
- /** The single destination of the Request
- */
- Module* dest;
+ /** This member holds a pointer to arbitary data set by the emitter of the message
+ */
+ char* data;
+ /** This is a pointer to the sender of the message, which can be used to
+ * directly trigger events, or to create a reply.
+ */
+ Module* source;
+ /** The single destination of the Request
+ */
+ Module* dest;
public:
- /** Create a new Request
- */
- Request(char* anydata, Module* src, Module* dst);
- /** Fetch the Request data
- */
- char* GetData();
- /** Fetch the request source
- */
- Module* GetSource();
- /** Fetch the request destination (should be 'this' in the receiving module)
- */
- Module* GetDest();
- /** Send the Request.
- * Upon returning the result will be arbitary data returned by the module you
- * sent the request to. It is up to your module to know what this data is and
- * how to deal with it.
- */
- char* Send();
+ /** Create a new Request
+ */
+ Request(char* anydata, Module* src, Module* dst);
+ /** Fetch the Request data
+ */
+ char* GetData();
+ /** Fetch the request source
+ */
+ Module* GetSource();
+ /** Fetch the request destination (should be 'this' in the receiving module)
+ */
+ Module* GetDest();
+ /** Send the Request.
+ * Upon returning the result will be arbitary data returned by the module you
+ * sent the request to. It is up to your module to know what this data is and
+ * how to deal with it.
+ */
+ char* Send();
};
class Event : public ModuleMessage
{
protected:
- /** This member holds a pointer to arbitary data set by the emitter of the message
- */
- char* data;
- /** This is a pointer to the sender of the message, which can be used to
- * directly trigger events, or to create a reply.
- */
- Module* source;
- /** The event identifier.
- * This is arbitary text which should be used to distinguish
- * one type of event from another.
- */
- std::string id;
+ /** This member holds a pointer to arbitary data set by the emitter of the message
+ */
+ char* data;
+ /** This is a pointer to the sender of the message, which can be used to
+ * directly trigger events, or to create a reply.
+ */
+ Module* source;
+ /** The event identifier.
+ * This is arbitary text which should be used to distinguish
+ * one type of event from another.
+ */
+ std::string id;
public:
- /** Create a new Event
- */
- Event(char* anydata, Module* src, std::string eventid);
- /** Get the Event data
- */
- char* GetData();
- /** Get the event Source
- */
- Module* GetSource();
- /** Get the event ID.
- * Use this to determine the event type for safe casting of the data
- */
- std::string GetEventID();
- /** Send the Event.
- * The return result of an Event::Send() will always be NULL as
- * no replies are expected.
- */
- char* Send();
+ /** Create a new Event
+ */
+ Event(char* anydata, Module* src, const std::string &eventid);
+ /** Get the Event data
+ */
+ char* GetData();
+ /** Get the event Source
+ */
+ Module* GetSource();
+ /** Get the event ID.
+ * Use this to determine the event type for safe casting of the data
+ */
+ std::string GetEventID();
+ /** Send the Event.
+ * The return result of an Event::Send() will always be NULL as
+ * no replies are expected.
+ */
+ char* Send();
};
/** Holds an extended mode's details.
class ExtMode : public classbase
{
public:
- char modechar;
- int type;
- bool needsoper;
- int params_when_on;
- int params_when_off;
- bool list;
- ExtMode(char mc, int ty, bool oper, int p_on, int p_off) : modechar(mc), type(ty), needsoper(oper), params_when_on(p_on), params_when_off(p_off), list(false) { };
+ char modechar;
+ int type;
+ bool needsoper;
+ int params_when_on;
+ int params_when_off;
+ bool list;
+ ExtMode(char mc, int ty, bool oper, int p_on, int p_off) : modechar(mc), type(ty), needsoper(oper), params_when_on(p_on), params_when_off(p_off), list(false) { };
+};
+
+
+/** 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
+{
+ 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();
+ }
};
/** Priority types which can be returned from Module::Prioritize()
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_OnOperCompare, I_OnChannelDelete, I_OnPostOper, I_OnSyncOtherMetaData, I_OnSetAway, I_OnCancelAway };
/** Base class for all InspIRCd modules
* This class is the base class for InspIRCd modules. All modules must inherit from this class,
/** Default constructor
* Creates a module class.
* @param Me An instance of the Server class which can be saved for future use
+ * \exception ModuleException Throwing this class, or any class derived from ModuleException, causes loading of the module to abort.
*/
Module(Server* Me);
*/
virtual int OnUserPreJoin(userrec* user, chanrec* chan, const char* cname);
- /** Called whenever a user is about to be kicked.
+ /** 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,
* notices etc.
* @param user The user being kicked
* @param chan The channel the user is being kicked from
* @param reason The kick reason
- * @return 1 to prevent the kick, 0 to allow it
+ * @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, std::string reason);
* @param dest The target of the message (chanrec* or userrec*)
* @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
*/
- virtual int OnUserPreMessage(userrec* user,void* dest,int target_type, std::string &text);
+ virtual int OnUserPreMessage(userrec* user,void* dest,int target_type, std::string &text,char status);
/** 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
* @param dest The target of the message (chanrec* or userrec*)
* @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
*/
- virtual int OnUserPreNotice(userrec* user,void* dest,int target_type, std::string &text);
+ virtual int OnUserPreNotice(userrec* user,void* dest,int target_type, std::string &text,char status);
/** 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
* @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. PRIVMSG @#chan has status== '@', 0 to send to everyone.
*/
- virtual void OnUserMessage(userrec* user, void* dest, int target_type, std::string text);
+ virtual void OnUserMessage(userrec* user, void* dest, int target_type, std::string text, char status);
- /** Called after any NOTICE sent from a user.
+ /** Called after any NOTICE sent from a user.
* The dest variable contains a userrec* if target_type is TYPE_USER and a chanrec*
* if target_type is TYPE_CHANNEL.
* @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 OnUserNotice(userrec* user, void* dest, int target_type, std::string text);
+ virtual void OnUserNotice(userrec* user, void* dest, int target_type, std::string text, char status);
/** Called after every MODE command sent from a user
* The dest variable contains a userrec* if target_type is TYPE_USER and a chanrec*
*/
virtual int OnCheckInvite(userrec* user, chanrec* chan);
- /** Called whenever a user joins a channel, to determine if key checks should go ahead or not.
+ /** Called whenever a user joins a channel, to determine if key checks should go ahead or not.
* This method will always be called for each join, wether or not the channel is actually +k, and
* determines the outcome of an if statement around the whole section of key checking code.
* if the user specified no key, the keygiven string will be a valid but empty value.
*/
virtual int OnCheckKey(userrec* user, chanrec* chan, std::string keygiven);
- /** Called whenever a user joins a channel, to determine if channel limit checks should go ahead or not.
+ /** 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
* determines the outcome of an if statement around the whole section of channel limit checking code.
* return 1 to explicitly allow the join to go ahead or 0 to ignore the event.
*/
virtual int OnCheckLimit(userrec* user, chanrec* chan);
- /** Called whenever a user joins a channel, to determine if banlist checks should go ahead or not.
+ /** 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
* determines the outcome of an if statement around the whole section of ban checking code.
* return 1 to explicitly allow the join to go ahead or 0 to ignore the event.
* @return nonzero if the event was handled, in which case readresult must be valid on exit
*/
virtual int OnRawSocketRead(int fd, char* buffer, unsigned int count, int &readresult);
+
+ virtual void OnSetAway(userrec* user);
+
+ virtual void OnCancelAway(userrec* user);
};
*/
virtual int CountUsers(chanrec* c);
+ /** Adds an InspTimer which will trigger at a future time
+ */
+ virtual void AddTimer(InspTimer* T);
+
/** Attempts to look up a nick and return a pointer to it.
* This function will return NULL if the nick does not exist.
*/
*/
virtual std::string ChanMode(userrec* User, chanrec* Chan);
- /** Checks if a user is on a channel.
- * This function will return true or false to indicate if user 'User' is on channel 'Chan'.
- */
- virtual bool IsOnChannel(userrec* User, chanrec* Chan);
-
/** Returns the server name of the server where the module is loaded.
*/
virtual std::string GetServerName();
* 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 void CallCommandHandler(std::string commandname, char** parameters, int pcnt, userrec* user);
+ virtual bool CallCommandHandler(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
*/
virtual void AddGLine(long duration, std::string source, std::string reason, std::string hostmask);
- /** 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.
- */
+ /** 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.
+ */
virtual void AddQLine(long duration, std::string source, std::string reason, std::string nickname);
- /** 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.
- */
+ /** 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.
+ */
virtual void AddZLine(long duration, std::string source, std::string reason, std::string ipaddr);
- /** 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.
- */
+ /** 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.
+ */
virtual void AddKLine(long duration, std::string source, std::string reason, std::string hostmask);
- /** 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.
- */
+ /** 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.
+ */
virtual void AddELine(long duration, std::string source, std::string reason, std::string hostmask);
/** Deletes a G-Line from all servers
virtual void DelSocket(InspSocket* sock);
virtual void RehashServer();
+
+ virtual long GetChannelCount();
+
+ virtual chanrec* GetChannelIndex(long index);
+
+ void DumpText(userrec* User, std::string LinePrefix, stringstream &TextStream);
};
/** Overloaded constructor.
* This constructor initialises the ConfigReader class to read a user-specified config file
*/
- ConfigReader(std::string filename); // read a module-specific config
+ ConfigReader(const std::string &filename); // read a module-specific config
/** Default destructor.
* This method destroys the ConfigReader class.
*/
* 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.
*/
- std::string ReadValue(std::string tag, std::string name, int index);
+ 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(std::string tag, std::string name, int index);
+ 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
* 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(std::string tag, std::string name, int index, bool needs_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.
* used with the index value of ConfigReader::ReadValue to loop through all copies of a
* multiple instance tag.
*/
- int Enumerate(std::string 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.
* function would return 2. Spaces and newlines both qualify as valid seperators
* between values.
*/
- int EnumerateValues(std::string tag, int index);
+ int EnumerateValues(const std::string &tag, int index);
};
*/
class FileReader : public classbase
{
- file_cache fc;
+ file_cache fc;
public:
/** Default constructor.
* This method does not load any file into memory, you must use the LoadFile method
* and other methods to be called. If the file could not be loaded, FileReader::FileSize
* returns 0.
*/
- FileReader(std::string filename);
+ FileReader(const std::string &filename);
/** Default destructor.
* This deletes the memory allocated to the file.
* and other methods to be called. If the file could not be loaded, FileReader::FileSize
* returns 0.
*/
- void LoadFile(std::string filename);
+ void LoadFile(const std::string &filename);
/** Returns true if the file exists
* This function will return false if the file could not be opened.