]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/mode.cpp
Take some debug crap out of ModeParser::ModeString()
[user/henk/code/inspircd.git] / src / mode.cpp
index c14343febc2ce5ffc0543b5d2e4e864685e60af3..ceb801c695a04f3f920310c00e52badc4e0962f6 100644 (file)
 
 using namespace std;
 
-#include "inspircd_config.h"
 #include "inspircd.h"
-#include "configreader.h"
-#include <unistd.h>
-#include "hash_map.h"
-#include "connection.h"
 #include "users.h"
 #include "modules.h"
 #include "inspstring.h"
-
-#include "commands.h"
 #include "mode.h"
 
 /* +s (secret) */
@@ -53,7 +46,6 @@ using namespace std;
 #include "modes/cmode_h.h"
 /* +v (channel voice) */
 #include "modes/cmode_v.h"
-
 /* +s (server notices) */
 #include "modes/umode_s.h"
 /* +w (see wallops) */
@@ -259,7 +251,8 @@ void ModeParser::DisplayCurrentModes(userrec *user, userrec* targetuser, chanrec
        {
                /* Display user's current mode string */
                user->WriteServ("221 %s :+%s",targetuser->nick,targetuser->FormatModes());
-               user->WriteServ("008 %s :+%s", targetuser->nick, targetuser->FormatNoticeMasks());
+               if (*targetuser->oper)
+                       user->WriteServ("008 %s +%s :Server notice mask", targetuser->nick, targetuser->FormatNoticeMasks());
                return;
        }
 
@@ -278,6 +271,8 @@ void ModeParser::Process(const char** parameters, int pcnt, userrec *user, bool
 
        ServerInstance->Log(DEBUG,"ModeParser::Process start");
 
+       LastParse = "";
+
        /* Special case for displaying the list for listmodes,
         * e.g. MODE #chan b, or MODE #chan +b without a parameter
         */
@@ -319,15 +314,23 @@ void ModeParser::Process(const char** parameters, int pcnt, userrec *user, bool
                                /* We don't have halfop */
                                ServerInstance->Log(DEBUG,"The user is not a halfop or above, checking other reasons for being able to set the modes");
 
-                               /* Are we a uline or is it a servermode? */
-                               if ((!ServerInstance->ULine(user->server)) && (!servermode))
-                               {
-                                       /* Not enough permission:
-                                        * NOT a uline and NOT a servermode,
-                                        * OR, NOT halfop or above.
-                                        */
-                                       user->WriteServ("482 %s %s :You're not a channel (half)operator",user->nick, targetchannel->name);
+                               int MOD_RESULT = 0;
+                               FOREACH_RESULT(I_OnAccessCheck,OnAccessCheck(user, NULL, targetchannel, AC_GENERAL_MODE));
+                               if (MOD_RESULT == ACR_DENY)
                                        return;
+
+                               if (MOD_RESULT == ACR_DEFAULT)
+                               {
+                                       /* Are we a uline or is it a servermode? */
+                                       if ((!ServerInstance->ULine(user->server)) && (!servermode))
+                                       {
+                                               /* Not enough permission:
+                                                * NOT a uline and NOT a servermode,
+                                                * OR, NOT halfop or above.
+                                                */
+                                               user->WriteServ("482 %s %s :You're not a channel (half)operator",user->nick, targetchannel->name);
+                                               return;
+                                       }
                                }
                        }
                }
@@ -350,6 +353,7 @@ void ModeParser::Process(const char** parameters, int pcnt, userrec *user, bool
                bool adding = true, state_change = false;
                unsigned char handler_id = 0;
                int parameter_counter = 2; /* Index of first parameter */
+               int parameter_count = 0;
 
                /* A mode sequence that doesnt start with + or -. Assume +. - Thanks for the suggestion spike (bug#132) */
                if ((*mode_sequence.begin() != '+') && (*mode_sequence.begin() != '-'))
@@ -417,7 +421,7 @@ void ModeParser::Process(const char** parameters, int pcnt, userrec *user, bool
                                                                        parameter = parameters[parameter_counter++];
 
                                                                        /* Yerk, invalid! */
-                                                                       if ((parameter.rfind(':') != std::string::npos) || (parameter.rfind(' ') != std::string::npos))
+                                                                       if ((parameter.find(':') == 0) || (parameter.rfind(' ') != std::string::npos))
                                                                                parameter = "";
                                                                }
                                                                else
@@ -463,6 +467,7 @@ void ModeParser::Process(const char** parameters, int pcnt, userrec *user, bool
                                                                if ((modehandlers[handler_id]->GetNumParams(adding)) && (parameter != ""))
                                                                {
                                                                        parameter_list << " " << parameter;
+                                                                       parameter_count++;
                                                                        /* Does this mode have a prefix? */
                                                                        if (modehandlers[handler_id]->GetPrefix() && targetchannel)
                                                                        {
@@ -479,6 +484,14 @@ void ModeParser::Process(const char** parameters, int pcnt, userrec *user, bool
 
                                                                /* Reset the state change flag */
                                                                state_change = false;
+
+                                                               if ((output_sequence.length() + parameter_list.str().length() > 450) || (output_sequence.length() > 100)
+                                                                               || (parameter_count > MAXMODES))
+                                                               {
+                                                                       /* We cant have a mode sequence this long */
+                                                                       letter = mode_sequence.end() - 1;
+                                                                       continue;
+                                                               }
                                                        }
                                                }
                                        }
@@ -498,10 +511,12 @@ void ModeParser::Process(const char** parameters, int pcnt, userrec *user, bool
                                if (type == MODETYPE_CHANNEL)
                                {
                                        targetchannel->WriteChannelWithServ(ServerInstance->Config->ServerName, "MODE %s %s%s", targetchannel->name, output_sequence.c_str(), parameter_list.str().c_str());
+                                       this->LastParse = targetchannel->name;
                                }
                                else
                                {
                                        targetuser->WriteServ("MODE %s %s%s",targetuser->nick,output_sequence.c_str(), parameter_list.str().c_str());
+                                       this->LastParse = targetuser->nick;
                                }
                        }
                        else
@@ -511,26 +526,26 @@ void ModeParser::Process(const char** parameters, int pcnt, userrec *user, bool
                                        ServerInstance->Log(DEBUG,"Write output sequence and parameters to channel: %s %s%s",targetchannel->name,output_sequence.c_str(),parameter_list.str().c_str());
                                        targetchannel->WriteChannel(user,"MODE %s %s%s",targetchannel->name,output_sequence.c_str(),parameter_list.str().c_str());
                                        FOREACH_MOD(I_OnMode,OnMode(user, targetchannel, TYPE_CHANNEL, output_sequence + parameter_list.str()));
+                                       this->LastParse = targetchannel->name;
                                }
                                else
                                {
                                        user->WriteTo(targetuser,"MODE %s %s%s",targetuser->nick,output_sequence.c_str(), parameter_list.str().c_str());
                                        FOREACH_MOD(I_OnMode,OnMode(user, targetuser, TYPE_USER, output_sequence));
+                                       this->LastParse = targetuser->nick;
                                }
                        }
+
+                       LastParse.append(" ");
+                       LastParse.append(output_sequence);
+                       LastParse.append(parameter_list.str());
                }
        }
 }
 
