diff options
-rw-r--r-- | include/base.h | 6 | ||||
-rw-r--r-- | include/inspircd.h | 2 | ||||
-rw-r--r-- | include/modules.h | 74 | ||||
-rw-r--r-- | src/InspIRCd.dev | 12 | ||||
-rw-r--r-- | src/InspIRCd.layout | 101 | ||||
-rw-r--r-- | src/base.cpp | 13 | ||||
-rw-r--r-- | src/inspircd.cpp | 30 | ||||
-rw-r--r-- | src/mode.cpp | 379 | ||||
-rw-r--r-- | src/modules.cpp | 44 | ||||
-rw-r--r-- | src/users.cpp | 4 |
10 files changed, 441 insertions, 224 deletions
diff --git a/include/base.h b/include/base.h index e755fc951..9b9795229 100644 --- a/include/base.h +++ b/include/base.h @@ -39,7 +39,7 @@ class Extensible : public classbase { /** Private data store */ - std::map<std::string,VoidPointer> Extension_Items; + std::map<std::string,char*> Extension_Items; public: @@ -49,7 +49,7 @@ public: * twice, Extensible::Extend will return false in this case. * On successful extension, Extend returns true. */ - bool Extend(std::string key, VoidPointer p); + bool Extend(std::string key, char* p); /** Shrink an Extensible class. * You must provide a key name. The given key name will be removed from the classes data. If @@ -62,7 +62,7 @@ public: * You must provide a key name, which is case sensitive. If you provide a non-existent key name, * the function returns NULL, otherwise a pointer to the item referenced by the key is returned. */ - VoidPointer GetExt(std::string key); + char* GetExt(std::string key); }; #endif diff --git a/include/inspircd.h b/include/inspircd.h index d8967afb7..09e286cdc 100644 --- a/include/inspircd.h +++ b/include/inspircd.h @@ -110,6 +110,8 @@ bool ModeDefined(char c, int i); bool ModeDefinedOper(char c, int i); int ModeDefinedOn(char c, int i); int ModeDefinedOff(char c, int i); +void ModeMakeList(char modechar); +bool ModeIsListMode(char modechar, int type); chanrec* add_channel(userrec *user, const char* cn, const char* key, bool override); chanrec* del_channel(userrec *user, const char* cname, const char* reason, bool local); void force_nickchange(userrec* user,const char* newnick); diff --git a/include/modules.h b/include/modules.h index e6b4739d8..866bed269 100644 --- a/include/modules.h +++ b/include/modules.h @@ -8,16 +8,36 @@ #ifndef __PLUGIN_H #define __PLUGIN_H +// log levels + #define DEBUG 10 #define VERBOSE 20 #define DEFAULT 30 #define SPARSE 40 #define NONE 50 +// used with OnExtendedMode() method of modules + #define MT_CHANNEL 1 #define MT_CLIENT 2 #define MT_SERVER 3 +// used with OnAccessCheck() method of modules + +#define ACR_DEFAULT 0 // Do default action (act as if the module isnt even loaded) +#define ACR_DENY 1 // deny the action +#define ACR_ALLOW 2 // allow the action + +#define AC_KICK 0 // a user is being kicked +#define AC_DEOP 1 // a user is being deopped +#define AC_OP 2 // a user is being opped +#define AC_VOICE 3 // a user is being voiced +#define AC_DEVOICE 4 // a user is being devoiced +#define AC_HALFOP 5 // a user is being halfopped +#define AC_DEHALFOP 6 // a user is being dehalfopped +#define AC_INVITE 7 // a user is being invited +#define AC_GENERAL_MODE 8 // a user channel mode is being changed + #include "dynamic.h" #include "base.h" #include "ctables.h" @@ -174,7 +194,7 @@ class Module : public classbase * If the mode is a channel mode, target is a chanrec*, and if it is a user mode, target is a userrec*. * You must cast this value yourself to make use of it. */ - virtual bool OnExtendedMode(userrec* user, void* target, char modechar, int type, bool mode_on, string_list ¶ms); + virtual int OnExtendedMode(userrec* user, void* target, char modechar, int type, bool mode_on, string_list ¶ms); /** Called whenever a user is about to join a channel, before any processing is done. * Returning any nonzero value from this function stops the process immediately, causing no @@ -241,6 +261,29 @@ class Module : public classbase * module to generate some meaninful output. */ virtual int OnUserPreNick(userrec* user, std::string newnick); + + /** 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> + * 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 (7) - a user is being invited<br> + * AC_GENERAL_MODE (8) - a user channel mode is being changed<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 + * denied 'upstream' causing other checks such as AC_DEOP to not be reached. Be very careful with use of the + * AC_GENERAL_MODE type, as it may inadvertently override the behaviour of other modules. When the access_type + * is AC_GENERAL_MODE, the destination of the mode will be NULL (as it has not yet been determined). + */ + virtual int OnAccessCheck(userrec* source,userrec* dest,chanrec* channel,int access_type); }; @@ -347,6 +390,10 @@ class Server : public classbase * representing the user's privilages upon the channel you specify. */ 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(); @@ -359,7 +406,7 @@ class Server : public classbase * server where the module is loaded. */ virtual Admin GetAdmin(); - /** Adds an extended mode letter which is parsed by a module + /** Adds an extended mode letter which is parsed by a module. * This allows modules to add extra mode letters, e.g. +x for hostcloak. * the "type" parameter is either MT_CHANNEL, MT_CLIENT, or MT_SERVER, to * indicate wether the mode is a channel mode, a client mode, or a server mode. @@ -379,6 +426,29 @@ class Server : public classbase */ virtual bool AddExtendedMode(char modechar, int type, bool requires_oper, int params_when_on, int params_when_off); + /** Adds an extended mode letter which is parsed by a module and handled in a list fashion. + * This call is used to implement modes like +q and +a. The characteristics of these modes are + * as follows: + * + * (1) They are ALWAYS on channels, not on users, therefore their type is MT_CHANNEL + * + * (2) They always take exactly one parameter when being added or removed + * + * (3) They can be set multiple times, usually on users in channels + * + * (4) The mode and its parameter are NOT stored in the channels modes structure + * + * It is down to the module handling the mode to maintain state and determine what 'items' (e.g. users, + * or a banlist) have the mode set on them, and process the modes at the correct times, e.g. during access + * checks on channels, etc. When the extended mode is triggered the OnExtendedMode method will be triggered + * as above. Note that the target you are given will be a channel, if for example your mode is set 'on a user' + * (in for example +a) you must use Server::Find to locate the user the mode is operating on. + * Your mode handler may return 1 to handle the mode AND tell the core to display the mode change, e.g. + * '+aaa one two three' in the case of the mode for 'two', or it may return -1 to 'eat' the mode change, + * so the above example would become '+aa one three' after processing. + */ + virtual bool AddExtendedListMode(char modechar); + /** 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: diff --git a/src/InspIRCd.dev b/src/InspIRCd.dev index f553ce649..2012957fc 100644 --- a/src/InspIRCd.dev +++ b/src/InspIRCd.dev @@ -1,7 +1,7 @@ [Project] FileName=InspIRCd.dev Name=InspIRCd - The Inspire Internet Relay Chat Daemon -UnitCount=50 +UnitCount=51 Type=1 Ver=1 ObjFiles= @@ -545,3 +545,13 @@ Priority=1000 OverrideBuildCmd=0 BuildCmd= +[Unit51] +FileName=modules\m_chanprotect.cpp +CompileCpp=1 +Folder=Modules +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/src/InspIRCd.layout b/src/InspIRCd.layout index 06ccc0a28..1e1e0138c 100644 --- a/src/InspIRCd.layout +++ b/src/InspIRCd.layout @@ -1,5 +1,5 @@ [Editors] -Focused=6 +Focused=-1 Order=2,4,6,3,7,25,5,24,39,42,43,-1,1,46,0,49 [Editor_0] @@ -13,9 +13,9 @@ LeftChar=1 [Editor_1] Open=1 Top=0 -CursorCol=2 -CursorRow=211 -TopLine=180 +CursorCol=23 +CursorRow=1610 +TopLine=1575 LeftChar=1 [Editor_2] @@ -37,9 +37,9 @@ LeftChar=1 [Editor_4] Open=1 Top=0 -CursorCol=71 -CursorRow=120 -TopLine=92 +CursorCol=1 +CursorRow=330 +TopLine=298 LeftChar=1 [Editor_5] @@ -52,9 +52,9 @@ LeftChar=1 [Editor_6] Open=1 -Top=1 -CursorCol=24 -CursorRow=140 +Top=0 +CursorCol=1 +CursorRow=117 TopLine=94 LeftChar=1 @@ -77,17 +77,17 @@ LeftChar=1 [Editor_9] Open=1 Top=0 -CursorCol=1 -CursorRow=113 +CursorCol=3 +CursorRow=66 TopLine=26 LeftChar=1 [Editor_10] Open=1 Top=0 -CursorCol=1 -CursorRow=102 -TopLine=76 +CursorCol=13 +CursorRow=62 +TopLine=49 LeftChar=1 [Editor_11] @@ -103,7 +103,7 @@ Open=1 Top=0 CursorCol=32 CursorRow=191 -TopLine=154 +TopLine=1 LeftChar=1 [Editor_13] @@ -141,9 +141,9 @@ LeftChar=1 [Editor_17] Open=1 Top=0 -CursorCol=1 -CursorRow=2 -TopLine=1 +CursorCol=46 +CursorRow=114 +TopLine=106 LeftChar=1 [Editor_18] @@ -164,10 +164,10 @@ LeftChar=1 [Editor_20] Open=1 -Top=0 -CursorCol=107 -CursorRow=164 -TopLine=140 +Top=1 +CursorCol=1 +CursorRow=40 +TopLine=1 LeftChar=1 [Editor_21] @@ -189,9 +189,9 @@ LeftChar=1 [Editor_23] Open=1 Top=0 -CursorCol=1 -CursorRow=69 -TopLine=14 +CursorCol=28 +CursorRow=42 +TopLine=2 LeftChar=1 [Editor_24] @@ -206,21 +206,21 @@ Open=1 Top=0 CursorCol=1 CursorRow=23 -TopLine=1 +TopLine=46 LeftChar=1 [Editor_26] Open=1 Top=0 -CursorCol=1 -CursorRow=13 -TopLine=23 +CursorCol=13 +CursorRow=49 +TopLine=32 LeftChar=1 [Editor_27] Open=1 Top=0 -CursorCol=3 -CursorRow=67 -TopLine=34 +CursorCol=13 +CursorRow=50 +TopLine=6 LeftChar=1 [Editor_28] Open=1 @@ -251,7 +251,7 @@ CursorRow=40 TopLine=8 LeftChar=1 [Editor_32] -Open=0 +Open=1 Top=0 CursorCol=1 CursorRow=1 @@ -262,7 +262,7 @@ Open=1 Top=0 CursorCol=23 CursorRow=36 -TopLine=1 +TopLine=10 LeftChar=1 [Editor_34] Open=1 @@ -288,9 +288,9 @@ LeftChar=1 [Editor_37] Open=1 Top=0 -CursorCol=5 -CursorRow=90 -TopLine=63 +CursorCol=13 +CursorRow=160 +TopLine=1 LeftChar=1 [Editor_38] Open=1 @@ -323,16 +323,16 @@ LeftChar=1 [Editor_42] Open=1 Top=0 -CursorCol=10 -CursorRow=538 -TopLine=510 +CursorCol=128 +CursorRow=1210 +TopLine=1187 LeftChar=1 [Editor_43] Open=1 Top=0 CursorCol=1 -CursorRow=86 -TopLine=49 +CursorRow=217 +TopLine=203 LeftChar=1 [Editor_44] Open=1 @@ -358,8 +358,8 @@ LeftChar=1 [Editor_47] Open=1 Top=0 -CursorCol=1 -CursorRow=52 +CursorCol=32 +CursorRow=46 TopLine=4 LeftChar=1 [Editor_48] @@ -372,7 +372,14 @@ LeftChar=1 [Editor_49] Open=1 Top=0 -CursorCol=1 -CursorRow=32 +CursorCol=31 +CursorRow=14 TopLine=1 LeftChar=1 +[Editor_50] +Open=1 +Top=0 +CursorCol=1 +CursorRow=9 +TopLine=37 +LeftChar=1 diff --git a/src/base.cpp b/src/base.cpp index 7e545694b..f1f66bd93 100644 --- a/src/base.cpp +++ b/src/base.cpp @@ -3,13 +3,16 @@ #include <time.h> #include <map> #include <string> +#include "inspircd.h" +#include "modules.h" -bool Extensible::Extend(std::string key, VoidPointer p) +bool Extensible::Extend(std::string key, char* p) { // only add an item if it doesnt already exist if (this->Extension_Items.find(key) == this->Extension_Items.end()) { - this->Extension_Items[key] == p; + this->Extension_Items[key] = p; + log(DEBUG,"Extending object with item %s",key.c_str()); return true; } // item already exists, return false @@ -22,17 +25,21 @@ bool Extensible::Shrink(std::string key) if (this->Extension_Items.find(key) != this->Extension_Items.end()) { this->Extension_Items.erase(this->Extension_Items.find(key)); + log(DEBUG,"Shrinking object with item %s",key.c_str()); return true; } return false; } -VoidPointer Extensible::GetExt(std::string key) +char* Extensible::GetExt(std::string key) { + log(DEBUG,"Checking extension items for %s",key.c_str()); if (this->Extension_Items.find(key) != this->Extension_Items.end()) { + log(DEBUG,"Found item %s %s",key.c_str(),(this->Extension_Items.find(key))->second); return (this->Extension_Items.find(key))->second; } + log(DEBUG,"Cant find item %s",key.c_str()); return NULL; } diff --git a/src/inspircd.cpp b/src/inspircd.cpp index f313c64c7..310ef4043 100644 --- a/src/inspircd.cpp +++ b/src/inspircd.cpp @@ -1310,6 +1310,7 @@ chanrec* add_channel(userrec *user, const char* cn, const char* key, bool overri if (!FindChan(cname)) { + int MOD_RESULT = 0; FOREACH_RESULT(OnUserPreJoin(user,NULL,cname)); if (MOD_RESULT) { return NULL; @@ -1347,6 +1348,7 @@ chanrec* add_channel(userrec *user, const char* cn, const char* key, bool overri // and bans (used by servers) if (!override) { + int MOD_RESULT = 0; FOREACH_RESULT(OnUserPreJoin(user,Ptr,cname)); if (MOD_RESULT) { return NULL; @@ -1600,18 +1602,28 @@ void kick_channel(userrec *src,userrec *user, chanrec *Ptr, char* reason) WriteServ(src->fd,"441 %s %s %s :They are not on that channel",src->nick, user->nick, Ptr->name); return; } - if (((cstatus(src,Ptr) < STATUS_HOP) || (cstatus(src,Ptr) < cstatus(user,Ptr))) && (!is_uline(src->server))) + + int MOD_RESULT = 0; + FOREACH_RESULT(OnAccessCheck(src,user,Ptr,AC_KICK)); + + if (MOD_RESULT == ACR_DENY) + return; + + if (MOD_RESULT == ACR_DEFAULT) { - if (cstatus(src,Ptr) == STATUS_HOP) - { - WriteServ(src->fd,"482 %s %s :You must be a channel operator",src->nick, Ptr->name); - } - else + if (((cstatus(src,Ptr) < STATUS_HOP) || (cstatus(src,Ptr) < cstatus(user,Ptr))) && (!is_uline(src->server))) { - WriteServ(src->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",src->nick, Ptr->name); + if (cstatus(src,Ptr) == STATUS_HOP) + { + WriteServ(src->fd,"482 %s %s :You must be a channel operator",src->nick, Ptr->name); + } + else + { + WriteServ(src->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",src->nick, Ptr->name); + } + + return; } - - return; } for (int i =0; i != MAXCHANS; i++) diff --git a/src/mode.cpp b/src/mode.cpp index c5f179f24..4a7c56bd3 100644 --- a/src/mode.cpp +++ b/src/mode.cpp @@ -71,47 +71,56 @@ char* give_ops(userrec *user,char *dest,chanrec *chan,int status) log(DEFAULT,"*** BUG *** give_ops was given an invalid parameter"); return NULL; } - if ((status < STATUS_OP) && (!is_uline(user->server))) + + if (!isnick(dest)) + { + log(DEFAULT,"the target nickname given to give_ops was invalid"); + WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest); + return NULL; + } + d = Find(dest); + if (!d) { - log(DEBUG,"%s cant give ops to %s because they nave status %d and needs %d",user->nick,dest,status,STATUS_OP); - WriteServ(user->fd,"482 %s %s :You're not a channel operator",user->nick, chan->name); + log(DEFAULT,"the target nickname given to give_ops couldnt be found"); + WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest); return NULL; } else { - if (!isnick(dest)) - { - log(DEFAULT,"the target nickname given to give_ops was invalid"); - WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest); + + int MOD_RESULT = 0; + FOREACH_RESULT(OnAccessCheck(user,d,chan,AC_OP)); + + if (MOD_RESULT == ACR_DENY) return NULL; - } - d = Find(dest); - if (!d) + if (MOD_RESULT == ACR_DEFAULT) { - log(DEFAULT,"the target nickname given to give_ops couldnt be found"); - WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest); - return NULL; + if ((status < STATUS_OP) && (!is_uline(user->server))) + { + log(DEBUG,"%s cant give ops to %s because they nave status %d and needs %d",user->nick,dest,status,STATUS_OP); + WriteServ(user->fd,"482 %s %s :You're not a channel operator",user->nick, chan->name); + return NULL; + } } - else + + + for (int i = 0; i != MAXCHANS; i++) { - for (int i = 0; i != MAXCHANS; i++) + if ((d->chans[i].channel != NULL) && (chan != NULL)) + if (!strcasecmp(d->chans[i].channel->name,chan->name)) { - if ((d->chans[i].channel != NULL) && (chan != NULL)) - if (!strcasecmp(d->chans[i].channel->name,chan->name)) + if (d->chans[i].uc_modes & UCMODE_OP) { - if (d->chans[i].uc_modes & UCMODE_OP) - { - /* mode already set on user, dont allow multiple */ - log(DEFAULT,"The target user given to give_ops was already opped on the channel"); - return NULL; - } - d->chans[i].uc_modes = d->chans[i].uc_modes | UCMODE_OP; - log(DEBUG,"gave ops: %s %s",d->chans[i].channel->name,d->nick); - return d->nick; + /* mode already set on user, dont allow multiple */ + log(DEFAULT,"The target user given to give_ops was already opped on the channel"); + return NULL; } + d->chans[i].uc_modes = d->chans[i].uc_modes | UCMODE_OP; + log(DEBUG,"gave ops: %s %s",d->chans[i].channel->name,d->nick); + return d->nick; } - log(DEFAULT,"The target channel given to give_ops was not in the users mode list"); } + log(DEFAULT,"The target channel given to give_ops was not in the users mode list"); } return NULL; } @@ -126,40 +135,47 @@ char* give_hops(userrec *user,char *dest,chanrec *chan,int status) log(DEFAULT,"*** BUG *** give_hops was given an invalid parameter"); return NULL; } - if ((status < STATUS_OP) && (!is_uline(user->server))) + + d = Find(dest); + if (!isnick(dest)) + { + WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest); + return NULL; + } + if (!d) { - WriteServ(user->fd,"482 %s %s :You're not a channel operator",user->nick, chan->name); + WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest); return NULL; } else { - d = Find(dest); - if (!isnick(dest)) - { - WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest); + int MOD_RESULT = 0; + FOREACH_RESULT(OnAccessCheck(user,d,chan,AC_HALFOP)); + + if (MOD_RESULT == ACR_DENY) return NULL; - } - if (!d) + if (MOD_RESULT == ACR_DEFAULT) { - WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest); - return NULL; + if ((status < STATUS_OP) && (!is_uline(user->server))) + { + WriteServ(user->fd,"482 %s %s :You're not a channel operator",user->nick, chan->name); + return NULL; + } } - else + + for (int i = 0; i != MAXCHANS; i++) { - for (int i = 0; i != MAXCHANS; i++) + if ((d->chans[i].channel != NULL) && (chan != NULL)) + if (!strcasecmp(d->chans[i].channel->name,chan->name)) { - if ((d->chans[i].channel != NULL) && (chan != NULL)) - if (!strcasecmp(d->chans[i].channel->name,chan->name)) + if (d->chans[i].uc_modes & UCMODE_HOP) { - if (d->chans[i].uc_modes & UCMODE_HOP) - { - /* mode already set on user, dont allow multiple */ - return NULL; - } - d->chans[i].uc_modes = d->chans[i].uc_modes | UCMODE_HOP; - log(DEBUG,"gave h-ops: %s %s",d->chans[i].channel->name,d->nick); - return d->nick; + /* mode already set on user, dont allow multiple */ + return NULL; } + d->chans[i].uc_modes = d->chans[i].uc_modes | UCMODE_HOP; + log(DEBUG,"gave h-ops: %s %s",d->chans[i].channel->name,d->nick); + return d->nick; } } } @@ -176,40 +192,47 @@ char* give_voice(userrec *user,char *dest,chanrec *chan,int status) log(DEFAULT,"*** BUG *** give_voice was given an invalid parameter"); return NULL; } - if ((status < STATUS_HOP) && (!is_uline(user->server))) + + d = Find(dest); + if (!isnick(dest)) + { + WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest); + return NULL; + } + if (!d) { - WriteServ(user->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",user->nick, chan->name); + WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest); return NULL; } else { - d = Find(dest); - if (!isnick(dest)) - { - WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest); + int MOD_RESULT = 0; + FOREACH_RESULT(OnAccessCheck(user,d,chan,AC_VOICE)); + + if (MOD_RESULT == ACR_DENY) return NULL; - } - if (!d) + if (MOD_RESULT == ACR_DEFAULT) { - WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest); - return NULL; + if ((status < STATUS_HOP) && (!is_uline(user->server))) + { + WriteServ(user->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",user->nick, chan->name); + return NULL; + } } - else + + for (int i = 0; i != MAXCHANS; i++) { - for (int i = 0; i != MAXCHANS; i++) + if ((d->chans[i].channel != NULL) && (chan != NULL)) + if (!strcasecmp(d->chans[i].channel->name,chan->name)) { - if ((d->chans[i].channel != NULL) && (chan != NULL)) - if (!strcasecmp(d->chans[i].channel->name,chan->name)) + if (d->chans[i].uc_modes & UCMODE_VOICE) { - if (d->chans[i].uc_modes & UCMODE_VOICE) - { - /* mode already set on user, dont allow multiple */ - return NULL; - } - d->chans[i].uc_modes = d->chans[i].uc_modes | UCMODE_VOICE; - log(DEBUG,"gave voice: %s %s",d->chans[i].channel->name,d->nick); - return d->nick; + /* mode already set on user, dont allow multiple */ + return NULL; } + d->chans[i].uc_modes = d->chans[i].uc_modes | UCMODE_VOICE; + log(DEBUG,"gave voice: %s %s",d->chans[i].channel->name,d->nick); + return d->nick; } } } @@ -226,46 +249,52 @@ char* take_ops(userrec *user,char *dest,chanrec *chan,int status) log(DEFAULT,"*** BUG *** take_ops was given an invalid parameter"); return NULL; } - if ((status < STATUS_OP) && (!is_uline(user->server))) + + d = Find(dest); + if (!isnick(dest)) + { + log(DEBUG,"take_ops was given an invalid target nickname of %s",dest); + WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest); + return NULL; + } + if (!d) { - log(DEBUG,"%s cant give ops to %s because they have status %d and needs %d",user->nick,dest,status,STATUS_OP); - WriteServ(user->fd,"482 %s %s :You're not a channel operator",user->nick, chan->name); + log(DEBUG,"take_ops couldnt resolve the target nickname: %s",dest); + WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest); return NULL; } else { - d = Find(dest); - if (!isnick(dest)) - { - log(DEBUG,"take_ops was given an invalid target nickname of %s",dest); - WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest); + int MOD_RESULT = 0; + FOREACH_RESULT(OnAccessCheck(user,d,chan,AC_DEOP)); + + if (MOD_RESULT == ACR_DENY) return NULL; - } - if (!d) + if (MOD_RESULT == ACR_DEFAULT) { - log(DEBUG,"take_ops couldnt resolve the target nickname: %s",dest); - WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest); - return NULL; + if ((status < STATUS_OP) && (!is_uline(user->server))) + { + WriteServ(user->fd,"482 %s %s :You are not a channel operator",user->nick, chan->name); + return NULL; + } } - else + + for (int i = 0; i != MAXCHANS; i++) { - for (int i = 0; i != MAXCHANS; i++) + if ((d->chans[i].channel != NULL) && (chan != NULL)) + if (!strcasecmp(d->chans[i].channel->name,chan->name)) { - if ((d->chans[i].channel != NULL) && (chan != NULL)) - if (!strcasecmp(d->chans[i].channel->name,chan->name)) + if ((d->chans[i].uc_modes & UCMODE_OP) == 0) { - if ((d->chans[i].uc_modes & UCMODE_OP) == 0) - { - /* mode already set on user, dont allow multiple */ - return NULL; - } - d->chans[i].uc_modes ^= UCMODE_OP; - log(DEBUG,"took ops: %s %s",d->chans[i].channel->name,d->nick); - return d->nick; + /* mode already set on user, dont allow multiple */ + return NULL; } + d->chans[i].uc_modes ^= UCMODE_OP; + log(DEBUG,"took ops: %s %s",d->chans[i].channel->name,d->nick); + return d->nick; } - log(DEBUG,"take_ops couldnt locate the target channel in the target users list"); } + log(DEBUG,"take_ops couldnt locate the target channel in the target users list"); } return NULL; } @@ -280,40 +309,47 @@ char* take_hops(userrec *user,char *dest,chanrec *chan,int status) log(DEFAULT,"*** BUG *** take_hops was given an invalid parameter"); return NULL; } - if ((status < STATUS_OP) && (!is_uline(user->server))) + + d = Find(dest); + if (!isnick(dest)) + { + WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest); + return NULL; + } + if (!d) { - WriteServ(user->fd,"482 %s %s :You're not a channel operator",user->nick, chan->name); + WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest); return NULL; } else { - d = Find(dest); - if (!isnick(dest)) - { - WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest); + int MOD_RESULT = 0; + FOREACH_RESULT(OnAccessCheck(user,d,chan,AC_DEHALFOP)); + + if (MOD_RESULT == ACR_DENY) return NULL; - } - if (!d) + if (MOD_RESULT == ACR_DEFAULT) { - WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest); - return NULL; + if ((status < STATUS_OP) && (!is_uline(user->server))) + { + WriteServ(user->fd,"482 %s %s :You are not a channel operator",user->nick, chan->name); + return NULL; + } } - else + + for (int i = 0; i != MAXCHANS; i++) { - for (int i = 0; i != MAXCHANS; i++) + if ((d->chans[i].channel != NULL) && (chan != NULL)) + if (!strcasecmp(d->chans[i].channel->name,chan->name)) { - if ((d->chans[i].channel != NULL) && (chan != NULL)) - if (!strcasecmp(d->chans[i].channel->name,chan->name)) + if ((d->chans[i].uc_modes & UCMODE_HOP) == 0) { - if ((d->chans[i].uc_modes & UCMODE_HOP) == 0) - { - /* mode already set on user, dont allow multiple */ - return NULL; - } - d->chans[i].uc_modes ^= UCMODE_HOP; - log(DEBUG,"took h-ops: %s %s",d->chans[i].channel->name,d->nick); - return d->nick; + /* mode already set on user, dont allow multiple */ + return NULL; } + d->chans[i].uc_modes ^= UCMODE_HOP; + log(DEBUG,"took h-ops: %s %s",d->chans[i].channel->name,d->nick); + return d->nick; } } } @@ -330,40 +366,47 @@ char* take_voice(userrec *user,char *dest,chanrec *chan,int status) log(DEFAULT,"*** BUG *** take_voice was given an invalid parameter"); return NULL; } - if ((status < STATUS_HOP) && (!is_uline(user->server))) + + d = Find(dest); + if (!isnick(dest)) + { + WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest); + return NULL; + } + if (!d) { - WriteServ(user->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",user->nick, chan->name); + WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest); return NULL; } else { - d = Find(dest); - if (!isnick(dest)) - { - WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest); + int MOD_RESULT = 0; + FOREACH_RESULT(OnAccessCheck(user,d,chan,AC_DEVOICE)); + + if (MOD_RESULT == ACR_DENY) return NULL; - } - if (!d) + if (MOD_RESULT == ACR_DEFAULT) { - WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest); - return NULL; + if ((status < STATUS_HOP) && (!is_uline(user->server))) + { + WriteServ(user->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",user->nick, chan->name); + return NULL; + } } - else + + for (int i = 0; i != MAXCHANS; i++) { - for (int i = 0; i != MAXCHANS; i++) + if ((d->chans[i].channel != NULL) && (chan != NULL)) + if (!strcasecmp(d->chans[i].channel->name,chan->name)) { - if ((d->chans[i].channel != NULL) && (chan != NULL)) - if (!strcasecmp(d->chans[i].channel->name,chan->name)) + if ((d->chans[i].uc_modes & UCMODE_VOICE) == 0) { - if ((d->chans[i].uc_modes & UCMODE_VOICE) == 0) - { - /* mode already set on user, dont allow multiple */ - return NULL; - } - d->chans[i].uc_modes ^= UCMODE_VOICE; - log(DEBUG,"took voice: %s %s",d->chans[i].channel->name,d->nick); - return d->nick; + /* mode already set on user, dont allow multiple */ + return NULL; } + d->chans[i].uc_modes ^= UCMODE_VOICE; + log(DEBUG,"took voice: %s %s",d->chans[i].channel->name,d->nick); + return d->nick; } } } @@ -463,6 +506,12 @@ void process_modes(char **parameters,userrec* user,chanrec *chan,int status, int return; } + int MOD_RESULT = 0; + FOREACH_RESULT(OnAccessCheck(user,NULL,chan,AC_GENERAL_MODE)); + + if (MOD_RESULT == ACR_DENY) + return; + log(DEBUG,"process_modes: start: parameters=%d",pcnt); strcpy(modelist,parameters[1]); /* mode list, e.g. +oo-o */ @@ -753,8 +802,11 @@ void process_modes(char **parameters,userrec* user,chanrec *chan,int status, int p.clear(); if (((!strchr(chan->custom_modes,modechar)) && (!mdir)) || ((strchr(chan->custom_modes,modechar)) && (mdir))) { - log(DEBUG,"Mode %c isnt set on %s but trying to remove!",modechar,chan->name); - break; + if (!ModeIsListMode(modechar,MT_CHANNEL)) + { + log(DEBUG,"Mode %c isnt set on %s but trying to remove!",modechar,chan->name); + break; + } } if (ModeDefined(modechar,MT_CHANNEL)) { @@ -785,27 +837,46 @@ void process_modes(char **parameters,userrec* user,chanrec *chan,int status, int { if (!handled) { - if (modules[i]->OnExtendedMode(user,chan,modechar,MT_CHANNEL,mdir,p)) + int t = modules[i]->OnExtendedMode(user,chan,modechar,MT_CHANNEL,mdir,p); + if (t != 0) { log(DEBUG,"OnExtendedMode returned nonzero for a module"); char app[] = {modechar, 0}; - if (ptr>0) + if (ModeIsListMode(modechar,MT_CHANNEL)) { - if ((modelist[ptr-1] == '+') || (modelist[ptr-1] == '-')) + if (t == -1) { - strcat(outlist, app); + pc++; } - else if (!strchr(outlist,modechar)) + else { - strcat(outlist, app); + if (ptr>0) + { + strcat(outlist, app); + } + strcpy(outpars[pc++],parameters[param++]); } } - chan->SetCustomMode(modechar,mdir); - // include parameters in output if mode has them - if ((ModeDefinedOn(modechar,MT_CHANNEL)>0) && (mdir)) + else { - chan->SetCustomModeParam(modelist[ptr],parameters[param],mdir); - strcpy(outpars[pc++],parameters[param++]); + if (ptr>0) + { + if ((modelist[ptr-1] == '+') || (modelist[ptr-1] == '-')) + { + strcat(outlist, app); + } + else if (!strchr(outlist,modechar)) + { + strcat(outlist, app); + } + } + chan->SetCustomMode(modechar,mdir); + // include parameters in output if mode has them + if ((ModeDefinedOn(modechar,MT_CHANNEL)>0) && (mdir)) + { + chan->SetCustomModeParam(modelist[ptr],parameters[param],mdir); + strcpy(outpars[pc++],parameters[param++]); + } } // break, because only one module can handle the mode. handled = true; diff --git a/src/modules.cpp b/src/modules.cpp index d2f012977..d4d647d7e 100644 --- a/src/modules.cpp +++ b/src/modules.cpp @@ -26,6 +26,7 @@ public: int params_when_on; int params_when_off; bool needsoper; + 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) { }; }; @@ -49,6 +50,20 @@ bool ModeDefined(char modechar, int type) return false; } +bool ModeIsListMode(char modechar, int type) +{ + log(DEBUG,"Size of extmodes vector is %d",EMode.size()); + for (ExtModeListIter i = EMode.begin(); i < EMode.end(); i++) + { + log(DEBUG,"i->modechar==%c, modechar=%c, i->type=%d, type=%d",i->modechar,modechar,i->type,type); + if ((i->modechar == modechar) && (i->type == type) && (i->list == true)) + { + return true; + } + } + return false; +} + bool ModeDefinedOper(char modechar, int type) { log(DEBUG,"Size of extmodes vector is %d",EMode.size()); @@ -99,6 +114,19 @@ bool DoAddExtendedMode(char modechar, int type, bool requires_oper, int params_o return true; } +// turns a mode into a listmode +void ModeMakeList(char modechar) +{ + for (ExtModeListIter i = EMode.begin(); i < EMode.end(); i++) + { + if ((i->modechar == modechar) && (i->type == MT_CHANNEL)) + { + i->list = true; + return; + } + } + return; +} // version is a simple class for holding a modules version number @@ -119,7 +147,7 @@ void Module::OnPacketReceive(char *p) { } void Module::OnRehash() { } void Module::OnServerRaw(std::string &raw, bool inbound, userrec* user) { } int Module::OnUserPreJoin(userrec* user, chanrec* chan, const char* cname) { return 0; } -bool Module::OnExtendedMode(userrec* user, void* target, char modechar, int type, bool mode_on, string_list ¶ms) { return false; } +int Module::OnExtendedMode(userrec* user, void* target, char modechar, int type, bool mode_on, string_list ¶ms) { return false; } Version Module::GetVersion() { return Version(1,0,0,0); } void Module::OnOper(userrec* user) { }; void Module::OnInfo(userrec* user) { }; @@ -127,6 +155,7 @@ void Module::OnWhois(userrec* source, userrec* dest) { }; int Module::OnUserPreMessage(userrec* user,void* dest,int target_type, std::string text) { return 0; }; int Module::OnUserPreNotice(userrec* user,void* dest,int target_type, std::string text) { return 0; }; int Module::OnUserPreNick(userrec* user, std::string newnick) { return 0; }; +int Module::OnAccessCheck(userrec* source,userrec* dest,chanrec* channel,int access_type) { return ACR_DEFAULT; }; // server is a wrapper class that provides methods to all of the C-style // exports in the core @@ -297,6 +326,11 @@ std::string Server::ChanMode(userrec* User, chanrec* Chan) return cmode(User,Chan); } +bool Server::IsOnChannel(userrec* User, chanrec* Chan) +{ + return has_channel(User,Chan); +} + std::string Server::GetServerName() { return getservername(); @@ -334,6 +368,14 @@ bool Server::AddExtendedMode(char modechar, int type, bool requires_oper, int pa return DoAddExtendedMode(modechar,type,requires_oper,params_when_on,params_when_off); } +bool Server::AddExtendedListMode(char modechar) +{ + bool res = DoAddExtendedMode(modechar,MT_CHANNEL,false,1,1); + if (res) + ModeMakeList(modechar); + return res; +} + int Server::CountUsers(chanrec* c) { return usercount(c); diff --git a/src/users.cpp b/src/users.cpp index b523033ba..cdb93a40f 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -114,7 +114,6 @@ bool userrec::HasPermission(char* command) log(DEBUG,"*** HasPermission: %s is an oper of type '%s'",this->nick,this->oper); ConfValue("type","classes",j,Classes,&config_f); char* myclass = strtok_r(Classes," ",&savept); - //myclass = savept; while (myclass) { log(DEBUG,"*** HasPermission: checking classtype '%s'",myclass); @@ -128,7 +127,6 @@ bool userrec::HasPermission(char* command) mycmd = strtok_r(CommandList," ",&savept2); - //mycmd = savept2; while (mycmd) { if (!strcasecmp(mycmd,command)) @@ -137,12 +135,10 @@ bool userrec::HasPermission(char* command) return true; } mycmd = strtok_r(NULL," ",&savept2); - //mycmd = savept2; } } } myclass = strtok_r(NULL," ",&savept); - //myclass = savept; } } } |