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