ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_whois.c
Revision: 9419
Committed: Sat Jun 13 16:33:51 2020 UTC (5 years, 2 months ago) by michael
Content type: text/x-csrc
File size: 11004 byte(s)
Log Message:
- Remove hardcoded numeric digit from RPL_WHOISCHANNELS

File Contents

# User Rev Content
1 adx 30 /*
2 michael 2820 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 adx 30 *
4 michael 9101 * Copyright (c) 1997-2020 ircd-hybrid development team
5 adx 30 *
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 michael 4565 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 adx 30 * USA
20     */
21    
22 michael 2820 /*! \file m_whois.c
23     * \brief Includes required functions for processing the WHOIS command.
24     * \version $Id$
25     */
26    
27 adx 30 #include "stdinc.h"
28 michael 1011 #include "list.h"
29 adx 30 #include "client.h"
30 michael 8484 #include "client_svstag.h"
31 adx 30 #include "hash.h"
32     #include "channel.h"
33     #include "channel_mode.h"
34     #include "ircd.h"
35     #include "numeric.h"
36 michael 1309 #include "conf.h"
37 michael 3347 #include "misc.h"
38     #include "server.h"
39     #include "user.h"
40 adx 30 #include "send.h"
41     #include "irc_string.h"
42     #include "parse.h"
43     #include "modules.h"
44    
45 michael 1243
46 michael 3513 static int
47 michael 9081 whois_can_see_channels(struct Channel *channel,
48 michael 3513 struct Client *source_p,
49     struct Client *target_p)
50     {
51 michael 9081 if (PubChannel(channel) && !HasUMode(target_p, UMODE_HIDECHANS))
52 michael 3513 return 1;
53    
54 michael 9081 if (source_p == target_p || IsMember(source_p, channel))
55 michael 3513 return 1;
56    
57 michael 5528 if (HasUMode(source_p, UMODE_OPER))
58 michael 3513 return 2;
59     return 0;
60     }
61    
62 adx 30 /* whois_person()
63     *
64     * inputs - source_p client to report to
65     * - target_p client to report on
66     * output - NONE
67     * side effects -
68     */
69     static void
70     whois_person(struct Client *source_p, struct Client *target_p)
71     {
72 michael 7687 dlink_node *node;
73 michael 5551 const struct ServicesTag *svstag = NULL;
74 adx 30
75 michael 3109 sendto_one_numeric(source_p, &me, RPL_WHOISUSER, target_p->name,
76     target_p->username, target_p->host,
77     target_p->info);
78 adx 30
79 michael 9419 if (dlink_list_length(&target_p->channel))
80 adx 30 {
81 michael 9419 char buf[IRCD_BUFSIZE];
82     char *bufptr = buf;
83 adx 30
84 michael 9419 /* :me.name 319 source_p->name target_p->name :~@#chan1 +#chan2 #chan3 ...\r\n */
85     /* 1 23456 7 89 0 1 */
86     size_t len = strlen(me.name) + strlen(source_p->name) + strlen(target_p->name) + 11;
87    
88     DLINK_FOREACH(node, target_p->channel.head)
89 adx 30 {
90 michael 9419 const struct ChannelMember *member = node->data;
91     int show = whois_can_see_channels(member->channel, source_p, target_p);
92    
93     if (show)
94 adx 30 {
95 michael 9419 if ((bufptr - buf) + member->channel->name_len + 1 + (show == 2) + 3 /* 3 for @%+ */ + len > sizeof(buf))
96     {
97     *(bufptr - 1) = '\0';
98     sendto_one_numeric(source_p, &me, RPL_WHOISCHANNELS, target_p->name, buf);
99     bufptr = buf;
100     }
101    
102     bufptr += snprintf(bufptr, sizeof(buf) - (bufptr - buf), "%s%s%s ",
103     show == 2 ? "~" : "", get_member_status(member, true), member->channel->name);
104 adx 30 }
105 michael 9419 }
106 adx 30
107 michael 9419 if (bufptr != buf)
108     {
109     *(bufptr - 1) = '\0';
110     sendto_one_numeric(source_p, &me, RPL_WHOISCHANNELS, target_p->name, buf);
111 adx 30 }
112     }
113    
114 michael 2748 if ((ConfigServerHide.hide_servers || IsHidden(target_p->servptr)) &&
115 michael 7870 !(HasUMode(source_p, UMODE_OPER) || source_p == target_p))
116 michael 3109 sendto_one_numeric(source_p, &me, RPL_WHOISSERVER, target_p->name,
117     ConfigServerHide.hidden_name,
118 michael 4340 ConfigServerInfo.network_desc);
119 adx 30 else
120 michael 3109 sendto_one_numeric(source_p, &me, RPL_WHOISSERVER, target_p->name,
121     target_p->servptr->name, target_p->servptr->info);
122 adx 30
123 michael 1164 if (HasUMode(target_p, UMODE_REGISTERED))
124 michael 3109 sendto_one_numeric(source_p, &me, RPL_WHOISREGNICK, target_p->name);
125 michael 1158
126 michael 6827 if (strcmp(target_p->account, "*"))
127 michael 3109 sendto_one_numeric(source_p, &me, RPL_WHOISACCOUNT, target_p->name,
128 michael 4819 target_p->account, "is");
129 michael 2478
130 michael 1483 if (target_p->away[0])
131 michael 3109 sendto_one_numeric(source_p, &me, RPL_AWAY, target_p->name,
132     target_p->away);
133 adx 30
134 michael 5517 if (HasUMode(target_p, UMODE_CALLERID | UMODE_SOFTCALLERID))
135 michael 2580 {
136 michael 8719 bool callerid = HasUMode(target_p, UMODE_CALLERID) != 0;
137 michael 3109
138     sendto_one_numeric(source_p, &me, RPL_TARGUMODEG, target_p->name,
139     callerid ? "+g" : "+G",
140     callerid ? "server side ignore" :
141     "server side ignore with the exception of common channels");
142 michael 2580 }
143 adx 660
144 michael 8481 if (HasUMode(target_p, UMODE_OPER) || HasFlag(target_p, FLAGS_SERVICE))
145     {
146     if (!HasUMode(target_p, UMODE_HIDDEN) || HasUMode(source_p, UMODE_OPER))
147     {
148     if (target_p->svstags.head)
149     svstag = target_p->svstags.head->data;
150 michael 5551
151 michael 8603 if (svstag == NULL || svstag->numeric != RPL_WHOISOPERATOR)
152 michael 8481 {
153     const char *text;
154     if (HasFlag(target_p, FLAGS_SERVICE))
155     text = "is a Network Service";
156     else if (HasUMode(target_p, UMODE_ADMIN))
157     text = "is a Server Administrator";
158     else /* HasUMode(target_p, UMODE_OPER) == true */
159     text = "is an IRC Operator";
160     sendto_one_numeric(source_p, &me, RPL_WHOISOPERATOR, target_p->name, text);
161     }
162     }
163     }
164 adx 30
165 michael 5554 DLINK_FOREACH(node, target_p->svstags.head)
166 michael 5551 {
167 michael 5554 svstag = node->data;
168 michael 5551
169 michael 5553 if (svstag->numeric == RPL_WHOISOPERATOR)
170     if (HasUMode(target_p, UMODE_HIDDEN) && !HasUMode(source_p, UMODE_OPER))
171     continue;
172    
173 michael 8481 if (svstag->umodes == 0 || HasUMode(source_p, svstag->umodes))
174 michael 5551 sendto_one_numeric(source_p, &me, svstag->numeric | SND_EXPLICIT, "%s :%s",
175     target_p->name, svstag->tag);
176     }
177    
178 michael 2511 if (HasUMode(target_p, UMODE_WEBIRC))
179 michael 3109 sendto_one_numeric(source_p, &me, RPL_WHOISTEXT, target_p->name,
180     "User connected using a webirc gateway");
181 michael 2511
182 michael 5528 if (HasUMode(source_p, UMODE_OPER) || source_p == target_p)
183 michael 2529 {
184 michael 9419 char buf[UMODE_MAX_STR];
185 michael 2529 char *m = buf;
186 michael 9419
187 michael 2529 *m++ = '+';
188 michael 5392 for (const struct user_modes *tab = umode_tab; tab->c; ++tab)
189 michael 5400 if (HasUMode(target_p, tab->flag))
190     *m++ = tab->c;
191 michael 2529 *m = '\0';
192    
193 michael 3109 sendto_one_numeric(source_p, &me, RPL_WHOISMODES, target_p->name, buf);
194 michael 2529 }
195    
196 michael 5631 if (HasUMode(source_p, UMODE_OPER) || source_p == target_p)
197 michael 6831 sendto_one_numeric(source_p, &me, RPL_WHOISACTUALLY, target_p->name,
198 michael 8214 target_p->username, target_p->realhost,
199 michael 6831 target_p->sockhost);
200 db 280
201 michael 9157 if (HasUMode(target_p, UMODE_SECURE))
202 michael 3109 sendto_one_numeric(source_p, &me, RPL_WHOISSECURE, target_p->name);
203 michael 2246
204 michael 9408 if (!EmptyString(target_p->tls_certfp))
205 michael 8603 if (HasUMode(source_p, UMODE_OPER) || source_p == target_p)
206 michael 9408 sendto_one_numeric(source_p, &me, RPL_WHOISCERTFP, target_p->name, target_p->tls_certfp);
207 michael 2229
208 michael 1997 if (MyConnect(target_p))
209 michael 3506 if (!HasUMode(target_p, UMODE_HIDEIDLE) || HasUMode(source_p, UMODE_OPER) ||
210     source_p == target_p)
211     sendto_one_numeric(source_p, &me, RPL_WHOISIDLE, target_p->name,
212 michael 5544 client_get_idle_time(source_p, target_p),
213 michael 8919 target_p->connection->created_real);
214 michael 7758
215     if (HasUMode(target_p, UMODE_SPY) && source_p != target_p)
216     sendto_one_notice(target_p, &me, ":*** Notice -- %s (%s@%s) [%s] is doing a /whois on you",
217     source_p->name, source_p->username, source_p->host, source_p->servptr->name);
218 adx 30 }
219 michael 1230
220 michael 1997 /* do_whois()
221     *
222     * inputs - pointer to /whois source
223     * - number of parameters
224     * - pointer to parameters array
225     * output - pointer to void
226     * side effects - Does whois
227     */
228     static void
229 michael 2354 do_whois(struct Client *source_p, const char *name)
230 michael 1997 {
231 michael 8431 struct Client *target_p;
232 michael 1997
233 michael 6255 if ((target_p = hash_find_client(name)) && IsClient(target_p))
234 michael 1997 whois_person(source_p, target_p);
235 michael 6255 else
236 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, name);
237 michael 1997
238 michael 3109 sendto_one_numeric(source_p, &me, RPL_ENDOFWHOIS, name);
239 michael 1997 }
240    
241 michael 3295 /*! \brief WHOIS command handler
242     *
243     * \param source_p Pointer to allocated Client struct from which the message
244     * originally comes from. This can be a local or remote client.
245     * \param parc Integer holding the number of supplied arguments.
246     * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
247     * pointers.
248     * \note Valid arguments for this command are:
249     * - parv[0] = command
250     * - parv[1] = nickname/servername
251     * - parv[2] = nickname
252     */
253 michael 9077 static void
254 michael 3156 m_whois(struct Client *source_p, int parc, char *parv[])
255 michael 1997 {
256 michael 7330 static uintmax_t last_used = 0;
257 michael 1997
258 michael 9374 if (EmptyString(parv[1]))
259 michael 1997 {
260 michael 3109 sendto_one_numeric(source_p, &me, ERR_NONICKNAMEGIVEN);
261 michael 9077 return;
262 michael 1997 }
263    
264 michael 9374 if (!EmptyString(parv[2]))
265 michael 1997 {
266     /* seeing as this is going across servers, we should limit it */
267 michael 8903 if ((last_used + ConfigGeneral.pace_wait_simple) > event_base->time.sec_monotonic)
268 michael 1997 {
269 michael 4759 sendto_one_numeric(source_p, &me, RPL_LOAD2HI, "WHOIS");
270 michael 9077 return;
271 michael 1997 }
272    
273 michael 8903 last_used = event_base->time.sec_monotonic;
274 michael 1997
275     /*
276     * if we have serverhide enabled, they can either ask the clients
277 michael 4298 * server, or our server.. I don't see why they would need to ask
278 michael 1997 * anything else for info about the client.. --fl_
279     */
280 michael 2196 if (ConfigServerHide.disable_remote_commands)
281 michael 1997 parv[1] = parv[2];
282    
283 michael 9397 if (server_hunt(source_p, ":%s WHOIS %s :%s", 1, parv)->ret != HUNTED_ISME)
284 michael 9077 return;
285 michael 1997
286     parv[1] = parv[2];
287     }
288    
289 michael 2354 do_whois(source_p, parv[1]);
290 michael 1997 }
291    
292 michael 3295 /*! \brief WHOIS command handler
293     *
294     * \param source_p Pointer to allocated Client struct from which the message
295     * originally comes from. This can be a local or remote client.
296     * \param parc Integer holding the number of supplied arguments.
297     * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
298     * pointers.
299     * \note Valid arguments for this command are:
300     * - parv[0] = command
301     * - parv[1] = nickname/servername
302     * - parv[2] = nickname
303     */
304 michael 9077 static void
305 michael 3156 mo_whois(struct Client *source_p, int parc, char *parv[])
306 michael 1997 {
307 michael 9374 if (EmptyString(parv[1]))
308 michael 1997 {
309 michael 3109 sendto_one_numeric(source_p, &me, ERR_NONICKNAMEGIVEN);
310 michael 9077 return;
311 michael 1997 }
312    
313 michael 9374 if (!EmptyString(parv[2]))
314 michael 1997 {
315 michael 9397 if (server_hunt(source_p, ":%s WHOIS %s :%s", 1, parv)->ret != HUNTED_ISME)
316 michael 9077 return;
317 michael 1997
318     parv[1] = parv[2];
319     }
320    
321 michael 2354 do_whois(source_p, parv[1]);
322 michael 1997 }
323    
324 michael 2820 static struct Message whois_msgtab =
325     {
326 michael 5881 .cmd = "WHOIS",
327 michael 9374 .handlers[UNREGISTERED_HANDLER] = { .handler = m_unregistered },
328     .handlers[CLIENT_HANDLER] = { .handler = m_whois },
329     .handlers[SERVER_HANDLER] = { .handler = mo_whois },
330     .handlers[ENCAP_HANDLER] = { .handler = m_ignore },
331     .handlers[OPER_HANDLER] = { .handler = mo_whois }
332 michael 1230 };
333    
334     static void
335     module_init(void)
336     {
337     mod_add_cmd(&whois_msgtab);
338     }
339    
340     static void
341     module_exit(void)
342     {
343     mod_del_cmd(&whois_msgtab);
344     }
345    
346 michael 2820 struct module module_entry =
347     {
348 michael 1230 .version = "$Revision$",
349     .modinit = module_init,
350     .modexit = module_exit,
351     };

Properties

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