1 /* Copyright (C) 1999-2004 Timo Sirainen */
2 
3 #include "module.h"
4 #include "module-formats.h"
5 #include "signals.h"
6 #include "levels.h"
7 #include "misc.h"
8 #include "settings.h"
9 #include "recode.h"
10 
11 #include "irc-servers.h"
12 
13 #include "printtext.h"
14 
event_whois(IRC_SERVER_REC * server,const char * data)15 static void event_whois(IRC_SERVER_REC *server, const char *data)
16 {
17 	char *params, *nick, *user, *host, *realname, *recoded;
18 
19 	g_return_if_fail(data != NULL);
20 
21 	params = event_get_params(data, 6, NULL, &nick, &user,
22 				  &host, NULL, &realname);
23 	recoded = recode_in(SERVER(server), realname, nick);
24 	printformat(server, nick, MSGLEVEL_CRAP,
25 		    IRCTXT_WHOIS, nick, user, host, recoded);
26 	g_free(params);
27 	g_free(recoded);
28 }
29 
event_whois_special(IRC_SERVER_REC * server,const char * data)30 static void event_whois_special(IRC_SERVER_REC *server, const char *data)
31 {
32 	char *params, *nick, *str;
33 
34 	g_return_if_fail(data != NULL);
35 
36 	params = event_get_params(data, 3 | PARAM_FLAG_GETREST, NULL, &nick, &str);
37 	printformat(server, nick, MSGLEVEL_CRAP,
38 		    IRCTXT_WHOIS_SPECIAL, nick, str);
39 	g_free(params);
40 }
41 
event_whois_idle(IRC_SERVER_REC * server,const char * data)42 static void event_whois_idle(IRC_SERVER_REC *server, const char *data)
43 {
44 	char *params, *nick, *secstr, *signonstr, *rest, *timestr;
45 	long days, hours, mins, secs;
46 	time_t signon;
47 
48 	g_return_if_fail(data != NULL);
49 
50 	params = event_get_params(data, 5 | PARAM_FLAG_GETREST, NULL,
51 				  &nick, &secstr, &signonstr, &rest);
52 
53 	secs = atol(secstr);
54 	signon = strstr(rest, "signon time") == NULL ? 0 :
55 		(time_t) atol(signonstr);
56 
57 	days = secs/3600/24;
58 	hours = (secs%(3600*24))/3600;
59 	mins = (secs%3600)/60;
60 	secs %= 60;
61 
62 	if (signon == 0)
63 		printformat(server, nick, MSGLEVEL_CRAP, IRCTXT_WHOIS_IDLE,
64 			    nick, days, hours, mins, secs);
65 	else {
66 		timestr = my_asctime(signon);
67 		printformat(server, nick, MSGLEVEL_CRAP,
68 			    IRCTXT_WHOIS_IDLE_SIGNON,
69 			    nick, days, hours, mins, secs, timestr);
70 		g_free(timestr);
71 	}
72 	g_free(params);
73 }
74 
event_whois_server(IRC_SERVER_REC * server,const char * data)75 static void event_whois_server(IRC_SERVER_REC *server, const char *data)
76 {
77 	char *params, *nick, *whoserver, *desc;
78 
79 	g_return_if_fail(data != NULL);
80 
81 	params = event_get_params(data, 4, NULL, &nick, &whoserver, &desc);
82 	printformat(server, nick, MSGLEVEL_CRAP,
83 		    IRCTXT_WHOIS_SERVER, nick, whoserver, desc);
84 	g_free(params);
85 }
86 
event_whois_oper(IRC_SERVER_REC * server,const char * data)87 static void event_whois_oper(IRC_SERVER_REC *server, const char *data)
88 {
89 	char *params, *nick, *type;
90 
91 	g_return_if_fail(data != NULL);
92 
93 	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 	if ((!strncmp(type, "is an ", 6)) || (!strncmp(type, "is a ", 5))) {
101 		type += 5;
102 		if (*type == ' ') type++;
103 	}
104 
105 	if (*type == '\0')
106 		type = "IRC Operator";
107 
108 	printformat(server, nick, MSGLEVEL_CRAP,
109 		IRCTXT_WHOIS_OPER, nick, type);
110 	g_free(params);
111 }
112 
event_whois_modes(IRC_SERVER_REC * server,const char * data)113 static void event_whois_modes(IRC_SERVER_REC *server, const char *data)
114 {
115 	char *params, *nick, *modes;
116 
117 	g_return_if_fail(data != NULL);
118 
119 	params = event_get_params(data, 3 | PARAM_FLAG_GETREST,
120 			NULL, &nick, &modes);
121 	if (!strncmp(modes, "is using modes ", 15))
122 		modes += 15;
123 	printformat(server, nick, MSGLEVEL_CRAP,
124 		    IRCTXT_WHOIS_MODES, nick, modes);
125 	g_free(params);
126 }
127 
event_whois_realhost(IRC_SERVER_REC * server,const char * data)128 static void event_whois_realhost(IRC_SERVER_REC *server, const char *data)
129 {
130 	char *params, *nick, *txt_real, *txt_hostname, *hostname;
131 
132 	g_return_if_fail(data != NULL);
133 
134         /* <yournick> real hostname <nick> <hostname> */
135 	params = event_get_params(data, 5, NULL, &nick, &txt_real,
136 				  &txt_hostname, &hostname);
137 	if (g_strcmp0(txt_real, "real") != 0 ||
138 	    g_strcmp0(txt_hostname, "hostname") != 0) {
139 		/* <yournick> <nick> :... from <hostname> */
140                 g_free(params);
141 		params = event_get_params(data, 3, NULL, &nick, &hostname);
142 
143 		hostname = strstr(hostname, "from ");
144                 if (hostname != NULL) hostname += 5;
145 	}
146 
147 	if (hostname != NULL) {
148 		if (!strncmp(hostname, "*@", 2))
149 			hostname += 2;
150 		printformat(server, nick, MSGLEVEL_CRAP,
151 			    IRCTXT_WHOIS_REALHOST, nick, hostname, "");
152 	} else {
153 		event_whois_special(server, data);
154 	}
155 	g_free(params);
156 }
157 
event_whois_usermode326(IRC_SERVER_REC * server,const char * data)158 static void event_whois_usermode326(IRC_SERVER_REC *server, const char *data)
159 {
160 	char *params, *nick, *usermode;
161 
162 	g_return_if_fail(data != NULL);
163 
164         /* <yournick> <nick> :has oper privs: <mode> */
165 	params = event_get_params(data, 3, NULL, &nick, &usermode);
166 	printformat(server, nick, MSGLEVEL_CRAP,
167 		    IRCTXT_WHOIS_USERMODE, nick, usermode);
168         g_free(params);
169 }
170 
event_whois_realhost327(IRC_SERVER_REC * server,const char * data)171 static void event_whois_realhost327(IRC_SERVER_REC *server, const char *data)
172 {
173 	char *params, *nick, *hostname, *ip, *text;
174 
175 	g_return_if_fail(data != NULL);
176 
177 	/* <yournick> <hostname> <ip> :Real hostname/IP */
178 	params = event_get_params(data, 5, NULL, &nick, &hostname, &ip, &text);
179 	if (*text != '\0') {
180 		printformat(server, nick, MSGLEVEL_CRAP,
181 			    IRCTXT_WHOIS_REALHOST, nick, hostname, ip);
182 	} else {
183 		event_whois_special(server, data);
184 	}
185 	g_free(params);
186 }
187 
event_whois_realhost338(IRC_SERVER_REC * server,const char * data)188 static void event_whois_realhost338(IRC_SERVER_REC *server, const char *data)
189 {
190 	char *params, *nick, *arg1, *arg2, *arg3;
191 
192 	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 	params = event_get_params(data, 5, NULL, &nick, &arg1, &arg2, &arg3);
201 	if (*arg3 != '\0') {
202 		printformat(server, nick, MSGLEVEL_CRAP,
203 			    IRCTXT_WHOIS_REALHOST, nick, arg1, arg2);
204 	} else if (*arg2 != '\0') {
205 		printformat(server, nick, MSGLEVEL_CRAP,
206 			    IRCTXT_WHOIS_REALHOST, nick, arg1, "");
207 	} else {
208 		event_whois_special(server, data);
209 	}
210 	g_free(params);
211 }
212 
event_whois_usermode(IRC_SERVER_REC * server,const char * data)213 static void event_whois_usermode(IRC_SERVER_REC *server, const char *data)
214 {
215 	char *params, *txt_usermodes, *nick, *usermode;
216 
217 	g_return_if_fail(data != NULL);
218 
219 	params = event_get_params(data, 4, NULL, &txt_usermodes,
220 				  &nick, &usermode);
221 
222 	if (g_strcmp0(txt_usermodes, "usermodes") == 0) {
223 		/* <yournick> usermodes <nick> usermode */
224 		printformat(server, nick, MSGLEVEL_CRAP,
225 			    IRCTXT_WHOIS_USERMODE, nick, usermode);
226 	} else {
227 		event_whois_special(server, data);
228 	}
229 	g_free(params);
230 }
231 
hide_safe_channel_id(IRC_SERVER_REC * server,char * chans)232 static void hide_safe_channel_id(IRC_SERVER_REC *server, char *chans)
233 {
234 	const char *idchan, *nick_flags;
235 	char *p, *dest, *end, id;
236 	int count, length, chanstart;
237 
238 	if (!server->isupport_sent)
239 		idchan = "!:5";
240 	else {
241 		idchan = g_hash_table_lookup(server->isupport, "IDCHAN");
242 		if (idchan == NULL)
243 			return;
244 	}
245 	nick_flags = server->get_nick_flags(SERVER(server));
246 
247 	while (*idchan != '\0') {
248 		id = *idchan;
249 		if (idchan[1] != ':')
250 			return;
251 
252 		length = strtoul(idchan+2, &end, 10);
253 		if (*end == ',')
254 			end++;
255 		else if (*end != '\0')
256 			return;
257 		idchan = end;
258 
259 		count = 0;
260 		chanstart = TRUE;
261 		for (dest = p = chans; *p != '\0'; p++) {
262 			if (count > 0)
263 				count--;
264 			else {
265 				if (*p == ' ')
266 					chanstart = TRUE;
267 				else {
268 					if (chanstart && *p == id)
269 						count = length;
270 					chanstart = chanstart && strchr(nick_flags, *p);
271 				}
272 				*dest++ = *p;
273 			}
274 		}
275 		*dest = '\0';
276 	}
277 }
278 
event_whois_channels(IRC_SERVER_REC * server,const char * data)279 static void event_whois_channels(IRC_SERVER_REC *server, const char *data)
280 {
281 	char *params, *nick, *chans, *recoded;
282 
283 	g_return_if_fail(data != NULL);
284 
285 	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 	chans = show_lowascii(chans);
292 	if (settings_get_bool("whois_hide_safe_channel_id"))
293 		hide_safe_channel_id(server, chans);
294 	recoded = recode_in(SERVER(server), chans, nick);
295 	printformat(server, nick, MSGLEVEL_CRAP,
296 		    IRCTXT_WHOIS_CHANNELS, nick, recoded);
297 	g_free(chans);
298 
299 	g_free(params);
300 	g_free(recoded);
301 }
302 
event_whois_away(IRC_SERVER_REC * server,const char * data)303 static void event_whois_away(IRC_SERVER_REC *server, const char *data)
304 {
305 	char *params, *nick, *awaymsg, *recoded;
306 
307 	g_return_if_fail(data != NULL);
308 
309 	params = event_get_params(data, 3, NULL, &nick, &awaymsg);
310 	recoded = recode_in(SERVER(server), awaymsg, nick);
311 	printformat(server, nick, MSGLEVEL_CRAP,
312 		    IRCTXT_WHOIS_AWAY, nick, recoded);
313 	g_free(params);
314 	g_free(recoded);
315 }
316 
event_end_of_whois(IRC_SERVER_REC * server,const char * data)317 static void event_end_of_whois(IRC_SERVER_REC *server, const char *data)
318 {
319 	char *params, *nick;
320 
321 	g_return_if_fail(data != NULL);
322 
323 	params = event_get_params(data, 2, NULL, &nick);
324 	if (server->whois_found) {
325 		printformat(server, nick, MSGLEVEL_CRAP,
326 			    IRCTXT_END_OF_WHOIS, nick);
327 	}
328 	g_free(params);
329 }
330 
event_whois_auth(IRC_SERVER_REC * server,const char * data)331 static void event_whois_auth(IRC_SERVER_REC *server, const char *data)
332 {
333 	char *params, *nick, *text;
334 
335 	g_return_if_fail(data != NULL);
336 
337 	params = event_get_params(data, 3, NULL, &nick, &text);
338 	printformat(server, nick, MSGLEVEL_CRAP,
339 		    IRCTXT_WHOIS_EXTRA, nick, text);
340 	g_free(params);
341 }
342 
event_whowas(IRC_SERVER_REC * server,const char * data)343 static void event_whowas(IRC_SERVER_REC *server, const char *data)
344 {
345 	char *params, *nick, *user, *host, *realname, *recoded;
346 
347 	g_return_if_fail(data != NULL);
348 
349 	params = event_get_params(data, 6, NULL, &nick, &user,
350 				  &host, NULL, &realname);
351 	recoded = recode_in(SERVER(server), realname, nick);
352 	printformat(server, nick, MSGLEVEL_CRAP,
353 		    IRCTXT_WHOWAS, nick, user, host, recoded);
354 	g_free(params);
355 	g_free(recoded);
356 }
357 
event_end_of_whowas(IRC_SERVER_REC * server,const char * data)358 static void event_end_of_whowas(IRC_SERVER_REC *server, const char *data)
359 {
360 	char *params, *nick;
361 
362 	g_return_if_fail(data != NULL);
363 
364 	params = event_get_params(data, 2, NULL, &nick);
365 	if (server->whowas_found) {
366 		printformat(server, nick, MSGLEVEL_CRAP,
367 			    IRCTXT_END_OF_WHOWAS, nick);
368 	}
369 	g_free(params);
370 }
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 
event_whois_default(IRC_SERVER_REC * server,const char * data)391 static void event_whois_default(IRC_SERVER_REC *server, const char *data)
392 {
393 	int i, num;
394 
395 	num = atoi(current_server_event);
396 	for (i = 0; events[i].num != 0; i++) {
397 		if (events[i].num == num) {
398 			events[i].func(server, data);
399 			return;
400 		}
401 	}
402 
403 	event_whois_special(server, data);
404 }
405 
fe_whois_init(void)406 void fe_whois_init(void)
407 {
408 	settings_add_bool("lookandfeel", "whois_hide_safe_channel_id", TRUE);
409 
410 	signal_add("event 311", (SIGNAL_FUNC) event_whois);
411 	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 	signal_add("event 317", (SIGNAL_FUNC) event_whois_idle);
415 	signal_add("event 319", (SIGNAL_FUNC) event_whois_channels);
416 	signal_add("event 313", (SIGNAL_FUNC) event_whois_oper);
417 	signal_add("event 330", (SIGNAL_FUNC) event_whois_auth);
418 	signal_add("event 377", (SIGNAL_FUNC) event_whois_usermode);
419 	signal_add("event 378", (SIGNAL_FUNC) event_whois_realhost);
420 	signal_add("event 379", (SIGNAL_FUNC) event_whois_modes);
421 	signal_add("event 327", (SIGNAL_FUNC) event_whois_realhost327);
422 	signal_add("event 326", (SIGNAL_FUNC) event_whois_usermode326);
423 	signal_add("event 338", (SIGNAL_FUNC) event_whois_realhost338);
424 	signal_add("whois away", (SIGNAL_FUNC) event_whois_away);
425 	signal_add("whois oper", (SIGNAL_FUNC) event_whois_oper);
426 	signal_add("whowas away", (SIGNAL_FUNC) event_whois_away);
427 	signal_add("whois default event", (SIGNAL_FUNC) event_whois_default);
428 	signal_add("event 318", (SIGNAL_FUNC) event_end_of_whois);
429 	signal_add("event 314", (SIGNAL_FUNC) event_whowas);
430 	signal_add("event 369", (SIGNAL_FUNC) event_end_of_whowas);
431 }
432 
fe_whois_deinit(void)433 void fe_whois_deinit(void)
434 {
435 	signal_remove("event 311", (SIGNAL_FUNC) event_whois);
436 	signal_remove("event 312", (SIGNAL_FUNC) event_whois_server);
437 	signal_remove("event 317", (SIGNAL_FUNC) event_whois_idle);
438 	signal_remove("event 319", (SIGNAL_FUNC) event_whois_channels);
439 	signal_remove("event 313", (SIGNAL_FUNC) event_whois_oper);
440 	signal_remove("event 330", (SIGNAL_FUNC) event_whois_auth);
441 	signal_remove("event 377", (SIGNAL_FUNC) event_whois_usermode);
442 	signal_remove("event 378", (SIGNAL_FUNC) event_whois_realhost);
443 	signal_remove("event 379", (SIGNAL_FUNC) event_whois_modes);
444 	signal_remove("event 327", (SIGNAL_FUNC) event_whois_realhost327);
445 	signal_remove("event 326", (SIGNAL_FUNC) event_whois_usermode326);
446 	signal_remove("event 338", (SIGNAL_FUNC) event_whois_realhost338);
447 	signal_remove("whois away", (SIGNAL_FUNC) event_whois_away);
448 	signal_remove("whois oper", (SIGNAL_FUNC) event_whois_oper);
449 	signal_remove("whowas away", (SIGNAL_FUNC) event_whois_away);
450 	signal_remove("whois default event", (SIGNAL_FUNC) event_whois_default);
451 	signal_remove("event 318", (SIGNAL_FUNC) event_end_of_whois);
452 	signal_remove("event 314", (SIGNAL_FUNC) event_whowas);
453 	signal_remove("event 369", (SIGNAL_FUNC) event_end_of_whowas);
454 }
455