2 * InspIRCd -- Internet Relay Chat Daemon
4 * Copyright (C) 2018 linuxdaemon <linuxdaemon.irc@gmail.com>
5 * Copyright (C) 2013, 2017-2018, 2020 Sadie Powell <sadie@witchery.services>
6 * Copyright (C) 2012, 2019 Robby <robby@chatbelgie.be>
7 * Copyright (C) 2012, 2015-2016 Attila Molnar <attilamolnar@hush.com>
8 * Copyright (C) 2010 Craig Edwards <brain@inspircd.org>
9 * Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
10 * Copyright (C) 2007 Robin Burchell <robin+git@viroteck.net>
11 * Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
13 * This file is part of InspIRCd. InspIRCd is free software: you can
14 * redistribute it and/or modify it under the terms of the GNU General Public
15 * License as published by the Free Software Foundation, version 2.
17 * This program is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
22 * You should have received a copy of the GNU General Public License
23 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "modules/whois.h"
33 RPL_WHOISSPECIAL = 320
38 const std::string name;
39 const std::string password;
40 const std::string hash;
41 const std::string host;
42 const std::string title;
43 const std::string vhost;
45 CustomTitle(const std::string& n, const std::string& p, const std::string& h, const std::string& hst, const std::string& t, const std::string& v)
55 bool MatchUser(User* user) const
57 const std::string userHost = user->ident + "@" + user->GetRealHost();
58 const std::string userIP = user->ident + "@" + user->GetIPString();
59 return InspIRCd::MatchMask(host, userHost, userIP);
62 bool CheckPass(User* user, const std::string& pass) const
64 return ServerInstance->PassCompare(user, password, pass, hash);
68 typedef std::multimap<std::string, CustomTitle> CustomVhostMap;
69 typedef std::pair<CustomVhostMap::iterator, CustomVhostMap::iterator> MatchingConfigs;
73 class CommandTitle : public Command
77 CustomVhostMap configs;
79 CommandTitle(Module* Creator) : Command(Creator,"TITLE", 2),
80 ctitle("ctitle", ExtensionItem::EXT_USER, Creator)
82 syntax = "<username> <password>";
85 CmdResult Handle(User* user, const Params& parameters) CXX11_OVERRIDE
87 MatchingConfigs matching = configs.equal_range(parameters[0]);
89 for (MatchingConfigs::first_type i = matching.first; i != matching.second; ++i)
91 CustomTitle config = i->second;
92 if (config.MatchUser(user) && config.CheckPass(user, parameters[1]))
94 ctitle.set(user, config.title);
96 ServerInstance->PI->SendMetaData(user, "ctitle", config.title);
98 if (!config.vhost.empty())
99 user->ChangeDisplayedHost(config.vhost);
101 user->WriteNotice("Custom title set to '" + config.title + "'");
107 user->WriteNotice("Invalid title credentials");
113 class ModuleCustomTitle : public Module, public Whois::LineEventListener
119 : Whois::LineEventListener(this)
124 void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
126 ConfigTagList tags = ServerInstance->Config->ConfTags("title");
127 CustomVhostMap newtitles;
128 for (ConfigIter i = tags.first; i != tags.second; ++i)
130 reference<ConfigTag> tag = i->second;
131 std::string name = tag->getString("name", "", 1);
133 throw ModuleException("<title:name> is empty at " + tag->getTagLocation());
135 std::string pass = tag->getString("password");
137 throw ModuleException("<title:password> is empty at " + tag->getTagLocation());
139 const std::string hash = tag->getString("hash", "plaintext", 1);
140 if (stdalgo::string::equalsci(hash, "plaintext"))
142 ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "<title> tag for %s at %s contains an plain text password, this is insecure!",
143 name.c_str(), tag->getTagLocation().c_str());
146 std::string host = tag->getString("host", "*@*", 1);
147 std::string title = tag->getString("title");
148 std::string vhost = tag->getString("vhost");
149 CustomTitle config(name, pass, hash, host, title, vhost);
150 newtitles.insert(std::make_pair(name, config));
152 cmd.configs.swap(newtitles);
155 // :kenny.chatspike.net 320 Brain Azhrarn :is getting paid to play games.
156 ModResult OnWhoisLine(Whois::Context& whois, Numeric::Numeric& numeric) CXX11_OVERRIDE
158 /* We use this and not OnWhois because this triggers for remote, too */
159 if (numeric.GetNumeric() == 312)
161 /* Insert our numeric before 312 */
162 const std::string* ctitle = cmd.ctitle.get(whois.GetTarget());
165 whois.SendLine(RPL_WHOISSPECIAL, ctitle);
168 /* Don't block anything */
169 return MOD_RES_PASSTHRU;
172 Version GetVersion() CXX11_OVERRIDE
174 return Version("Allows the server administrator to define accounts which can grant a custom title in /WHOIS and an optional virtual host.", VF_OPTCOMMON | VF_VENDOR);
178 MODULE_INIT(ModuleCustomTitle)