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