]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/coremods/core_whois.cpp
m_ssl_openssl Store a pointer to the OpenSSLIOHook object in SSL objects
[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 (User::ChanList::iterator 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                         char prefix = memb->GetPrefixChar();
72                         if (prefix)
73                                 list.push_back(prefix);
74                         list.append(c->name).push_back(' ');
75                 }
76         }
77
78         return list;
79 }
80
81 void CommandWhois::SplitChanList(User* source, User* dest, const std::string& cl)
82 {
83         std::string line;
84         std::ostringstream prefix;
85         std::string::size_type start, pos;
86
87         prefix << dest->nick << " :";
88         line = prefix.str();
89         int namelen = ServerInstance->Config->ServerName.length() + 6;
90
91         for (start = 0; (pos = cl.find(' ', start)) != std::string::npos; start = pos+1)
92         {
93                 if (line.length() + namelen + pos - start > 510)
94                 {
95                         ServerInstance->SendWhoisLine(source, dest, 319, line);
96                         line = prefix.str();
97                 }
98
99                 line.append(cl.substr(start, pos - start + 1));
100         }
101
102         if (line.length() != prefix.str().length())
103         {
104                 ServerInstance->SendWhoisLine(source, dest, 319, line);
105         }
106 }
107
108 void CommandWhois::DoWhois(User* user, User* dest, unsigned long signon, unsigned long idle)
109 {
110         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());
111         if (user == dest || user->HasPrivPermission("users/auspex"))
112         {
113                 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());
114         }
115
116         std::string cl = ChannelList(user, dest, false);
117         const ServerConfig::OperSpyWhoisState state = user->HasPrivPermission("users/auspex") ? ServerInstance->Config->OperSpyWhois : ServerConfig::SPYWHOIS_NONE;
118
119         if (state == ServerConfig::SPYWHOIS_SINGLEMSG)
120                 cl.append(ChannelList(user, dest, true));
121
122         SplitChanList(user, dest, cl);
123
124         if (state == ServerConfig::SPYWHOIS_SPLITMSG)
125         {
126                 std::string scl = ChannelList(user, dest, true);
127                 if (scl.length())
128                 {
129                         ServerInstance->SendWhoisLine(user, dest, 336, "%s :is on private/secret channels:", dest->nick.c_str());
130                         SplitChanList(user, dest, scl);
131                 }
132         }
133         if (user != dest && !ServerInstance->Config->HideWhoisServer.empty() && !user->HasPrivPermission("servers/auspex"))
134         {
135                 ServerInstance->SendWhoisLine(user, dest, 312, "%s %s :%s", dest->nick.c_str(), ServerInstance->Config->HideWhoisServer.c_str(), ServerInstance->Config->Network.c_str());
136         }
137         else
138         {
139                 ServerInstance->SendWhoisLine(user, dest, 312, "%s %s :%s", dest->nick.c_str(), dest->server->GetName().c_str(), dest->server->GetDesc().c_str());
140         }
141
142         if (dest->IsAway())
143         {
144                 ServerInstance->SendWhoisLine(user, dest, 301, "%s :%s", dest->nick.c_str(), dest->awaymsg.c_str());
145         }
146
147         if (dest->IsOper())
148         {
149                 if (ServerInstance->Config->GenericOper)
150                         ServerInstance->SendWhoisLine(user, dest, 313, "%s :is an IRC operator", dest->nick.c_str());
151                 else
152                         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());
153         }
154
155         if (user == dest || user->HasPrivPermission("users/auspex"))
156         {
157                 if (dest->IsModeSet(snomaskmode))
158                 {
159                         ServerInstance->SendWhoisLine(user, dest, 379, "%s :is using modes +%s %s", dest->nick.c_str(), dest->FormatModes(), snomaskmode->GetUserParameter(dest).c_str());
160                 }
161                 else
162                 {
163                         ServerInstance->SendWhoisLine(user, dest, 379, "%s :is using modes +%s", dest->nick.c_str(), dest->FormatModes());
164                 }
165         }
166
167         FOREACH_MOD(OnWhois, (user,dest));
168
169         /*
170          * We only send these if we've been provided them. That is, if hidewhois is turned off, and user is local, or
171          * if remote whois is queried, too. This is to keep the user hidden, and also since you can't reliably tell remote time. -- w00t
172          */
173         if ((idle) || (signon))
174         {
175                 ServerInstance->SendWhoisLine(user, dest, 317, "%s %lu %lu :seconds idle, signon time", dest->nick.c_str(), idle, signon);
176         }
177
178         ServerInstance->SendWhoisLine(user, dest, 318, "%s :End of /WHOIS list.", dest->nick.c_str());
179 }
180
181 CmdResult CommandWhois::HandleRemote(const std::vector<std::string>& parameters, RemoteUser* target)
182 {
183         if (parameters.size() < 2)
184                 return CMD_FAILURE;
185
186         User* user = ServerInstance->FindUUID(parameters[0]);
187         if (!user)
188                 return CMD_FAILURE;
189
190         unsigned long idle = ConvToInt(parameters.back());
191         DoWhois(user, target, target->signon, idle);
192
193         return CMD_SUCCESS;
194 }
195
196 CmdResult CommandWhois::HandleLocal(const std::vector<std::string>& parameters, LocalUser* user)
197 {
198         User *dest;
199         int userindex = 0;
200         unsigned long idle = 0, signon = 0;
201
202         if (CommandParser::LoopCall(user, this, parameters, 0))
203                 return CMD_SUCCESS;
204
205         /*
206          * If 2 paramters are specified (/whois nick nick), ignore the first one like spanningtree
207          * does, and use the second one, otherwise, use the only paramter. -- djGrrr
208          */
209         if (parameters.size() > 1)
210                 userindex = 1;
211
212         dest = ServerInstance->FindNickOnly(parameters[userindex]);
213
214         if ((dest) && (dest->registered == REG_ALL))
215         {
216                 /*
217                  * Okay. Umpteenth attempt at doing this, so let's re-comment...
218                  * For local users (/w localuser), we show idletime if hidewhois is disabled
219                  * For local users (/w localuser localuser), we always show idletime, hence parameters.size() > 1 check.
220                  * For remote users (/w remoteuser), we do NOT show idletime
221                  * For remote users (/w remoteuser remoteuser), spanningtree will handle calling do_whois, so we can ignore this case.
222                  * Thanks to djGrrr for not being impatient while I have a crap day coding. :p -- w00t
223                  */
224                 LocalUser* localuser = IS_LOCAL(dest);
225                 if (localuser && (ServerInstance->Config->HideWhoisServer.empty() || parameters.size() > 1))
226                 {
227                         idle = abs((long)((localuser->idle_lastmsg)-ServerInstance->Time()));
228                         signon = dest->signon;
229                 }
230
231                 DoWhois(user,dest,signon,idle);
232         }
233         else
234         {
235                 /* no such nick/channel */
236                 user->WriteNumeric(ERR_NOSUCHNICK, "%s :No such nick/channel", !parameters[userindex].empty() ? parameters[userindex].c_str() : "*");
237                 user->WriteNumeric(RPL_ENDOFWHOIS, "%s :End of /WHOIS list.", !parameters[userindex].empty() ? parameters[userindex].c_str() : "*");
238                 return CMD_FAILURE;
239         }
240
241         return CMD_SUCCESS;
242 }
243
244 COMMAND_INIT(CommandWhois)