]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/mode.cpp
Made SANICK not collide the user (theres no need to in the new 1.1 now we have return...
[user/henk/code/inspircd.git] / src / mode.cpp
index 301fbc872f6116120af384d02ed3616637ec4857..3bdcb1a300cd49448434a240531d8ee09061c883 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;
        }
 
@@ -351,6 +344,10 @@ void ModeParser::Process(const char** parameters, int pcnt, userrec *user, bool
                unsigned char handler_id = 0;
                int parameter_counter = 2; /* Index of first parameter */
 
+               /* A mode sequence that doesnt start with + or -. Assume +. - Thanks for the suggestion spike (bug#132) */
+               if ((*mode_sequence.begin() != '+') && (*mode_sequence.begin() != '-'))
+                       mode_sequence.insert(0, "+");
+
                for (std::string::const_iterator letter = mode_sequence.begin(); letter != mode_sequence.end(); letter++)
                {
                        unsigned char modechar = *letter;
@@ -413,7 +410,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
@@ -427,7 +424,12 @@ void ModeParser::Process(const char** parameters, int pcnt, userrec *user, bool
                                                         * eat any parameter that  came with the mode, and continue to next
                                                         */
                                                        if ((IS_LOCAL(user)) && (modehandlers[handler_id]->NeedsOper()) && (!*user->oper))
+                                                       {
+                                                               user->WriteServ("481 %s :Permission Denied- Only IRC operators may %sset %s mode %c", user->nick,
+                                                                               adding ? "" : "un", type == MODETYPE_CHANNEL ? "channel" : "user",
+                                                                               modehandlers[handler_id]->GetModeChar());
                                                                continue;
+                                                       }
 
                                                        /* Call the handler for the mode */
                                                        ModeAction ma = modehandlers[handler_id]->OnModeChange(user, targetuser, targetchannel, parameter, adding);
@@ -492,7 +494,7 @@ void ModeParser::Process(const char** parameters, int pcnt, userrec *user, bool
                                }
                                else
                                {
-                                       targetuser->WriteServ("MODE %s %s",targetuser->nick,output_sequence.c_str());
+                                       targetuser->WriteServ("MODE %s %s%s",targetuser->nick,output_sequence.c_str(), parameter_list.str().c_str());
                                }
                        }
                        else
@@ -505,7 +507,7 @@ void ModeParser::Process(const char** parameters, int pcnt, userrec *user, bool
                                }
                                else
                                {
-                                       user->WriteTo(targetuser,"MODE %s %s",targetuser->nick,output_sequence.c_str());
+                                       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));
                                }
                        }
@@ -513,17 +515,6 @@ void ModeParser::Process(const char** parameters, int pcnt, userrec *user, bool
        }
 }
 
-
-void cmd_mode::Handle (const char** parameters, int pcnt, userrec *user)
-{
-       if (!user)
-               return;
-
-       ServerInstance->Modes->Process(parameters, pcnt, user, false);
-
-       return;
-}
-
 void ModeParser::CleanMask(std::string &mask)
 {
        std::string::size_type pos_of_pling = mask.find_first_of('!');
@@ -569,6 +560,12 @@ bool ModeParser::AddMode(ModeHandler* mh, unsigned const char modeletter)
        if ((mh->GetModeChar() < 'A') || (mh->GetModeChar() > 'z'))
                return false;
 
+       /* A mode prefix of ',' is not acceptable, it would fuck up server to server.
+        * A mode prefix of ':' will fuck up both server to server, and client to server.
+        */
+       if ((mh->GetPrefix() == ',') || (mh->GetPrefix() == ':'))
+               return false;
+
        mh->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
        pos = (mh->GetModeChar()-65) | mask;
 
@@ -580,6 +577,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;
@@ -642,9 +674,96 @@ std::string ModeParser::ParaModeList()
        return modestr;
 }
 
