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