ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_who.c
Revision: 2756
Committed: Sun Jan 5 22:50:35 2014 UTC (11 years, 7 months ago) by michael
Content type: text/x-csrc
File size: 10243 byte(s)
Log Message:
- m_who.c:do_who(): don't hide hopcount to irc operators

File Contents

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

Properties

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