+ModeHandler* ModeParser::FindPrefix(unsigned const char pfxletter)
+{
+       for (unsigned char mode = 'A'; mode <= 'z'; mode++)
+       {
+               unsigned char pos = (mode-65) | MASK_CHANNEL;
+
+               if ((modehandlers[pos]) && (modehandlers[pos]->GetPrefix() == pfxletter))
+               {
+                       return modehandlers[pos];
+               }
+       }
+       return NULL;
+}
+
+std::string ModeParser::ModeString(userrec* user, chanrec* channel)
+{
+       std::string types;
+       std::string pars;
+
+       for (unsigned char mode = 'A'; mode <= 'z'; mode++)
+       {
+               unsigned char pos = (mode-65) | MASK_CHANNEL;
+               ModeHandler* mh = modehandlers[pos];
+               if ((mh) && (mh->GetNumParams(true)) && (mh->GetNumParams(false)))
+               {
+                       ModePair ret;
+                       ret = mh->ModeSet(NULL, user, channel, user->nick);
+                       if (ret.first)
+                       {
+                               pars.append(" ");
+                               pars.append(user->nick);
+                               types.push_back(mh->GetModeChar());
+                       }
+               }
+       }
+
+       return types+pars;
+}
+
+std::string ModeParser::ChanModes()
+{
+       std::string type1;      /* Listmodes EXCEPT those with a prefix */
+       std::string type2;      /* Modes that take a param when adding or removing */
+       std::string type3;      /* Modes that only take a param when adding */
+       std::string type4;      /* Modes that dont take a param */
+
+       for (unsigned char mode = 'A'; mode <= 'z'; mode++)
+       {
+               unsigned char pos = (mode-65) | MASK_CHANNEL;
+                /* One parameter when adding */
+               if (modehandlers[pos])
+               {       
+                       if (modehandlers[pos]->GetNumParams(true))
+                       {
+                               if ((modehandlers[pos]->IsListMode()) && (!modehandlers[pos]->GetPrefix()))
+                               {
+                                       type1 += modehandlers[pos]->GetModeChar();
+                               }
+                               else
+                               {
+                                       /* ... and one parameter when removing */
+                                       if (modehandlers[pos]->GetNumParams(false))
+                                       {
+                                               /* But not a list mode */
+                                               if (!modehandlers[pos]->GetPrefix())
+                                               {
+                                                       type2 += modehandlers[pos]->GetModeChar();
+                                               }
+                                       }
+                                       else
+                                       {
+                                               /* No parameters when removing */
+                                               type3 += modehandlers[pos]->GetModeChar();
+                                       }
+                               }
+                       }
+                       else
+                       {
+                               type4 += modehandlers[pos]->GetModeChar();
+                       }
+               }
+                        
+       }
+
+       return type1 + "," + type2 + "," + type3 + "," + type4;
+}
+
 bool ModeParser::PrefixComparison(const prefixtype one, const prefixtype two)
 {       
-       return (one.second) < (two.second);
+       return one.second > two.second;
 }
 
 std::string ModeParser::BuildPrefixes()
@@ -652,18 +771,28 @@ std::string ModeParser::BuildPrefixes()
        std::string mletters = "";
        std::string mprefixes = "";
        pfxcontainer pfx;
+       std::map<char,char> prefix_to_mode;
 
        for (unsigned char mode = 'A'; mode <= 'z'; mode++)
        {
                unsigned char pos = (mode-65) | MASK_CHANNEL;
 
                if ((modehandlers[pos]) && (modehandlers[pos]->GetPrefix()))
+               {
                        pfx.push_back(std::make_pair<char,unsigned int>(modehandlers[pos]->GetPrefix(), modehandlers[pos]->GetPrefixRank()));
+                       prefix_to_mode[modehandlers[pos]->GetPrefix()] = modehandlers[pos]->GetModeChar();
+               }
        }
 
        sort(pfx.begin(), pfx.end(), ModeParser::PrefixComparison);
 
-       return "";
+       for (pfxcontainer::iterator n = pfx.begin(); n != pfx.end(); n++)
+       {
+               mletters = mletters + n->first;
+               mprefixes = mprefixes + prefix_to_mode.find(n->first)->second;
+       }
+
+       return "(" + mprefixes + ")" + mletters;
 }
 
 bool ModeParser::AddModeWatcher(ModeWatcher* mw)
@@ -711,6 +840,47 @@ 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 */
@@ -745,27 +915,3 @@ ModeParser::ModeParser(InspIRCd* Instance) : ServerInstance(Instance)
        this->AddMode(new ModeUserServerNoticeMask(Instance), 'n');
 }
 
-bool ModeParser::InsertMode(std::string &output, const char* mode, unsigned short section)
-{
-       unsigned short currsection = 1;
-       unsigned int pos = output.find("CHANMODES=", 0) + 10; // +10 for the length of "CHANMODES="
-
-       if(section > 4 || section == 0)
-       {
-               ServerInstance->Log(DEBUG, "InsertMode: CHANMODES doesn't have a section %dh :/", section);
-               return false;
-       }
-
-       for(; pos < output.size(); pos++)
-       {
-               if(section == currsection)
-                       break;
-
-               if(output[pos] == ',')
-                       currsection++;
-       }
-
-       output.insert(pos, mode);
-       return true;
-}
-