]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/coremods/core_info/core_info.cpp
Fix not rejecting attempts to set snomasks with SAMODE/override.
[user/henk/code/inspircd.git] / src / coremods / core_info / core_info.cpp
index 56c3c956db04fb6e5a7577d553212127f892fdcf..24eaaae03a717899109f5dd92f4c6cc266ef6d25 100644 (file)
@@ -1,7 +1,9 @@
 /*
  * InspIRCd -- Internet Relay Chat Daemon
  *
- *   Copyright (C) 2014 Attila Molnar <attilamolnar@hush.com>
+ *   Copyright (C) 2018, 2020 Sadie Powell <sadie@witchery.services>
+ *   Copyright (C) 2018 linuxdaemon <linuxdaemon.irc@gmail.com>
+ *   Copyright (C) 2014, 2016, 2018 Attila Molnar <attilamolnar@hush.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
 #include "inspircd.h"
 #include "core_info.h"
 
+enum
+{
+       // From RFC 2812.
+       RPL_WELCOME = 1,
+       RPL_YOURHOST = 2,
+       RPL_CREATED = 3,
+       RPL_MYINFO = 4
+};
+
+RouteDescriptor ServerTargetCommand::GetRouting(User* user, const Params& parameters)
+{
+       // Parameter must be a server name, not a nickname or uuid
+       if ((!parameters.empty()) && (parameters[0].find('.') != std::string::npos))
+               return ROUTE_UNICAST(parameters[0]);
+       return ROUTE_LOCALONLY;
+}
+
 class CoreModInfo : public Module
 {
        CommandAdmin cmdadmin;
@@ -27,26 +46,139 @@ class CoreModInfo : public Module
        CommandInfo cmdinfo;
        CommandModules cmdmodules;
        CommandMotd cmdmotd;
+       CommandServList cmdservlist;
        CommandTime cmdtime;
        CommandVersion cmdversion;
+       Numeric::Numeric numeric004;
+
+       /** Returns a list of user or channel mode characters.
+        * Used for constructing the parts of the mode list in the 004 numeric.
+        * @param mt Controls whether to list user modes or channel modes
+        * @param needparam Return modes only if they require a parameter to be set
+        * @return The available mode letters that satisfy the given conditions
+       */
+       static std::string CreateModeList(ModeType mt, bool needparam = false)
+       {
+               std::string modestr;
+               for (unsigned char mode = 'A'; mode <= 'z'; mode++)
+               {
+                       ModeHandler* mh = ServerInstance->Modes.FindMode(mode, mt);
+                       if ((mh) && ((!needparam) || (mh->NeedsParam(true))))
+                               modestr.push_back(mode);
+               }
+               return modestr;
+       }
 
+       void OnServiceChange(const ServiceProvider& prov)
+       {
+               if (prov.service != SERVICE_MODE)
+                       return;
+
+               std::vector<std::string>& params = numeric004.GetParams();
+               params.erase(params.begin()+2, params.end());
+
+               // Create lists of modes
+               // 1. User modes
+               // 2. Channel modes
+               // 3. Channel modes that require a parameter when set
+               numeric004.push(CreateModeList(MODETYPE_USER));
+               numeric004.push(CreateModeList(MODETYPE_CHANNEL));
+               numeric004.push(CreateModeList(MODETYPE_CHANNEL, true));
+       }
  public:
        CoreModInfo()
