]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/modules/m_dccallow.cpp
Update copyright headers.
[user/henk/code/inspircd.git] / src / modules / m_dccallow.cpp
index 9d85f01da36a7981ce428e406f7bc1ed4da99490..20dfa9db8393c64c089f4b9a2147d7bd6ea8723f 100644 (file)
@@ -1,13 +1,19 @@
 /*
  * InspIRCd -- Internet Relay Chat Daemon
  *
- *   Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
- *   Copyright (C) 2008 John Brooks <john.brooks@dereferenced.net>
- *   Copyright (C) 2008 Pippijn van Steenhoven <pip88nl@gmail.com>
- *   Copyright (C) 2006-2008 Craig Edwards <craigedwards@brainbox.cc>
+ *   Copyright (C) 2019 Matt Schatz <genius3000@g3k.solutions>
+ *   Copyright (C) 2018 linuxdaemon <linuxdaemon.irc@gmail.com>
+ *   Copyright (C) 2016 Adam <Adam@anope.org>
+ *   Copyright (C) 2013, 2017-2020 Sadie Powell <sadie@witchery.services>
+ *   Copyright (C) 2012-2016 Attila Molnar <attilamolnar@hush.com>
+ *   Copyright (C) 2012, 2014, 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 John Brooks <special@inspircd.org>
  *   Copyright (C) 2007-2008 Robin Burchell <robin+git@viroteck.net>
- *   Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
- *   Copyright (C) 2006 Jamie ??? <???@???>
+ *   Copyright (C) 2007-2008 Dennis Friis <peavey@inspircd.org>
+ *   Copyright (C) 2006 jamie <jamie@e03df62e-2008-0410-955e-edbf42e46eb7>
  *
  * 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
 
 enum
 {
+       // From ircd-ratbox.
+       RPL_HELPSTART = 704,
+       RPL_HELPTXT = 705,
+       RPL_ENDOFHELP = 706,
+
        // InspIRCd-specific?
        RPL_DCCALLOWSTART = 990,
        RPL_DCCALLOWLIST = 991,
@@ -36,16 +47,11 @@ enum
        RPL_DCCALLOWREMOVED = 995,
        ERR_DCCALLOWINVALID = 996,
        RPL_DCCALLOWEXPIRED = 997,
-       ERR_UNKNOWNDCCALLOWCMD = 998,
-       // TODO: These numerics are conflicting and should be removed
-       // and be replaced with helpop.
-       RPL_DCCALLOWHELP = 998,
-       RPL_ENDOFDCCALLOWHELP = 999
+       ERR_UNKNOWNDCCALLOWCMD = 998
 };
 
 static const char* const helptext[] =
 {
-       "DCCALLOW [(+|-)<nick> [<time>]]|[LIST|HELP]",
        "You may allow DCCs from specific users by specifying a",
        "DCC allow for the user you want to receive DCCs from.",
        "For example, to allow the user Brain to send you inspircd.exe",
@@ -54,7 +60,7 @@ static const char* const helptext[] =
        "Brain would then be able to send you files. They would have to",
        "resend the file again if the server gave them an error message",
        "before you added them to your DCCALLOW list.",
-       "DCCALLOW entries will be temporary by default, if you want to add",
+       "DCCALLOW entries will be temporary. If you want to add",
        "them to your DCCALLOW list until you leave IRC, type:",
        "/DCCALLOW +Brain 0",
        "To remove the user from your DCCALLOW list, type:",
@@ -63,7 +69,7 @@ static const char* const helptext[] =
        "/DCCALLOW LIST",
        "NOTE: If the user leaves IRC or changes their nickname",
        "  they will be removed from your DCCALLOW list.",
-       "  your DCCALLOW list will be deleted when you leave IRC."
+       "  Your DCCALLOW list will be deleted when you leave IRC."
 };
 
 class BannedFileList
@@ -98,14 +104,84 @@ typedef std::vector<DCCAllow> dccallowlist;
 dccallowlist* dl;
 typedef std::vector<BannedFileList> bannedfilelist;
 bannedfilelist bfl;
-typedef SimpleExtItem<dccallowlist> DCCAllowExt;
 
-class CommandDccallow : public Command
+class DCCAllowExt : public SimpleExtItem<dccallowlist>
 {
-       DCCAllowExt& ext;
-
  public:
        unsigned int maxentries;
+
+       DCCAllowExt(Module* Creator)
+               : SimpleExtItem<dccallowlist>("dccallow", ExtensionItem::EXT_USER, Creator)
+       {
+       }
+
+       void FromInternal(Extensible* container, const std::string& value) CXX11_OVERRIDE
+       {
+               LocalUser* user = IS_LOCAL(static_cast<User*>(container));
+               if (!user)
+                       return;
+
+               // Remove the old list and create a new one.
+               unset(user);
+               dccallowlist* list = new dccallowlist();
+
+               irc::spacesepstream ts(value);
+               while (!ts.StreamEnd())
+               {
+                       // Check we have space for another entry.
+                       if (list->size() >= maxentries)
+                       {
+                               ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Oversized DCC allow list received for %s: %s",
+                                       user->uuid.c_str(), value.c_str());
+                               delete list;
+                               return;
+                       }
+
+                       // Extract the fields.
+                       DCCAllow dccallow;
+                       if (!ts.GetToken(dccallow.nickname) ||
+                               !ts.GetToken(dccallow.hostmask) ||
+                               !ts.GetNumericToken(dccallow.set_on) ||
+                               !ts.GetNumericToken(dccallow.length))
+                       {
+                               ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Malformed DCC allow list received for %s: %s",
+                                       user->uuid.c_str(), value.c_str());
+                               delete list;
+                               return;
+                       }
+
+                       // Store the DCC allow entry.
+                       list->push_back(dccallow);
+               }
+
+       }
+
+       std::string ToInternal(const Extensible* container, void* item) const CXX11_OVERRIDE
+       {
+               dccallowlist* list = static_cast<dccallowlist*>(item);
+               std::string buf;
+               for (dccallowlist::const_iterator iter = list->begin(); iter != list->end(); ++iter)
+               {
+                       if (iter != list->begin())
+                               buf.push_back(' ');
+
+                       buf.append(iter->nickname);
+                       buf.push_back(' ');
+                       buf.append(iter->hostmask);
+                       buf.push_back(' ');
+                       buf.append(ConvToStr(iter->set_on));
+                       buf.push_back(' ');
+                       buf.append(ConvToStr(iter->length));
+               }
+               return buf;
+       }
+};
+
+class CommandDccallow : public Command
+{
+ public:
+       DCCAllowExt& ext;
+       unsigned long defaultlength;
        CommandDccallow(Module* parent, DCCAllowExt& Ext)
                : Command(parent, "DCCALLOW", 0)
                , ext(Ext)
@@ -114,9 +190,9 @@ class CommandDccallow : public Command
                /* XXX we need to fix this so it can work with translation stuff (i.e. move +- into a seperate param */
        }
 
