#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()); \
} \
} \
} \
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 char *GetReason()
+ {
+ return (char*)err.c_str();
+ }
+};
+
/** Priority types which can be returned from Module::Prioritize()
*/
enum Priority { PRIORITY_FIRST, PRIORITY_DONTCARE, PRIORITY_LAST, PRIORITY_BEFORE, PRIORITY_AFTER };
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);
* @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
* @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 void DelSocket(InspSocket* sock);
virtual void RehashServer();
+
+ virtual long GetChannelCount();
+
+ virtual chanrec* GetChannelIndex(long index);
};