]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/coremods/core_whois.cpp
Move src/commands/cmd_*.cpp to src/coremods[/core_*]/
[user/henk/code/inspircd.git] / src / coremods / core_whois.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
5  *   Copyright (C) 2008 Thomas Stagner <aquanight@inspircd.org>
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
24 /** Handle /WHOIS.
25  */
26 class CommandWhois : public SplitCommand
27 {
28         ChanModeReference secretmode;
29         ChanModeReference privatemode;
30         UserModeReference snomaskmode;
31
32         void SplitChanList(User* source, User* dest, const std::string& cl);
33         void DoWhois(User* user, User* dest, unsigned long signon, unsigned long idle);
34         std::string ChannelList(User* source, User* dest, bool spy);
35
36  public:
37         /** Constructor for whois.
38          */
39         CommandWhois(Module* parent)
40                 : SplitCommand(parent, "WHOIS", 1)
41                 , secretmode(parent, "secret")
42                 , privatemode(parent, "private")
43                 , snomaskmode(parent, "snomask")
44         {
45                 Penalty = 2;
46                 syntax = "<nick>{,<nick>}";
47         }
48
49         /** Handle command.
50          * @param parameters The parameters to the command
51          * @param user The user issuing the command
52          * @return A value from CmdResult to indicate command success or failure.
53          */
54         CmdResult HandleLocal(const std::vector<std::string>& parameters, LocalUser* user);
55         CmdResult HandleRemote(const std::vector<std::string>& parameters, RemoteUser* target);
56 };
57
58 std::string CommandWhois::ChannelList(User* source, User* dest, bool spy)
59 {
60         std::string list;
61
62         for (UCListIter i = dest->chans.begin(); i != dest->chans.end(); i++)
63         {
64                 Membership* memb = *i;
65                 Channel* c = memb->chan;
66                 /* If the target is the sender, neither +p nor +s is set, or
67                  * the channel contains the user, it is not a spy channel
68                  */
69                 if (spy != (source == dest || !(c->IsModeSet(privatemode) || c->IsModeSet(secretmode)) || c->HasUser(source)))
70                 {
71                         list.push_back(memb->GetPrefixChar());
72                         list.append(c->name).push_back(' ');
73                 }
74         }
75
76         return list;
77 }
78
79 void CommandWhois::SplitChanList(User* source, User* dest, const std::string& cl)
80 {
81         std::string line;
82         std::ostringstream prefix;
83         std::string::size_type start, pos;
84
85         prefix << dest->nick << " :";
86         line = prefix.str();
87         int namelen = ServerInstance->Config->ServerName.length() + 6;
88
89         for (start = 0; (pos = cl.find(' ', start)) != std::string::npos; start = pos+1)
90         {
91                 if (line.length() + namelen + pos - start > 510)
92                 {
93                         ServerInstance->SendWhoisLine(source, dest, 319, line);
94                         line = prefix.str();
95                 }
96
97                 line.append(cl.substr(start, pos - start + 1));
98         }
99
100         if (line.length() != prefix.str().length())
101         {
102                 ServerInstance->SendWhoisLine(source, dest, 319, line);
103         }
104 }
105
106 void CommandWhois::DoWhois(User* user, User* dest, unsigned long signon, unsigned long idle)
107 {
108         ServerInstance->SendWhoisLine(user, dest, 311, "%s %s %s * :%s", dest->nick.c_str(), dest->ident.c_str(), dest->dhost.c_str(), dest->fullname.c_str());
109         if (user == dest || user->HasPrivPermission("users/auspex"))
110         {
111                 ServerInstance->SendWhoisLine(user, dest, 378, "%s :is connecting from %s@%s %s", dest->nick.c_str(), dest->ident.c_str(), dest->host.c_str(), dest->GetIPString().c_str());
112         }
113
114         std::string cl = ChannelList(user, dest, false);
115         const ServerConfig::OperSpyWhoisState state = user->HasPrivPermission("users/auspex") ? ServerInstance->Config->OperSpyWhois : ServerConfig::SPYWHOIS_NONE;
116
117         if (state == ServerConfig::SPYWHOIS_SINGLEMSG)
118                 cl.append(ChannelList(user, dest, true));
119
120         SplitChanList(user, dest, cl);
121
122         if (state == ServerConfig::SPYWHOIS_SPLITMSG)
123         {
124                 std::string scl = ChannelList(user, dest, true);
125                 if (scl.length())
126                 {
127                         ServerInstance->SendWhoisLine(user, dest, 336, "%s :is on private/secret channels:", dest->nick.c_str());
128                         SplitChanList(user, dest, scl);
129                 }
130         }
131         if (user != dest && !ServerInstance->Config->HideWhoisServer.empty() && !user->HasPrivPermission("servers/auspex"))
132         {
133                 ServerInstance->SendWhoisLine(user, dest, 312, "%s %s :%s", dest->nick.c_str(), ServerInstance->Config->HideWhoisServer.c_str(), ServerInstance->Config->Network.c_str());
134         }
135         else
136         {
137                 ServerInstance->SendWhoisLine(user, dest, 312, "%s %s :%s", dest->nick.c_str(), dest->server->GetName().c_str(), dest->server->GetDesc().c_str());
138         }
139
140         if (dest->IsAway())
141         {
142                 ServerInstance->SendWhoisLine(user, dest, 301, "%s :%s", dest->nick.c_str(), dest->awaymsg.c_str());
143         }
144
145         if (dest->IsOper())
146         {
147                 if (ServerInstance->Config->GenericOper)
148                         ServerInstance->SendWhoisLine(user, dest, 313, "%s :is an IRC operator", dest->nick.c_str());
149                 else
150                         ServerInstance->SendWhoisLine(user, dest, 313, "%s :is %s %s on %s", dest->nick.c_str(), (strchr("AEIOUaeiou",dest->oper->name[0]) ? "an" : "a"),dest->oper->name.c_str(), ServerInstance->Config->Network.c_str());
151         }
152
153         if (user == dest || user->HasPrivPermission("users/auspex"))
154         {
155                 if (dest->IsModeSet(snomaskmode))
156                 {
157                         ServerInstance->SendWhoisLine(user, dest, 379, "%s :is using modes +%s %s", dest->nick.c_str(), dest->FormatModes(), snomaskmode->GetUserParameter(dest).c_str());
158                 }
159                 else
160                 {
161                         ServerInstance->SendWhoisLine(user, dest, 379, "%s :is using modes +%s", dest->nick.c_str(), dest->FormatModes());
162                 }
163         }
164
165         FOREACH_MOD(OnWhois, (user,dest));
166
167         /*
168          * We only send these if we've been provided them. That is, if hidewhois is turned off, and user is local, or
169          * if remote whois is queried, too. This is to keep the user hidden, and also since you can't reliably tell remote time. -- w00t
170          */
171         if ((idle) || (signon))
172         {
173                 ServerInstance->SendWhoisLine(user, dest, 317, "%s %lu %lu :seconds idle, signon time", dest->nick.c_str(), idle, signon);
174         }
175
176         ServerInstance->SendWhoisLine(user, dest, 318, "%s :End of /WHOIS list.", dest->nick.c_str());
177 }
178
179 CmdResult CommandWhois::HandleRemote(const std::vector<std::string>& parameters, RemoteUser* target)
180 {
181         if (parameters.size() < 2)
182                 return CMD_FAILURE;
183
184         User* user = ServerInstance->FindUUID(parameters[0]);
185         if (!user)
186                 return CMD_FAILURE;
187
188         unsigned long idle = ConvToInt(parameters.back());
189         DoWhois(user, target, target->signon, idle);
190
191         return CMD_SUCCESS;
192 }
193
194 CmdResult CommandWhois::HandleLocal(const std::vector<std::string>& parameters, LocalUser* user)
195 {
196         User *dest;
197         int userindex = 0;
198         unsigned long idle = 0, signon = 0;
199
200         if (CommandParser::LoopCall(user, this, parameters, 0))
201                 return CMD_SUCCESS;
202
203         /*
204          * If 2 paramters are specified (/whois nick nick), ignore the first one like spanningtree
205          * does, and use the second one, otherwise, use the only paramter. -- djGrrr
206          */
207         if (parameters.size() > 1)
208                 userindex = 1;
209
210         dest = ServerInstance->FindNickOnly(parameters[userindex]);
211
212         if ((dest) && (dest->registered == REG_ALL))
213         {
214                 /*
215                  * Okay. Umpteenth attempt at doing this, so let's re-comment...
216                  * For local users (/w localuser), we show idletime if hidewhois is disabled
217                  * For local users (/w localuser localuser), we always show idletime, hence parameters.size() > 1 check.
218                  * For remote users (/w remoteuser), we do NOT show idletime
219                  * For remote users (/w remoteuser remoteuser), spanningtree will handle calling do_whois, so we can ignore this case.
220                  * Thanks to djGrrr for not being impatient while I have a crap day coding. :p -- w00t
221                  */
222                 LocalUser* localuser = IS_LOCAL(dest);
223                 if (localuser && (ServerInstance->Config->HideWhoisServer.empty() || parameters.size() > 1))
224                 {
225                         idle = abs((long)((localuser->idle_lastmsg)-ServerInstance->Time()));
226                         signon = dest->signon;
227                 }
228
229                 DoWhois(user,dest,signon,idle);
230         }
231         else
232         {
233                 /* no such nick/channel */
234                 user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", !parameters[userindex].empty() ? parameters[userindex].c_str() : "*");
235                 user->WriteNumeric(RPL_ENDOFWHOIS, "%s :End of /WHOIS list.", !parameters[userindex].empty() ? parameters[userindex].c_str() : "*");
236                 return CMD_FAILURE;
237         }
238
239         return CMD_SUCCESS;
240 }
241
242 COMMAND_INIT(CommandWhois)