]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/modules/m_banredirect.cpp
Add support for blocking tag messages with the deaf mode.
[user/henk/code/inspircd.git] / src / modules / m_banredirect.cpp
index 446d575df88f75810d04579adbf883bd432e9041..579bf9d32ae9df4d889cacb05941f656823ebee1 100644 (file)
@@ -1,12 +1,19 @@
 /*
  * InspIRCd -- Internet Relay Chat Daemon
  *
- *   Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
- *   Copyright (C) 2007, 2009 Robin Burchell <robin+git@viroteck.net>
- *   Copyright (C) 2008 Pippijn van Steenhoven <pip88nl@gmail.com>
+ *   Copyright (C) 2018 linuxdaemon <linuxdaemon.irc@gmail.com>
+ *   Copyright (C) 2014 Adam <Adam@anope.org>
+ *   Copyright (C) 2013-2016 Attila Molnar <attilamolnar@hush.com>
+ *   Copyright (C) 2013, 2017-2018 Sadie Powell <sadie@witchery.services>
+ *   Copyright (C) 2013 Daniel Vassdal <shutter@canternet.org>
+ *   Copyright (C) 2012, 2019 Robby <robby@chatbelgie.be>
+ *   Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
+ *   Copyright (C) 2009 Matt Smith <dz@inspircd.org>
+ *   Copyright (C) 2008, 2010 Craig Edwards <brain@inspircd.org>
+ *   Copyright (C) 2008 Uli Schlachter <psychon@inspircd.org>
+ *   Copyright (C) 2007-2009 Robin Burchell <robin+git@viroteck.net>
+ *   Copyright (C) 2007 Oliver Lupton <om@inspircd.org>
  *   Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
- *   Copyright (C) 2007 Craig Edwards <craigedwards@brainbox.cc>
- *   Copyright (C) 2007 Oliver Lupton <oliverlupton@gmail.com>
  *
  * This file is part of InspIRCd.  InspIRCd is free software: you can
  * redistribute it and/or modify it under the terms of the GNU General Public
@@ -50,11 +57,11 @@ class BanRedirect : public ModeWatcher
        BanRedirect(Module* parent)
                : ModeWatcher(parent, "ban", MODETYPE_CHANNEL)
                , ban(parent, "ban")
-               , extItem("banredirect", parent)
+               , extItem("banredirect", ExtensionItem::EXT_CHANNEL, parent)
        {
        }
 
-       bool BeforeMode(User* source, User* dest, Channel* channel, std::string &param, bool adding)
+       bool BeforeMode(User* source, User* dest, Channel* channel, std::string& param, bool adding) CXX11_OVERRIDE
        {
                /* nick!ident@host -> nick!ident@host
                 * nick!ident@host#chan -> nick!ident@host#chan
@@ -74,12 +81,15 @@ class BanRedirect : public ModeWatcher
                        if (param.length() >= 2 && param[1] == ':')
                                return true;
 
+                       if (param.find('#') == std::string::npos)
+                               return true;
+
                        ListModeBase* banlm = static_cast<ListModeBase*>(*ban);
                        unsigned int maxbans = banlm->GetLimit(channel);
                        ListModeBase::ModeList* list = banlm->GetList(channel);
                        if ((list) && (adding) && (maxbans <= list->size()))
                        {
-                               source->WriteNumeric(478, "%s %s :Channel ban list for %s is full (maximum entries for this channel is %u)", source->nick.c_str(), channel->name.c_str(), channel->name.c_str(), maxbans);
+                               source->WriteNumeric(ERR_BANLISTFULL, channel->name, banlm->GetModeChar(), InspIRCd::Format("Channel ban list for %s is full (maximum entries for this channel is %u)", channel->name.c_str(), maxbans));
                                return false;
                        }
 
@@ -123,6 +133,14 @@ class BanRedirect : public ModeWatcher
                                mask[NICK].swap(mask[IDENT]);
                        }
 
+                       if (!mask[NICK].empty() && mask[IDENT].empty() && mask[HOST].empty())
+                       {
+                               if (mask[NICK].find('.') != std::string::npos || mask[NICK].find(':') != std::string::npos)
+                               {
+                                       mask[NICK].swap(mask[HOST]);
+                               }
+                       }
+
                        for(int i = 0; i < 3; i++)
                        {
                                if(mask[i].empty())
@@ -139,25 +157,25 @@ class BanRedirect : public ModeWatcher
                                {
                                        if (!ServerInstance->IsChannel(mask[CHAN]))
                                        {
-                                               source->WriteNumeric(403, "%s %s :Invalid channel name in redirection (%s)", source->nick.c_str(), channel->name.c_str(), mask[CHAN].c_str());
+                                               source->WriteNumeric(ERR_NOSUCHCHANNEL, channel->name, InspIRCd::Format("Invalid channel name in redirection (%s)", mask[CHAN].c_str()));
                                                return false;
                                        }
 
                                        Channel *c = ServerInstance->FindChan(mask[CHAN]);
                                        if (!c)
                                        {
-                                               source->WriteNumeric(690, "%s :Target channel %s must exist to be set as a redirect.",source->nick.c_str(),mask[CHAN].c_str());
+                                               source->WriteNumeric(690, InspIRCd::Format("Target channel %s must exist to be set as a redirect.", mask[CHAN].c_str()));
                                                return false;
                                        }
                                        else if (adding && c->GetPrefixValue(source) < OP_VALUE)
                                        {
-                                               source->WriteNumeric(690, "%s :You must be opped on %s to set it as a redirect.",source->nick.c_str(), mask[CHAN].c_str());
+                                               source->WriteNumeric(690, InspIRCd::Format("You must be opped on %s to set it as a redirect.", mask[CHAN].c_str()));
                                                return false;
                                        }
 
-                                       if (assign(channel->name) == mask[CHAN])
+                                       if (irc::equals(channel->name, mask[CHAN]))
                                        {
-                                               source->WriteNumeric(690, "%s %s :You cannot set a ban redirection to the channel the ban is on", source->nick.c_str(), channel->name.c_str());
+                                               source->WriteNumeric(690, channel->name, "You cannot set a ban redirection to the channel the ban is on");
                                                return false;
                                        }
                                }
@@ -171,6 +189,21 @@ class BanRedirect : public ModeWatcher
                                                redirects = new BanRedirectList;
                                                extItem.set(channel, redirects);
                                        }
+                                       else
+                                       {
+                                               for (BanRedirectList::iterator redir = redirects->begin(); redir != redirects->end(); ++redir)
+                                               {
+                                                       // Mimic the functionality used when removing the mode
+                                                       if (irc::equals(redir->targetchan, mask[CHAN]) && irc::equals(redir->banmask, param))
+                                                       {
+                                                               // Make sure the +b handler will still set the right ban
+                                                               param.append(mask[CHAN]);
+                                                               // Silently ignore the duplicate and don't set metadata
+                                                               // This still allows channel ops to set/unset a redirect ban to clear "ghost" redirects
+                                                               return true;
+                                                       }
+                                               }
+                                       }
 
                                        /* Here 'param' doesn't have the channel on it yet */
                                        redirects->push_back(BanRedirectEntry(mask[CHAN], param));
