diff options
Diffstat (limited to 'src/modules/m_dccallow.cpp')
-rw-r--r-- | src/modules/m_dccallow.cpp | 260 |
1 files changed, 137 insertions, 123 deletions
diff --git a/src/modules/m_dccallow.cpp b/src/modules/m_dccallow.cpp index 05fff8937..e0ea4c7ae 100644 --- a/src/modules/m_dccallow.cpp +++ b/src/modules/m_dccallow.cpp @@ -25,7 +25,46 @@ #include "inspircd.h" -/* $ModDesc: Provides support for the /DCCALLOW command */ +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 { @@ -40,11 +79,17 @@ class DCCAllow std::string nickname; std::string hostmask; time_t set_on; - long length; + unsigned long length; DCCAllow() { } - DCCAllow(const std::string &nick, const std::string &hm, const time_t so, const long ln) : nickname(nick), hostmask(hm), set_on(so), length(ln) { } + 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<User *> userlist; @@ -53,21 +98,26 @@ typedef std::vector<DCCAllow> dccallowlist; dccallowlist* dl; typedef std::vector<BannedFileList> bannedfilelist; bannedfilelist bfl; -SimpleExtItem<dccallowlist>* ext; +typedef SimpleExtItem<dccallowlist> DCCAllowExt; class CommandDccallow : public Command { + DCCAllowExt& ext; + public: unsigned int maxentries; - CommandDccallow(Module* parent) : Command(parent, "DCCALLOW", 0) + unsigned long defaultlength; + CommandDccallow(Module* parent, DCCAllowExt& Ext) + : Command(parent, "DCCALLOW", 0) + , ext(Ext) { syntax = "[(+|-)<nick> [<time>]]|[LIST|HELP]"; /* 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> ¶meters, User *user) + 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 @@ -95,21 +145,21 @@ class CommandDccallow : public Command } else { - user->WriteNumeric(998, "%s :DCCALLOW command not understood. For help on DCCALLOW, type /DCCALLOW HELP", user->nick.c_str()); + user->WriteNumeric(ERR_UNKNOWNDCCALLOWCMD, "DCCALLOW command not understood. For help on DCCALLOW, type /DCCALLOW HELP"); return CMD_FAILURE; } } - std::string nick = parameters[0].substr(1); + std::string nick(parameters[0], 1); User *target = ServerInstance->FindNickOnly(nick); - if ((target) && (!IS_SERVER(target)) && (!target->quitting) && (target->registered == REG_ALL)) + if ((target) && (!target->quitting) && (target->registered == REG_ALL)) { if (action == '-') { // check if it contains any entries - dl = ext->get(user); + dl = ext.get(user); if (dl) { for (dccallowlist::iterator i = dl->begin(); i != dl->end(); ++i) @@ -118,7 +168,7 @@ class CommandDccallow : public Command if (i->nickname == target->nick) { dl->erase(i); - user->WriteNumeric(995, "%s %s :Removed %s from your DCCALLOW list", user->nick.c_str(), user->nick.c_str(), target->nick.c_str()); + user->WriteNumeric(RPL_DCCALLOWREMOVED, user->nick, InspIRCd::Format("Removed %s from your DCCALLOW list", target->nick.c_str())); break; } } @@ -128,22 +178,22 @@ class CommandDccallow : public Command { if (target == user) { - user->WriteNumeric(996, "%s %s :You cannot add yourself to your own DCCALLOW list!", user->nick.c_str(), user->nick.c_str()); + user->WriteNumeric(ERR_DCCALLOWINVALID, user->nick, "You cannot add yourself to your own DCCALLOW list!"); return CMD_FAILURE; } - dl = ext->get(user); + dl = ext.get(user); if (!dl) { dl = new dccallowlist; - ext->set(user, dl); + ext.set(user, dl); // add this user to the userlist ul.push_back(user); } if (dl->size() >= maxentries) { - user->WriteNumeric(996, "%s %s :Too many nicks on DCCALLOW list", user->nick.c_str(), user->nick.c_str()); + user->WriteNumeric(ERR_DCCALLOWINVALID, user->nick, "Too many nicks on DCCALLOW list"); return CMD_FAILURE; } @@ -151,29 +201,32 @@ class CommandDccallow : public Command { if (k->nickname == target->nick) { - user->WriteNumeric(996, "%s %s :%s is already on your DCCALLOW list", user->nick.c_str(), user->nick.c_str(), target->nick.c_str()); + user->WriteNumeric(ERR_DCCALLOWINVALID, user->nick, InspIRCd::Format("%s is already on your DCCALLOW list", target->nick.c_str())); return CMD_FAILURE; } } - std::string mask = target->nick+"!"+target->ident+"@"+target->dhost; - std::string default_length = ServerInstance->Config->ConfValue("dccallow")->getString("length"); - - long length; + std::string mask = target->nick+"!"+target->ident+"@"+target->GetDisplayedHost(); + unsigned long length; if (parameters.size() < 2) { - length = ServerInstance->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 = ServerInstance->Duration(parameters[1]); + if (!InspIRCd::Duration(parameters[1], length)) + { + user->WriteNotice("*** Invalid duration for DCC allow"); + return CMD_FAILURE; + } } - if (!ServerInstance->IsValidMask(mask)) + if (!InspIRCd::IsValidMask(mask)) { return CMD_FAILURE; } @@ -182,11 +235,11 @@ class CommandDccallow : public Command if (length > 0) { - user->WriteNumeric(993, "%s %s :Added %s to DCCALLOW list for %ld seconds", user->nick.c_str(), user->nick.c_str(), 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 { - user->WriteNumeric(994, "%s %s :Added %s to DCCALLOW list for this session", user->nick.c_str(), user->nick.c_str(), target->nick.c_str()); + user->WriteNumeric(RPL_DCCALLOWPERMANENT, user->nick, InspIRCd::Format("Added %s to DCCALLOW list for this session", target->nick.c_str())); } /* route it. */ @@ -196,40 +249,24 @@ class CommandDccallow : public Command else { // nick doesn't exist - user->WriteNumeric(401, "%s %s :No such nick/channel", user->nick.c_str(), nick.c_str()); + user->WriteNumeric(Numerics::NoSuchNick(nick)); return CMD_FAILURE; } } return CMD_FAILURE; } - RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters) + RouteDescriptor GetRouting(User* user, const Params& parameters) CXX11_OVERRIDE { return ROUTE_BROADCAST; } void DisplayHelp(User* user) { - user->WriteNumeric(998, "%s :DCCALLOW [(+|-)<nick> [<time>]]|[LIST|HELP]", user->nick.c_str()); - user->WriteNumeric(998, "%s :You may allow DCCs from specific users by specifying a", user->nick.c_str()); - user->WriteNumeric(998, "%s :DCC allow for the user you want to receive DCCs from.", user->nick.c_str()); - user->WriteNumeric(998, "%s :For example, to allow the user Brain to send you inspircd.exe", user->nick.c_str()); - user->WriteNumeric(998, "%s :you would type:", user->nick.c_str()); - user->WriteNumeric(998, "%s :/DCCALLOW +Brain", user->nick.c_str()); - user->WriteNumeric(998, "%s :Brain would then be able to send you files. They would have to", user->nick.c_str()); - user->WriteNumeric(998, "%s :resend the file again if the server gave them an error message", user->nick.c_str()); - user->WriteNumeric(998, "%s :before you added them to your DCCALLOW list.", user->nick.c_str()); - user->WriteNumeric(998, "%s :DCCALLOW entries will be temporary by default, if you want to add", user->nick.c_str()); - user->WriteNumeric(998, "%s :them to your DCCALLOW list until you leave IRC, type:", user->nick.c_str()); - user->WriteNumeric(998, "%s :/DCCALLOW +Brain 0", user->nick.c_str()); - user->WriteNumeric(998, "%s :To remove the user from your DCCALLOW list, type:", user->nick.c_str()); - user->WriteNumeric(998, "%s :/DCCALLOW -Brain", user->nick.c_str()); - user->WriteNumeric(998, "%s :To see the users in your DCCALLOW list, type:", user->nick.c_str()); - user->WriteNumeric(998, "%s :/DCCALLOW LIST", user->nick.c_str()); - user->WriteNumeric(998, "%s :NOTE: If the user leaves IRC or changes their nickname", user->nick.c_str()); - user->WriteNumeric(998, "%s : they will be removed from your DCCALLOW list.", user->nick.c_str()); - user->WriteNumeric(998, "%s : your DCCALLOW list will be deleted when you leave IRC.", user->nick.c_str()); - user->WriteNumeric(999, "%s :End of DCCALLOW HELP", user->nick.c_str()); + user->WriteNumeric(RPL_HELPSTART, "*", "DCCALLOW [(+|-)<nick> [<time>]]|[LIST|HELP]"); + for (size_t i = 0; i < sizeof(helptext)/sizeof(helptext[0]); i++) + user->WriteNumeric(RPL_HELPTXT, "*", helptext[i]); + user->WriteNumeric(RPL_ENDOFHELP, "*", "End of DCCALLOW HELP"); LocalUser* localuser = IS_LOCAL(user); if (localuser) @@ -239,100 +276,78 @@ class CommandDccallow : public Command void DisplayDCCAllowList(User* user) { // display current DCCALLOW list - user->WriteNumeric(990, "%s :Users on your DCCALLOW list:", user->nick.c_str()); + user->WriteNumeric(RPL_DCCALLOWSTART, "Users on your DCCALLOW list:"); - dl = ext->get(user); + dl = ext.get(user); if (dl) { for (dccallowlist::const_iterator c = dl->begin(); c != dl->end(); ++c) { - user->WriteNumeric(991, "%s %s :%s (%s)", user->nick.c_str(), user->nick.c_str(), c->nickname.c_str(), c->hostmask.c_str()); + user->WriteNumeric(RPL_DCCALLOWLIST, user->nick, InspIRCd::Format("%s (%s)", c->nickname.c_str(), c->hostmask.c_str())); } } - user->WriteNumeric(992, "%s :End of DCCALLOW list", user->nick.c_str()); + user->WriteNumeric(RPL_DCCALLOWEND, "End of DCCALLOW list"); } }; class ModuleDCCAllow : public Module { + DCCAllowExt ext; CommandDccallow cmd; - public: + bool blockchat; + std::string defaultaction; + public: ModuleDCCAllow() - : cmd(this) + : ext("dccallow", ExtensionItem::EXT_USER, this) + , cmd(this, ext) + , blockchat(false) { - ext = NULL; } - void init() + void OnUserQuit(User* user, const std::string &reason, const std::string &oper_message) CXX11_OVERRIDE { - ext = new SimpleExtItem<dccallowlist>("dccallow", this); - ServerInstance->Modules->AddService(*ext); - ServerInstance->Modules->AddService(cmd); - OnRehash(NULL); - Implementation eventlist[] = { I_OnUserPreMessage, I_OnUserPreNotice, I_OnUserQuit, I_OnUserPostNick, I_OnRehash }; - ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation)); - } - - virtual void OnRehash(User* user) - { - ReadFileConf(); - ConfigTag* tag = ServerInstance->Config->ConfValue("dccallow"); - cmd.maxentries = tag->getInt("maxentries", 20); - } - - virtual void OnUserQuit(User* user, const std::string &reason, const std::string &oper_message) - { - dccallowlist* udl = ext->get(user); + dccallowlist* udl = ext.get(user); // remove their DCCALLOW list if they have one if (udl) - { - userlist::iterator it = std::find(ul.begin(), ul.end(), user); - if (it != ul.end()) - ul.erase(it); - } + stdalgo::erase(ul, user); // remove them from any DCCALLOW lists // they are currently on RemoveNick(user); } - virtual void OnUserPostNick(User* user, const std::string &oldnick) + void OnUserPostNick(User* user, const std::string &oldnick) CXX11_OVERRIDE { RemoveNick(user); } - virtual ModResult OnUserPreMessage(User* user, void* dest, int target_type, std::string &text, char status, CUList &exempt_list) - { - return OnUserPreNotice(user, dest, target_type, text, status, exempt_list); - } - - virtual ModResult OnUserPreNotice(User* user, void* dest, int target_type, std::string &text, char status, CUList &exempt_list) + ModResult OnUserPreMessage(User* user, const MessageTarget& target, MessageDetails& details) CXX11_OVERRIDE { if (!IS_LOCAL(user)) return MOD_RES_PASSTHRU; - if (target_type == TYPE_USER) + if (target.type == MessageTarget::TYPE_USER) { - User* u = (User*)dest; + User* u = target.Get<User>(); /* Always allow a user to dcc themselves (although... why?) */ if (user == u) return MOD_RES_PASSTHRU; - if ((text.length()) && (text[0] == '\1')) + if ((details.text.length()) && (details.text[0] == '\1')) { 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(text.c_str(), "\1DCC ", 5) == 0) + if (strncmp(details.text.c_str(), "\1DCC ", 5) == 0) { - dl = ext->get(u); + dl = ext.get(u); if (dl && dl->size()) { for (dccallowlist::const_iterator iter = dl->begin(); iter != dl->end(); ++iter) @@ -340,17 +355,14 @@ class ModuleDCCAllow : public Module return MOD_RES_PASSTHRU; } - std::string buf = text.substr(5); + std::string buf = details.text.substr(5); size_t s = buf.find(' '); if (s == std::string::npos) return MOD_RES_PASSTHRU; - irc::string type = assign(buf.substr(0, s)); - - ConfigTag* conftag = ServerInstance->Config->ConfValue("dccallow"); - bool blockchat = conftag->getBool("blockchat"); + const std::string type = buf.substr(0, s); - if (type == "SEND") + if (stdalgo::string::equalsci(type, "SEND")) { size_t first; @@ -375,7 +387,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; @@ -384,7 +395,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 { @@ -398,16 +409,16 @@ class ModuleDCCAllow : public Module if ((!found) && (defaultaction == "allow")) return MOD_RES_PASSTHRU; - user->WriteServ("NOTICE %s :The user %s is not accepting DCC SENDs from you. Your file %s was not sent.", user->nick.c_str(), u->nick.c_str(), filename.c_str()); - u->WriteServ("NOTICE %s :%s (%s@%s) attempted to send you a file named %s, which was blocked.", u->nick.c_str(), user->nick.c_str(), user->ident.c_str(), user->dhost.c_str(), filename.c_str()); - u->WriteServ("NOTICE %s :If you trust %s and were expecting this, you can type /DCCALLOW HELP for information on the DCCALLOW system.", u->nick.c_str(), user->nick.c_str()); + user->WriteNotice("The user " + u->nick + " is not accepting DCC SENDs from you. Your file " + filename + " was not sent."); + u->WriteNotice(user->nick + " (" + user->ident + "@" + user->GetDisplayedHost() + ") attempted to send you a file named " + filename + ", which was blocked."); + 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 ((type == "CHAT") && (blockchat)) + else if ((blockchat) && (stdalgo::string::equalsci(type, "CHAT"))) { - user->WriteServ("NOTICE %s :The user %s is not accepting DCC CHAT requests from you.", user->nick.c_str(), u->nick.c_str()); - u->WriteServ("NOTICE %s :%s (%s@%s) attempted to initiate a DCC CHAT session, which was blocked.", u->nick.c_str(), user->nick.c_str(), user->ident.c_str(), user->dhost.c_str()); - u->WriteServ("NOTICE %s :If you trust %s and were expecting this, you can type /DCCALLOW HELP for information on the DCCALLOW system.", u->nick.c_str(), user->nick.c_str()); + 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."); + 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; } } @@ -421,7 +432,7 @@ class ModuleDCCAllow : public Module for (userlist::iterator iter = ul.begin(); iter != ul.end();) { User* u = (User*)(*iter); - dl = ext->get(u); + dl = ext.get(u); if (dl) { if (dl->size()) @@ -429,9 +440,10 @@ class ModuleDCCAllow : public Module dccallowlist::iterator iter2 = dl->begin(); while (iter2 != dl->end()) { - if (iter2->length != 0 && (iter2->set_on + iter2->length) <= ServerInstance->Time()) + time_t expires = iter2->set_on + iter2->length; + if (iter2->length != 0 && expires <= ServerInstance->Time()) { - u->WriteNumeric(997, "%s %s :DCCALLOW entry for %s has expired", u->nick.c_str(), u->nick.c_str(), iter2->nickname.c_str()); + u->WriteNumeric(RPL_DCCALLOWEXPIRED, u->nick, InspIRCd::Format("DCCALLOW entry for %s has expired", iter2->nickname.c_str())); iter2 = dl->erase(iter2); } else @@ -455,7 +467,7 @@ class ModuleDCCAllow : public Module for (userlist::iterator iter = ul.begin(); iter != ul.end();) { User *u = (User*)(*iter); - dl = ext->get(u); + dl = ext.get(u); if (dl) { if (dl->size()) @@ -465,8 +477,8 @@ class ModuleDCCAllow : public Module if (i->nickname == user->nick) { - u->WriteServ("NOTICE %s :%s left the network or changed their nickname and has been removed from your DCCALLOW list", u->nick.c_str(), i->nickname.c_str()); - u->WriteNumeric(995, "%s %s :Removed %s from your DCCALLOW list", u->nick.c_str(), u->nick.c_str(), i->nickname.c_str()); + u->WriteNotice(i->nickname + " left the network or changed their nickname and has been removed from your DCCALLOW list"); + u->WriteNumeric(RPL_DCCALLOWREMOVED, u->nick, InspIRCd::Format("Removed %s from your DCCALLOW list", i->nickname.c_str())); dl->erase(i); break; } @@ -495,27 +507,29 @@ class ModuleDCCAllow : public Module } } - void ReadFileConf() + void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE { - 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); - virtual ~ModuleDCCAllow() - { - delete ext; + ConfigTag* tag = ServerInstance->Config->ConfValue("dccallow"); + cmd.maxentries = tag->getUInt("maxentries", 20); + cmd.defaultlength = tag->getDuration("length", 0); + blockchat = tag->getBool("blockchat"); + defaultaction = tag->getString("action"); } - virtual Version GetVersion() + 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); } }; |