]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/commands/cmd_notice.cpp
Allow <connect motd> to select an alternate MOTD file to display
[user/henk/code/inspircd.git] / src / commands / cmd_notice.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2010 InspIRCd Development Team
6  * See: http://wiki.inspircd.org/Credits
7  *
8  * This program is free but copyrighted software; see
9  *            the file COPYING for details.
10  *
11  * ---------------------------------------------------
12  */
13
14 #include "inspircd.h"
15 /** Handle /NOTICE. These command handlers can be reloaded by the core,
16  * and handle basic RFC1459 commands. Commands within modules work
17  * the same way, however, they can be fully unloaded, where these
18  * may not.
19  */
20 class CommandNotice : public Command
21 {
22  public:
23         /** Constructor for notice.
24          */
25         CommandNotice ( Module* parent) : Command(parent,"NOTICE",2,2) { syntax = "<target>{,<target>} <message>"; }
26         /** Handle command.
27          * @param parameters The parameters to the comamnd
28          * @param pcnt The number of parameters passed to teh command
29          * @param user The user issuing the command
30          * @return A value from CmdResult to indicate command success or failure.
31          */
32         CmdResult Handle(const std::vector<std::string>& parameters, User *user);
33
34         RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters)
35         {
36                 if (IS_LOCAL(user))
37                         // This is handled by the OnUserNotice hook to split the LoopCall pieces
38                         return ROUTE_LOCALONLY;
39                 else
40                         return ROUTE_MESSAGE(parameters[0]);
41         }
42 };
43
44
45 CmdResult CommandNotice::Handle (const std::vector<std::string>& parameters, User *user)
46 {
47         User *dest;
48         Channel *chan;
49
50         CUList exempt_list;
51
52         user->idle_lastmsg = ServerInstance->Time();
53
54         if (ServerInstance->Parser->LoopCall(user, this, parameters, 0))
55                 return CMD_SUCCESS;
56         if (parameters[0][0] == '$')
57         {
58                 if (!user->HasPrivPermission("users/mass-message"))
59                         return CMD_SUCCESS;
60
61                 ModResult MOD_RESULT;
62                 std::string temp = parameters[1];
63                 FIRST_MOD_RESULT(OnUserPreNotice, MOD_RESULT, (user, (void*)parameters[0].c_str(), TYPE_SERVER, temp, 0, exempt_list));
64                 if (MOD_RESULT == MOD_RES_DENY)
65                         return CMD_FAILURE;
66                 const char* text = temp.c_str();
67                 const char* servermask = (parameters[0].c_str()) + 1;
68
69                 FOREACH_MOD(I_OnText,OnText(user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, exempt_list));
70                 if (InspIRCd::Match(ServerInstance->Config->ServerName,servermask, NULL))
71                 {
72                         user->SendAll("NOTICE", "%s", text);
73                 }
74                 FOREACH_MOD(I_OnUserNotice,OnUserNotice(user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, exempt_list));
75                 return CMD_SUCCESS;
76         }
77         char status = 0;
78         const char* target = parameters[0].c_str();
79
80         if (ServerInstance->Modes->FindPrefix(*target))
81         {
82                 status = *target;
83                 target++;
84         }
85         if (*target == '#')
86         {
87                 chan = ServerInstance->FindChan(target);
88
89                 exempt_list.insert(user);
90
91                 if (chan)
92                 {
93                         if (IS_LOCAL(user))
94                         {
95                                 if ((chan->IsModeSet('n')) && (!chan->HasUser(user)))
96                                 {
97                                         user->WriteNumeric(404, "%s %s :Cannot send to channel (no external messages)", user->nick.c_str(), chan->name.c_str());
98                                         return CMD_FAILURE;
99                                 }
100                                 if ((chan->IsModeSet('m')) && (chan->GetPrefixValue(user) < VOICE_VALUE))
101                                 {
102                                         user->WriteNumeric(404, "%s %s :Cannot send to channel (+m)", user->nick.c_str(), chan->name.c_str());
103                                         return CMD_FAILURE;
104                                 }
105                         }
106                         ModResult MOD_RESULT;
107
108                         std::string temp = parameters[1];
109                         FIRST_MOD_RESULT(OnUserPreNotice, MOD_RESULT, (user,chan,TYPE_CHANNEL,temp,status, exempt_list));
110                         if (MOD_RESULT == MOD_RES_DENY)
111                                 return CMD_FAILURE;
112
113                         const char* text = temp.c_str();
114
115                         if (temp.empty())
116                         {
117                                 user->WriteNumeric(412, "%s :No text to send", user->nick.c_str());
118                                 return CMD_FAILURE;
119                         }
120
121                         FOREACH_MOD(I_OnText,OnText(user,chan,TYPE_CHANNEL,text,status,exempt_list));
122
123                         if (status)
124                         {
125                                 if (ServerInstance->Config->UndernetMsgPrefix)
126                                 {
127                                         chan->WriteAllExcept(user, false, status, exempt_list, "NOTICE %c%s :%c %s", status, chan->name.c_str(), status, text);
128                                 }
129                                 else
130                                 {
131                                         chan->WriteAllExcept(user, false, status, exempt_list, "NOTICE %c%s :%s", status, chan->name.c_str(), text);
132                                 }
133                         }
134                         else
135                         {
136                                 chan->WriteAllExcept(user, false, status, exempt_list, "NOTICE %s :%s", chan->name.c_str(), text);
137                         }
138
139                         FOREACH_MOD(I_OnUserNotice,OnUserNotice(user,chan,TYPE_CHANNEL,text,status,exempt_list));
140                 }
141                 else
142                 {
143                         /* no such nick/channel */
144                         user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), target);
145                         return CMD_FAILURE;
146                 }
147                 return CMD_SUCCESS;
148         }
149
150         const char* destnick = parameters[0].c_str();
151
152         if (IS_LOCAL(user))
153         {
154                 const char* targetserver = strchr(destnick, '@');
155
156                 if (targetserver)
157                 {
158                         std::string nickonly;
159
160                         nickonly.assign(destnick, 0, targetserver - destnick);
161                         dest = ServerInstance->FindNickOnly(nickonly);
162                         if (dest && strcasecmp(dest->server.c_str(), targetserver + 1))
163                         {
164                                 /* Incorrect server for user */
165                                 user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
166                                 return CMD_FAILURE;
167                         }
168                 }
169                 else
170                         dest = ServerInstance->FindNickOnly(destnick);
171         }
172         else
173                 dest = ServerInstance->FindNick(destnick);
174
175         if (dest)
176         {
177                 if (parameters[1].empty())
178                 {
179                         user->WriteNumeric(412, "%s :No text to send", user->nick.c_str());
180                         return CMD_FAILURE;
181                 }
182
183                 ModResult MOD_RESULT;
184                 std::string temp = parameters[1];
185                 FIRST_MOD_RESULT(OnUserPreNotice, MOD_RESULT, (user,dest,TYPE_USER,temp,0,exempt_list));
186                 if (MOD_RESULT == MOD_RES_DENY) {
187                         return CMD_FAILURE;
188                 }
189                 const char* text = temp.c_str();
190
191                 FOREACH_MOD(I_OnText,OnText(user,dest,TYPE_USER,text,0,exempt_list));
192
193                 if (IS_LOCAL(dest))
194                 {
195                         // direct write, same server
196                         user->WriteTo(dest, "NOTICE %s :%s", dest->nick.c_str(), text);
197                 }
198
199                 FOREACH_MOD(I_OnUserNotice,OnUserNotice(user,dest,TYPE_USER,text,0,exempt_list));
200         }
201         else
202         {
203                 /* no such nick/channel */
204                 user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
205                 return CMD_FAILURE;
206         }
207
208         return CMD_SUCCESS;
209
210 }
211
212 COMMAND_INIT(CommandNotice)