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