ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/modules/m_whois.c
Revision: 660
Committed: Fri Jun 9 18:51:22 2006 UTC (20 years, 2 months ago) by adx
Content type: text/x-csrc
File size: 11798 byte(s)
Log Message:
+ backported numeric changes

File Contents

# User Rev Content
1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * m_whois.c: Shows who a user is.
4     *
5     * Copyright (C) 2005 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    
25     #include "stdinc.h"
26     #include "fdlist.h"
27     #include "tools.h"
28     #include "common.h"
29     #include "handlers.h"
30     #include "client.h"
31     #include "hash.h"
32     #include "channel.h"
33     #include "channel_mode.h"
34     #include "ircd.h"
35     #include "numeric.h"
36     #include "s_conf.h"
37     #include "s_misc.h"
38     #include "s_serv.h"
39     #include "send.h"
40     #include "list.h"
41     #include "irc_string.h"
42     #include "sprintf_irc.h"
43     #include "msg.h"
44     #include "parse.h"
45     #include "modules.h"
46     #include "hook.h"
47    
48     static void do_whois(struct Client *, int, char **);
49     static int single_whois(struct Client *, struct Client *);
50     static void whois_person(struct Client *, struct Client *);
51     static int global_whois(struct Client *, const char *);
52    
53     static void m_whois(struct Client *, struct Client *, int, char *[]);
54     static void mo_whois(struct Client *, struct Client *, int, char *[]);
55    
56     struct Message whois_msgtab = {
57     "WHOIS", 0, 0, 0, 0, MFLG_SLOW, 0,
58     { m_unregistered, m_whois, mo_whois, m_ignore, mo_whois, m_ignore }
59     };
60    
61     #ifndef STATIC_MODULES
62 knight 31 const char *_version = "$Revision$";
63 adx 30 static struct Callback *whois_cb;
64    
65     static void *
66     va_whois(va_list args)
67     {
68     struct Client *source_p = va_arg(args, struct Client *);
69     int parc = va_arg(args, int);
70     char **parv = va_arg(args, char **);
71    
72     do_whois(source_p, parc, parv);
73     return NULL;
74     }
75    
76     void
77     _modinit(void)
78     {
79     whois_cb = register_callback("doing_whois", va_whois);
80     mod_add_cmd(&whois_msgtab);
81     }
82    
83     void
84     _moddeinit(void)
85     {
86     mod_del_cmd(&whois_msgtab);
87     uninstall_hook(whois_cb, va_whois);
88     }
89     #endif
90    
91     /*
92     ** m_whois
93     ** parv[0] = sender prefix
94     ** parv[1] = nickname masklist
95     */
96     static void
97     m_whois(struct Client *client_p, struct Client *source_p,
98     int parc, char *parv[])
99     {
100 adx 269 static time_t last_used = 0;
101    
102 adx 30 if (parc < 2 || EmptyString(parv[1]))
103     {
104     sendto_one(source_p, form_str(ERR_NONICKNAMEGIVEN),
105     me.name, source_p->name);
106     return;
107     }
108    
109 michael 93 if (parc > 2 && !EmptyString(parv[2]))
110 adx 30 {
111     /* seeing as this is going across servers, we should limit it */
112     if ((last_used + ConfigFileEntry.pace_wait_simple) > CurrentTime)
113     {
114     sendto_one(source_p, form_str(RPL_LOAD2HI),
115     me.name, source_p->name);
116     return;
117     }
118     else
119     last_used = CurrentTime;
120    
121     /* if we have serverhide enabled, they can either ask the clients
122     * server, or our server.. I dont see why they would need to ask
123     * anything else for info about the client.. --fl_
124     */
125     if (ConfigFileEntry.disable_remote)
126     parv[1] = parv[2];
127    
128     if (hunt_server(client_p, source_p, ":%s WHOIS %s :%s", 1,
129     parc, parv) != HUNTED_ISME)
130     return;
131    
132     parv[1] = parv[2];
133     }
134    
135     #ifdef STATIC_MODULES
136     do_whois(source_p, parc, parv);
137     #else
138     execute_callback(whois_cb, source_p, parc, parv);
139     #endif
140     }
141    
142     /*
143     ** mo_whois
144     ** parv[0] = sender prefix
145     ** parv[1] = nickname masklist
146     */
147     static void
148     mo_whois(struct Client *client_p, struct Client *source_p,
149     int parc, char *parv[])
150     {
151     if (parc < 2 || EmptyString(parv[1]))
152     {
153     sendto_one(source_p, form_str(ERR_NONICKNAMEGIVEN),
154     me.name, source_p->name);
155     return;
156     }
157    
158 michael 93 if (parc > 2 && !EmptyString(parv[2]))
159 adx 30 {
160     if (hunt_server(client_p, source_p, ":%s WHOIS %s :%s", 1,
161     parc, parv) != HUNTED_ISME)
162     return;
163    
164     parv[1] = parv[2];
165     }
166    
167     #ifdef STATIC_MODULES
168     do_whois(source_p, parc, parv);
169     #else
170     execute_callback(whois_cb, source_p, parc, parv);
171     #endif
172     }
173    
174     /* do_whois()
175     *
176     * inputs - pointer to /whois source
177     * - number of parameters
178     * - pointer to parameters array
179     * output - pointer to void
180     * side effects - Does whois
181     */
182     static void
183     do_whois(struct Client *source_p, int parc, char **parv)
184     {
185 adx 269 static time_t last_used = 0;
186 adx 30 struct Client *target_p;
187     char *nick;
188     char *p = NULL;
189     int found = 0;
190    
191     nick = parv[1];
192     while (*nick == ',')
193     nick++;
194     if ((p = strchr(nick,',')) != NULL)
195     *p = '\0';
196    
197     if (*nick == '\0')
198     return;
199    
200     collapse(nick);
201    
202     if (strpbrk(nick, "?#*") == NULL)
203     {
204     if ((target_p = find_client(nick)) != NULL)
205     {
206     if (IsServer(source_p->from))
207 adx 268 client_burst_if_needed(source_p->from, target_p);
208 adx 30
209     if (IsClient(target_p))
210     {
211 adx 268 whois_person(source_p, target_p);
212     found = 1;
213 adx 30 }
214     }
215     else if (!ServerInfo.hub && uplink && IsCapable(uplink, CAP_LL))
216     {
217     if (parc > 2)
218     sendto_one(uplink,":%s WHOIS %s :%s",
219     source_p->name, nick, nick);
220     else
221     sendto_one(uplink,":%s WHOIS %s",
222     source_p->name, nick);
223     return;
224     }
225     }
226     else /* wilds is true */
227     {
228     /* disallow wild card whois on lazylink leafs for now */
229     if (!ServerInfo.hub && uplink && IsCapable(uplink, CAP_LL))
230     return;
231    
232 adx 268 if (!IsOper(source_p))
233     {
234     if ((last_used + ConfigFileEntry.pace_wait_simple) > CurrentTime)
235     {
236     sendto_one(source_p, form_str(RPL_LOAD2HI),
237     me.name, source_p->name);
238     return;
239     }
240     else
241     last_used = CurrentTime;
242     }
243    
244 adx 30 /* Oh-oh wilds is true so have to do it the hard expensive way */
245     if (MyClient(source_p))
246     found = global_whois(source_p, nick);
247     }
248    
249     if (!found)
250     {
251     if (!IsDigit(*nick))
252     sendto_one(source_p, form_str(ERR_NOSUCHNICK),
253     me.name, source_p->name, nick);
254     }
255    
256     sendto_one(source_p, form_str(RPL_ENDOFWHOIS),
257     me.name, source_p->name, parv[1]);
258     }
259    
260     /* global_whois()
261     *
262     * Inputs - source_p client to report to
263     * - target_p client to report on
264     * Output - if found return 1
265     * Side Effects - do a single whois on given client
266     * writing results to source_p
267     */
268     static int
269     global_whois(struct Client *source_p, const char *nick)
270     {
271     dlink_node *ptr;
272     struct Client *target_p;
273     int found = 0;
274    
275     DLINK_FOREACH(ptr, global_client_list.head)
276     {
277     target_p = ptr->data;
278    
279     if (!IsClient(target_p))
280     continue;
281    
282     if (!match(nick, target_p->name))
283     continue;
284    
285     assert(target_p->servptr != NULL);
286    
287     /* 'Rules' established for sending a WHOIS reply:
288     *
289     *
290     * - if wildcards are being used dont send a reply if
291     * the querier isnt any common channels and the
292     * client in question is invisible and wildcards are
293     * in use (allow exact matches only);
294     *
295     * - only send replies about common or public channels
296     * the target user(s) are on;
297     */
298    
299     found |= single_whois(source_p, target_p);
300     }
301    
302     return (found);
303     }
304    
305     /* single_whois()
306     *
307     * Inputs - source_p client to report to
308     * - target_p client to report on
309     * Output - if found return 1
310     * Side Effects - do a single whois on given client
311     * writing results to source_p
312     */
313     static int
314     single_whois(struct Client *source_p, struct Client *target_p)
315     {
316     dlink_node *ptr;
317     struct Channel *chptr;
318    
319     if (!IsInvisible(target_p) || target_p == source_p)
320     {
321     /* always show user if they are visible (no +i) */
322     whois_person(source_p, target_p);
323     return 1;
324     }
325    
326     /* target_p is +i. Check if it is on any common channels with source_p */
327     DLINK_FOREACH(ptr, target_p->channel.head)
328     {
329     chptr = ((struct Membership *) ptr->data)->chptr;
330     if (IsMember(source_p, chptr))
331     {
332     whois_person(source_p, target_p);
333     return 1;
334     }
335     }
336    
337     return 0;
338     }
339    
340     /* whois_person()
341     *
342     * inputs - source_p client to report to
343     * - target_p client to report on
344     * output - NONE
345     * side effects -
346     */
347     static void
348     whois_person(struct Client *source_p, struct Client *target_p)
349     {
350     char buf[IRCD_BUFSIZE];
351     dlink_node *lp;
352     struct Client *server_p;
353     struct Channel *chptr;
354     struct Membership *ms;
355     int cur_len = 0;
356     int mlen;
357     char *t = NULL;
358     int tlen;
359     int reply_to_send = NO;
360    
361     server_p = target_p->servptr;
362    
363     sendto_one(source_p, form_str(RPL_WHOISUSER),
364     me.name, source_p->name, target_p->name,
365     target_p->username, target_p->host, target_p->info);
366    
367     cur_len = mlen = ircsprintf(buf, form_str(RPL_WHOISCHANNELS),
368     me.name, source_p->name, target_p->name, "");
369     t = buf + mlen;
370    
371     DLINK_FOREACH(lp, target_p->channel.head)
372     {
373     ms = lp->data;
374     chptr = ms->chptr;
375    
376     if (ShowChannel(source_p, chptr))
377     {
378     /* Don't show local channels if user is doing a remote whois */
379     if (!MyConnect(source_p) && (chptr->chname[0] == '&'))
380     continue;
381    
382     if ((cur_len + 3 + strlen(chptr->chname) + 1) > (IRCD_BUFSIZE - 2))
383     {
384     *(t - 1) = '\0';
385     sendto_one(source_p, "%s", buf);
386     cur_len = mlen;
387     t = buf + mlen;
388     }
389    
390     tlen = ircsprintf(t, "%s%s ", get_member_status(ms, YES), chptr->chname);
391     t += tlen;
392     cur_len += tlen;
393     reply_to_send = YES;
394     }
395     }
396    
397     if (reply_to_send)
398     {
399     *(t - 1) = '\0';
400     sendto_one(source_p, "%s", buf);
401     }
402    
403     if (IsOper(source_p) || !ConfigServerHide.hide_servers || target_p == source_p)
404     sendto_one(source_p, form_str(RPL_WHOISSERVER),
405     me.name, source_p->name, target_p->name,
406     server_p->name, server_p->info);
407     else
408     sendto_one(source_p, form_str(RPL_WHOISSERVER),
409     me.name, source_p->name, target_p->name,
410     ConfigServerHide.hidden_name,
411     ServerInfo.network_desc);
412    
413     if (target_p->away != NULL)
414     sendto_one(source_p, form_str(RPL_AWAY),
415     me.name, source_p->name, target_p->name,
416     target_p->away);
417    
418 adx 660 if (IsSetCallerId(target_p) && !IsSoftCallerId(target_p))
419     sendto_one(source_p, form_str(RPL_TARGUMODEG),
420     me.name, source_p->name, target_p->name);
421    
422 adx 30 if (IsOper(target_p))
423     sendto_one(source_p, form_str((IsAdmin(target_p) &&
424     !IsOperHiddenAdmin(target_p)) ? RPL_WHOISADMIN :
425     RPL_WHOISOPERATOR), me.name, source_p->name, target_p->name);
426    
427     if (IsOper(source_p) && IsCaptured(target_p))
428     sendto_one(source_p, form_str(RPL_ISCAPTURED),
429     me.name, source_p->name, target_p->name);
430    
431 db 280 if (ConfigFileEntry.use_whois_actually)
432 adx 30 {
433 db 280 int show_ip = 0;
434    
435 michael 472 if ((target_p->sockhost[0] != '\0') && irccmp(target_p->sockhost, "0"))
436 db 280 {
437     if ((IsAdmin(source_p) || source_p == target_p))
438     show_ip = 1;
439     else if (IsIPSpoof(target_p))
440     show_ip = (IsOper(source_p) && !ConfigFileEntry.hide_spoof_ips);
441     else
442     show_ip = 1;
443    
444 michael 472 sendto_one(source_p, form_str(RPL_WHOISACTUALLY),
445     me.name, source_p->name, target_p->name,
446     show_ip ? target_p->sockhost : "255.255.255.255");
447 db 280 }
448 adx 30 }
449    
450     if (MyConnect(target_p)) /* Can't do any of this if not local! db */
451     {
452     #ifdef HAVE_LIBCRYPTO
453     if (target_p->localClient->fd.ssl)
454     sendto_one(source_p, form_str(RPL_WHOISSSL),
455     me.name, source_p->name, target_p->name);
456     #endif
457     sendto_one(source_p, form_str(RPL_WHOISIDLE),
458     me.name, source_p->name, target_p->name,
459     CurrentTime - target_p->localClient->last,
460     target_p->firsttime);
461     }
462     }

Properties

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