-       CmdResult Handle(const std::vector<std::string>& parameters, User* user) CXX11_OVERRIDE
+       CmdResult Handle(User* user, const Params& parameters) CXX11_OVERRIDE
        {
-               /* syntax: DCCALLOW [+|-]<nick> (<time>) */
+               /* syntax: DCCALLOW [(+|-)<nick> [<time>]]|[LIST|HELP] */
                if (!parameters.size())
                {
                        // display current DCCALLOW list
@@ -130,13 +206,13 @@ class CommandDccallow : public Command
                        // if they didn't specify an action, this is probably a command
                        if (action != '+' && action != '-')
                        {
-                               if (!strcasecmp(parameters[0].c_str(), "LIST"))
+                               if (irc::equals(parameters[0], "LIST"))
                                {
                                        // list current DCCALLOW list
                                        DisplayDCCAllowList(user);
                                        return CMD_FAILURE;
                                }
-                               else if (!strcasecmp(parameters[0].c_str(), "HELP"))
+                               else if (irc::equals(parameters[0], "HELP"))
                                {
                                        // display help
                                        DisplayHelp(user);
@@ -190,7 +266,7 @@ class CommandDccallow : public Command
                                                ul.push_back(user);
                                        }
 
-                                       if (dl->size() >= maxentries)
+                                       if (dl->size() >= ext.maxentries)
                                        {
                                                user->WriteNumeric(ERR_DCCALLOWINVALID, user->nick, "Too many nicks on DCCALLOW list");
                                                return CMD_FAILURE;
@@ -206,20 +282,23 @@ class CommandDccallow : public Command
                                        }
 
                                        std::string mask = target->nick+"!"+target->ident+"@"+target->GetDisplayedHost();
-                                       std::string default_length = ServerInstance->Config->ConfValue("dccallow")->getString("length");
-
                                        unsigned long length;
                                        if (parameters.size() < 2)
                                        {
-                                               length = InspIRCd::Duration(default_length);
+                                               length = defaultlength;
                                        }
-                                       else if (!atoi(parameters[1].c_str()))
+                                       else if (!InspIRCd::IsValidDuration(parameters[1]))
                                        {
-                                               length = 0;
+                                               user->WriteNumeric(ERR_DCCALLOWINVALID, user->nick, InspIRCd::Format("%s is not a valid DCCALLOW duration", parameters[1].c_str()));
+                                               return CMD_FAILURE;
                                        }
                                        else
                                        {
-                                               length = InspIRCd::Duration(parameters[1]);
+                                               if (!InspIRCd::Duration(parameters[1], length))
+                                               {
+                                                       user->WriteNotice("*** Invalid duration for DCC allow");
+                                                       return CMD_FAILURE;
+                                               }
                                        }
 
                                        if (!InspIRCd::IsValidMask(mask))
@@ -231,7 +310,7 @@ class CommandDccallow : public Command
 
                                        if (length > 0)
                                        {
-                                               user->WriteNumeric(RPL_DCCALLOWTIMED, user->nick, InspIRCd::Format("Added %s to DCCALLOW list for %ld seconds", target->nick.c_str(), length));
+                                               user->WriteNumeric(RPL_DCCALLOWTIMED, user->nick, InspIRCd::Format("Added %s to DCCALLOW list for %s", target->nick.c_str(), InspIRCd::DurationString(length).c_str()));
                                        }
                                        else
                                        {
@@ -252,16 +331,17 @@ class CommandDccallow : public Command
                return CMD_FAILURE;
        }
 
-       RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters) CXX11_OVERRIDE
+       RouteDescriptor GetRouting(User* user, const Params& parameters) CXX11_OVERRIDE
        {
                return ROUTE_BROADCAST;
        }
 
        void DisplayHelp(User* user)
        {
+               user->WriteNumeric(RPL_HELPSTART, "*", "DCCALLOW [(+|-)<nick> [<time>]]|[LIST|HELP]");
                for (size_t i = 0; i < sizeof(helptext)/sizeof(helptext[0]); i++)
-                       user->WriteNumeric(RPL_DCCALLOWHELP, helptext[i]);
-               user->WriteNumeric(RPL_ENDOFDCCALLOWHELP, "End of DCCALLOW HELP");
+                       user->WriteNumeric(RPL_HELPTXT, "*", helptext[i]);
+               user->WriteNumeric(RPL_ENDOFHELP, "*", "End of DCCALLOW HELP");
 
                LocalUser* localuser = IS_LOCAL(user);
                if (localuser)
@@ -291,11 +371,14 @@ class ModuleDCCAllow : public Module
 {
        DCCAllowExt ext;
        CommandDccallow cmd;
+       bool blockchat;
+       std::string defaultaction;
 
  public:
        ModuleDCCAllow()
-               : ext("dccallow", ExtensionItem::EXT_USER, this)
+               : ext(this)
                , cmd(this, ext)
+               , blockchat(false)
        {
        }
 
@@ -330,14 +413,16 @@ class ModuleDCCAllow : public Module
                        if (user == u)
                                return MOD_RES_PASSTHRU;
 
-                       if ((details.text.length()) && (details.text[0] == '\1'))
+                       std::string ctcpname;
+                       std::string ctcpbody;
+                       if (details.IsCTCP(ctcpname, ctcpbody))
                        {
                                Expire();
 
                                // :jamie!jamie@test-D4457903BA652E0F.silverdream.org PRIVMSG eimaj :DCC SEND m_dnsbl.cpp 3232235786 52650 9676
                                // :jamie!jamie@test-D4457903BA652E0F.silverdream.org PRIVMSG eimaj :VERSION
 
-                               if (strncmp(details.text.c_str(), "\1DCC ", 5) == 0)
+                               if (irc::equals(ctcpname, "DCC") && !ctcpbody.empty())
                                {
                                        dl = ext.get(u);
                                        if (dl && dl->size())
@@ -347,21 +432,17 @@ class ModuleDCCAllow : public Module
                                                                return MOD_RES_PASSTHRU;
                                        }
 
-                                       std::string buf = details.text.substr(5);
-                                       size_t s = buf.find(' ');
+                                       size_t s = ctcpbody.find(' ');
                                        if (s == std::string::npos)
                                                return MOD_RES_PASSTHRU;
 
-                                       const std::string type = buf.substr(0, s);
+                                       const std::string type = ctcpbody.substr(0, s);
 
-                                       ConfigTag* conftag = ServerInstance->Config->ConfValue("dccallow");
-                                       bool blockchat = conftag->getBool("blockchat");
-
-                                       if (stdalgo::string::equalsci(type, "SEND"))
+                                       if (irc::equals(type, "SEND"))
                                        {
                                                size_t first;
 
-                                               buf = buf.substr(s + 1);
+                                               std::string buf = ctcpbody.substr(s + 1);
 
                                                if (!buf.empty() && buf[0] == '"')
                                                {
@@ -382,7 +463,6 @@ class ModuleDCCAllow : public Module
                                                if (s == std::string::npos)
                                                        return MOD_RES_PASSTHRU;
 
-                                               std::string defaultaction = conftag->getString("action");
                                                std::string filename = buf.substr(first, s);
 
                                                bool found = false;
@@ -391,7 +471,7 @@ class ModuleDCCAllow : public Module
                                                        if (InspIRCd::Match(filename, bfl[i].filemask, ascii_case_insensitive_map))
                                                        {
                                                                /* We have a matching badfile entry, override whatever the default action is */
-                                                               if (bfl[i].action == "allow")
+                                                               if (stdalgo::string::equalsci(bfl[i].action, "allow"))
                                                                        return MOD_RES_PASSTHRU;
                                                                else
                                                                {
@@ -410,7 +490,7 @@ class ModuleDCCAllow : public Module
                                                u->WriteNotice("If you trust " + user->nick + " and were expecting this, you can type /DCCALLOW HELP for information on the DCCALLOW system.");
                                                return MOD_RES_DENY;
                                        }
-                                       else if ((blockchat) && (stdalgo::string::equalsci(type, "CHAT")))
+                                       else if (blockchat && irc::equals(type, "CHAT"))
                                        {
                                                user->WriteNotice("The user " + u->nick + " is not accepting DCC CHAT requests from you.");
                                                u->WriteNotice(user->nick + " (" + user->ident + "@" + user->GetDisplayedHost() + ") attempted to initiate a DCC CHAT session, which was blocked.");
@@ -505,23 +585,27 @@ class ModuleDCCAllow : public Module
 
        void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
        {
-               ConfigTag* tag = ServerInstance->Config->ConfValue("dccallow");
-               cmd.maxentries = tag->getUInt("maxentries", 20);
-
-               bfl.clear();
+               bannedfilelist newbfl;
                ConfigTagList tags = ServerInstance->Config->ConfTags("banfile");
                for (ConfigIter i = tags.first; i != tags.second; ++i)
                {
                        BannedFileList bf;
                        bf.filemask = i->second->getString("pattern");
                        bf.action = i->second->getString("action");
-                       bfl.push_back(bf);
+                       newbfl.push_back(bf);
                }
+               bfl.swap(newbfl);
+
+               ConfigTag* tag = ServerInstance->Config->ConfValue("dccallow");
+               cmd.ext.maxentries = tag->getUInt("maxentries", 20);
+               cmd.defaultlength = tag->getDuration("length", 0);
+               blockchat = tag->getBool("blockchat");
+               defaultaction = tag->getString("action");
        }
 
        Version GetVersion() CXX11_OVERRIDE
        {
-               return Version("Provides support for the /DCCALLOW command", VF_COMMON | VF_VENDOR);
+               return Version("Provides the DCCALLOW command", VF_COMMON | VF_VENDOR);
        }
 };