]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/cmd_who.cpp
Annotations
[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)
41 {
42         bool realhost = false;
43         bool realname = false;
44
45         if (user->registered != REG_ALL)
46                 return false;
47
48         if (opt_realname)
49                 realname = match(user->fullname, matchtext);
50
51         if (opt_showrealhost)
52                 realhost = match(user->host, matchtext);
53
54         return ((realname) || (realhost) || (match(user->dhost, matchtext)) || (match(user->nick, matchtext)) || (match(user->server, matchtext)));
55 }
56
57
58
59 extern "C" command_t* init_command(InspIRCd* Instance)
60 {
61         return new cmd_who(Instance);
62 }
63
64 CmdResult cmd_who::Handle (const char** parameters, int pcnt, userrec *user)
65 {
66         /*
67          * XXX - RFC says:
68          *   The <name> passed to WHO is matched against users' host, server, real
69          *   name and nickname
70          * Currently, we support WHO #chan, WHO nick, WHO 0, WHO *, and the addition of a 'o' flag, as per RFC.
71          */
72
73         /* WHO options */
74         bool opt_viewopersonly = false;
75         bool opt_showrealhost = false;
76         bool opt_unlimit = false;
77         bool opt_realname = false;
78
79         chanrec *ch = NULL;
80         std::vector<std::string> whoresults;
81         std::string initial = "352 " + std::string(user->nick) + " ";
82
83         const char* matchtext = NULL;
84
85         /* Change '0' into '*' so the wildcard matcher can grok it */
86         matchtext = parameters[0];
87         if (!strcmp(matchtext,"0"))
88                 matchtext = "*";
89
90         if (pcnt > 1)
91         {
92                 /* parse flags */
93                 const char *iter = parameters[1];
94
95                 while (*iter)
96                 {
97                         switch (*iter)
98                         {
99                                 case 'o':
100                                         opt_viewopersonly = true;
101                                 break;
102                                 case 'h':
103                                         if (*user->oper)
104                                                 opt_showrealhost = true;
105                                 break;
106                                 case 'u':
107                                         if (*user->oper)
108                                                 opt_unlimit = true;
109                                 break;
110                                 case 'r':
111                                         opt_realname = true;
112                                 break;
113                         }
114
115                         *iter++;
116                 }
117         }
118
119
120         /* who on a channel? */
121         ch = ServerInstance->FindChan(matchtext);
122
123         if (ch)
124         {
125                 /* who on a channel. */
126                 CUList *cu = ch->GetUsers();
127
128                 for (CUList::iterator i = cu->begin(); i != cu->end(); i++)
129                 {
130                         /* opers only, please */
131                         if (opt_viewopersonly && !*(i->second)->oper)
132                                 continue;
133
134                         /* XXX - code duplication; this could be more efficient -- w00t */
135                         std::string wholine = initial;
136
137                         wholine = wholine + ch->name + " " + i->second->ident + " " + (opt_showrealhost ? i->second->host : i->second->dhost) + " " + 
138                                         i->second->server + " " + i->second->nick + " ";
139
140                         /* away? */
141                         if (*(i->second)->awaymsg)
142                         {
143                                 wholine.append("G");
144                         }
145                         else
146                         {
147                                 wholine.append("H");
148                         }
149
150                         /* oper? */
151                         if (*(i->second)->oper)
152                         {
153                                 wholine.append("*");
154                         }
155
156                         wholine = wholine + ch->GetPrefixChar(i->second) + " :0 " + i->second->fullname;
157                         whoresults.push_back(wholine);
158                 }
159         }
160         else
161         {
162                 /* Match against wildcard of nick, server or host */
163
164                 if (opt_viewopersonly)
165                 {
166                         /* Showing only opers */
167                         for (std::vector<userrec*>::iterator i = ServerInstance->all_opers.begin(); i != ServerInstance->all_opers.end(); i++)
168                         {
169                                 userrec* oper = *i;
170
171                                 if (whomatch(oper, matchtext, opt_realname, opt_showrealhost))
172                                 {
173                                         std::string wholine = initial;
174         
175                                         wholine = wholine + getlastchanname(oper) + " " + oper->ident + " " + (opt_showrealhost ? oper->host : oper->dhost) + " " + 
176                                                         oper->server + " " + oper->nick + " ";
177
178                                         ch = ServerInstance->FindChan(getlastchanname(oper));
179
180                                         /* away? */
181                                         if (*oper->awaymsg)
182                                         {
183                                                 wholine.append("G");
184                                         }
185                                         else
186                                         {
187                                                 wholine.append("H");
188                                         }
189         
190                                         /* oper? */
191                                         if (*oper->oper)
192                                         {
193                                                 wholine.append("*");
194                                         }
195         
196                                         wholine = wholine + (ch ? ch->GetPrefixChar(oper) : "") + " :0 " + oper->fullname;
197                                         whoresults.push_back(wholine);
198                                 }
199                         }
200                 }
201                 else
202                 {
203                         for (user_hash::iterator i = ServerInstance->clientlist.begin(); i != ServerInstance->clientlist.end(); i++)
204                         {
205                                 if (whomatch(i->second, matchtext, opt_realname, opt_showrealhost))
206                                 {
207                                         std::string wholine = initial;
208         
209                                         wholine = wholine + getlastchanname(i->second) + " " + i->second->ident + " " + (opt_showrealhost ? i->second->host : i->second->dhost) + " " + 
210                                                 i->second->server + " " + i->second->nick + " ";
211         
212                                         ch = ServerInstance->FindChan(getlastchanname(i->second));
213
214                                         /* away? */
215                                         if (*(i->second)->awaymsg)
216                                         {
217                                                 wholine.append("G");
218                                         }
219                                         else
220                                         {
221                                                 wholine.append("H");
222                                         }
223
224                                         /* oper? */
225                                         if (*(i->second)->oper)
226                                         {
227                                                 wholine.append("*");
228                                         }
229
230                                         wholine = wholine + (ch ? ch->GetPrefixChar(i->second) : "") + " :0 " + i->second->fullname;
231                                         whoresults.push_back(wholine);
232                                 }
233                         }
234                 }
235         }
236         /* Send the results out */
237         if ((whoresults.size() < (size_t)ServerInstance->Config->MaxWhoResults) && (!opt_unlimit))
238         {
239                 for (std::vector<std::string>::const_iterator n = whoresults.begin(); n != whoresults.end(); n++)
240                         user->WriteServ(*n);
241                 user->WriteServ("315 %s %s :End of /WHO list.",user->nick, *parameters[0] ? parameters[0] : "*");
242                 return CMD_SUCCESS;
243         }
244         else
245         {
246                 /* BZZT! Too many results. */
247                 user->WriteServ("315 %s %s :Too many results",user->nick, parameters[0]);
248                 return CMD_FAILURE;
249         }
250 }