1 /*
2  * Copyright (C) 2004-2020 ZNC, see the NOTICE file for details.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <znc/User.h>
18 #include <znc/IRCNetwork.h>
19 
20 using std::vector;
21 using std::map;
22 
23 class CSendRaw_Mod : public CModule {
SendClient(const CString & sLine)24     void SendClient(const CString& sLine) {
25         CUser* pUser = CZNC::Get().FindUser(sLine.Token(1));
26 
27         if (pUser) {
28             CIRCNetwork* pNetwork = pUser->FindNetwork(sLine.Token(2));
29 
30             if (pNetwork) {
31                 pNetwork->PutUser(sLine.Token(3, true));
32                 PutModule(t_f("Sent [{1}] to {2}/{3}")(sLine.Token(3, true),
33                                                        pUser->GetUsername(),
34                                                        pNetwork->GetName()));
35             } else {
36                 PutModule(t_f("Network {1} not found for user {2}")(
37                     sLine.Token(2), sLine.Token(1)));
38             }
39         } else {
40             PutModule(t_f("User {1} not found")(sLine.Token(1)));
41         }
42     }
43 
SendServer(const CString & sLine)44     void SendServer(const CString& sLine) {
45         CUser* pUser = CZNC::Get().FindUser(sLine.Token(1));
46 
47         if (pUser) {
48             CIRCNetwork* pNetwork = pUser->FindNetwork(sLine.Token(2));
49 
50             if (pNetwork) {
51                 pNetwork->PutIRC(sLine.Token(3, true));
52                 PutModule(t_f("Sent [{1}] to IRC server of {2}/{3}")(
53                     sLine.Token(3, true), pUser->GetUsername(),
54                     pNetwork->GetName()));
55             } else {
56                 PutModule(t_f("Network {1} not found for user {2}")(
57                     sLine.Token(2), sLine.Token(1)));
58             }
59         } else {
60             PutModule(t_f("User {1} not found")(sLine.Token(1)));
61         }
62     }
63 
CurrentClient(const CString & sLine)64     void CurrentClient(const CString& sLine) {
65         CString sData = sLine.Token(1, true);
66         GetClient()->PutClient(sData);
67     }
68 
69   public:
~CSendRaw_Mod()70     ~CSendRaw_Mod() override {}
71 
OnLoad(const CString & sArgs,CString & sErrorMsg)72     bool OnLoad(const CString& sArgs, CString& sErrorMsg) override {
73         if (!GetUser()->IsAdmin()) {
74             sErrorMsg =
75                 t_s("You must have admin privileges to load this module");
76             return false;
77         }
78 
79         return true;
80     }
81 
GetWebMenuTitle()82     CString GetWebMenuTitle() override { return t_s("Send Raw"); }
WebRequiresAdmin()83     bool WebRequiresAdmin() override { return true; }
84 
OnWebRequest(CWebSock & WebSock,const CString & sPageName,CTemplate & Tmpl)85     bool OnWebRequest(CWebSock& WebSock, const CString& sPageName,
86                       CTemplate& Tmpl) override {
87         if (sPageName == "index") {
88             if (WebSock.IsPost()) {
89                 CUser* pUser = CZNC::Get().FindUser(
90                     WebSock.GetParam("network").Token(0, false, "/"));
91                 if (!pUser) {
92                     WebSock.GetSession()->AddError(t_s("User not found"));
93                     return true;
94                 }
95 
96                 CIRCNetwork* pNetwork = pUser->FindNetwork(
97                     WebSock.GetParam("network").Token(1, false, "/"));
98                 if (!pNetwork) {
99                     WebSock.GetSession()->AddError(t_s("Network not found"));
100                     return true;
101                 }
102 
103                 bool bToServer = WebSock.GetParam("send_to") == "server";
104                 const CString sLine = WebSock.GetParam("line");
105 
106                 Tmpl["user"] = pUser->GetUsername();
107                 Tmpl[bToServer ? "to_server" : "to_client"] = "true";
108                 Tmpl["line"] = sLine;
109 
110                 if (bToServer) {
111                     pNetwork->PutIRC(sLine);
112                 } else {
113                     pNetwork->PutUser(sLine);
114                 }
115 
116                 WebSock.GetSession()->AddSuccess(t_s("Line sent"));
117             }
118 
119             const map<CString, CUser*>& msUsers = CZNC::Get().GetUserMap();
120             for (const auto& it : msUsers) {
121                 CTemplate& l = Tmpl.AddRow("UserLoop");
122                 l["Username"] = it.second->GetUsername();
123 
124                 vector<CIRCNetwork*> vNetworks = it.second->GetNetworks();
125                 for (const CIRCNetwork* pNetwork : vNetworks) {
126                     CTemplate& NetworkLoop = l.AddRow("NetworkLoop");
127                     NetworkLoop["Username"] = it.second->GetUsername();
128                     NetworkLoop["Network"] = pNetwork->GetName();
129                 }
130             }
131 
132             return true;
133         }
134 
135         return false;
136     }
137 
MODCONSTRUCTOR(CSendRaw_Mod)138     MODCONSTRUCTOR(CSendRaw_Mod) {
139         AddHelpCommand();
140         AddCommand("Client", t_d("[user] [network] [data to send]"),
141                    t_d("The data will be sent to the user's IRC client(s)"),
142                    [=](const CString& sLine) { SendClient(sLine); });
143         AddCommand("Server", t_d("[user] [network] [data to send]"),
144                    t_d("The data will be sent to the IRC server the user is "
145                        "connected to"),
146                    [=](const CString& sLine) { SendServer(sLine); });
147         AddCommand("Current", t_d("[data to send]"),
148                    t_d("The data will be sent to your current client"),
149                    [=](const CString& sLine) { CurrentClient(sLine); });
150     }
151 };
152 
153 template <>
TModInfo(CModInfo & Info)154 void TModInfo<CSendRaw_Mod>(CModInfo& Info) {
155     Info.SetWikiPage("send_raw");
156 }
157 
158 USERMODULEDEFS(CSendRaw_Mod,
159                t_s("Lets you send some raw IRC lines as/to someone else"))
160