]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/mode.cpp
Make classbase and refcountbase uncopyable; expand comments on their indended uses
[user/henk/code/inspircd.git] / src / mode.cpp
index b7ee7b38500643e1abea6222cebae9f7dbd12890..47553f238294278fa8ebc4f166044943a9e87d7c 100644 (file)
@@ -11,8 +11,6 @@
  * ---------------------------------------------------
  */
 
-/* $Core */
-
 #include "inspircd.h"
 #include "inspstring.h"
 
 /* +s (server notice masks) */
 #include "modes/umode_s.h"
 
-ModeHandler::ModeHandler(Module* Creator, char modeletter, ParamSpec Params, ModeType type)
-       : mode(modeletter), parameters_taken(Params), list(false), m_type(type), m_paramtype(TR_TEXT),
-       oper(false), prefix(0), count(0), levelrequired(HALFOP_VALUE), creator(Creator)
+ModeHandler::ModeHandler(Module* Creator, const std::string& Name, char modeletter, ParamSpec Params, ModeType type)
+       : m_paramtype(TR_TEXT), parameters_taken(Params), mode(modeletter), prefix(0), oper(false),
+       list(false), m_type(type), count(0), levelrequired(HALFOP_VALUE), creator(Creator), name(Name)
+{
+}
+
+CullResult ModeHandler::cull()
 {
+       ServerInstance->Modes->DelMode(this);
+       return classbase::cull();
 }
 
 ModeHandler::~ModeHandler()
 {
+       if (ServerInstance && ServerInstance->Modes->FindMode(mode, m_type) == this)
+               ServerInstance->Logs->Log("MODE", DEBUG, "ERROR: Destructor for mode %c called while not culled", mode);
 }
 
 bool ModeHandler::IsListMode()
@@ -138,7 +144,7 @@ void ModeHandler::OnParameterMissing(User* user, User* dest, Channel* channel)
 {
 }
 
-bool ModeHandler::CheckTimeStamp(std::string& theirs, const std::string& ours, Channel*)
+bool ModeHandler::ResolveModeConflict(std::string& theirs, const std::string& ours, Channel*)
 {
        return (theirs < ours);
 }
@@ -188,7 +194,8 @@ ModeAction SimpleChannelModeHandler::OnModeChange(User* source, User* dest, Chan
        return MODEACTION_DENY;
 }
 
-ModeWatcher::ModeWatcher(InspIRCd* Instance, char modeletter, ModeType type) : ServerInstance(Instance), mode(modeletter), m_type(type)
+ModeWatcher::ModeWatcher(Module* Creator, char modeletter, ModeType type)
+       : mode(modeletter), m_type(type), creator(Creator)
 {
 }
 
@@ -268,7 +275,7 @@ ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, bool
        int pcnt = mh->GetNumParams(adding);
 
        ModResult MOD_RESULT;
-       FIRST_MOD_RESULT(ServerInstance, OnRawMode, MOD_RESULT, (user, chan, modechar, parameter, adding, pcnt));
+       FIRST_MOD_RESULT(OnRawMode, MOD_RESULT, (user, chan, modechar, parameter, adding, pcnt));
 
        if (IS_LOCAL(user) && (MOD_RESULT == MOD_RES_DENY))
                return MODEACTION_DENY;
@@ -338,6 +345,12 @@ ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, bool
                return MODEACTION_DENY;
        }
 
+       if (mh->GetTranslateType() == TR_NICK && !ServerInstance->FindNick(parameter))
+       {
+               user->WriteNumeric(ERR_NOSUCHNICK, "%s %s :No such nick/channel", user->nick.c_str(), parameter.c_str());
+               return MODEACTION_DENY;
+       }
+
        /* Call the handler for the mode */
        ModeAction ma = mh->OnModeChange(user, targetuser, chan, parameter, adding);
 
@@ -384,22 +397,15 @@ void ModeParser::Process(const std::vector<std::string>& parameters, User *user,
                return;
        }
 
-       std::string mode_sequence = parameters[1];
+       ModResult MOD_RESULT;
+       FIRST_MOD_RESULT(OnPreMode, MOD_RESULT, (user, targetuser, targetchannel, parameters));
 
        bool SkipAccessChecks = false;
 
