/src/irssi/src/fe-common/irc/fe-whois.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 1999-2004 Timo Sirainen */ |
2 | | |
3 | | #include "module.h" |
4 | | #include <irssi/src/fe-common/irc/module-formats.h> |
5 | | #include <irssi/src/core/signals.h> |
6 | | #include <irssi/src/core/levels.h> |
7 | | #include <irssi/src/core/misc.h> |
8 | | #include <irssi/src/core/settings.h> |
9 | | #include <irssi/src/core/recode.h> |
10 | | |
11 | | #include <irssi/src/irc/core/irc-servers.h> |
12 | | |
13 | | #include <irssi/src/fe-common/core/printtext.h> |
14 | | |
15 | | static void event_whois(IRC_SERVER_REC *server, const char *data) |
16 | 3.09k | { |
17 | 3.09k | char *params, *nick, *user, *host, *realname, *recoded; |
18 | | |
19 | 3.09k | g_return_if_fail(data != NULL); |
20 | | |
21 | 3.09k | params = event_get_params(data, 6, NULL, &nick, &user, |
22 | 3.09k | &host, NULL, &realname); |
23 | 3.09k | recoded = recode_in(SERVER(server), realname, nick); |
24 | 3.09k | printformat(server, nick, MSGLEVEL_CRAP, |
25 | 3.09k | IRCTXT_WHOIS, nick, user, host, recoded); |
26 | 3.09k | g_free(params); |
27 | 3.09k | g_free(recoded); |
28 | 3.09k | } |
29 | | |
30 | | static void event_whois_special(IRC_SERVER_REC *server, const char *data) |
31 | 7.32k | { |
32 | 7.32k | char *params, *nick, *str; |
33 | | |
34 | 7.32k | g_return_if_fail(data != NULL); |
35 | | |
36 | 7.32k | params = event_get_params(data, 3 | PARAM_FLAG_GETREST, NULL, &nick, &str); |
37 | 7.32k | printformat(server, nick, MSGLEVEL_CRAP, |
38 | 7.32k | IRCTXT_WHOIS_SPECIAL, nick, str); |
39 | 7.32k | g_free(params); |
40 | 7.32k | } |
41 | | |
42 | | static void event_whois_idle(IRC_SERVER_REC *server, const char *data) |
43 | 783 | { |
44 | 783 | char *params, *nick, *secstr, *signonstr, *rest, *timestr; |
45 | 783 | long days, hours, mins, secs; |
46 | 783 | time_t signon; |
47 | | |
48 | 783 | g_return_if_fail(data != NULL); |
49 | | |
50 | 783 | params = event_get_params(data, 5 | PARAM_FLAG_GETREST, NULL, |
51 | 783 | &nick, &secstr, &signonstr, &rest); |
52 | | |
53 | 783 | secs = atol(secstr); |
54 | 783 | signon = strstr(rest, "signon time") == NULL ? 0 : |
55 | 783 | (time_t) atol(signonstr); |
56 | | |
57 | 783 | days = secs/3600/24; |
58 | 783 | hours = (secs%(3600*24))/3600; |
59 | 783 | mins = (secs%3600)/60; |
60 | 783 | secs %= 60; |
61 | | |
62 | 783 | if (signon == 0) |
63 | 358 | printformat(server, nick, MSGLEVEL_CRAP, IRCTXT_WHOIS_IDLE, |
64 | 783 | nick, days, hours, mins, secs); |
65 | 425 | else { |
66 | 425 | timestr = my_asctime(signon); |
67 | 425 | printformat(server, nick, MSGLEVEL_CRAP, |
68 | 425 | IRCTXT_WHOIS_IDLE_SIGNON, |
69 | 425 | nick, days, hours, mins, secs, timestr); |
70 | 425 | g_free(timestr); |
71 | 425 | } |
72 | 783 | g_free(params); |
73 | 783 | } |
74 | | |
75 | | static void event_whois_server(IRC_SERVER_REC *server, const char *data) |
76 | 725 | { |
77 | 725 | char *params, *nick, *whoserver, *desc; |
78 | | |
79 | 725 | g_return_if_fail(data != NULL); |
80 | | |
81 | 725 | params = event_get_params(data, 4, NULL, &nick, &whoserver, &desc); |
82 | 725 | printformat(server, nick, MSGLEVEL_CRAP, |
83 | 725 | IRCTXT_WHOIS_SERVER, nick, whoserver, desc); |
84 | 725 | g_free(params); |
85 | 725 | } |
86 | | |
87 | | static void event_whois_oper(IRC_SERVER_REC *server, const char *data) |
88 | 3.17k | { |
89 | 3.17k | char *params, *nick, *type; |
90 | | |
91 | 3.17k | g_return_if_fail(data != NULL); |
92 | | |
93 | 3.17k | params = event_get_params(data, 3, NULL, &nick, &type); |
94 | | |
95 | | /* Bugfix: http://bugs.irssi.org/?do=details&task_id=99 |
96 | | * Author: Geert Hauwaerts <geert@irssi.org> |
97 | | * Date: Wed Sep 15 20:17:24 CEST 2004 |
98 | | */ |
99 | | |
100 | 3.17k | if ((!strncmp(type, "is an ", 6)) || (!strncmp(type, "is a ", 5))) { |
101 | 1.89k | type += 5; |
102 | 1.89k | if (*type == ' ') type++; |
103 | 1.89k | } |
104 | | |
105 | 3.17k | if (*type == '\0') |
106 | 537 | type = "IRC Operator"; |
107 | | |
108 | 3.17k | printformat(server, nick, MSGLEVEL_CRAP, |
109 | 3.17k | IRCTXT_WHOIS_OPER, nick, type); |
110 | 3.17k | g_free(params); |
111 | 3.17k | } |
112 | | |
113 | | static void event_whois_modes(IRC_SERVER_REC *server, const char *data) |
114 | 1.64k | { |
115 | 1.64k | char *params, *nick, *modes; |
116 | | |
117 | 1.64k | g_return_if_fail(data != NULL); |
118 | | |
119 | 1.64k | params = event_get_params(data, 3 | PARAM_FLAG_GETREST, |
120 | 1.64k | NULL, &nick, &modes); |
121 | 1.64k | if (!strncmp(modes, "is using modes ", 15)) |
122 | 569 | modes += 15; |
123 | 1.64k | printformat(server, nick, MSGLEVEL_CRAP, |
124 | 1.64k | IRCTXT_WHOIS_MODES, nick, modes); |
125 | 1.64k | g_free(params); |
126 | 1.64k | } |
127 | | |
128 | | static void event_whois_realhost(IRC_SERVER_REC *server, const char *data) |
129 | 8.24k | { |
130 | 8.24k | char *params, *nick, *txt_real, *txt_hostname, *hostname; |
131 | | |
132 | 8.24k | g_return_if_fail(data != NULL); |
133 | | |
134 | | /* <yournick> real hostname <nick> <hostname> */ |
135 | 8.24k | params = event_get_params(data, 5, NULL, &nick, &txt_real, |
136 | 8.24k | &txt_hostname, &hostname); |
137 | 8.24k | if (g_strcmp0(txt_real, "real") != 0 || |
138 | 8.24k | g_strcmp0(txt_hostname, "hostname") != 0) { |
139 | | /* <yournick> <nick> :... from <hostname> */ |
140 | 6.17k | g_free(params); |
141 | 6.17k | params = event_get_params(data, 3, NULL, &nick, &hostname); |
142 | | |
143 | 6.17k | hostname = strstr(hostname, "from "); |
144 | 6.17k | if (hostname != NULL) hostname += 5; |
145 | 6.17k | } |
146 | | |
147 | 8.24k | if (hostname != NULL) { |
148 | 2.76k | if (!strncmp(hostname, "*@", 2)) |
149 | 670 | hostname += 2; |
150 | 2.76k | printformat(server, nick, MSGLEVEL_CRAP, |
151 | 2.76k | IRCTXT_WHOIS_REALHOST, nick, hostname, ""); |
152 | 5.47k | } else { |
153 | 5.47k | event_whois_special(server, data); |
154 | 5.47k | } |
155 | 8.24k | g_free(params); |
156 | 8.24k | } |
157 | | |
158 | | static void event_whois_usermode326(IRC_SERVER_REC *server, const char *data) |
159 | 470 | { |
160 | 470 | char *params, *nick, *usermode; |
161 | | |
162 | 470 | g_return_if_fail(data != NULL); |
163 | | |
164 | | /* <yournick> <nick> :has oper privs: <mode> */ |
165 | 470 | params = event_get_params(data, 3, NULL, &nick, &usermode); |
166 | 470 | printformat(server, nick, MSGLEVEL_CRAP, |
167 | 470 | IRCTXT_WHOIS_USERMODE, nick, usermode); |
168 | 470 | g_free(params); |
169 | 470 | } |
170 | | |
171 | | static void event_whois_realhost327(IRC_SERVER_REC *server, const char *data) |
172 | 1.04k | { |
173 | 1.04k | char *params, *nick, *hostname, *ip, *text; |
174 | | |
175 | 1.04k | g_return_if_fail(data != NULL); |
176 | | |
177 | | /* <yournick> <hostname> <ip> :Real hostname/IP */ |
178 | 1.04k | params = event_get_params(data, 5, NULL, &nick, &hostname, &ip, &text); |
179 | 1.04k | if (*text != '\0') { |
180 | 364 | printformat(server, nick, MSGLEVEL_CRAP, |
181 | 364 | IRCTXT_WHOIS_REALHOST, nick, hostname, ip); |
182 | 679 | } else { |
183 | 679 | event_whois_special(server, data); |
184 | 679 | } |
185 | 1.04k | g_free(params); |
186 | 1.04k | } |
187 | | |
188 | | static void event_whois_realhost338(IRC_SERVER_REC *server, const char *data) |
189 | 1.64k | { |
190 | 1.64k | char *params, *nick, *arg1, *arg2, *arg3; |
191 | | |
192 | 1.64k | g_return_if_fail(data != NULL); |
193 | | |
194 | | /* |
195 | | * :<server> 338 <yournick> <nick> <user>@<host> <ip> :Actual user@host, actual IP |
196 | | * (ircu) or |
197 | | * :<server> 338 <yournick> <nick> <ip> :actually using host |
198 | | * (ratbox) |
199 | | */ |
200 | 1.64k | params = event_get_params(data, 5, NULL, &nick, &arg1, &arg2, &arg3); |
201 | 1.64k | if (*arg3 != '\0') { |
202 | 374 | printformat(server, nick, MSGLEVEL_CRAP, |
203 | 374 | IRCTXT_WHOIS_REALHOST, nick, arg1, arg2); |
204 | 1.27k | } else if (*arg2 != '\0') { |
205 | 656 | printformat(server, nick, MSGLEVEL_CRAP, |
206 | 656 | IRCTXT_WHOIS_REALHOST, nick, arg1, ""); |
207 | 656 | } else { |
208 | 615 | event_whois_special(server, data); |
209 | 615 | } |
210 | 1.64k | g_free(params); |
211 | 1.64k | } |
212 | | |
213 | | static void event_whois_usermode(IRC_SERVER_REC *server, const char *data) |
214 | 816 | { |
215 | 816 | char *params, *txt_usermodes, *nick, *usermode; |
216 | | |
217 | 816 | g_return_if_fail(data != NULL); |
218 | | |
219 | 816 | params = event_get_params(data, 4, NULL, &txt_usermodes, |
220 | 816 | &nick, &usermode); |
221 | | |
222 | 816 | if (g_strcmp0(txt_usermodes, "usermodes") == 0) { |
223 | | /* <yournick> usermodes <nick> usermode */ |
224 | 262 | printformat(server, nick, MSGLEVEL_CRAP, |
225 | 262 | IRCTXT_WHOIS_USERMODE, nick, usermode); |
226 | 554 | } else { |
227 | 554 | event_whois_special(server, data); |
228 | 554 | } |
229 | 816 | g_free(params); |
230 | 816 | } |
231 | | |
232 | | static void hide_safe_channel_id(IRC_SERVER_REC *server, char *chans) |
233 | 1.17k | { |
234 | 1.17k | const char *idchan, *nick_flags; |
235 | 1.17k | char *p, *dest, *end, id; |
236 | 1.17k | int count, length, chanstart; |
237 | | |
238 | 1.17k | if (!server->isupport_sent) |
239 | 828 | idchan = "!:5"; |
240 | 348 | else { |
241 | 348 | idchan = g_hash_table_lookup(server->isupport, "IDCHAN"); |
242 | 348 | if (idchan == NULL) |
243 | 348 | return; |
244 | 348 | } |
245 | 828 | nick_flags = server->get_nick_flags(SERVER(server)); |
246 | | |
247 | 1.65k | while (*idchan != '\0') { |
248 | 828 | id = *idchan; |
249 | 828 | if (idchan[1] != ':') |
250 | 0 | return; |
251 | | |
252 | 828 | length = strtoul(idchan+2, &end, 10); |
253 | 828 | if (*end == ',') |
254 | 0 | end++; |
255 | 828 | else if (*end != '\0') |
256 | 0 | return; |
257 | 828 | idchan = end; |
258 | | |
259 | 828 | count = 0; |
260 | 828 | chanstart = TRUE; |
261 | 53.8k | for (dest = p = chans; *p != '\0'; p++) { |
262 | 53.0k | if (count > 0) |
263 | 1.28k | count--; |
264 | 51.7k | else { |
265 | 51.7k | if (*p == ' ') |
266 | 23.8k | chanstart = TRUE; |
267 | 27.8k | else { |
268 | 27.8k | if (chanstart && *p == id) |
269 | 259 | count = length; |
270 | 27.8k | chanstart = chanstart && strchr(nick_flags, *p); |
271 | 27.8k | } |
272 | 51.7k | *dest++ = *p; |
273 | 51.7k | } |
274 | 53.0k | } |
275 | 828 | *dest = '\0'; |
276 | 828 | } |
277 | 828 | } |
278 | | |
279 | | static void event_whois_channels(IRC_SERVER_REC *server, const char *data) |
280 | 1.17k | { |
281 | 1.17k | char *params, *nick, *chans, *recoded; |
282 | | |
283 | 1.17k | g_return_if_fail(data != NULL); |
284 | | |
285 | 1.17k | params = event_get_params(data, 3, NULL, &nick, &chans); |
286 | | |
287 | | /* sure - we COULD print the channel names as-is, but since the |
288 | | colors, bolds, etc. are mostly just to fool people, I think we |
289 | | should show the channel names as they REALLY are so they could |
290 | | even be joined without any extra tricks. */ |
291 | 1.17k | chans = show_lowascii(chans); |
292 | 1.17k | if (settings_get_bool("whois_hide_safe_channel_id")) |
293 | 1.17k | hide_safe_channel_id(server, chans); |
294 | 1.17k | recoded = recode_in(SERVER(server), chans, nick); |
295 | 1.17k | printformat(server, nick, MSGLEVEL_CRAP, |
296 | 1.17k | IRCTXT_WHOIS_CHANNELS, nick, recoded); |
297 | 1.17k | g_free(chans); |
298 | | |
299 | 1.17k | g_free(params); |
300 | 1.17k | g_free(recoded); |
301 | 1.17k | } |
302 | | |
303 | | static void event_whois_away(IRC_SERVER_REC *server, const char *data) |
304 | 0 | { |
305 | 0 | char *params, *nick, *awaymsg, *recoded; |
306 | |
|
307 | 0 | g_return_if_fail(data != NULL); |
308 | | |
309 | 0 | params = event_get_params(data, 3, NULL, &nick, &awaymsg); |
310 | 0 | recoded = recode_in(SERVER(server), awaymsg, nick); |
311 | 0 | printformat(server, nick, MSGLEVEL_CRAP, |
312 | 0 | IRCTXT_WHOIS_AWAY, nick, recoded); |
313 | 0 | g_free(params); |
314 | 0 | g_free(recoded); |
315 | 0 | } |
316 | | |
317 | | static void event_end_of_whois(IRC_SERVER_REC *server, const char *data) |
318 | 1.51k | { |
319 | 1.51k | char *params, *nick; |
320 | | |
321 | 1.51k | g_return_if_fail(data != NULL); |
322 | | |
323 | 1.51k | params = event_get_params(data, 2, NULL, &nick); |
324 | 1.51k | if (server->whois_found) { |
325 | 0 | printformat(server, nick, MSGLEVEL_CRAP, |
326 | 0 | IRCTXT_END_OF_WHOIS, nick); |
327 | 0 | } |
328 | 1.51k | g_free(params); |
329 | 1.51k | } |
330 | | |
331 | | static void event_whois_auth(IRC_SERVER_REC *server, const char *data) |
332 | 324 | { |
333 | 324 | char *params, *nick, *text; |
334 | | |
335 | 324 | g_return_if_fail(data != NULL); |
336 | | |
337 | 324 | params = event_get_params(data, 3, NULL, &nick, &text); |
338 | 324 | printformat(server, nick, MSGLEVEL_CRAP, |
339 | 324 | IRCTXT_WHOIS_EXTRA, nick, text); |
340 | 324 | g_free(params); |
341 | 324 | } |
342 | | |
343 | | static void event_whowas(IRC_SERVER_REC *server, const char *data) |
344 | 3.15k | { |
345 | 3.15k | char *params, *nick, *user, *host, *realname, *recoded; |
346 | | |
347 | 3.15k | g_return_if_fail(data != NULL); |
348 | | |
349 | 3.15k | params = event_get_params(data, 6, NULL, &nick, &user, |
350 | 3.15k | &host, NULL, &realname); |
351 | 3.15k | recoded = recode_in(SERVER(server), realname, nick); |
352 | 3.15k | printformat(server, nick, MSGLEVEL_CRAP, |
353 | 3.15k | IRCTXT_WHOWAS, nick, user, host, recoded); |
354 | 3.15k | g_free(params); |
355 | 3.15k | g_free(recoded); |
356 | 3.15k | } |
357 | | |
358 | | static void event_end_of_whowas(IRC_SERVER_REC *server, const char *data) |
359 | 294 | { |
360 | 294 | char *params, *nick; |
361 | | |
362 | 294 | g_return_if_fail(data != NULL); |
363 | | |
364 | 294 | params = event_get_params(data, 2, NULL, &nick); |
365 | 294 | if (server->whowas_found) { |
366 | 0 | printformat(server, nick, MSGLEVEL_CRAP, |
367 | 0 | IRCTXT_END_OF_WHOWAS, nick); |
368 | 0 | } |
369 | 294 | g_free(params); |
370 | 294 | } |
371 | | |
372 | | struct whois_event_table { |
373 | | int num; |
374 | | void (*func)(IRC_SERVER_REC *, const char *); |
375 | | }; |
376 | | |
377 | | static struct whois_event_table events[] = { |
378 | | { 312, event_whois_server }, |
379 | | { 326, event_whois_usermode326 }, |
380 | | { 327, event_whois_realhost327 }, |
381 | | { 338, event_whois_realhost338 }, |
382 | | { 379, event_whois_modes }, |
383 | | { 378, event_whois_realhost }, |
384 | | { 377, event_whois_usermode }, |
385 | | { 317, event_whois_idle }, |
386 | | { 330, event_whois_auth }, |
387 | | { 319, event_whois_channels }, |
388 | | { 0, NULL } |
389 | | }; |
390 | | |
391 | | static void event_whois_default(IRC_SERVER_REC *server, const char *data) |
392 | 0 | { |
393 | 0 | int i, num; |
394 | |
|
395 | 0 | num = atoi(current_server_event); |
396 | 0 | for (i = 0; events[i].num != 0; i++) { |
397 | 0 | if (events[i].num == num) { |
398 | 0 | events[i].func(server, data); |
399 | 0 | return; |
400 | 0 | } |
401 | 0 | } |
402 | | |
403 | 0 | event_whois_special(server, data); |
404 | 0 | } |
405 | | |
406 | | void fe_whois_init(void) |
407 | 2 | { |
408 | 2 | settings_add_bool("lookandfeel", "whois_hide_safe_channel_id", TRUE); |
409 | | |
410 | 2 | signal_add("event 311", (SIGNAL_FUNC) event_whois); |
411 | 2 | signal_add("event 312", (SIGNAL_FUNC) event_whois_server); |
412 | | /* readding this events fixes the printing of /whois -yes * |
413 | | Bug http://bugs.irssi.org/?do=details&task_id=123 */ |
414 | 2 | signal_add("event 317", (SIGNAL_FUNC) event_whois_idle); |
415 | 2 | signal_add("event 319", (SIGNAL_FUNC) event_whois_channels); |
416 | 2 | signal_add("event 313", (SIGNAL_FUNC) event_whois_oper); |
417 | 2 | signal_add("event 330", (SIGNAL_FUNC) event_whois_auth); |
418 | 2 | signal_add("whois account", (SIGNAL_FUNC) event_whois_auth); |
419 | 2 | signal_add("event 377", (SIGNAL_FUNC) event_whois_usermode); |
420 | 2 | signal_add("event 378", (SIGNAL_FUNC) event_whois_realhost); |
421 | 2 | signal_add("event 379", (SIGNAL_FUNC) event_whois_modes); |
422 | 2 | signal_add("event 327", (SIGNAL_FUNC) event_whois_realhost327); |
423 | 2 | signal_add("event 326", (SIGNAL_FUNC) event_whois_usermode326); |
424 | 2 | signal_add("event 338", (SIGNAL_FUNC) event_whois_realhost338); |
425 | 2 | signal_add("whois away", (SIGNAL_FUNC) event_whois_away); |
426 | 2 | signal_add("whois oper", (SIGNAL_FUNC) event_whois_oper); |
427 | 2 | signal_add("whowas away", (SIGNAL_FUNC) event_whois_away); |
428 | 2 | signal_add("whois default event", (SIGNAL_FUNC) event_whois_default); |
429 | 2 | signal_add("event 318", (SIGNAL_FUNC) event_end_of_whois); |
430 | 2 | signal_add("event 314", (SIGNAL_FUNC) event_whowas); |
431 | 2 | signal_add("event 369", (SIGNAL_FUNC) event_end_of_whowas); |
432 | 2 | } |
433 | | |
434 | | void fe_whois_deinit(void) |
435 | 0 | { |
436 | 0 | signal_remove("event 311", (SIGNAL_FUNC) event_whois); |
437 | 0 | signal_remove("event 312", (SIGNAL_FUNC) event_whois_server); |
438 | 0 | signal_remove("event 317", (SIGNAL_FUNC) event_whois_idle); |
439 | 0 | signal_remove("event 319", (SIGNAL_FUNC) event_whois_channels); |
440 | 0 | signal_remove("event 313", (SIGNAL_FUNC) event_whois_oper); |
441 | 0 | signal_remove("event 330", (SIGNAL_FUNC) event_whois_auth); |
442 | 0 | signal_remove("whois account", (SIGNAL_FUNC) event_whois_auth); |
443 | 0 | signal_remove("event 377", (SIGNAL_FUNC) event_whois_usermode); |
444 | 0 | signal_remove("event 378", (SIGNAL_FUNC) event_whois_realhost); |
445 | 0 | signal_remove("event 379", (SIGNAL_FUNC) event_whois_modes); |
446 | 0 | signal_remove("event 327", (SIGNAL_FUNC) event_whois_realhost327); |
447 | 0 | signal_remove("event 326", (SIGNAL_FUNC) event_whois_usermode326); |
448 | 0 | signal_remove("event 338", (SIGNAL_FUNC) event_whois_realhost338); |
449 | 0 | signal_remove("whois away", (SIGNAL_FUNC) event_whois_away); |
450 | 0 | signal_remove("whois oper", (SIGNAL_FUNC) event_whois_oper); |
451 | 0 | signal_remove("whowas away", (SIGNAL_FUNC) event_whois_away); |
452 | 0 | signal_remove("whois default event", (SIGNAL_FUNC) event_whois_default); |
453 | 0 | signal_remove("event 318", (SIGNAL_FUNC) event_end_of_whois); |
454 | 0 | signal_remove("event 314", (SIGNAL_FUNC) event_whowas); |
455 | 0 | signal_remove("event 369", (SIGNAL_FUNC) event_end_of_whowas); |
456 | 0 | } |