]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/commands/cmd_notice.cpp
Move <performance:nouserdns> to <connect:nouserdns>.
[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         LocalUser* localuser = IS_LOCAL(user);
61         if (localuser)
62                 localuser->idle_lastmsg = ServerInstance->Time();
63
64         if (ServerInstance->Parser->LoopCall(user, this, parameters, 0))
65                 return CMD_SUCCESS;
66         if (parameters[0][0] == '$')
67         {
68                 if (!user->HasPrivPermission("users/mass-message"))
69                         return CMD_SUCCESS;
70
71                 ModResult MOD_RESULT;
72                 std::string temp = parameters[1];
73                 FIRST_MOD_RESULT(OnUserPreNotice, MOD_RESULT, (user, (void*)parameters[0].c_str(), TYPE_SERVER, temp, 0, exempt_list));
74                 if (MOD_RESULT == MOD_RES_DENY)
75                         return CMD_FAILURE;
76                 const char* text = temp.c_str();
77                 const char* servermask = (parameters[0].c_str()) + 1;
78
79                 FOREACH_MOD(I_OnText,OnText(user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, exempt_list));
80                 if (InspIRCd::Match(ServerInstance->Config->ServerName,servermask, NULL))
81                 {
82                         user->SendAll("NOTICE", "%s", text);
83                 }
84                 FOREACH_MOD(I_OnUserNotice,OnUserNotice(user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, exempt_list));
85                 return CMD_SUCCESS;
86         }
87         char status = 0;
88         const char* target = parameters[0].c_str();
89
90         if (ServerInstance->Modes->FindPrefix(*target))
91         {
92                 status = *target;
93                 target++;
94         }
95         if (*target == '#')
96         {
97                 chan = ServerInstance->FindChan(target);
98
99                 exempt_list.insert(user);
100
101                 if (chan)
102                 {
103                         if (localuser)
104                         {
105                                 if ((chan->IsModeSet('n')) && (!chan->HasUser(user)))
106                                 {
107                                         user->WriteNumeric(404, "%s %s :Cannot send to channel (no external messages)", user->nick.c_str(), chan->name.c_str());
108                                         return CMD_FAILURE;
109                                 }
110                                 if ((chan->IsModeSet('m')) && (chan->GetPrefixValue(user) < VOICE_VALUE))
111                                 {
112                                         user->WriteNumeric(404, "%s %s :Cannot send to channel (+m)", user->nick.c_str(), chan->name.c_str());
113                                         return CMD_FAILURE;
114                                 }
115
116                                 if (ServerInstance->Config->RestrictBannedUsers)
117                                 {
118                                         if (chan->IsBanned(user))
119                                         {
120                                                 user->WriteNumeric(404, "%s %s :Cannot send to channel (you're banned)", user->nick.c_str(), chan->name.c_str());
121                                                 return CMD_FAILURE;
122                                         }
123                                 }
124                         }
125                         ModResult MOD_RESULT;
126
127                         std::string temp = parameters[1];
128                         FIRST_MOD_RESULT(OnUserPreNotice, MOD_RESULT, (user,chan,TYPE_CHANNEL,temp,status, exempt_list));
129                         if (MOD_RESULT == MOD_RES_DENY)
130                                 return CMD_FAILURE;
131
132                         const char* text = temp.c_str();
133
134                         if (temp.empty())
135                         {
136                                 user->WriteNumeric(412, "%s :No text to send", user->nick.c_str());
137                                 return CMD_FAILURE;
138                         }
139
140                         FOREACH_MOD(I_OnText,OnText(user,chan,TYPE_CHANNEL,text,status,exempt_list));
141
142                         if (status)
143                         {
144                                 if (ServerInstance->Config->UndernetMsgPrefix)
145                                 {
146                                         chan->WriteAllExcept(user, false, status, exempt_list, "NOTICE %c%s :%c %s", status, chan->name.c_str(), status, text);
147                                 }
148                                 else
149                                 {
150                                         chan->WriteAllExcept(user, false, status, exempt_list, "NOTICE %c%s :%s", status, chan->name.c_str(), text);
151                                 }
152                         }
153                         else
154                         {
155                                 chan->WriteAllExcept(user, false, status, exempt_list, "NOTICE %s :%s", chan->name.c_str(), text);
156                         }
157
158                         FOREACH_MOD(I_OnUserNotice,OnUserNotice(user,chan,TYPE_CHANNEL,text,status,exempt_list));
159                 }
160                 else
161                 {
162                         /* no such nick/channel */
163                         user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), target);
164                         return CMD_FAILURE;
165                 }
166                 return CMD_SUCCESS;
167         }
168
169         const char* destnick = parameters[0].c_str();
170
171         if (localuser)
172         {
173                 const char* targetserver = strchr(destnick, '@');
174
175                 if (targetserver)
176                 {
177                         std::string nickonly;
178
179                         nickonly.assign(destnick, 0, targetserver - destnick);
180                         dest = ServerInstance->FindNickOnly(nickonly);
181                         if (dest && strcasecmp(dest->server.c_str(), targetserver + 1))
182                         {
183                                 /* Incorrect server for user */
184                                 user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
185                                 return CMD_FAILURE;
186                         }
187                 }
188                 else
189                         dest = ServerInstance->FindNickOnly(destnick);
190         }
191         else
192                 dest = ServerInstance->FindNick(destnick);
193
194         if ((dest) && (dest->registered == REG_ALL))
195         {
196                 if (parameters[1].empty())
197                 {
198                         user->WriteNumeric(412, "%s :No text to send", user->nick.c_str());
199                         return CMD_FAILURE;
200                 }
201
202                 ModResult MOD_RESULT;
203                 std::string temp = parameters[1];
204                 FIRST_MOD_RESULT(OnUserPreNotice, MOD_RESULT, (user,dest,TYPE_USER,temp,0,exempt_list));
205                 if (MOD_RESULT == MOD_RES_DENY) {
206                         return CMD_FAILURE;
207                 }
208                 const char* text = temp.c_str();
209
210                 FOREACH_MOD(I_OnText,OnText(user,dest,TYPE_USER,text,0,exempt_list));
211
212                 if (IS_LOCAL(dest))
213                 {
214                         // direct write, same server
215                         user->WriteTo(dest, "NOTICE %s :%s", dest->nick.c_str(), text);
216                 }
217
218                 FOREACH_MOD(I_OnUserNotice,OnUserNotice(user,dest,TYPE_USER,text,0,exempt_list));
219         }
220         else
221         {
222                 /* no such nick/channel */
223                 user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
224                 return CMD_FAILURE;
225         }
226
227         return CMD_SUCCESS;
228
229 }
230
231 COMMAND_INIT(CommandNotice)