-       if (!IS_LOCAL(user) || ServerInstance->ULine(user->server))
-       {
+       if (!IS_LOCAL(user) || ServerInstance->ULine(user->server) || MOD_RESULT == MOD_RES_ALLOW)
                SkipAccessChecks = true;
-       }
-       else
-       {
-               ModResult MOD_RESULT;
-               FIRST_MOD_RESULT(ServerInstance, OnPreMode, MOD_RESULT, (user, targetuser, targetchannel, parameters));
-               if (MOD_RESULT == MOD_RES_DENY)
-                       return;
-               SkipAccessChecks = (MOD_RESULT == MOD_RES_ALLOW);
-       }
+       else if (MOD_RESULT == MOD_RES_DENY)
+               return;
 
        if (targetuser && !SkipAccessChecks && user != targetuser)
        {
@@ -407,6 +413,8 @@ void ModeParser::Process(const std::vector<std::string>& parameters, User *user,
                return;
        }
 
+       std::string mode_sequence = parameters[1];
+
        std::string output_mode;
        std::ostringstream output_parameters;
        LastParseParams.push_back(output_mode);
@@ -450,7 +458,7 @@ void ModeParser::Process(const std::vector<std::string>& parameters, User *user,
                        if (merge && targetchannel && targetchannel->IsModeSet(modechar) && !mh->IsListMode())
                        {
                                std::string ours = targetchannel->GetModeParameter(modechar);
-                               if (!mh->CheckTimeStamp(parameter, ours, targetchannel))
+                               if (!mh->ResolveModeConflict(parameter, ours, targetchannel))
                                        /* we won the mode merge, don't apply this mode */
                                        continue;
                        }
@@ -545,7 +553,7 @@ void ModeParser::DisplayListModes(User* user, Channel* chan, std::string &mode_s
                        return;
 
                ModResult MOD_RESULT;
-               FIRST_MOD_RESULT(ServerInstance, OnRawMode, MOD_RESULT, (user, chan, mletter, "", true, 0));
+               FIRST_MOD_RESULT(OnRawMode, MOD_RESULT, (user, chan, mletter, "", true, 0));
                if (MOD_RESULT == MOD_RES_DENY)
                        continue;
 
@@ -656,7 +664,7 @@ bool ModeParser::DelMode(ModeHandler* mh)
        mh->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL;
        pos = (mh->GetModeChar()-65) | mask;
 
-       if (!modehandlers[pos])
+       if (modehandlers[pos] != mh)
                return false;
 
        /* Note: We can't stack here, as we have modes potentially being removed across many different channels.
@@ -958,58 +966,70 @@ void ModeHandler::RemoveMode(Channel* channel, irc::modestacker* stack)
        }
 }
 
-ModeParser::ModeParser(InspIRCd* Instance)
+struct builtin_modes
 {
-       ModeHandler* modes[] =
+       ModeChannelSecret s;
+       ModeChannelPrivate p;
+       ModeChannelModerated m;
+       ModeChannelTopicOps t;
+
+       ModeChannelNoExternal n;
+       ModeChannelInviteOnly i;
+       ModeChannelKey k;
+       ModeChannelLimit l;
+
+       ModeChannelBan b;
+       ModeChannelOp o;
+       // halfop is added by configreader
+       ModeChannelVoice v;
+
+       ModeUserWallops uw;
+       ModeUserInvisible ui;
+       ModeUserOperator uo;
+       ModeUserServerNoticeMask us;
+
+       void init(ModeParser* modes)
        {
-               new ModeChannelSecret(Instance),
-               new ModeChannelPrivate(Instance),
-               new ModeChannelModerated(Instance),
-               new ModeChannelTopicOps(Instance),
-
-               new ModeChannelNoExternal(Instance),
-               new ModeChannelInviteOnly(Instance),
-               new ModeChannelKey(Instance),
-               new ModeChannelLimit(Instance),
-
-               new ModeChannelBan(Instance),
-               new ModeChannelOp(Instance),
-               new ModeChannelHalfOp(Instance),
-               new ModeChannelVoice(Instance),
+               modes->AddMode(&s);
+               modes->AddMode(&p);
+               modes->AddMode(&m);
+               modes->AddMode(&t);
+               modes->AddMode(&n);
+               modes->AddMode(&i);
+               modes->AddMode(&k);
+               modes->AddMode(&l);
+               modes->AddMode(&b);
+               modes->AddMode(&o);
+               modes->AddMode(&v);
+               modes->AddMode(&uw);
+               modes->AddMode(&ui);
+               modes->AddMode(&uo);
+               modes->AddMode(&us);
+       }
+};
 
-               new ModeUserWallops(Instance),
-               new ModeUserInvisible(Instance),
-               new ModeUserOperator(Instance),
-               new ModeUserServerNoticeMask(Instance),
-#define BUILTIN_MODE_COUNT 16
-       };
+static builtin_modes static_modes;
 
+ModeParser::ModeParser()
+{
        /* Clear mode handler list */
        memset(modehandlers, 0, sizeof(modehandlers));
 
        /* Last parse string */
        LastParse.clear();
 
-       /* Initialise the RFC mode letters */
-       for (int index = 0; index < BUILTIN_MODE_COUNT; index++)
-               this->AddMode(modes[index]);
-
        seq = 0;
        memset(&sent, 0, sizeof(sent));
+
+       static_modes.init(this);
 }
 
 ModeParser::~ModeParser()
 {
-       int count = 0;
-       for(int i=0; i < 256; i++)
+       ModeHandler* mh = ServerInstance->Modes->FindMode('h', MODETYPE_CHANNEL);
+       if (mh)
        {
-               ModeHandler* mh = modehandlers[i];
-               if (mh)
-               {
-                       count++;
-                       delete mh;
-               }
+               mh->cull();
+               delete mh;
        }
-       if (count != BUILTIN_MODE_COUNT)
-               throw CoreException("Mode handler found non-core modes remaining at deallocation");
 }