/* * InspIRCd -- Internet Relay Chat Daemon * * Copyright (C) 2019 Matt Schatz * Copyright (C) 2018 linuxdaemon * Copyright (C) 2016 Adam * Copyright (C) 2013, 2017-2019 Sadie Powell * Copyright (C) 2012-2016 Attila Molnar * Copyright (C) 2012, 2014, 2019 Robby * Copyright (C) 2009-2010 Daniel De Graaf * Copyright (C) 2009 Matt Smith * Copyright (C) 2008, 2010 Craig Edwards * Copyright (C) 2008 John Brooks * Copyright (C) 2007-2008 Robin Burchell * Copyright (C) 2007-2008 Dennis Friis * Copyright (C) 2006 jamie * * 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 * License as published by the Free Software Foundation, version 2. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "inspircd.h" enum { // From ircd-ratbox. RPL_HELPSTART = 704, RPL_HELPTXT = 705, RPL_ENDOFHELP = 706, // InspIRCd-specific? RPL_DCCALLOWSTART = 990, RPL_DCCALLOWLIST = 991, RPL_DCCALLOWEND = 992, RPL_DCCALLOWTIMED = 993, RPL_DCCALLOWPERMANENT = 994, RPL_DCCALLOWREMOVED = 995, ERR_DCCALLOWINVALID = 996, RPL_DCCALLOWEXPIRED = 997, ERR_UNKNOWNDCCALLOWCMD = 998 }; static const char* const helptext[] = { "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", "you would type:", "/DCCALLOW +Brain", "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. 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:", "/DCCALLOW -Brain", "To see the users in your DCCALLOW list, type:", "/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." }; class BannedFileList { public: std::string filemask; std::string action; }; class DCCAllow { public: std::string nickname; std::string hostmask; time_t set_on; unsigned long length; DCCAllow() { } DCCAllow(const std::string& nick, const std::string& hm, time_t so, unsigned long ln) : nickname(nick) , hostmask(hm) , set_on(so) , length(ln) { } }; typedef std::vector userlist; userlist ul; typedef std::vector dccallowlist; dccallowlist* dl; typedef std::vector bannedfilelist; bannedfilelist bfl; class DCCAllowExt : public SimpleExtItem { public: unsigned int maxentries; DCCAllowExt(Module* Creator) : SimpleExtItem("dccallow", ExtensionItem::EXT_USER, Creator) { } void FromInternal(Extensible* container, const std::string& value) CXX11_OVERRIDE { LocalUser* user = IS_LOCAL(static_cast(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(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) { syntax = "[(+|-) [