-
-void cmd_mode::Handle (const char** parameters, int pcnt, userrec *user)
+const std::string& ModeParser::GetLastParse()
 {
-       if (!user)
-               return;
-
-       ServerInstance->Modes->Process(parameters, pcnt, user, false);
-
-       return;
+       return LastParse;
 }
 
 void ModeParser::CleanMask(std::string &mask)
@@ -595,6 +610,41 @@ bool ModeParser::AddMode(ModeHandler* mh, unsigned const char modeletter)
        return true;
 }
 
+bool ModeParser::DelMode(ModeHandler* mh)
+{
+       unsigned char mask = 0;
+       unsigned char pos = 0;
+
+       if ((mh->GetModeChar() < 'A') || (mh->GetModeChar() > 'z'))
+               return false;
+
+       mh->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
+       pos = (mh->GetModeChar()-65) | mask;
+
+       if (!modehandlers[pos])
+               return false;
+
+       switch (mh->GetModeType())
+       {
+               case MODETYPE_USER:
+                       for (user_hash::iterator i = ServerInstance->clientlist.begin(); i != ServerInstance->clientlist.end(); i++)
+                       {
+                               mh->RemoveMode(i->second);
+                       }
+               break;
+               case MODETYPE_CHANNEL:
+                       for (chan_hash::iterator i = ServerInstance->chanlist.begin(); i != ServerInstance->chanlist.end(); i++)
+                       {
+                               mh->RemoveMode(i->second);
+                       }
+               break;
+       }
+
+       modehandlers[pos] = NULL;
+
+       return true;
+}
+
 ModeHandler* ModeParser::FindMode(unsigned const char modeletter, ModeType mt)
 {
        unsigned char mask = 0;
@@ -684,7 +734,7 @@ std::string ModeParser::ModeString(userrec* user, chanrec* channel)
                {
                        ModePair ret;
                        ret = mh->ModeSet(NULL, user, channel, user->nick);
-                       if (ret.first)
+                       if ((ret.first) && (ret.second == user->nick))
                        {
                                pars.append(" ");
                                pars.append(user->nick);
@@ -823,12 +873,56 @@ bool ModeParser::DelModeWatcher(ModeWatcher* mw)
        return true;
 }
 
+/** This default implementation can remove simple user modes
+ */
+void ModeHandler::RemoveMode(userrec* user)
+{
+       char moderemove[MAXBUF];
+       const char* parameters[] = { user->nick, moderemove };
+
+       if (user->IsModeSet(this->GetModeChar()))
+       {
+               userrec* n = new userrec(ServerInstance);
+
+               sprintf(moderemove,"-%c",this->GetModeChar());
+               n->SetFd(FD_MAGIC_NUMBER);
+
+               ServerInstance->SendMode(parameters, 2, n);
+
+               delete n;
+       }
+}
+
+/** This default implementation can remove simple channel modes
+ * (no parameters)
+ */
+void ModeHandler::RemoveMode(chanrec* channel)
+{
+       char moderemove[MAXBUF];
+       const char* parameters[] = { channel->name, moderemove };
+
+       if (channel->IsModeSet(this->GetModeChar()))
+       {
+               userrec* n = new userrec(ServerInstance);
+
+               sprintf(moderemove,"-%c",this->GetModeChar());
+               n->SetFd(FD_MAGIC_NUMBER);
+
+               ServerInstance->SendMode(parameters, 2, n);
+
+               delete n;
+       }
+}
+
 ModeParser::ModeParser(InspIRCd* Instance) : ServerInstance(Instance)
 {
        /* Clear mode list */
        memset(modehandlers, 0, sizeof(modehandlers));
        memset(modewatchers, 0, sizeof(modewatchers));
 
+       /* Last parse string */
+       LastParse = "";
+
        /* Initialise the RFC mode letters */
 
        /* Start with channel simple modes, no params */