]> git.netwichtig.de Git - user/henk/code/inspircd.git/commitdiff
Fixes for bug #493, tidyups to clearing of channel modes on losing FJOIN. Module...
authorbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>
Wed, 2 Apr 2008 23:53:29 +0000 (23:53 +0000)
committerbrain <brain@e03df62e-2008-0410-955e-edbf42e46eb7>
Wed, 2 Apr 2008 23:53:29 +0000 (23:53 +0000)
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@9283 e03df62e-2008-0410-955e-edbf42e46eb7

15 files changed:
include/mode.h
include/modes/cmode_b.h
include/modes/cmode_h.h
include/modes/cmode_k.h
include/modes/cmode_o.h
include/modes/cmode_v.h
include/u_listmode.h
src/mode.cpp
src/modes/cmode_b.cpp
src/modes/cmode_h.cpp
src/modes/cmode_k.cpp
src/modes/cmode_o.cpp
src/modes/cmode_v.cpp
src/modules/m_chanprotect.cpp
src/modules/m_spanningtree/fjoin.cpp

index ea52acf362a63ecf136a9f82e9d3cc33e8d0bffa..e15ddeeb0bd416d5022b1d28252ea3d16a2c5ad6 100644 (file)
@@ -276,7 +276,7 @@ class CoreExport ModeHandler : public Extensible
         * your mode properly from each user.
         * @param user The user which the server wants to remove your mode from
         */
-       virtual void RemoveMode(User* user);
+       virtual void RemoveMode(User* user, irc::modestacker* stack = NULL);
 
        /**
         * When a MODETYPE_CHANNEL mode handler is being removed, the server will call this method for every channel on the server.
@@ -286,7 +286,7 @@ class CoreExport ModeHandler : public Extensible
         * your mode properly from each channel. Note that in the case of listmodes, you should remove the entire list of items.
         * @param channel The channel which the server wants to remove your mode from
         */
-       virtual void RemoveMode(Channel* channel);
+       virtual void RemoveMode(Channel* channel, irc::modestacker* stack = NULL);
 
        char GetNeededPrefix();
 
index fc5eb08924078f40c64b7e5aeb7391a6b9e59091..bbeef1c62957985d8389e6ca9d969f5dcf7fc5b3 100644 (file)
@@ -30,7 +30,7 @@ class ModeChannelBan : public ModeHandler
        void DisplayList(User* user, Channel* channel);
        void DisplayEmptyList(User* user, Channel* channel);
        ModePair ModeSet(User* source, User* dest, Channel* channel, const std::string &parameter);
-       void RemoveMode(User* user);
-       void RemoveMode(Channel* channel);
+       void RemoveMode(User* user, irc::modestacker* stack = NULL);
+       void RemoveMode(Channel* channel, irc::modestacker* stack = NULL);
 };
 
index c8ea793c058abd418a435d4f9cb3ef1a70d39b8c..9c72a14316d9839e88f29bbce3c3b0058e4b3912 100644 (file)
@@ -28,7 +28,7 @@ class ModeChannelHalfOp : public ModeHandler
        std::string DelHalfOp(User *user,const char *dest,Channel *chan,int status);
        ModePair ModeSet(User* source, User* dest, Channel* channel, const std::string &parameter);
        unsigned int GetPrefixRank();
-       void RemoveMode(Channel* channel);
-       void RemoveMode(User* user);
+       void RemoveMode(Channel* channel, irc::modestacker* stack = NULL);
+       void RemoveMode(User* user, irc::modestacker* stack = NULL);
 };
 
index dce0550fe8aabc8e6787f4260a818e366f1a610e..c06c0c007d4b67e56066df9726abbb5fd3d7be23 100644 (file)
@@ -24,6 +24,6 @@ class ModeChannelKey : public ModeHandler
        ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding, bool servermode);
        ModePair ModeSet(User* source, User* dest, Channel* channel, const std::string &parameter);
        bool CheckTimeStamp(time_t theirs, time_t ours, const std::string &their_param, const std::string &our_param, Channel* channel);