-               : cmdadmin(this), cmdcommands(this), cmdinfo(this), cmdmodules(this), cmdmotd(this), cmdtime(this), cmdversion(this)
+               : cmdadmin(this)
+               , cmdcommands(this)
+               , cmdinfo(this)
+               , cmdmodules(this)
+               , cmdmotd(this)
+               , cmdservlist(this)
+               , cmdtime(this)
+               , cmdversion(this)
+               , numeric004(RPL_MYINFO)
        {
+               numeric004.push(ServerInstance->Config->ServerName);
+               numeric004.push(INSPIRCD_BRANCH);
        }
 
        void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
        {
+               // Process the escape codes in the MOTDs.
+               ConfigFileCache newmotds;
+               for (ServerConfig::ClassVector::const_iterator iter = ServerInstance->Config->Classes.begin(); iter != ServerInstance->Config->Classes.end(); ++iter)
+               {
+                       ConfigTag* tag = (*iter)->config;
+                       // Don't process the file if it has already been processed.
+                       const std::string motd = tag->getString("motd", "motd");
+                       if (newmotds.find(motd) != newmotds.end())
+                               continue;
+
+                       // We can't process the file if it doesn't exist.
+                       ConfigFileCache::iterator file = ServerInstance->Config->Files.find(motd);
+                       if (file == ServerInstance->Config->Files.end())
+                               continue;
+
+                       // Process escape codes.
+                       newmotds[file->first] = file->second;
+                       InspIRCd::ProcessColors(newmotds[file->first]);
+               }
+
+               cmdmotd.motds.swap(newmotds);
+
                ConfigTag* tag = ServerInstance->Config->ConfValue("admin");
                cmdadmin.AdminName = tag->getString("name");
                cmdadmin.AdminEmail = tag->getString("email", "null@example.com");
                cmdadmin.AdminNick = tag->getString("nick", "admin");
        }
 
+       void OnUserConnect(LocalUser* user) CXX11_OVERRIDE
+       {
+               user->WriteNumeric(RPL_WELCOME, InspIRCd::Format("Welcome to the %s IRC Network %s", ServerInstance->Config->Network.c_str(), user->GetFullRealHost().c_str()));
+               user->WriteNumeric(RPL_YOURHOST, InspIRCd::Format("Your host is %s, running version %s", ServerInstance->Config->GetServerName().c_str(), INSPIRCD_BRANCH));
+               user->WriteNumeric(RPL_CREATED, InspIRCd::TimeString(ServerInstance->startup_time, "This server was created %H:%M:%S %b %d %Y"));
+               user->WriteNumeric(numeric004);
+
+               ServerInstance->ISupport.SendTo(user);
+
+               /* Trigger MOTD and LUSERS output, give modules a chance too */
+               ModResult MOD_RESULT;
+               std::string command("LUSERS");
+               CommandBase::Params parameters;
+               FIRST_MOD_RESULT(OnPreCommand, MOD_RESULT, (command, parameters, user, true));
+               if (!MOD_RESULT)
+                       ServerInstance->Parser.CallHandler(command, parameters, user);
+
+               MOD_RESULT = MOD_RES_PASSTHRU;
+               command = "MOTD";
+               FIRST_MOD_RESULT(OnPreCommand, MOD_RESULT, (command, parameters, user, true));
+               if (!MOD_RESULT)
+                       ServerInstance->Parser.CallHandler(command, parameters, user);
+
+               if (ServerInstance->Config->RawLog)
+               {
+                       ClientProtocol::Messages::Privmsg rawlogmsg(ServerInstance->FakeClient, user, "*** Raw I/O logging is enabled on this server. All messages, passwords, and commands are being recorded.");
+                       user->Send(ServerInstance->GetRFCEvents().privmsg, rawlogmsg);
+               }
+       }
+
+       void OnServiceAdd(ServiceProvider& service) CXX11_OVERRIDE
+       {
+               OnServiceChange(service);
+       }
+
+       void OnServiceDel(ServiceProvider& service) CXX11_OVERRIDE
+       {
+               OnServiceChange(service);
+       }
+
+       void Prioritize() CXX11_OVERRIDE
+       {
+               ServerInstance->Modules.SetPriority(this, I_OnUserConnect, PRIORITY_FIRST);
+       }
+
        Version GetVersion() CXX11_OVERRIDE
        {
-               return Version("Provides the ADMIN, COMMANDS, INFO, MODULES, MOTD, TIME and VERSION commands", VF_VENDOR|VF_CORE);
+               return Version("Provides the ADMIN, COMMANDS, INFO, MODULES, MOTD, TIME, SERVLIST, and VERSION commands", VF_VENDOR|VF_CORE);
        }
 };