]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_spanningtree/postcommand.cpp
Sync helpop chmodes s and p with docs
[user/henk/code/inspircd.git] / src / modules / m_spanningtree / postcommand.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2013-2016 Attila Molnar <attilamolnar@hush.com>
5  *   Copyright (C) 2013, 2018-2019 Sadie Powell <sadie@witchery.services>
6  *   Copyright (C) 2012 Robby <robby@chatbelgie.be>
7  *   Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
8  *   Copyright (C) 2007 Craig Edwards <brain@inspircd.org>
9  *
10  * This file is part of InspIRCd.  InspIRCd is free software: you can
11  * redistribute it and/or modify it under the terms of the GNU General Public
12  * License as published by the Free Software Foundation, version 2.
13  *
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
17  * details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  */
22
23 #include "inspircd.h"
24
25 #include "main.h"
26 #include "utils.h"
27 #include "treeserver.h"
28 #include "commandbuilder.h"
29
30 void ModuleSpanningTree::OnPostCommand(Command* command, const CommandBase::Params& parameters, LocalUser* user, CmdResult result, bool loop)
31 {
32         if (result == CMD_SUCCESS)
33                 Utils->RouteCommand(NULL, command, parameters, user);
34 }
35
36 void SpanningTreeUtilities::RouteCommand(TreeServer* origin, CommandBase* thiscmd, const CommandBase::Params& parameters, User* user)
37 {
38         const std::string& command = thiscmd->name;
39         RouteDescriptor routing = thiscmd->GetRouting(user, parameters);
40         if (routing.type == ROUTE_TYPE_LOCALONLY)
41                 return;
42
43         const bool encap = ((routing.type == ROUTE_TYPE_OPT_BCAST) || (routing.type == ROUTE_TYPE_OPT_UCAST));
44         CmdBuilder params(user, encap ? "ENCAP" : command.c_str());
45         params.push_tags(parameters.GetTags());
46         TreeServer* sdest = NULL;
47
48         if (routing.type == ROUTE_TYPE_OPT_BCAST)
49         {
50                 params.push('*');
51                 params.push(command);
52         }
53         else if (routing.type == ROUTE_TYPE_UNICAST || routing.type == ROUTE_TYPE_OPT_UCAST)
54         {
55                 sdest = static_cast<TreeServer*>(routing.server);
56                 if (!sdest)
57                 {
58                         // Assume the command handler already validated routing.serverdest and have only returned success if the target is something that the
59                         // user executing the command is allowed to look up e.g. target is not an uuid if user is local.
60                         sdest = FindRouteTarget(routing.serverdest);
61                         if (!sdest)
62                         {
63                                 ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Trying to route %s%s to nonexistent server %s", (encap ? "ENCAP " : ""), command.c_str(), routing.serverdest.c_str());
64                                 return;
65                         }
66                 }
67
68                 if (encap)
69                 {
70                         params.push(sdest->GetId());
71                         params.push(command);
72                 }
73         }
74         else
75         {
76                 Module* srcmodule = thiscmd->creator;
77                 Version ver = srcmodule->GetVersion();
78
79                 if (!(ver.Flags & (VF_COMMON | VF_CORE)) && srcmodule != Creator)
80                 {
81                         ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Routed command %s from non-VF_COMMON module %s",
82                                 command.c_str(), srcmodule->ModuleSourceFile.c_str());
83                         return;
84                 }
85         }
86
87         std::string output_text = CommandParser::TranslateUIDs(thiscmd->translation, parameters, true, thiscmd);
88
89         params.push(output_text);
90
91         if (routing.type == ROUTE_TYPE_MESSAGE)
92         {
93                 char pfx = 0;
94                 std::string dest = routing.serverdest;
95                 if (ServerInstance->Modes->FindPrefix(dest[0]))
96                 {
97                         pfx = dest[0];
98                         dest.erase(dest.begin());
99                 }
100                 if (dest[0] == '#')
101                 {
102                         Channel* c = ServerInstance->FindChan(dest);
103                         if (!c)
104                                 return;
105                         // TODO OnBuildExemptList hook was here
106                         CUList exempts;
107                         std::string message;
108                         if (parameters.size() >= 2)
109                                 message.assign(parameters[1]);
110                         SendChannelMessage(user, c, message, pfx, parameters.GetTags(), exempts, command.c_str(), origin ? origin->GetSocket() : NULL);
111                 }
112                 else if (dest[0] == '$')
113                 {
114                         params.Forward(origin);
115                 }
116                 else
117                 {
118                         // user target?
119                         User* d = ServerInstance->FindNick(dest);
120                         if (!d || IS_LOCAL(d))
121                                 return;
122                         TreeServer* tsd = TreeServer::Get(d)->GetRoute();
123                         if (tsd == origin)
124                                 // huh? no routing stuff around in a circle, please.
125                                 return;
126                         params.Unicast(d);
127                 }
128         }
129         else if (routing.type == ROUTE_TYPE_BROADCAST || routing.type == ROUTE_TYPE_OPT_BCAST)
130         {
131                 params.Forward(origin);
132         }
133         else if (routing.type == ROUTE_TYPE_UNICAST || routing.type == ROUTE_TYPE_OPT_UCAST)
134         {
135                 params.Unicast(sdest->ServerUser);
136         }
137 }