-       void RemoveMode(Channel* channel);
-       void RemoveMode(User* user);
+       void RemoveMode(Channel* channel, irc::modestacker* stack = NULL);
+       void RemoveMode(User* user, irc::modestacker* stack = NULL);
 };
index f78ac8eb0d4aa0653ca3c3fc691f7093e23bfb04..0c48eff1ec15ac996724f2bce250072b7d8efd6a 100644 (file)
@@ -28,7 +28,7 @@ class ModeChannelOp : public ModeHandler
        std::string DelOp(User *user,const char *dest,Channel *chan,int status);
        ModePair ModeSet(User* source, User* dest, Channel* channel, const std::string &parameter);
        unsigned int GetPrefixRank();
-       void RemoveMode(Channel* channel);
-       void RemoveMode(User* user);
+       void RemoveMode(Channel* channel, irc::modestacker* stack = NULL);
+       void RemoveMode(User* user, irc::modestacker* stack = NULL);
 };
 
index f66761809241811e07daf64999a5ab8af82151fd..4e699fe9d971585ff70db14425fe4b2a18a1f4bb 100644 (file)
@@ -28,7 +28,7 @@ class ModeChannelVoice : public ModeHandler
        std::string DelVoice(User *user,const char *dest,Channel *chan,int status);
        ModePair ModeSet(User* source, User* dest, Channel* channel, const std::string &parameter);
        unsigned int GetPrefixRank();
-       void RemoveMode(User* user);
-       void RemoveMode(Channel* channel);
+       void RemoveMode(User* user, irc::modestacker* stack = NULL);
+       void RemoveMode(Channel* channel, irc::modestacker* stack = NULL);
 };
 
index a388d7f18207292c4a802d3c49d1e040735608ab..6c6e2ca28fbc63374a5e9c096e824eb390983c48 100644 (file)
@@ -168,7 +168,7 @@ class ListModeBase : public ModeHandler
         * See mode.h
         * @param channel The channel to remove all instances of the mode from
         */
