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