ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_who.c
(Generate patch)

Comparing:
ircd-hybrid-7.2/modules/m_who.c (file contents), Revision 1011 by michael, Fri Sep 18 10:14:09 2009 UTC vs.
ircd-hybrid/trunk/modules/m_who.c (file contents), Revision 3109 by michael, Thu Mar 6 19:25:12 2014 UTC

# Line 1 | Line 1
1   /*
2 < *  ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 < *  m_who.c: Shows who is on a channel.
2 > *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3   *
4 < *  Copyright (C) 2002 by the past and present ircd coders, and others.
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
# Line 18 | Line 17
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 < *  $Id$
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"
27 #include "common.h"  
28 #include "handlers.h"
29   #include "client.h"
30   #include "channel.h"
31   #include "channel_mode.h"
# Line 35 | Line 35
35   #include "s_serv.h"
36   #include "send.h"
37   #include "irc_string.h"
38 < #include "sprintf_irc.h"
39 < #include "s_conf.h"
40 < #include "msg.h"
38 > #include "conf.h"
39   #include "parse.h"
40   #include "modules.h"
41  
44 static time_t last_used = 0;
45
46 static void m_who(struct Client *, struct Client *, int, char *[]);
47
48 struct Message who_msgtab = {
49  "WHO", 0, 0, 2, 0, MFLG_SLOW, 0,
50  {m_unregistered, m_who, m_ignore, m_ignore, m_who, m_ignore}
51 };
52
53 #ifndef STATIC_MODULES
54 void
55 _modinit(void)
56 {
57  mod_add_cmd(&who_msgtab);
58 }
42  
43 < void
44 < _moddeinit(void)
45 < {
46 <  mod_del_cmd(&who_msgtab);
47 < }
48 <
49 < const char *_version = "$Revision$";
50 < #endif
51 <
69 < static void who_global(struct Client *, char *, int);
70 < static void do_who(struct Client *, struct Client *,
71 <                   const char *, const char *);
72 < static void do_who_on_channel(struct Client *, struct Channel *,
73 <                              const char *, int, int);
74 <
75 < /*
76 < ** m_who
77 < **      parv[0] = sender prefix
78 < **      parv[1] = nickname mask list
79 < **      parv[2] = additional selection flag, only 'o' for now.
80 < */
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 < m_who(struct Client *client_p, struct Client *source_p,
54 <      int parc, char *parv[])
53 > do_who(struct Client *source_p, struct Client *target_p,
54 >       const char *chname, const char *op_flags)
55   {
56 <  struct Client *target_p;
86 <  char *mask = parv[1];
87 <  dlink_node *lp;
88 <  int server_oper = parc > 2 ? (*parv[2] == 'o') : 0; /* Show OPERS only */
89 <  struct Channel *chptr;
90 <
91 <  /* See if mask is there, collapse it or return if not there */
92 <  if (EmptyString(mask))
93 <  {
94 <    who_global(source_p, mask, server_oper);
95 <    sendto_one(source_p, form_str(RPL_ENDOFWHO),
96 <               me.name, source_p->name, "*");
97 <    return;
98 <  }
56 >  char status[IRCD_BUFSIZE];
57  
58 <  /* mask isn't NULL at this point. repeat after me... -db */
59 <  collapse(mask);
60 <
61 <  /* '/who *' */
104 <  if (mask[0] == '*' && !mask[1])
105 <  {
106 <    if ((lp = source_p->channel.head) != NULL)
107 <    {
108 <      struct Channel *mychannel = ((struct Membership *)lp->data)->chptr;
109 <      do_who_on_channel(source_p, mychannel, mychannel->chname, YES,
110 <                        server_oper);
111 <    }
112 <
113 <    sendto_one(source_p, form_str(RPL_ENDOFWHO), me.name, source_p->name, "*");
114 <    return;
115 <  }
116 <
117 <  /* '/who #some_channel' */
118 <  if (IsChanPrefix(*mask))
119 <  {
120 <    /* List all users on a given channel */
121 <    if ((chptr = hash_find_channel(mask)) != NULL)
122 <    {
123 <      if (IsMember(source_p, chptr))
124 <        do_who_on_channel(source_p, chptr, chptr->chname, YES, server_oper);
125 <      else if (!SecretChannel(chptr))
126 <        do_who_on_channel(source_p, chptr, chptr->chname, NO, server_oper);
127 <    }
128 <
129 <    sendto_one(source_p, form_str(RPL_ENDOFWHO),
130 <               me.name, source_p->name, mask);
131 <    return;
132 <  }
133 <
134 <  /* '/who nick' */
135 <  if (((target_p = find_client(mask)) != NULL) &&
136 <      IsClient(target_p) && (!server_oper || IsOper(target_p)))
137 <  {
138 <    DLINK_FOREACH(lp, target_p->channel.head)
139 <    {
140 <      chptr = ((struct Membership *) lp->data)->chptr;
141 <      if (PubChannel(chptr) || IsMember(source_p, chptr))
142 <        break;
143 <    }
144 <
145 <    if (lp != NULL)
146 <      do_who(source_p, target_p, chptr->chname,
147 <             get_member_status(lp->data, NO));
148 <    else
149 <      do_who(source_p, target_p, NULL, "");
150 <
151 <    sendto_one(source_p, form_str(RPL_ENDOFWHO),
152 <               me.name, source_p->name, mask);
153 <    return;
154 <  }
155 <
156 <  /* '/who 0' */
157 <  if (mask[0] == '0' && !mask[1])
158 <    who_global(source_p, NULL, server_oper);
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 <    who_global(source_p, mask, server_oper);
64 <
65 < /* Wasn't a nick, wasn't a channel, wasn't a '*' so ... */
66 <  sendto_one(source_p, form_str(RPL_ENDOFWHO),
67 <             me.name, source_p->name, mask);
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_numeric(source_p, &me, RPL_WHOREPLY,
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_numeric(source_p, &me, RPL_WHOREPLY,
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
# Line 179 | Line 94 | 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;
183 <  struct Client *target_p;
97 >  dlink_node *ptr = NULL;
98  
99    DLINK_FOREACH(ptr, chptr->members.head)
100    {
101 <    target_p = ((struct Membership *)ptr->data)->client_p;
101 >    struct Client *target_p = ((struct Membership *)ptr->data)->client_p;
102  
103 <    if (!IsInvisible(target_p) || IsMarked(target_p))
103 >    if (!HasUMode(target_p, UMODE_INVISIBLE) || HasFlag(target_p, FLAGS_MARK))
104        continue;
105  
106 <    if (server_oper && !IsOper(target_p))
107 <      continue;
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 <    SetMark(target_p);
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 || IsOper(source_p)) &&
119 <       match(mask, target_p->servptr->name)) ||
120 <      match(mask, target_p->info))
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  
# Line 228 | Line 144 | who_global(struct Client *source_p, char
144   {
145    struct Channel *chptr;
146    struct Client *target_p;
147 <  dlink_node *lp;
232 <  dlink_node *lp_next;
233 <  dlink_node *gcptr;
234 <  dlink_node *gcptr_next;
147 >  dlink_node *lp = NULL, *gcptr = NULL;
148    int maxmatches = 500;
149 +  static time_t last_used = 0;
150  
151 <  if (!IsOper(source_p))
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);
156 >      sendto_one_numeric(source_p, &me, RPL_LOAD2HI);
157        return;
158      }
159  
# Line 247 | Line 161 | who_global(struct Client *source_p, char
161    }
162  
163    /* first, list all matching invisible clients on common channels */
164 <  DLINK_FOREACH_SAFE(lp, lp_next, source_p->channel.head)
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_SAFE(gcptr, gcptr_next, global_client_list.head)
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 (IsInvisible(target_p))
178 >    if (HasUMode(target_p, UMODE_INVISIBLE))
179      {
180 <      ClearMark(target_p);
180 >      DelFlag(target_p, FLAGS_MARK);
181        continue;
182      }
183  
184 <    if (server_oper && !IsOper(target_p))
185 <      continue;
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))
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  
# Line 303 | Line 219 | 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, *ptr_next = NULL;
307 <  struct Client *target_p;
308 <  struct Membership *ms;
222 >  dlink_node *ptr = NULL;
223  
224 <  DLINK_FOREACH_SAFE(ptr, ptr_next, chptr->members.head)
224 >  DLINK_FOREACH(ptr, chptr->members.head)
225    {
226 <    ms = ptr->data;
227 <    target_p = ms->client_p;
226 >    struct Membership *ms = ptr->data;
227 >    struct Client *target_p = ms->client_p;
228  
229 <    if (member || !IsInvisible(target_p))
229 >    if (member || !HasUMode(target_p, UMODE_INVISIBLE))
230      {
231 <      if (server_oper && !IsOper(target_p))
232 <        continue;
233 <      do_who(source_p, target_p, chname, get_member_status(ms, NO));
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 < /* do_who()
241 < *
242 < * inputs       - pointer to client requesting who
243 < *              - pointer to client to do who on
244 < *              - The reported name
245 < *              - channel flags
246 < * output       - NONE
247 < * side effects - do a who on given person
248 < */
333 < static void
334 < do_who(struct Client *source_p, struct Client *target_p,
335 <       const char *chname, const char *op_flags)
240 > /*
241 > ** m_who
242 > **      parv[0] = command
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 <  char status[6];
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 <  if (IsOper(source_p))
257 <    ircsprintf(status, "%c%s%s%s", target_p->away ? 'G' : 'H',
258 <               IsOper(target_p) ? "*" : "", IsCaptured(target_p) ? "#" : "", op_flags);
259 <  else
260 <    ircsprintf(status, "%c%s%s", target_p->away ? 'G' : 'H',
261 <               IsOper(target_p) ? "*" : "", op_flags);
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_numeric(source_p, &me, RPL_ENDOFWHO, "*");
261 >    return 0;
262 >  }
263  
264 <  if (ConfigServerHide.hide_servers)
264 >  /* mask isn't NULL at this point. repeat after me... -db */
265 >  collapse(mask);
266 >
267 >  /* '/who #some_channel' */
268 >  if (IsChanPrefix(*mask))
269    {
270 <    sendto_one(source_p, form_str(RPL_WHOREPLY), me.name, source_p->name,
271 <               (chname) ? (chname) : "*",
272 <               target_p->username, target_p->host,
273 <               IsOper(source_p) ? target_p->servptr->name : "*",
274 <               target_p->name, status, 0, target_p->info);
270 >    /* List all users on a given channel */
271 >    if ((chptr = hash_find_channel(mask)) != NULL)
272 >    {
273 >      if (IsMember(source_p, chptr))
274 >        do_who_on_channel(source_p, chptr, chptr->chname, 1, server_oper);
275 >      else if (!SecretChannel(chptr))
276 >        do_who_on_channel(source_p, chptr, chptr->chname, 0, server_oper);
277 >    }
278 >
279 >    sendto_one_numeric(source_p, &me, RPL_ENDOFWHO, mask);
280 >    return 0;
281    }
282 <  else
282 >
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 <    sendto_one(source_p, form_str(RPL_WHOREPLY), me.name, source_p->name,
288 <               (chname) ? (chname) : "*", target_p->username,
289 <               target_p->host, target_p->servptr->name, target_p->name,
290 <               status, target_p->hopcount, target_p->info);
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_numeric(source_p, &me, RPL_ENDOFWHO, mask);
301 >    return 0;
302 >  }
303 >
304 >  /* '/who *' */
305 >  if (!strcmp(mask, "*"))
306 >  {
307 >    if ((lp = source_p->channel.head) != NULL)
308 >    {
309 >      struct Channel *mychannel = ((struct Membership *)lp->data)->chptr;
310 >      do_who_on_channel(source_p, mychannel, mychannel->chname, 1,
311 >                        server_oper);
312 >    }
313 >
314 >    sendto_one_numeric(source_p, &me, RPL_ENDOFWHO, "*");
315 >    return 0;
316    }
317 +
318 +  /* '/who 0' */
319 +  if (!strcmp(mask, "0"))
320 +    who_global(source_p, NULL, server_oper);
321 +  else
322 +    who_global(source_p, mask, server_oper);
323 +
324 +  /* Wasn't a nick, wasn't a channel, wasn't a '*' so ... */
325 +  sendto_one_numeric(source_p, &me, RPL_ENDOFWHO, mask);
326 +  return 0;
327 + }
328 +
329 + static struct Message who_msgtab =
330 + {
331 +  "WHO", 0, 0, 2, MAXPARA, MFLG_SLOW, 0,
332 +  { m_unregistered, m_who, m_ignore, m_ignore, m_who, m_ignore }
333 + };
334 +
335 + static void
336 + module_init(void)
337 + {
338 +  mod_add_cmd(&who_msgtab);
339   }
340 +
341 + static void
342 + module_exit(void)
343 + {
344 +  mod_del_cmd(&who_msgtab);
345 + }
346 +
347 + struct module module_entry =
348 + {
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 + };

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)