]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/commands/cmd_notice.cpp
Merge pull request #308 from SaberUK/insp20-fingerprint
[user/henk/code/inspircd.git] / src / commands / cmd_notice.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
5  *   Copyright (C) 2007-2008 Craig Edwards <craigedwards@brainbox.cc>
6  *   Copyright (C) 2007 Robin Burchell <robin+git@viroteck.net>
7  *
8  * This file is part of InspIRCd.  InspIRCd is free software: you can
9  * redistribute it and/or modify it under the terms of the GNU General Public
10  * License as published by the Free Software Foundation, version 2.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
15  * details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21
22 #include "inspircd.h"
23 /** Handle /NOTICE. These command handlers can be reloaded by the core,
24  * and handle basic RFC1459 commands. Commands within modules work
25  * the same way, however, they can be fully unloaded, where these
26  * may not.
27  */
28 class CommandNotice : public Command
29 {
30  public:
31         /** Constructor for notice.
32          */
33         CommandNotice ( Module* parent) : Command(parent,"NOTICE",2,2) { syntax = "<target>{,<target>} <message>"; }
34         /** Handle command.
35          * @param parameters The parameters to the comamnd
36          * @param pcnt The number of parameters passed to teh command
37          * @param user The user issuing the command
38          * @return A value from CmdResult to indicate command success or failure.
39          */
40         CmdResult Handle(const std::vector<std::string>& parameters, User *user);
41
42         RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters)
43         {
44                 if (IS_LOCAL(user))
45                         // This is handled by the OnUserNotice hook to split the LoopCall pieces
46                         return ROUTE_LOCALONLY;
47                 else
48                         return ROUTE_MESSAGE(parameters[0]);
49         }
50 };
51
52
53 CmdResult CommandNotice::Handle (const std::vector<std::string>& parameters, User *user)
54 {
55         User *dest;
56         Channel *chan;
57
58         CUList exempt_list;
59
60         user->idle_lastmsg = ServerInstance->Time();
61
62         if (ServerInstance->Parser->LoopCall(user, this, parameters, 0))
63                 return CMD_SUCCESS;
64         if (parameters[0][0] == '$')
65         {
66                 if (!user->HasPrivPermission("users/mass-message"))
67                         return CMD_SUCCESS;
68
69                 ModResult MOD_RESULT;
70                 std::string temp = parameters[1];
71                 FIRST_MOD_RESULT(OnUserPreNotice, MOD_RESULT, (user, (void*)parameters[0].c_str(), TYPE_SERVER, temp, 0, exempt_list));
72                 if (MOD_RESULT == MOD_RES_DENY)
73                         return CMD_FAILURE;
74                 const char* text = temp.c_str();
75                 const char* servermask = (parameters[0].c_str()) + 1;
76
77                 FOREACH_MOD(I_OnText,OnText(user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, exempt_list));
78                 if (InspIRCd::Match(ServerInstance->Config->ServerName,servermask, NULL))
79                 {
80                         user->SendAll("NOTICE", "%s", text);
81                 }
82                 FOREACH_MOD(I_OnUserNotice,OnUserNotice(user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, exempt_list));
83                 return CMD_SUCCESS;
84         }
85         char status = 0;
86         const char* target = parameters[0].c_str();
87
88         if (ServerInstance->Modes->FindPrefix(*target))
89         {
90                 status = *target;
91                 target++;
92         }
93         if (*target == '#')
94         {
95                 chan = ServerInstance->FindChan(target);
96
97                 exempt_list.insert(user);
98
99                 if (chan)
100                 {
101                         if (IS_LOCAL(user))
102                         {
103                                 if ((chan->IsModeSet('n')) && (!chan->HasUser(user)))
104                                 {
105                                         user->WriteNumeric(404, "%s %s :Cannot send to channel (no external messages)", user->nick.c_str(), chan->name.c_str());
106                                         return CMD_FAILURE;
107                                 }
108                                 if ((chan->IsModeSet('m')) && (chan->GetPrefixValue(user) < VOICE_VALUE))
109                                 {
110                                         user->WriteNumeric(404, "%s %s :Cannot send to channel (+m)", user->nick.c_str(), chan->name.c_str());
111                                         return CMD_FAILURE;
112                                 }
113
114                                 if (ServerInstance->Config->RestrictBannedUsers)
115                                 {
116                                         if (chan->IsBanned(user))
117                                         {
118                                                 user->WriteNumeric(404, "%s %s :Cannot send to channel (you're banned)", user->nick.c_str(), chan->name.c_str());
119                                                 return CMD_FAILURE;
120                                         }
121                                 }
122                         }
123                         ModResult MOD_RESULT;
124
125                         std::string temp = parameters[1];
126                         FIRST_MOD_RESULT(OnUserPreNotice, MOD_RESULT, (user,chan,TYPE_CHANNEL,temp,status, exempt_list));
127                         if (MOD_RESULT == MOD_RES_DENY)
128                                 return CMD_FAILURE;
129
130                         const char* text = temp.c_str();
131
132                         if (temp.empty())
133                         {
134                                 user->WriteNumeric(412, "%s :No text to send", user->nick.c_str());
135                                 return CMD_FAILURE;
136                         }
137
138                         FOREACH_MOD(I_OnText,OnText(user,chan,TYPE_CHANNEL,text,status,exempt_list));
139
140                         if (status)
141                         {
142                                 if (ServerInstance->Config->UndernetMsgPrefix)
143                                 {
144                                         chan->WriteAllExcept(user, false, status, exempt_list, "NOTICE %c%s :%c %s", status, chan->name.c_str(), status, text);
145                                 }
146                                 else
147                                 {
148                                         chan->WriteAllExcept(user, false, status, exempt_list, "NOTICE %c%s :%s", status, chan->name.c_str(), text);
149                                 }
150                         }
151                         else
152                         {
153                                 chan->WriteAllExcept(user, false, status, exempt_list, "NOTICE %s :%s", chan->name.c_str(), text);
154                         }
155
156                         FOREACH_MOD(I_OnUserNotice,OnUserNotice(user,chan,TYPE_CHANNEL,text,status,exempt_list));
157                 }
158                 else
159                 {
160                         /* no such nick/channel */
161                         user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), target);
162                         return CMD_FAILURE;
163                 }
164                 return CMD_SUCCESS;
165         }
166
167         const char* destnick = parameters[0].c_str();
168
169         if (IS_LOCAL(user))
170         {
171                 const char* targetserver = strchr(destnick, '@');
172
173                 if (targetserver)
174                 {
175                         std::string nickonly;
176
177                         nickonly.assign(destnick, 0, targetserver - destnick);
178                         dest = ServerInstance->FindNickOnly(nickonly);
179                         if (dest && strcasecmp(dest->server.c_str(), targetserver + 1))
180                         {
181                                 /* Incorrect server for user */
182                                 user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
183                                 return CMD_FAILURE;
184                         }
185                 }
186                 else
187                         dest = ServerInstance->FindNickOnly(destnick);
188         }
189         else
190                 dest = ServerInstance->FindNick(destnick);
191
192         if (dest)
193         {
194                 if (parameters[1].empty())
195                 {
196                         user->WriteNumeric(412, "%s :No text to send", user->nick.c_str());
197                         return CMD_FAILURE;
198                 }
199
200                 ModResult MOD_RESULT;
201                 std::string temp = parameters[1];
202                 FIRST_MOD_RESULT(OnUserPreNotice, MOD_RESULT, (user,dest,TYPE_USER,temp,0,exempt_list));
203                 if (MOD_RESULT == MOD_RES_DENY) {
204                         return CMD_FAILURE;
205                 }
206                 const char* text = temp.c_str();
207
208                 FOREACH_MOD(I_OnText,OnText(user,dest,TYPE_USER,text,0,exempt_list));
209
210                 if (IS_LOCAL(dest))
211                 {
212                         // direct write, same server
213                         user->WriteTo(dest, "NOTICE %s :%s", dest->nick.c_str(), text);
214                 }
215
216                 FOREACH_MOD(I_OnUserNotice,OnUserNotice(user,dest,TYPE_USER,text,0,exempt_list));
217         }
218         else
219         {
220                 /* no such nick/channel */
221                 user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
222                 return CMD_FAILURE;
223         }
224
225         return CMD_SUCCESS;
226
227 }
228
229 COMMAND_INIT(CommandNotice)