]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/commands/cmd_notice.cpp
Merge pull request #92 from Robby-/insp20-headers
[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                         ModResult MOD_RESULT;
115
116                         std::string temp = parameters[1];
117                         FIRST_MOD_RESULT(OnUserPreNotice, MOD_RESULT, (user,chan,TYPE_CHANNEL,temp,status, exempt_list));
118                         if (MOD_RESULT == MOD_RES_DENY)
119                                 return CMD_FAILURE;
120
121                         const char* text = temp.c_str();
122
123                         if (temp.empty())
124                         {
125                                 user->WriteNumeric(412, "%s :No text to send", user->nick.c_str());
126                                 return CMD_FAILURE;
127                         }
128
129                         FOREACH_MOD(I_OnText,OnText(user,chan,TYPE_CHANNEL,text,status,exempt_list));
130
131                         if (status)
132                         {
133                                 if (ServerInstance->Config->UndernetMsgPrefix)
134                                 {
135                                         chan->WriteAllExcept(user, false, status, exempt_list, "NOTICE %c%s :%c %s", status, chan->name.c_str(), status, text);
136                                 }
137                                 else
138                                 {
139                                         chan->WriteAllExcept(user, false, status, exempt_list, "NOTICE %c%s :%s", status, chan->name.c_str(), text);
140                                 }
141                         }
142                         else
143                         {
144                                 chan->WriteAllExcept(user, false, status, exempt_list, "NOTICE %s :%s", chan->name.c_str(), text);
145                         }
146
147                         FOREACH_MOD(I_OnUserNotice,OnUserNotice(user,chan,TYPE_CHANNEL,text,status,exempt_list));
148                 }
149                 else
150                 {
151                         /* no such nick/channel */
152                         user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), target);
153                         return CMD_FAILURE;
154                 }
155                 return CMD_SUCCESS;
156         }
157
158         const char* destnick = parameters[0].c_str();
159
160         if (IS_LOCAL(user))
161         {
162                 const char* targetserver = strchr(destnick, '@');
163
164                 if (targetserver)
165                 {
166                         std::string nickonly;
167
168                         nickonly.assign(destnick, 0, targetserver - destnick);
169                         dest = ServerInstance->FindNickOnly(nickonly);
170                         if (dest && strcasecmp(dest->server.c_str(), targetserver + 1))
171                         {
172                                 /* Incorrect server for user */
173                                 user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
174                                 return CMD_FAILURE;
175                         }
176                 }
177                 else
178                         dest = ServerInstance->FindNickOnly(destnick);
179         }
180         else
181                 dest = ServerInstance->FindNick(destnick);
182
183         if (dest)
184         {
185                 if (parameters[1].empty())
186                 {
187                         user->WriteNumeric(412, "%s :No text to send", user->nick.c_str());
188                         return CMD_FAILURE;
189                 }
190
191                 ModResult MOD_RESULT;
192                 std::string temp = parameters[1];
193                 FIRST_MOD_RESULT(OnUserPreNotice, MOD_RESULT, (user,dest,TYPE_USER,temp,0,exempt_list));
194                 if (MOD_RESULT == MOD_RES_DENY) {
195                         return CMD_FAILURE;
196                 }
197                 const char* text = temp.c_str();
198
199                 FOREACH_MOD(I_OnText,OnText(user,dest,TYPE_USER,text,0,exempt_list));
200
201                 if (IS_LOCAL(dest))
202                 {
203                         // direct write, same server
204                         user->WriteTo(dest, "NOTICE %s :%s", dest->nick.c_str(), text);
205                 }
206
207                 FOREACH_MOD(I_OnUserNotice,OnUserNotice(user,dest,TYPE_USER,text,0,exempt_list));
208         }
209         else
210         {
211                 /* no such nick/channel */
212                 user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
213                 return CMD_FAILURE;
214         }
215
216         return CMD_SUCCESS;
217
218 }
219
220 COMMAND_INIT(CommandNotice)