]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/cmd_who.cpp
Remove unused debug
[user/henk/code/inspircd.git] / src / cmd_who.cpp
1 /*   +------------------------------------+
2  *   | Inspire Internet Relay Chat Daemon |
3  *   +------------------------------------+
4  *
5  *  InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
6  *   E-mail:
7  *<brain@chatspike.net>
8  *<Craig@chatspike.net>
9  *
10  * Written by Craig Edwards, Craig McLure, and others.
11  * This program is free but copyrighted software; see
12  *the file COPYING for details.
13  *
14  * ---------------------------------------------------
15  */
16
17 #include "configreader.h"
18 #include "users.h"
19 #include "modules.h"
20 #include "wildcard.h"
21 #include "commands/cmd_who.h"
22
23 /* get the last 'visible' chan of a user */
24 static char *getlastchanname(userrec *u)
25 {
26         for (std::vector<ucrec*>::const_iterator v = u->chans.begin(); v != u->chans.end(); v++)
27         {
28                 ucrec* temp = (ucrec*)*v;
29
30                 if (temp->channel)
31                 {
32                         if (!temp->channel->IsModeSet('s'))
33                                 return temp->channel->name;
34                 }
35         }
36
37         return "*";
38 }
39
40 bool whomatch(userrec* user, const char* matchtext, bool opt_realname, bool opt_showrealhost, bool opt_mode)
41 {
42         bool realhost = false;
43         bool realname = false;
44         bool positive = true;
45
46         if (user->registered != REG_ALL)
47                 return false;
48
49         if (opt_mode)
50         {
51                 for (const char* n = matchtext; *n; n++)
52                 {
53                         if (*n == '+')
54                         {
55                                 positive = true;
56                                 continue;
57                         }
58                         else if (*n == '-')
59                         {
60                                 positive = false;
61                                 continue;
62                         }
63                         if (user->IsModeSet(*n) != positive)
64                                 return false;
65                 }
66                 return true;
67         }
68
69         if (opt_realname)
70                 realname = match(user->fullname, matchtext);
71
72         if (opt_showrealhost)
73                 realhost = match(user->host, matchtext);
74
75         return ((realname) || (realhost) || (match(user->dhost, matchtext)) || (match(user->nick, matchtext)) || (match(user->server, matchtext)));
76 }
77
78
79
80 extern "C" command_t* init_command(InspIRCd* Instance)
81 {
82         return new cmd_who(Instance);
83 }
84
85 bool cmd_who::CanView(chanrec* chan, userrec* user)
86 {
87         if (!user || !chan)
88                 return false;
89
90         /* Execute items in fastest-to-execute first order */
91         if (*user->oper)
92                 return true;
93         else if (!chan->IsModeSet('s') && !chan->IsModeSet('p'))
94                 return true;
95         else if (chan->HasUser(user))
96                 return true;
97
98         return false;
99 }
100
101 CmdResult cmd_who::Handle (const char** parameters, int pcnt, userrec *user)
102 {
103         /*
104          * XXX - RFC says:
105          *   The <name> passed to WHO is matched against users' host, server, real
106          *   name and nickname
107          * Currently, we support WHO #chan, WHO nick, WHO 0, WHO *, and the addition of a 'o' flag, as per RFC.
108          */
109
110         /* WHO options */
111         bool opt_viewopersonly = false;
112         bool opt_showrealhost = false;
113         bool opt_unlimit = false;
114         bool opt_realname = false;
115         bool opt_mode = false;
116
117         chanrec *ch = NULL;
118         std::vector<std::string> whoresults;
119         std::string initial = "352 " + std::string(user->nick) + " ";
120
121         const char* matchtext = NULL;
122
123         /* Change '0' into '*' so the wildcard matcher can grok it */
124         matchtext = parameters[0];
125         if (!strcmp(matchtext,"0"))
126                 matchtext = "*";
127
128         if (pcnt > 1)
129         {
130                 /* parse flags */
131                 const char *iter = parameters[1];
132
133                 while (*iter)
134                 {
135                         switch (*iter)
136                         {
137                                 case 'o':
138                                         opt_viewopersonly = true;
139                                 break;
140                                 case 'h':
141                                         if (*user->oper)
142                                                 opt_showrealhost = true;
143                                 break;
144                                 case 'u':
145                                         if (*user->oper)
146                                                 opt_unlimit = true;
147                                 break;
148                                 case 'r':
149                                         opt_realname = true;
150                                 break;
151                                 case 'm':
152                                         opt_mode = true;
153                                 break;
154                         }
155
156                         *iter++;
157                 }
158         }
159
160
161         /* who on a channel? */
162         ch = ServerInstance->FindChan(matchtext);
163
164         if ((ch) && (CanView(ch,user)))
165         {
166                 /* who on a channel. */
167                 CUList *cu = ch->GetUsers();
168
169                 for (CUList::iterator i = cu->begin(); i != cu->end(); i++)
170                 {
171                         /* opers only, please */
172                         if (opt_viewopersonly && !*(i->second)->oper)
173                                 continue;
174
175                         /* XXX - code duplication; this could be more efficient -- w00t */
176                         std::string wholine = initial;
177
178                         wholine = wholine + ch->name + " " + i->second->ident + " " + (opt_showrealhost ? i->second->host : i->second->dhost) + " " + 
179                                         i->second->server + " " + i->second->nick + " ";
180
181                         /* away? */
182                         if (*(i->second)->awaymsg)
183                         {
184                                 wholine.append("G");
185                         }
186                         else
187                         {
188                                 wholine.append("H");
189                         }
190
191                         /* oper? */
192                         if (*(i->second)->oper)
193                         {
194                                 wholine.append("*");
195                         }
196
197                         wholine = wholine + ch->GetPrefixChar(i->second) + " :0 " + i->second->fullname;
198                         whoresults.push_back(wholine);
199                 }
200         }
201         else
202         {
203                 /* Match against wildcard of nick, server or host */
204
205                 if (opt_viewopersonly)
206                 {
207                         /* Showing only opers */
208                         for (std::vector<userrec*>::iterator i = ServerInstance->all_opers.begin(); i != ServerInstance->all_opers.end(); i++)
209                         {
210                                 userrec* oper = *i;
211
212                                 if (whomatch(oper, matchtext, opt_realname, opt_showrealhost, opt_mode))
213                                 {
214                                         std::string wholine = initial;
215         
216                                         wholine = wholine + getlastchanname(oper) + " " + oper->ident + " " + (opt_showrealhost ? oper->host : oper->dhost) + " " + 
217                                                         oper->server + " " + oper->nick + " ";
218
219                                         ch = ServerInstance->FindChan(getlastchanname(oper));
220
221                                         /* away? */
222                                         if (*oper->awaymsg)
223                                         {
224                                                 wholine.append("G");
225                                         }
226                                         else
227                                         {
228                                                 wholine.append("H");
229                                         }
230         
231                                         /* oper? */
232                                         if (*oper->oper)
233                                         {
234                                                 wholine.append("*");
235                                         }
236         
237                                         wholine = wholine + (ch ? ch->GetPrefixChar(oper) : "") + " :0 " + oper->fullname;
238                                         whoresults.push_back(wholine);
239                                 }
240                         }
241                 }
242                 else
243                 {
244                         for (user_hash::iterator i = ServerInstance->clientlist.begin(); i != ServerInstance->clientlist.end(); i++)
245                         {
246                                 if (whomatch(i->second, matchtext, opt_realname, opt_showrealhost, opt_mode))
247                                 {
248                                         std::string wholine = initial;
249         
250                                         wholine = wholine + getlastchanname(i->second) + " " + i->second->ident + " " + (opt_showrealhost ? i->second->host : i->second->dhost) + " " + 
251                                                 i->second->server + " " + i->second->nick + " ";
252         
253                                         ch = ServerInstance->FindChan(getlastchanname(i->second));
254
255                                         /* away? */
256                                         if (*(i->second)->awaymsg)
257                                         {
258                                                 wholine.append("G");
259                                         }
260                                         else
261                                         {
262                                                 wholine.append("H");
263                                         }
264
265                                         /* oper? */
266                                         if (*(i->second)->oper)
267                                         {
268                                                 wholine.append("*");
269                                         }
270
271                                         wholine = wholine + (ch ? ch->GetPrefixChar(i->second) : "") + " :0 " + i->second->fullname;
272                                         whoresults.push_back(wholine);
273                                 }
274                         }
275                 }
276         }
277         /* Send the results out */
278         if ((whoresults.size() < (size_t)ServerInstance->Config->MaxWhoResults) && (!opt_unlimit))
279         {
280                 for (std::vector<std::string>::const_iterator n = whoresults.begin(); n != whoresults.end(); n++)
281                         user->WriteServ(*n);
282                 user->WriteServ("315 %s %s :End of /WHO list.",user->nick, *parameters[0] ? parameters[0] : "*");
283                 return CMD_SUCCESS;
284         }
285         else
286         {
287                 /* BZZT! Too many results. */
288                 user->WriteServ("315 %s %s :Too many results",user->nick, parameters[0]);
289                 return CMD_FAILURE;
290         }
291 }