]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/cmd_who.cpp
Fix for peavy :p
[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 CmdResult cmd_who::Handle (const char** parameters, int pcnt, userrec *user)
86 {
87         /*
88          * XXX - RFC says:
89          *   The <name> passed to WHO is matched against users' host, server, real
90          *   name and nickname
91          * Currently, we support WHO #chan, WHO nick, WHO 0, WHO *, and the addition of a 'o' flag, as per RFC.
92          */
93
94         /* WHO options */
95         bool opt_viewopersonly = false;
96         bool opt_showrealhost = false;
97         bool opt_unlimit = false;
98         bool opt_realname = false;
99         bool opt_mode = false;
100
101         chanrec *ch = NULL;
102         std::vector<std::string> whoresults;
103         std::string initial = "352 " + std::string(user->nick) + " ";
104
105         const char* matchtext = NULL;
106
107         /* Change '0' into '*' so the wildcard matcher can grok it */
108         matchtext = parameters[0];
109         if (!strcmp(matchtext,"0"))
110                 matchtext = "*";
111
112         if (pcnt > 1)
113         {
114                 /* parse flags */
115                 const char *iter = parameters[1];
116
117                 while (*iter)
118                 {
119                         switch (*iter)
120                         {
121                                 case 'o':
122                                         opt_viewopersonly = true;
123                                 break;
124                                 case 'h':
125                                         if (*user->oper)
126                                                 opt_showrealhost = true;
127                                 break;
128                                 case 'u':
129                                         if (*user->oper)
130                                                 opt_unlimit = true;
131                                 break;
132                                 case 'r':
133                                         opt_realname = true;
134                                 break;
135                                 case 'm':
136                                         opt_mode = true;
137                                 break;
138                         }
139
140                         *iter++;
141                 }
142         }
143
144
145         /* who on a channel? */
146         ch = ServerInstance->FindChan(matchtext);
147
148         if (ch)
149         {
150                 /* who on a channel. */
151                 CUList *cu = ch->GetUsers();
152
153                 for (CUList::iterator i = cu->begin(); i != cu->end(); i++)
154                 {
155                         /* opers only, please */
156                         if (opt_viewopersonly && !*(i->second)->oper)
157                                 continue;
158
159                         /* XXX - code duplication; this could be more efficient -- w00t */
160                         std::string wholine = initial;
161
162                         wholine = wholine + ch->name + " " + i->second->ident + " " + (opt_showrealhost ? i->second->host : i->second->dhost) + " " + 
163                                         i->second->server + " " + i->second->nick + " ";
164
165                         /* away? */
166                         if (*(i->second)->awaymsg)
167                         {
168                                 wholine.append("G");
169                         }
170                         else
171                         {
172                                 wholine.append("H");
173                         }
174
175                         /* oper? */
176                         if (*(i->second)->oper)
177                         {
178                                 wholine.append("*");
179                         }
180
181                         wholine = wholine + ch->GetPrefixChar(i->second) + " :0 " + i->second->fullname;
182                         whoresults.push_back(wholine);
183                 }
184         }
185         else
186         {
187                 /* Match against wildcard of nick, server or host */
188
189                 if (opt_viewopersonly)
190                 {
191                         /* Showing only opers */
192                         for (std::vector<userrec*>::iterator i = ServerInstance->all_opers.begin(); i != ServerInstance->all_opers.end(); i++)
193                         {
194                                 userrec* oper = *i;
195
196                                 if (whomatch(oper, matchtext, opt_realname, opt_showrealhost, opt_mode))
197                                 {
198                                         std::string wholine = initial;
199         
200                                         wholine = wholine + getlastchanname(oper) + " " + oper->ident + " " + (opt_showrealhost ? oper->host : oper->dhost) + " " + 
201                                                         oper->server + " " + oper->nick + " ";
202
203                                         ch = ServerInstance->FindChan(getlastchanname(oper));
204
205                                         /* away? */
206                                         if (*oper->awaymsg)
207                                         {
208                                                 wholine.append("G");
209                                         }
210                                         else
211                                         {
212                                                 wholine.append("H");
213                                         }
214         
215                                         /* oper? */
216                                         if (*oper->oper)
217                                         {
218                                                 wholine.append("*");
219                                         }
220         
221                                         wholine = wholine + (ch ? ch->GetPrefixChar(oper) : "") + " :0 " + oper->fullname;
222                                         whoresults.push_back(wholine);
223                                 }
224                         }
225                 }
226                 else
227                 {
228                         for (user_hash::iterator i = ServerInstance->clientlist.begin(); i != ServerInstance->clientlist.end(); i++)
229                         {
230                                 if (whomatch(i->second, matchtext, opt_realname, opt_showrealhost, opt_mode))
231                                 {
232                                         std::string wholine = initial;
233         
234                                         wholine = wholine + getlastchanname(i->second) + " " + i->second->ident + " " + (opt_showrealhost ? i->second->host : i->second->dhost) + " " + 
235                                                 i->second->server + " " + i->second->nick + " ";
236         
237                                         ch = ServerInstance->FindChan(getlastchanname(i->second));
238
239                                         /* away? */
240                                         if (*(i->second)->awaymsg)
241                                         {
242                                                 wholine.append("G");
243                                         }
244                                         else
245                                         {
246                                                 wholine.append("H");
247                                         }
248
249                                         /* oper? */
250                                         if (*(i->second)->oper)
251                                         {
252                                                 wholine.append("*");
253                                         }
254
255                                         wholine = wholine + (ch ? ch->GetPrefixChar(i->second) : "") + " :0 " + i->second->fullname;
256                                         whoresults.push_back(wholine);
257                                 }
258                         }
259                 }
260         }
261         /* Send the results out */
262         if ((whoresults.size() < (size_t)ServerInstance->Config->MaxWhoResults) && (!opt_unlimit))
263         {
264                 for (std::vector<std::string>::const_iterator n = whoresults.begin(); n != whoresults.end(); n++)
265                         user->WriteServ(*n);
266                 user->WriteServ("315 %s %s :End of /WHO list.",user->nick, *parameters[0] ? parameters[0] : "*");
267                 return CMD_SUCCESS;
268         }
269         else
270         {
271                 /* BZZT! Too many results. */
272                 user->WriteServ("315 %s %s :Too many results",user->nick, parameters[0]);
273                 return CMD_FAILURE;
274         }
275 }