-       virtual void RemoveMode(Channel* channel)
+       virtual void RemoveMode(Channel* channel, irc::modestacker* stack)
        {
                modelist* el;
                channel->GetExt(infokey, el);
@@ -181,9 +181,15 @@ class ListModeBase : public ModeHandler
 
                        for (modelist::iterator it = el->begin(); it != el->end(); it++)
                        {
-                               modestack.Push(this->GetModeChar(), assign(it->mask));
+                               if (stack)
+                                       stack->Push(this->GetModeChar(), assign(it->mask));
+                               else
+                                       modestack.Push(this->GetModeChar(), assign(it->mask));
                        }
 
+                       if (stack)
+                               return;
+
                        while (modestack.GetStackedLine(stackresult))
                        {
                                for (size_t j = 0; j < stackresult.size(); j++)
@@ -198,7 +204,7 @@ class ListModeBase : public ModeHandler
 
        /** See mode.h
         */
-       virtual void RemoveMode(User*)
+       virtual void RemoveMode(User*, irc::modestacker* stack)
        {
                /* Listmodes dont get set on users */
        }
index 9b90599ceeb587203b8288b4a836df90a07eb79b..83aff70cf56400a4e64d29d89dc26cc196f65948 100644 (file)
@@ -776,6 +776,9 @@ bool ModeParser::DelMode(ModeHandler* mh)
        if (!modehandlers[pos])
                return false;
 
+       /* Note: We can't stack here, as we have modes potentially being removed across many different channels.
+        * To stack here we have to make the algorithm slower. Discuss.
+        */
        switch (mh->GetModeType())
        {
                case MODETYPE_USER:
@@ -1048,30 +1051,44 @@ bool ModeParser::DelModeWatcher(ModeWatcher* mw)
 
 /** This default implementation can remove simple user modes
  */
-void ModeHandler::RemoveMode(User* user)
+void ModeHandler::RemoveMode(User* user, irc::modestacker* stack)
 {
        char moderemove[MAXBUF];
        const char* parameters[] = { user->nick, moderemove };
 
        if (user->IsModeSet(this->GetModeChar()))
        {
-               sprintf(moderemove,"-%c",this->GetModeChar());
-               ServerInstance->Parser->CallHandler("MODE", parameters, 2, user);
+               if (stack)
+               {
+                       stack->Push(this->GetModeChar());
+               }
+               else
+               {
+                       sprintf(moderemove,"-%c",this->GetModeChar());
+                       ServerInstance->Parser->CallHandler("MODE", parameters, 2, user);
+               }
        }
 }
 
 /** This default implementation can remove simple channel modes
  * (no parameters)
  */
-void ModeHandler::RemoveMode(Channel* channel)
+void ModeHandler::RemoveMode(Channel* channel, irc::modestacker* stack)
 {
        char moderemove[MAXBUF];
        const char* parameters[] = { channel->name, moderemove };
 
        if (channel->IsModeSet(this->GetModeChar()))
        {
-               sprintf(moderemove,"-%c",this->GetModeChar());
-               ServerInstance->SendMode(parameters, 2, ServerInstance->FakeClient);
+               if (stack)
+               {
+                       stack->Push(this->GetModeChar());
+               }
+               else
+               {
+                       sprintf(moderemove,"-%c",this->GetModeChar());
+                       ServerInstance->SendMode(parameters, 2, ServerInstance->FakeClient);
+               }
        }
 }
 
index 1efb5d399e31d7d79930bc09e5de14ad130dc260..4eea2e44d523766130d512577496b954f57061b6 100644 (file)
@@ -49,7 +49,7 @@ ModeAction ModeChannelBan::OnModeChange(User* source, User*, Channel* channel, s
        return MODEACTION_ALLOW;
 }
 
-void ModeChannelBan::RemoveMode(Channel* channel)
+void ModeChannelBan::RemoveMode(Channel* channel, irc::modestacker* stack)
 {
        BanList copy;
        char moderemove[MAXBUF];
@@ -61,13 +61,20 @@ void ModeChannelBan::RemoveMode(Channel* channel)
 
        for (BanList::iterator i = copy.begin(); i != copy.end(); i++)
        {
-               sprintf(moderemove,"-%c",this->GetModeChar());
-               const char* parameters[] = { channel->name, moderemove, i->data };
-               ServerInstance->SendMode(parameters, 3, ServerInstance->FakeClient);
+               if (stack)
+               {
+                       stack->Push(this->GetModeChar(), i->data);
+               }
+               else
+               {
+                       sprintf(moderemove,"-%c",this->GetModeChar());
+                       const char* parameters[] = { channel->name, moderemove, i->data };
+                       ServerInstance->SendMode(parameters, 3, ServerInstance->FakeClient);
+               }
        }
 }
 
-void ModeChannelBan::RemoveMode(User*)
+void ModeChannelBan::RemoveMode(User*, irc::modestacker* stack)
 {
 }
 
index 26ec55de31ce2410312d67453105da3f895a9fe3..8217ccc2d8dedce8cb0bd677a979d59c584ada9c 100644 (file)
@@ -45,7 +45,7 @@ ModePair ModeChannelHalfOp::ModeSet(User*, User*, Channel* channel, const std::s
        return std::make_pair(false, parameter);
 }
 
-void ModeChannelHalfOp::RemoveMode(Channel* channel)
+void ModeChannelHalfOp::RemoveMode(Channel* channel, irc::modestacker* stack)
 {
        CUList* clist = channel->GetHalfoppedUsers();
        CUList copy;
@@ -59,14 +59,21 @@ void ModeChannelHalfOp::RemoveMode(Channel* channel)
 
        for (CUList::iterator i = copy.begin(); i != copy.end(); i++)
        {
-               sprintf(moderemove,"-%c",this->GetModeChar());
-               const char* parameters[] = { channel->name, moderemove, i->first->nick };
-               ServerInstance->SendMode(parameters, 3, ServerInstance->FakeClient);
+               if (stack)
+               {
+                       stack->Push(this->GetModeChar(), i->first->nick);
+               }
+               else
+               {
+                       sprintf(moderemove,"-%c",this->GetModeChar());
+                       const char* parameters[] = { channel->name, moderemove, i->first->nick };
+                       ServerInstance->SendMode(parameters, 3, ServerInstance->FakeClient);
+               }
        }
 
 }
 
-void ModeChannelHalfOp::RemoveMode(User*)
+void ModeChannelHalfOp::RemoveMode(User*, irc::modestacker* stack)
 {
 }
 
index 21b5d8464ce7e6d2a2234071b866f5680dffdf39..194c0efcbc0a14c679cdd9421dd1d2c9f3e5e680 100644 (file)
@@ -33,7 +33,7 @@ ModePair ModeChannelKey::ModeSet(User*, User*, Channel* channel, const std::stri
         }
 }
 
-void ModeChannelKey::RemoveMode(Channel* channel)
+void ModeChannelKey::RemoveMode(Channel* channel, irc::modestacker* stack)
 {
        /** +k needs a parameter when being removed,
         * so we have a special-case RemoveMode here for it
@@ -43,12 +43,17 @@ void ModeChannelKey::RemoveMode(Channel* channel)
 
        if (channel->IsModeSet(this->GetModeChar()))
        {
-               sprintf(moderemove,"-%c",this->GetModeChar());
-               ServerInstance->SendMode(parameters, 3, ServerInstance->FakeClient);
+               if (stack)
+                       stack->Push(this->GetModeChar(), channel->key);
+               else
+               {
+                       sprintf(moderemove,"-%c",this->GetModeChar());
+                       ServerInstance->SendMode(parameters, 3, ServerInstance->FakeClient);
+               }
        }
 }
 
-void ModeChannelKey::RemoveMode(User*)
+void ModeChannelKey::RemoveMode(User*, irc::modestacker* stack)
 {
 }
 
index f62635658a99d8630ce30977e4c76d4f9581caa6..c4e3c241e8921799b182888aa1d1b5b20cc64d6f 100644 (file)
@@ -46,7 +46,7 @@ ModePair ModeChannelOp::ModeSet(User*, User*, Channel* channel, const std::strin
 }
 
 
-void ModeChannelOp::RemoveMode(Channel* channel)
+void ModeChannelOp::RemoveMode(Channel* channel, irc::modestacker* stack)
 {
        CUList* clist = channel->GetOppedUsers();
        CUList copy;
@@ -60,13 +60,18 @@ void ModeChannelOp::RemoveMode(Channel* channel)
 
        for (CUList::iterator i = copy.begin(); i != copy.end(); i++)
        {
-               sprintf(moderemove,"-%c",this->GetModeChar());
-               const char* parameters[] = { channel->name, moderemove, i->first->nick };
-               ServerInstance->SendMode(parameters, 3, ServerInstance->FakeClient);
+               if (stack)
+                       stack->Push(this->GetModeChar(), i->first->nick);
+               else
+               {
+                       sprintf(moderemove,"-%c",this->GetModeChar());
+                       const char* parameters[] = { channel->name, moderemove, i->first->nick };
+                       ServerInstance->SendMode(parameters, 3, ServerInstance->FakeClient);
+               }
        }
 }
 
-void ModeChannelOp::RemoveMode(User*)
+void ModeChannelOp::RemoveMode(User*, irc::modestacker* stack)
 {
 }
 
index 45a9e1879cefe5c963eb400e91cc28508dfe29a3..15196d4a89c3d75164e196efb27630e8cfa6232a 100644 (file)
@@ -46,7 +46,7 @@ ModePair ModeChannelVoice::ModeSet(User*, User*, Channel* channel, const std::st
        return std::make_pair(false, parameter);
 }
 
-void ModeChannelVoice::RemoveMode(Channel* channel)
+void ModeChannelVoice::RemoveMode(Channel* channel, irc::modestacker* stack)
 {
        CUList* clist = channel->GetVoicedUsers();
        CUList copy;
@@ -60,13 +60,18 @@ void ModeChannelVoice::RemoveMode(Channel* channel)
 
        for (CUList::iterator i = copy.begin(); i != copy.end(); i++)
        {
-               sprintf(moderemove,"-%c",this->GetModeChar());
-               const char* parameters[] = { channel->name, moderemove, i->first->nick };
-               ServerInstance->SendMode(parameters, 3, ServerInstance->FakeClient);
+               if (stack)
+                       stack->Push(this->GetModeChar(), i->first->nick);
+               else
+               {
+                       sprintf(moderemove,"-%c",this->GetModeChar());
+                       const char* parameters[] = { channel->name, moderemove, i->first->nick };
+                       ServerInstance->SendMode(parameters, 3, ServerInstance->FakeClient);
+               }
        }
 }
 
-void ModeChannelVoice::RemoveMode(User*)
+void ModeChannelVoice::RemoveMode(User*, irc::modestacker* stack)
 {
 }
 
index daa728e61211d1f9bdc657a9e0ab31f6f5ae2221..0cc4fe8d7b971efbfafc1f470fee920f56ffa0be 100644 (file)
@@ -62,7 +62,7 @@ class FounderProtectBase
                return std::make_pair(false, parameter);
        }
 
-       void RemoveMode(Channel* channel, char mc)
+       void RemoveMode(Channel* channel, char mc, irc::modestacker* stack)
        {
                CUList* cl = channel->GetUsers();
                std::string item = extend + std::string(channel->name);
@@ -75,10 +75,16 @@ class FounderProtectBase
                {
                        if (i->first->GetExt(item))
                        {
-                               modestack.Push(mc, i->first->nick);
+                               if (stack)
+                                       stack->Push(mc, i->first->nick);
+                               else
+                                       modestack.Push(mc, i->first->nick);
                        }
                }
 
+               if (stack)
+                       return;
+
                while (modestack.GetStackedLine(stackresult))
                {
                        for (size_t j = 0; j < stackresult.size(); j++)
@@ -165,12 +171,12 @@ class ChanFounder : public ModeHandler, public FounderProtectBase
                return FounderProtectBase::ModeSet(source, dest, channel, parameter);
        }
 
-       void RemoveMode(Channel* channel)
+       void RemoveMode(Channel* channel, irc::modestacker* stack)
        {
-               FounderProtectBase::RemoveMode(channel, this->GetModeChar());
+               FounderProtectBase::RemoveMode(channel, this->GetModeChar(), stack);
        }
 
-       void RemoveMode(User* user)
+       void RemoveMode(User* user, irc::modestacker* stack)
        {
        }
 
@@ -231,12 +237,12 @@ class ChanProtect : public ModeHandler, public FounderProtectBase
                return FounderProtectBase::ModeSet(source, dest, channel, parameter);
        }
 
-       void RemoveMode(Channel* channel)
+       void RemoveMode(Channel* channel, irc::modestacker* stack)
        {
-               FounderProtectBase::RemoveMode(channel, this->GetModeChar());
+               FounderProtectBase::RemoveMode(channel, this->GetModeChar(), stack);
        }
 
-       void RemoveMode(User* user)
+       void RemoveMode(User* user, irc::modestacker* stack)
        {
        }
 
index 0bddb4da7a6539b04980fc804d9d66420234fe2a..3d119ee786bbc095accac2dc05e77db87d32333b 100644 (file)
@@ -189,11 +189,29 @@ bool TreeSocket::RemoveStatus(const std::string &prefix, std::deque<std::string>
 
        if (c)
        {
-               for (char modeletter = 'A'; modeletter <= 'z'; modeletter++)
+               irc::modestacker stack(false);
+               std::deque<std::string> stackresult;
+               const char* mode_junk[MAXMODES+2];
+               mode_junk[0] = c->name;
+
+               for (char modeletter = 'A'; modeletter <= 'z'; ++modeletter)
                {
                        ModeHandler* mh = Instance->Modes->FindMode(modeletter, MODETYPE_CHANNEL);
+
+                       /* Passing a pointer to a modestacker here causes the mode to be put onto the mode stack,
+                        * rather than applied immediately. Module unloads require this to be done immediately,
+                        * for this function we require tidyness instead. Fixes bug #493
+                        */
                        if (mh)
-                               mh->RemoveMode(c);
+                               mh->RemoveMode(c, &stack);
+               }
+
+               while (stack.GetStackedLine(stackresult))
+               {
+                       for (size_t j = 0; j < stackresult.size(); j++)
+                               mode_junk[j+1] = stackresult[j].c_str();
+
+                       Instance->SendMode(mode_junk, stackresult.size() + 1, Instance->FakeClient);
                }
        }
        return true;