1 /*
2  fe-events.c : irssi
3 
4     Copyright (C) 1999-2000 Timo Sirainen
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
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 along
17     with this program; if not, write to the Free Software Foundation, Inc.,
18     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20 
21 #include "module.h"
22 #include "module-formats.h"
23 #include "signals.h"
24 #include "misc.h"
25 #include "settings.h"
26 
27 #include "levels.h"
28 #include "servers.h"
29 #include "servers-redirect.h"
30 #include "servers-reconnect.h"
31 #include "queries.h"
32 #include "ignore.h"
33 #include "recode.h"
34 
35 #include "irc-servers.h"
36 #include "irc-channels.h"
37 #include "irc-nicklist.h"
38 #include "irc-masks.h"
39 
40 #include "printtext.h"
41 #include "fe-queries.h"
42 #include "fe-windows.h"
43 #include "fe-irc-server.h"
44 #include "fe-irc-channels.h"
45 
event_privmsg(IRC_SERVER_REC * server,const char * data,const char * nick,const char * addr)46 static void event_privmsg(IRC_SERVER_REC *server, const char *data,
47 			  const char *nick, const char *addr)
48 {
49 	char *params, *target, *msg, *recoded;
50 
51 	g_return_if_fail(data != NULL);
52 
53 	params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg);
54 	if (nick == NULL) nick = server->real_address;
55 	if (addr == NULL) addr = "";
56 
57 	if (fe_channel_is_opchannel(server, target)) {
58 		/* Hybrid 6 feature, send msg to all ops in channel */
59 		const char *cleantarget = fe_channel_skip_prefix(server, target);
60 		recoded = recode_in(SERVER(server), msg, cleantarget);
61 
62 		/* pass the original target to the signal, with the @+ here
63 		 * the other one is only needed for recode_in*/
64 		signal_emit("message irc op_public", 5,
65 			    server, recoded, nick, addr, target);
66 	} else {
67 		recoded = recode_in(SERVER(server), msg, server_ischannel(SERVER(server), target) ? target : nick);
68 		signal_emit(server_ischannel(SERVER(server), target) ?
69 			    "message public" : "message private", 5,
70 			    server, recoded, nick, addr,
71 			    get_visible_target(server, target));
72 	}
73 
74 	g_free(params);
75 	g_free(recoded);
76 }
77 
ctcp_action(IRC_SERVER_REC * server,const char * data,const char * nick,const char * addr,const char * target)78 static void ctcp_action(IRC_SERVER_REC *server, const char *data,
79 			const char *nick, const char *addr,
80 			const char *target)
81 {
82 	char *recoded;
83 
84 	g_return_if_fail(data != NULL);
85 	recoded = recode_in(SERVER(server), data, target);
86 	signal_emit("message irc action", 5,
87 		    server, recoded, nick, addr,
88 		    get_visible_target(server, target));
89 	g_free(recoded);
90 }
91 
event_notice(IRC_SERVER_REC * server,const char * data,const char * nick,const char * addr)92 static void event_notice(IRC_SERVER_REC *server, const char *data,
93 			 const char *nick, const char *addr)
94 {
95 	char *params, *target, *msg, *recoded;
96 
97 	g_return_if_fail(data != NULL);
98 
99 	params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg);
100 	recoded = recode_in(SERVER(server), msg, target);
101 	if (nick == NULL) {
102 		nick = server->real_address == NULL ?
103 			server->connrec->address :
104 			server->real_address;
105 	}
106 
107 	signal_emit("message irc notice", 5, server, recoded, nick, addr,
108 		    get_visible_target(server, target));
109 	g_free(params);
110 	g_free(recoded);
111 }
112 
event_join(IRC_SERVER_REC * server,const char * data,const char * nick,const char * addr)113 static void event_join(IRC_SERVER_REC *server, const char *data,
114 		       const char *nick, const char *addr)
115 {
116 	char *params, *channel, *tmp;
117 
118 	g_return_if_fail(data != NULL);
119 
120 	params = event_get_params(data, 1, &channel);
121 	tmp = strchr(channel, 7); /* ^G does something weird.. */
122 	if (tmp != NULL) *tmp = '\0';
123 
124 	signal_emit("message join", 4, server,
125 		    get_visible_target(server, channel), nick, addr);
126 	g_free(params);
127 }
128 
event_part(IRC_SERVER_REC * server,const char * data,const char * nick,const char * addr)129 static void event_part(IRC_SERVER_REC *server, const char *data,
130 		       const char *nick, const char *addr)
131 {
132 	char *params, *channel, *reason, *recoded;
133 
134 	g_return_if_fail(data != NULL);
135 
136 	params = event_get_params(data, 2 | PARAM_FLAG_GETREST,
137 				  &channel, &reason);
138 	recoded = recode_in(SERVER(server), reason, channel);
139 	signal_emit("message part", 5, server,
140 		    get_visible_target(server, channel), nick, addr, recoded);
141 	g_free(params);
142 	g_free(recoded);
143 }
144 
event_quit(IRC_SERVER_REC * server,const char * data,const char * nick,const char * addr)145 static void event_quit(IRC_SERVER_REC *server, const char *data,
146 		       const char *nick, const char *addr)
147 {
148 	char *recoded;
149 
150 	g_return_if_fail(data != NULL);
151 
152 	if (*data == ':') data++; /* quit message */
153 	recoded = recode_in(SERVER(server), data, nick);
154 	signal_emit("message quit", 4, server, nick, addr, recoded);
155 	g_free(recoded);
156 }
157 
event_kick(IRC_SERVER_REC * server,const char * data,const char * kicker,const char * addr)158 static void event_kick(IRC_SERVER_REC *server, const char *data,
159 		       const char *kicker, const char *addr)
160 {
161 	char *params, *channel, *nick, *reason, *recoded;
162 
163 	g_return_if_fail(data != NULL);
164 
165 	params = event_get_params(data, 3 | PARAM_FLAG_GETREST,
166 				  &channel, &nick, &reason);
167 	recoded = recode_in(SERVER(server), reason, channel);
168 	signal_emit("message kick", 6,
169 		    server, get_visible_target(server, channel),
170 		    nick, kicker, addr, recoded);
171 	g_free(params);
172 	g_free(recoded);
173 }
174 
event_kill(IRC_SERVER_REC * server,const char * data,const char * nick,const char * addr)175 static void event_kill(IRC_SERVER_REC *server, const char *data,
176 		       const char *nick, const char *addr)
177 {
178 	char *params, *path, *reason;
179 
180 	g_return_if_fail(data != NULL);
181 
182 	params = event_get_params(data, 2 | PARAM_FLAG_GETREST,
183 				  NULL, &path);
184 	reason = strstr(path, " (");
185 	if (reason == NULL || reason[strlen(reason)-1] != ')') {
186 		/* weird server, maybe it didn't give path */
187                 reason = path;
188 		path = "";
189 	} else {
190 		/* reason inside (...) */
191 		*reason = '\0';
192 		reason += 2;
193 		reason[strlen(reason)-1] = '\0';
194 	}
195 
196 	if (addr != NULL) {
197 		printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_KILL,
198 			    nick, addr, reason, path);
199 	} else {
200 		printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_KILL_SERVER,
201 			    nick, reason, path);
202 	}
203 
204 	g_free(params);
205 }
206 
event_nick(IRC_SERVER_REC * server,const char * data,const char * sender,const char * addr)207 static void event_nick(IRC_SERVER_REC *server, const char *data,
208 		       const char *sender, const char *addr)
209 {
210 	char *params, *newnick;
211 
212 	g_return_if_fail(data != NULL);
213 
214 	params = event_get_params(data, 1, &newnick);
215 
216 	/* NOTE: server->nick was already changed in irc/core/irc-nicklist.c */
217 	signal_emit(g_ascii_strcasecmp(newnick, server->nick) == 0 ?
218 		    "message own_nick" : "message nick", 4,
219 		    server, newnick, sender, addr);
220 
221 	g_free(params);
222 }
223 
event_mode(IRC_SERVER_REC * server,const char * data,const char * nick,const char * addr)224 static void event_mode(IRC_SERVER_REC *server, const char *data,
225 		       const char *nick, const char *addr)
226 {
227 	char *params, *channel, *mode;
228 
229 	g_return_if_fail(data != NULL);
230 
231 	params = event_get_params(data, 2 | PARAM_FLAG_GETREST,
232 				  &channel, &mode);
233 
234 	signal_emit("message irc mode", 5,
235 		    server, get_visible_target(server, channel),
236 		    nick, addr, g_strchomp(mode));
237 	g_free(params);
238 }
239 
event_pong(IRC_SERVER_REC * server,const char * data,const char * nick)240 static void event_pong(IRC_SERVER_REC *server, const char *data, const char *nick)
241 {
242 	char *params, *host, *reply;
243 
244 	g_return_if_fail(data != NULL);
245 	if (nick == NULL) nick = server->real_address;
246 
247 	params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &host, &reply);
248 	printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_PONG, host, reply);
249 	g_free(params);
250 }
251 
event_invite(IRC_SERVER_REC * server,const char * data,const char * nick,const char * addr)252 static void event_invite(IRC_SERVER_REC *server, const char *data,
253 			 const char *nick, const char *addr)
254 {
255 	char *params, *channel;
256 
257 	g_return_if_fail(data != NULL);
258 
259 	params = event_get_params(data, 2, NULL, &channel);
260 	signal_emit("message invite", 4,
261 		    server, get_visible_target(server, channel), nick, addr);
262 	g_free(params);
263 }
264 
event_topic(IRC_SERVER_REC * server,const char * data,const char * nick,const char * addr)265 static void event_topic(IRC_SERVER_REC *server, const char *data,
266 			const char *nick, const char *addr)
267 {
268 	char *params, *channel, *topic, *recoded;
269 
270 	g_return_if_fail(data != NULL);
271 
272 	params = event_get_params(data, 2 | PARAM_FLAG_GETREST,
273 				  &channel, &topic);
274 	recoded = recode_in(SERVER(server), topic, channel);
275 	signal_emit("message topic", 5, server,
276 		    get_visible_target(server, channel), recoded, nick, addr);
277 	g_free(params);
278 	g_free(recoded);
279 }
280 
event_error(IRC_SERVER_REC * server,const char * data)281 static void event_error(IRC_SERVER_REC *server, const char *data)
282 {
283 	g_return_if_fail(data != NULL);
284 
285 	if (*data == ':') data++;
286 	printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_ERROR, data);
287 }
288 
event_wallops(IRC_SERVER_REC * server,const char * data,const char * nick,const char * addr)289 static void event_wallops(IRC_SERVER_REC *server, const char *data, const char *nick, const char *addr)
290 {
291 	g_return_if_fail(data != NULL);
292 
293 	if (*data == ':') data++;
294 	if (ignore_check(SERVER(server), nick, addr, NULL, data, MSGLEVEL_WALLOPS))
295 		return;
296 
297 	if (g_ascii_strncasecmp(data, "\001ACTION ", 8) != 0)
298 		printformat(server, NULL, MSGLEVEL_WALLOPS, IRCTXT_WALLOPS, nick, data);
299 	else {
300 		/* Action in WALLOP */
301 		int len;
302 		char *tmp;
303 
304 		tmp = g_strdup(data+8);
305 		len = strlen(tmp);
306 		if (len >= 1 && tmp[len-1] == 1) tmp[len-1] = '\0';
307 		printformat(server, NULL, MSGLEVEL_WALLOPS, IRCTXT_ACTION_WALLOPS, nick, tmp);
308 		g_free(tmp);
309 	}
310 }
311 
event_silence(IRC_SERVER_REC * server,const char * data,const char * nick,const char * addr)312 static void event_silence(IRC_SERVER_REC *server, const char *data, const char *nick, const char *addr)
313 {
314 	g_return_if_fail(data != NULL);
315 
316 	g_return_if_fail(*data == '+' || *data == '-');
317 
318 	printformat(server, NULL, MSGLEVEL_CRAP, *data == '+' ? IRCTXT_SILENCED : IRCTXT_UNSILENCED, data+1);
319 }
320 
channel_sync(CHANNEL_REC * channel)321 static void channel_sync(CHANNEL_REC *channel)
322 {
323 	g_return_if_fail(channel != NULL);
324 
325 	printformat(channel->server, channel->visible_name,
326 		    MSGLEVEL_CLIENTNOTICE|MSGLEVEL_NO_ACT,
327 		    IRCTXT_CHANNEL_SYNCED, channel->visible_name,
328 		    (long) (time(NULL)-channel->createtime));
329 }
330 
event_connected(IRC_SERVER_REC * server)331 static void event_connected(IRC_SERVER_REC *server)
332 {
333 	const char *nick;
334 
335 	g_return_if_fail(server != NULL);
336 
337         nick = server->connrec->nick;
338 	if (g_ascii_strcasecmp(server->nick, nick) == 0)
339 		return;
340 
341 	/* someone has our nick, find out who. */
342 	server_redirect_event(server, "whois", 1, nick, TRUE, NULL,
343 			      "event 311", "nickfind event whois",
344 			      "", "event empty", NULL);
345 	irc_send_cmdv(server, "WHOIS %s", nick);
346 }
347 
event_nickfind_whois(IRC_SERVER_REC * server,const char * data)348 static void event_nickfind_whois(IRC_SERVER_REC *server, const char *data)
349 {
350 	char *params, *nick, *user, *host, *realname;
351 
352 	g_return_if_fail(data != NULL);
353 
354 	params = event_get_params(data, 6, NULL, &nick, &user, &host, NULL, &realname);
355 	printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_YOUR_NICK_OWNED, nick, user, host, realname);
356 	g_free(params);
357 }
358 
event_ban_type_changed(void * ban_typep)359 static void event_ban_type_changed(void *ban_typep)
360 {
361 	GString *str;
362 	int ban_type;
363 
364 	ban_type = GPOINTER_TO_INT(ban_typep);
365 
366 	if (ban_type == 0) {
367 		printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
368 			    IRCTXT_BANTYPE, "Error, using Normal");
369                 return;
370 	}
371 
372 	if (ban_type == (IRC_MASK_USER|IRC_MASK_DOMAIN)) {
373 		printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
374 			    IRCTXT_BANTYPE, "Normal");
375 	} else if (ban_type == (IRC_MASK_HOST|IRC_MASK_DOMAIN)) {
376 		printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
377 			    IRCTXT_BANTYPE, "Host");
378 	} else if (ban_type == IRC_MASK_DOMAIN) {
379 		printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
380 			    IRCTXT_BANTYPE, "Domain");
381 	} else {
382 		str = g_string_new("Custom:");
383 		if (ban_type & IRC_MASK_NICK)
384 			g_string_append(str, " Nick");
385 		if (ban_type & IRC_MASK_USER)
386 			g_string_append(str, " User");
387 		if (ban_type & IRC_MASK_HOST)
388 			g_string_append(str, " Host");
389 		if (ban_type & IRC_MASK_DOMAIN)
390 			g_string_append(str, " Domain");
391 
392 		printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
393 			    IRCTXT_BANTYPE, str->str);
394 		g_string_free(str, TRUE);
395 	}
396 }
397 
sig_whois_event_not_found(IRC_SERVER_REC * server,const char * data)398 static void sig_whois_event_not_found(IRC_SERVER_REC *server, const char *data)
399 {
400 	char *params, *nick;
401 
402 	g_return_if_fail(data != NULL);
403 
404 	params = event_get_params(data, 2, NULL, &nick);
405 	printformat(server, nick, MSGLEVEL_CRAP, IRCTXT_WHOIS_NOT_FOUND, nick);
406 	g_free(params);
407 }
408 
sig_whowas_event_end(IRC_SERVER_REC * server,const char * data,const char * sender,const char * addr)409 static void sig_whowas_event_end(IRC_SERVER_REC *server, const char *data,
410 				 const char *sender, const char *addr)
411 {
412 	char *params, *nick;
413 
414 	g_return_if_fail(data != NULL);
415 
416 	if (server->whowas_found) {
417 		signal_emit("event 369", 4, server, data, sender, addr);
418 		return;
419 	}
420 
421 	params = event_get_params(data, 2, NULL, &nick);
422 	printformat(server, nick, MSGLEVEL_CRAP, IRCTXT_WHOIS_NOT_FOUND, nick);
423 	g_free(params);
424 }
425 
event_received(IRC_SERVER_REC * server,const char * data,const char * nick,const char * addr)426 static void event_received(IRC_SERVER_REC *server, const char *data,
427 			   const char *nick, const char *addr)
428 {
429 	if (!i_isdigit(*data)) {
430 		printtext(server, NULL, MSGLEVEL_CRAP, "%s", data);
431 		return;
432 	}
433 
434 	/* numeric event. */
435         signal_emit("default event numeric", 4, server, data, nick, addr);
436 }
437 
fe_events_init(void)438 void fe_events_init(void)
439 {
440 	signal_add("event privmsg", (SIGNAL_FUNC) event_privmsg);
441 	signal_add("ctcp action", (SIGNAL_FUNC) ctcp_action);
442 	signal_add("event notice", (SIGNAL_FUNC) event_notice);
443 	signal_add("event join", (SIGNAL_FUNC) event_join);
444 	signal_add("event part", (SIGNAL_FUNC) event_part);
445 	signal_add("event quit", (SIGNAL_FUNC) event_quit);
446 	signal_add("event kick", (SIGNAL_FUNC) event_kick);
447 	signal_add("event kill", (SIGNAL_FUNC) event_kill);
448 	signal_add("event nick", (SIGNAL_FUNC) event_nick);
449 	signal_add("event mode", (SIGNAL_FUNC) event_mode);
450 	signal_add("event pong", (SIGNAL_FUNC) event_pong);
451 	signal_add("event invite", (SIGNAL_FUNC) event_invite);
452 	signal_add("event topic", (SIGNAL_FUNC) event_topic);
453 	signal_add("event error", (SIGNAL_FUNC) event_error);
454 	signal_add("event wallops", (SIGNAL_FUNC) event_wallops);
455 	signal_add("event silence", (SIGNAL_FUNC) event_silence);
456 
457 	signal_add("default event", (SIGNAL_FUNC) event_received);
458 
459 	signal_add("channel sync", (SIGNAL_FUNC) channel_sync);
460 	signal_add("event connected", (SIGNAL_FUNC) event_connected);
461 	signal_add("nickfind event whois", (SIGNAL_FUNC) event_nickfind_whois);
462 	signal_add("ban type changed", (SIGNAL_FUNC) event_ban_type_changed);
463 	signal_add("whois event not found", (SIGNAL_FUNC) sig_whois_event_not_found);
464 	signal_add("whowas event end", (SIGNAL_FUNC) sig_whowas_event_end);
465 }
466 
fe_events_deinit(void)467 void fe_events_deinit(void)
468 {
469 	signal_remove("event privmsg", (SIGNAL_FUNC) event_privmsg);
470 	signal_remove("ctcp action", (SIGNAL_FUNC) ctcp_action);
471 	signal_remove("event notice", (SIGNAL_FUNC) event_notice);
472 	signal_remove("event join", (SIGNAL_FUNC) event_join);
473 	signal_remove("event part", (SIGNAL_FUNC) event_part);
474 	signal_remove("event quit", (SIGNAL_FUNC) event_quit);
475 	signal_remove("event kick", (SIGNAL_FUNC) event_kick);
476 	signal_remove("event kill", (SIGNAL_FUNC) event_kill);
477 	signal_remove("event nick", (SIGNAL_FUNC) event_nick);
478 	signal_remove("event mode", (SIGNAL_FUNC) event_mode);
479 	signal_remove("event pong", (SIGNAL_FUNC) event_pong);
480 	signal_remove("event invite", (SIGNAL_FUNC) event_invite);
481 	signal_remove("event topic", (SIGNAL_FUNC) event_topic);
482 	signal_remove("event error", (SIGNAL_FUNC) event_error);
483 	signal_remove("event wallops", (SIGNAL_FUNC) event_wallops);
484 	signal_remove("event silence", (SIGNAL_FUNC) event_silence);
485 
486 	signal_remove("default event", (SIGNAL_FUNC) event_received);
487 
488 	signal_remove("channel sync", (SIGNAL_FUNC) channel_sync);
489 	signal_remove("event connected", (SIGNAL_FUNC) event_connected);
490 	signal_remove("nickfind event whois", (SIGNAL_FUNC) event_nickfind_whois);
491 	signal_remove("ban type changed", (SIGNAL_FUNC) event_ban_type_changed);
492 	signal_remove("whois event not found", (SIGNAL_FUNC) sig_whois_event_not_found);
493 	signal_remove("whowas event end", (SIGNAL_FUNC) sig_whowas_event_end);
494 }
495