]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Added Module::OnAccessCheck
authorbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>
Sat, 1 May 2004 12:44:07 +0000 (12:44 +0000)
committerbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>
Sat, 1 May 2004 12:44:07 +0000 (12:44 +0000)
Added ListMode support
Fixed Extensible class bug

git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@759 e03df62e-2008-0410-955e-edbf42e46eb7

include/base.h
include/inspircd.h
include/modules.h
src/InspIRCd.dev
src/InspIRCd.layout
src/base.cpp
src/inspircd.cpp
src/mode.cpp
src/modules.cpp
src/users.cpp

index e755fc95159959faaccce0d8a178123117a0749f..9b9795229c65a0182d59807e848de6809c6a5151 100644 (file)
@@ -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
index d8967afb785d86ecf67d4528d6474b76d599a4ec..09e286cdc1d48e29507b57593082f46bdb6d0377 100644 (file)
@@ -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);
index e6b4739d8c7a34c63414e0ec5b19434a63d5383d..866bed269a7f4a9422213e0be0e5598e4a5783a6 100644 (file)
@@ -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 &params);
+       virtual int OnExtendedMode(userrec* user, void* target, char modechar, int type, bool mode_on, string_list &params);
        
        /** 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:
index f553ce649a9cc526e44fd45daaba102debd10110..2012957fc1ad114c14ec7bbbd16bf4b54dc74470 100644 (file)
@@ -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=
+
index 06ccc0a2866d1e927eb5256db0dcca3ad5597654..1e1e0138c8f055357963358f73ba0cb4371594a9 100644 (file)
@@ -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
index 7e545694bc9f5aa988ef94060f051dc52e905fef..f1f66bd93d383bee51e801cd26c82a8d85c15ffa 100644 (file)
@@ -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;
 }
 
index f313c64c74e2c7671b3a5748604f8cd9a1660953..310ef4043dcd73be4e1c1e077a7ae609260fbc3c 100644 (file)
@@ -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++)
index c5f179f24b49e8e9ccb9ecf10959160ac45e5841..4a7c56bd3733a7a889b641f93dc35bc2f317ae54 100644 (file)
@@ -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;
index d2f01297781c3ef270e9262ece46abd3e7dff679..d4d647d7efb3ff8fb2931652d232a4dea24548c9 100644 (file)
@@ -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 &params) { return false; }
+int Module::OnExtendedMode(userrec* user, void* target, char modechar, int type, bool mode_on, string_list &params) { 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);
index b523033ba926f20631b41d1d1d2c6b97a6982f09..cdb93a40f2bb8445586b8b335ea10e3e4ca17cab 100644 (file)
@@ -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;
                                }
                        }
                }