@@ -188,8 +221,7 @@ class BanRedirect : public ModeWatcher
 
                                                for(BanRedirectList::iterator redir = redirects->begin(); redir != redirects->end(); redir++)
                                                {
-                                                       /* Ugly as fuck */
-                                                       if((irc::string(redir->targetchan.c_str()) == irc::string(mask[CHAN].c_str())) && (irc::string(redir->banmask.c_str()) == irc::string(param.c_str())))
+                                                       if ((irc::equals(redir->targetchan, mask[CHAN])) && (irc::equals(redir->banmask, param)))
                                                        {
                                                                redirects->erase(redir);
 
@@ -229,43 +261,25 @@ class ModuleBanRedirect : public Module
        {
        }
 
-       void init() CXX11_OVERRIDE
+       void OnCleanup(ExtensionItem::ExtensibleType type, Extensible* item) CXX11_OVERRIDE
        {
-               ServerInstance->Modes->AddModeWatcher(&re);
-               ServerInstance->Modules->AddService(re.extItem);
-               Implementation list[] = { I_OnUserPreJoin };
-               ServerInstance->Modules->Attach(list, this, sizeof(list)/sizeof(Implementation));
-       }
-
-       void OnCleanup(int target_type, void* item) CXX11_OVERRIDE
-       {
-               if(target_type == TYPE_CHANNEL)
+               if (type == ExtensionItem::EXT_CHANNEL)
                {
                        Channel* chan = static_cast<Channel*>(item);
                        BanRedirectList* redirects = re.extItem.get(chan);
 
                        if(redirects)
                        {
-                               irc::modestacker modestack(false);
+                               ModeHandler* ban = ServerInstance->Modes->FindMode('b', MODETYPE_CHANNEL);
+                               Modes::ChangeList changelist;
 
                                for(BanRedirectList::iterator i = redirects->begin(); i != redirects->end(); i++)
-                               {
-                                       modestack.Push('b', i->targetchan.insert(0, i->banmask));
-                               }
+                                       changelist.push_remove(ban, i->targetchan.insert(0, i->banmask));
 
                                for(BanRedirectList::iterator i = redirects->begin(); i != redirects->end(); i++)
-                               {
-                                       modestack.PushPlus();
-                                       modestack.Push('b', i->banmask);
-                               }
+                                       changelist.push_add(ban, i->banmask);
 
-                               std::vector<std::string> stackresult;
-                               stackresult.push_back(chan->name);
-                               while (modestack.GetStackedLine(stackresult))
-                               {
-                                       ServerInstance->Modes->Process(stackresult, ServerInstance->FakeClient, ModeParser::MODE_LOCALONLY);
-                                       stackresult.erase(stackresult.begin() + 1, stackresult.end());
-                               }
+                               ServerInstance->Modes->Process(ServerInstance->FakeClient, chan, NULL, changelist, ModeParser::MODE_LOCALONLY);
                        }
                }
        }
@@ -316,15 +330,15 @@ class ModuleBanRedirect : public Module
                                                if (destchan)
                                                        destlimit = destchan->GetModeParameter(limitmode);
 
-                                               if(destchan && destchan->IsModeSet(redirectmode) && !destlimit.empty() && (destchan->GetUserCounter() >= atoi(destlimit.c_str())))
+                                               if(destchan && destchan->IsModeSet(redirectmode) && !destlimit.empty() && (destchan->GetUserCounter() >= ConvToNum<size_t>(destlimit)))
                                                {
-                                                       user->WriteNumeric(474, "%s %s :Cannot join channel (You are banned)", user->nick.c_str(), chan->name.c_str());
+                                                       user->WriteNumeric(ERR_BANNEDFROMCHAN, chan->name, "Cannot join channel (you're banned)");
                                                        return MOD_RES_DENY;
                                                }
                                                else
                                                {
-                                                       user->WriteNumeric(474, "%s %s :Cannot join channel (You are banned)", user->nick.c_str(), chan->name.c_str());
-                                                       user->WriteNumeric(470, "%s %s %s :You are banned from this channel, so you are automatically transfered to the redirected channel.", user->nick.c_str(), chan->name.c_str(), redir->targetchan.c_str());
+                                                       user->WriteNumeric(ERR_BANNEDFROMCHAN, chan->name, "Cannot join channel (you're banned)");
+                                                       user->WriteNumeric(470, chan->name, redir->targetchan, "You are banned from this channel, so you are automatically being transferred to the redirected channel.");
                                                        nofollow = true;
                                                        Channel::JoinUser(user, redir->targetchan);
                                                        nofollow = false;
@@ -337,16 +351,9 @@ class ModuleBanRedirect : public Module
                return MOD_RES_PASSTHRU;
        }
 
-       ~ModuleBanRedirect()
-       {
-               /* XXX is this the best place to do this? */
-               if (!ServerInstance->Modes->DelModeWatcher(&re))
-                       ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Failed to delete modewatcher!");
-       }
-
        Version GetVersion() CXX11_OVERRIDE
        {
-               return Version("Allows an extended ban (+b) syntax redirecting banned users to another channel", VF_COMMON|VF_VENDOR);
+               return Version("Allows specifying a channel to redirect a banned user to in the ban mask.", VF_COMMON|VF_VENDOR);
        }
 };