ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_who.c
Revision: 2820
Committed: Wed Jan 15 23:10:26 2014 UTC (11 years, 7 months ago) by michael
Content type: text/x-csrc
File size: 10319 byte(s)
Log Message:
- Clean up all files in modules/ (fixed indentation, removed whitespaces/tabs)
- Fixed copyright years
- Made module handlers int type for later use

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 *
4 * Copyright (c) 1997-2014 ircd-hybrid development team
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 * USA
20 */
21
22 /*! \file m_who.c
23 * \brief Includes required functions for processing the WHO command.
24 * \version $Id$
25 */
26
27 #include "stdinc.h"
28 #include "list.h"
29 #include "client.h"
30 #include "channel.h"
31 #include "channel_mode.h"
32 #include "hash.h"
33 #include "ircd.h"
34 #include "numeric.h"
35 #include "s_serv.h"
36 #include "send.h"
37 #include "irc_string.h"
38 #include "conf.h"
39 #include "parse.h"
40 #include "modules.h"
41
42
43 /* do_who()
44 *
45 * inputs - pointer to client requesting who
46 * - pointer to client to do who on
47 * - The reported name
48 * - channel flags
49 * output - NONE
50 * side effects - do a who on given person
51 */
52 static void
53 do_who(struct Client *source_p, struct Client *target_p,
54 const char *chname, const char *op_flags)
55 {
56 char status[IRCD_BUFSIZE];
57
58 if (HasUMode(source_p, UMODE_OPER))
59 snprintf(status, sizeof(status), "%c%s%s%s", target_p->away[0] ? 'G' : 'H',
60 HasUMode(target_p, UMODE_REGISTERED) ? "r" : "",
61 HasUMode(target_p, UMODE_OPER) ? "*" : "", op_flags);
62 else
63 snprintf(status, sizeof(status), "%c%s%s%s", target_p->away[0] ? 'G' : 'H',
64 HasUMode(target_p, UMODE_REGISTERED) ? "r" : "",
65 HasUMode(target_p, UMODE_OPER) &&
66 !HasUMode(target_p, UMODE_HIDDEN) ? "*" : "", op_flags);
67
68 if (ConfigServerHide.hide_servers || IsHidden(target_p->servptr))
69 sendto_one(source_p, form_str(RPL_WHOREPLY), me.name, source_p->name,
70 (chname) ? (chname) : "*",
71 target_p->username, target_p->host,
72 HasUMode(source_p, UMODE_OPER) ? target_p->servptr->name : "*",
73 target_p->name, status,
74 HasUMode(source_p, UMODE_OPER) ? target_p->hopcount : 0, target_p->info);
75 else
76 sendto_one(source_p, form_str(RPL_WHOREPLY), me.name, source_p->name,
77 (chname) ? (chname) : "*", target_p->username,
78 target_p->host, target_p->servptr->name, target_p->name,
79 status, target_p->hopcount, target_p->info);
80 }
81
82 /* who_common_channel
83 * inputs - pointer to client requesting who
84 * - pointer to channel member chain.
85 * - char * mask to match
86 * - int if oper on a server or not
87 * - pointer to int maxmatches
88 * output - NONE
89 * side effects - lists matching clients on specified channel,
90 * marks matched clients.
91 *
92 */
93 static void
94 who_common_channel(struct Client *source_p, struct Channel *chptr,
95 char *mask, int server_oper, int *maxmatches)
96 {
97 dlink_node *ptr = NULL;
98
99 DLINK_FOREACH(ptr, chptr->members.head)
100 {
101 struct Client *target_p = ((struct Membership *)ptr->data)->client_p;
102
103 if (!HasUMode(target_p, UMODE_INVISIBLE) || HasFlag(target_p, FLAGS_MARK))
104 continue;
105
106 if (server_oper)
107 if (!HasUMode(target_p, UMODE_OPER) ||
108 (HasUMode(target_p, UMODE_HIDDEN) && !HasUMode(source_p, UMODE_OPER)))
109 continue;
110
111 AddFlag(target_p, FLAGS_MARK);
112
113 assert(target_p->servptr != NULL);
114
115 if ((mask == NULL) ||
116 !match(mask, target_p->name) || !match(mask, target_p->username) ||
117 !match(mask, target_p->host) ||
118 ((!ConfigServerHide.hide_servers || HasUMode(source_p, UMODE_OPER)) &&
119 !match(mask, target_p->servptr->name)) ||
120 !match(mask, target_p->info))
121 {
122 do_who(source_p, target_p, NULL, "");
123
124 if (*maxmatches > 0)
125 {
126 if (--(*maxmatches) == 0)
127 return;
128 }
129 }
130 }
131 }
132
133 /* who_global()
134 *
135 * inputs - pointer to client requesting who
136 * - char * mask to match
137 * - int if oper on a server or not
138 * output - NONE
139 * side effects - do a global scan of all clients looking for match
140 * this is slightly expensive on EFnet ...
141 */
142 static void
143 who_global(struct Client *source_p, char *mask, int server_oper)
144 {
145 struct Channel *chptr;
146 struct Client *target_p;
147 dlink_node *lp = NULL, *gcptr = NULL;
148 int maxmatches = 500;
149 static time_t last_used = 0;
150
151 if (!HasUMode(source_p, UMODE_OPER))
152 {
153 if ((last_used + ConfigFileEntry.pace_wait) > CurrentTime)
154 {
155 /* safe enough to give this on a local connect only */
156 sendto_one(source_p, form_str(RPL_LOAD2HI), me.name, source_p->name);
157 return;
158 }
159
160 last_used = CurrentTime;
161 }
162
163 /* first, list all matching invisible clients on common channels */
164 DLINK_FOREACH(lp, source_p->channel.head)
165 {
166 chptr = ((struct Membership *)lp->data)->chptr;
167 who_common_channel(source_p, chptr, mask, server_oper, &maxmatches);
168 }
169
170 /* second, list all matching visible clients */
171 DLINK_FOREACH(gcptr, global_client_list.head)
172 {
173 target_p = gcptr->data;
174
175 if (!IsClient(target_p))
176 continue;
177
178 if (HasUMode(target_p, UMODE_INVISIBLE))
179 {
180 DelFlag(target_p, FLAGS_MARK);
181 continue;
182 }
183
184 if (server_oper)
185 if (!HasUMode(target_p, UMODE_OPER) ||
186 (HasUMode(target_p, UMODE_HIDDEN) && !HasUMode(source_p, UMODE_OPER)))
187 continue;
188
189 assert(target_p->servptr != NULL);
190
191 if (!mask ||
192 !match(mask, target_p->name) || !match(mask, target_p->username) ||
193 !match(mask, target_p->host) || !match(mask, target_p->servptr->name) ||
194 !match(mask, target_p->info))
195 {
196 do_who(source_p, target_p, NULL, "");
197
198 if (maxmatches > 0)
199 {
200 if (--maxmatches == 0)
201 return;
202 }
203 }
204 }
205 }
206
207 /* do_who_on_channel()
208 *
209 * inputs - pointer to client requesting who
210 * - pointer to channel to do who on
211 * - The "real name" of this channel
212 * - int if source_p is a server oper or not
213 * - int if client is member or not
214 * - int server_op flag
215 * output - NONE
216 * side effects - do a who on given channel
217 */
218 static void
219 do_who_on_channel(struct Client *source_p, struct Channel *chptr,
220 const char *chname, int member, int server_oper)
221 {
222 dlink_node *ptr = NULL;
223
224 DLINK_FOREACH(ptr, chptr->members.head)
225 {
226 struct Membership *ms = ptr->data;
227 struct Client *target_p = ms->client_p;
228
229 if (member || !HasUMode(target_p, UMODE_INVISIBLE))
230 {
231 if (server_oper)
232 if (!HasUMode(target_p, UMODE_OPER) ||
233 (HasUMode(target_p, UMODE_HIDDEN) && !HasUMode(source_p, UMODE_OPER)))
234 continue;
235 do_who(source_p, target_p, chname, get_member_status(ms, !!HasCap(source_p, CAP_MULTI_PREFIX)));
236 }
237 }
238 }
239
240 /*
241 ** m_who
242 ** parv[0] = sender prefix
243 ** parv[1] = nickname mask list
244 ** parv[2] = additional selection flag, only 'o' for now.
245 */
246 static int
247 m_who(struct Client *client_p, struct Client *source_p,
248 int parc, char *parv[])
249 {
250 struct Client *target_p = NULL;
251 struct Channel *chptr = NULL;
252 char *mask = parv[1];
253 dlink_node *lp = NULL;
254 int server_oper = parc > 2 ? (*parv[2] == 'o') : 0; /* Show OPERS only */
255
256 /* See if mask is there, collapse it or return if not there */
257 if (EmptyString(mask))
258 {
259 who_global(source_p, mask, server_oper);
260 sendto_one(source_p, form_str(RPL_ENDOFWHO),
261 me.name, source_p->name, "*");
262 return 0;
263 }
264
265 /* mask isn't NULL at this point. repeat after me... -db */
266 collapse(mask);
267
268 /* '/who #some_channel' */
269 if (IsChanPrefix(*mask))
270 {
271 /* List all users on a given channel */
272 if ((chptr = hash_find_channel(mask)) != NULL)
273 {
274 if (IsMember(source_p, chptr))
275 do_who_on_channel(source_p, chptr, chptr->chname, 1, server_oper);
276 else if (!SecretChannel(chptr))
277 do_who_on_channel(source_p, chptr, chptr->chname, 0, server_oper);
278 }
279
280 sendto_one(source_p, form_str(RPL_ENDOFWHO),
281 me.name, source_p->name, mask);
282 return 0;
283 }
284
285 /* '/who nick' */
286 if (((target_p = hash_find_client(mask)) != NULL) &&
287 IsClient(target_p) && (!server_oper || HasUMode(target_p, UMODE_OPER)))
288 {
289 DLINK_FOREACH(lp, target_p->channel.head)
290 {
291 chptr = ((struct Membership *) lp->data)->chptr;
292 if (PubChannel(chptr) || IsMember(source_p, chptr))
293 break;
294 }
295
296 if (lp != NULL)
297 do_who(source_p, target_p, chptr->chname,
298 get_member_status(lp->data, !!HasCap(source_p, CAP_MULTI_PREFIX)));
299 else
300 do_who(source_p, target_p, NULL, "");
301
302 sendto_one(source_p, form_str(RPL_ENDOFWHO),
303 me.name, source_p->name, mask);
304 return 0;
305 }
306
307 /* '/who *' */
308 if (!strcmp(mask, "*"))
309 {
310 if ((lp = source_p->channel.head) != NULL)
311 {
312 struct Channel *mychannel = ((struct Membership *)lp->data)->chptr;
313 do_who_on_channel(source_p, mychannel, mychannel->chname, 1,
314 server_oper);
315 }
316
317 sendto_one(source_p, form_str(RPL_ENDOFWHO),
318 me.name, source_p->name, "*");
319 return 0;
320 }
321
322 /* '/who 0' */
323 if (!strcmp(mask, "0"))
324 who_global(source_p, NULL, server_oper);
325 else
326 who_global(source_p, mask, server_oper);
327
328 /* Wasn't a nick, wasn't a channel, wasn't a '*' so ... */
329 sendto_one(source_p, form_str(RPL_ENDOFWHO),
330 me.name, source_p->name, mask);
331 return 0;
332 }
333
334 static struct Message who_msgtab =
335 {
336 "WHO", 0, 0, 2, MAXPARA, MFLG_SLOW, 0,
337 { m_unregistered, m_who, m_ignore, m_ignore, m_who, m_ignore }
338 };
339
340 static void
341 module_init(void)
342 {
343 mod_add_cmd(&who_msgtab);
344 }
345
346 static void
347 module_exit(void)
348 {
349 mod_del_cmd(&who_msgtab);
350 }
351
352 struct module module_entry =
353 {
354 .node = { NULL, NULL, NULL },
355 .name = NULL,
356 .version = "$Revision$",
357 .handle = NULL,
358 .modinit = module_init,
359 .modexit = module_exit,
360 .flags = 0
361 };

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision