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