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