]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/commands/cmd_privmsg.cpp
135ab809e81718667bee64a7810758a654a3895d
[user/henk/code/inspircd.git] / src / commands / cmd_privmsg.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2008 InspIRCd Development Team
6  * See: http://www.inspircd.org/wiki/index.php/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 #include "commands/cmd_privmsg.h"
16
17 extern "C" DllExport  Command* init_command(InspIRCd* Instance)
18 {
19         return new CommandPrivmsg(Instance);
20 }
21
22 CmdResult CommandPrivmsg::Handle (const std::vector<std::string>& parameters, User *user)
23 {
24         User *dest;
25         Channel *chan;
26         CUList except_list;
27
28         user->idle_lastmsg = ServerInstance->Time();
29         
30         if (ServerInstance->Parser->LoopCall(user, this, parameters, 0))
31                 return CMD_SUCCESS;
32
33         if ((parameters[0][0] == '$') && (IS_OPER(user) || ServerInstance->ULine(user->server)))
34         {
35                 int MOD_RESULT = 0;
36                 std::string temp = parameters[1];
37                 FOREACH_RESULT(I_OnUserPreMessage,OnUserPreMessage(user, (void*)parameters[0].c_str(), TYPE_SERVER, temp, 0, except_list));
38                 if (MOD_RESULT)
39                         return CMD_FAILURE;
40
41                 const char* text = temp.c_str();
42                 const char* servermask = (parameters[0].c_str()) + 1;
43
44                 FOREACH_MOD(I_OnText,OnText(user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, except_list));
45                 if (InspIRCd::Match(ServerInstance->Config->ServerName, servermask, NULL))
46                 {
47                         user->SendAll("PRIVMSG", "%s", text);
48                 }
49                 FOREACH_MOD(I_OnUserMessage,OnUserMessage(user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, except_list));
50                 return CMD_SUCCESS;
51         }
52         char status = 0;
53         const char* target = parameters[0].c_str();
54
55         if (ServerInstance->Modes->FindPrefix(*target))
56         {
57                 status = *target;
58                 target++;
59         }
60         if (*target == '#')
61         {
62                 chan = ServerInstance->FindChan(target);
63
64                 except_list[user] = user->nick;
65
66                 if (chan)
67                 {
68                         if (IS_LOCAL(user))
69                         {
70                                 if ((chan->IsModeSet('n')) && (!chan->HasUser(user)))
71                                 {
72                                         user->WriteNumeric(404, "%s %s :Cannot send to channel (no external messages)", user->nick.c_str(), chan->name.c_str());
73                                         return CMD_FAILURE;
74                                 }
75                                 if ((chan->IsModeSet('m')) && (chan->GetStatus(user) < STATUS_VOICE))
76                                 {
77                                         user->WriteNumeric(404, "%s %s :Cannot send to channel (+m)", user->nick.c_str(), chan->name.c_str());
78                                         return CMD_FAILURE;
79                                 }
80                         }
81                         int MOD_RESULT = 0;
82
83                         std::string temp = parameters[1];
84                         FOREACH_RESULT(I_OnUserPreMessage,OnUserPreMessage(user,chan,TYPE_CHANNEL,temp,status,except_list));
85                         if (MOD_RESULT) {
86                                 return CMD_FAILURE;
87                         }
88                         const char* text = temp.c_str();
89
90                         /* Check again, a module may have zapped the input string */
91                         if (temp.empty())
92                         {
93                                 user->WriteNumeric(412, "%s :No text to send", user->nick.c_str());
94                                 return CMD_FAILURE;
95                         }
96
97                         FOREACH_MOD(I_OnText,OnText(user,chan,TYPE_CHANNEL,text,status,except_list));
98
99                         if (status)
100                         {
101                                 if (ServerInstance->Config->UndernetMsgPrefix)
102                                 {
103                                         chan->WriteAllExcept(user, false, status, except_list, "PRIVMSG %c%s :%c %s", status, chan->name.c_str(), status, text);
104                                 }
105                                 else
106                                 {
107                                         chan->WriteAllExcept(user, false, status, except_list, "PRIVMSG %c%s :%s", status, chan->name.c_str(), text);
108                                 }
109                         }
110                         else 
111                         {
112                                 chan->WriteAllExcept(user, false, status, except_list, "PRIVMSG %s :%s", chan->name.c_str(), text);
113                         }
114
115                         FOREACH_MOD(I_OnUserMessage,OnUserMessage(user,chan,TYPE_CHANNEL,text,status,except_list));
116                 }
117                 else
118                 {
119                         /* no such nick/channel */
120                         user->WriteNumeric(401, "%s %s :No such nick/channel", user->nick.c_str(), target);
121                         return CMD_FAILURE;
122                 }
123                 return CMD_SUCCESS;
124         }
125
126         const char* destnick = parameters[0].c_str();
127
128         if (IS_LOCAL(user))
129         {
130                 const char* targetserver = strchr(destnick, '@');
131         
132                 if (targetserver)
133                 {
134                         std::string nickonly;
135
136                         nickonly.assign(destnick, 0, targetserver - destnick + 1);
137                         dest = ServerInstance->FindNickOnly(nickonly);
138                         if (dest && strcasecmp(dest->server, targetserver + 1))
139                         {
140                                 /* Incorrect server for user */
141                                 user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
142                                 return CMD_FAILURE;
143                         }
144                 }
145                 else
146                         dest = ServerInstance->FindNickOnly(destnick);
147         }
148         else
149                 dest = ServerInstance->FindNick(destnick);
150
151         if (dest)
152         {
153                 if (parameters[1].empty())
154                 {
155                         user->WriteNumeric(412, "%s :No text to send", user->nick.c_str());
156                         return CMD_FAILURE;
157                 }
158
159                 if (IS_AWAY(dest))
160                 {
161                         /* auto respond with aweh msg */
162                         user->WriteNumeric(301, "%s %s :%s", user->nick.c_str(), dest->nick.c_str(), dest->awaymsg.c_str());
163                 }
164
165                 int MOD_RESULT = 0;
166                 
167                 std::string temp = parameters[1];
168                 FOREACH_RESULT(I_OnUserPreMessage,OnUserPreMessage(user, dest, TYPE_USER, temp, 0, except_list));
169                 if (MOD_RESULT) {
170                         return CMD_FAILURE;
171                 }
172                 const char* text = temp.c_str();
173
174                 FOREACH_MOD(I_OnText,OnText(user, dest, TYPE_USER, text, 0, except_list));
175
176                 if (IS_LOCAL(dest))
177                 {
178                         // direct write, same server
179                         user->WriteTo(dest, "PRIVMSG %s :%s", dest->nick.c_str(), text);
180                 }
181
182                 FOREACH_MOD(I_OnUserMessage,OnUserMessage(user, dest, TYPE_USER, text, 0, except_list));
183         }
184         else
185         {
186                 /* no such nick/channel */
187                 user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
188                 return CMD_FAILURE;
189         }
190         return CMD_SUCCESS;
191 }
192