ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/modules/m_whois.c
Revision: 1241
Committed: Thu Sep 29 20:26:09 2011 UTC (15 years ago) by michael
Content type: text/x-csrc
File size: 11425 byte(s)
Log Message:
- move firsttime, since, and lasttime Client struct members to LocalUser struct
- m_watch.c: show_watch() now properly reports signon times. This also fixes
  an invalid signon time of zero for remote clients.

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

Properties

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