4
Copyright (C) 1999-2000 Timo Sirainen
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.
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.
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
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
#include "special-vars.h"
28
#include "irc-servers.h"
29
#include "servers-idle.h"
38
static GSList *ctcp_cmds;
40
static CTCP_CMD_REC *ctcp_cmd_find(const char *name)
44
for (tmp = ctcp_cmds; tmp != NULL; tmp = tmp->next) {
45
CTCP_CMD_REC *rec = tmp->data;
47
if (g_strcasecmp(rec->name, name) == 0)
54
void ctcp_register(const char *name)
58
rec = ctcp_cmd_find(name);
60
rec = g_new0(CTCP_CMD_REC, 1);
61
rec->name = g_strdup(name);
64
ctcp_cmds = g_slist_append(ctcp_cmds, rec);
70
static void ctcp_cmd_destroy(CTCP_CMD_REC *rec)
72
ctcp_cmds = g_slist_remove(ctcp_cmds, rec);
77
void ctcp_unregister(const char *name)
81
rec = ctcp_cmd_find(name);
82
if (rec != NULL && --rec->refcount == 0)
83
ctcp_cmd_destroy(rec);
86
static void ctcp_queue_clean(IRC_SERVER_REC *server)
90
for (tmp = server->ctcpqueue; tmp != NULL; tmp = next) {
92
if (!server_idle_find(server, GPOINTER_TO_INT(tmp->data))) {
94
g_slist_remove(server->ctcpqueue, tmp->data);
99
/* Send CTCP reply with flood protection */
100
void ctcp_send_reply(IRC_SERVER_REC *server, const char *data)
104
g_return_if_fail(server != NULL);
105
g_return_if_fail(data != NULL);
107
ctcp_queue_clean(server);
109
if ((int)g_slist_length(server->ctcpqueue) >=
110
settings_get_int("max_ctcp_queue"))
113
/* Add to first in idle queue */
114
tag = server_idle_add(server, data);
116
g_slist_append(server->ctcpqueue, GINT_TO_POINTER(tag));
120
static void ctcp_ping(IRC_SERVER_REC *server, const char *data,
125
g_return_if_fail(data != NULL);
126
g_return_if_fail(server != NULL);
127
g_return_if_fail(nick != NULL);
129
if (strlen(data) > 100) {
130
/* Yes, this is kind of a kludge, but people who PING you
131
with messages this long deserve not to get the reply.
133
The problem with long messages is that when you send lots
134
of data to server, it's input buffer gets full and you get
135
killed from server because of "excess flood".
137
Irssi's current flood protection doesn't count the message
138
length, but even if it did, the CTCP flooder would still
139
be able to at least slow down your possibility to send
140
messages to server. */
144
str = g_strdup_printf("NOTICE %s :\001PING %s\001", nick, data);
145
ctcp_send_reply(server, str);
149
static void ctcp_send_parsed_reply(IRC_SERVER_REC *server, const char *nick,
150
const char *cmd, const char *args)
154
g_return_if_fail(server != NULL);
155
g_return_if_fail(nick != NULL);
160
pstr = parse_special_string(args, SERVER(server), NULL, "", NULL, 0);
161
str = g_strdup_printf("NOTICE %s :\001%s %s\001", nick, cmd, pstr);
162
ctcp_send_reply(server, str);
168
static void ctcp_version(IRC_SERVER_REC *server, const char *data,
171
ctcp_send_parsed_reply(server, nick, "VERSION",
172
settings_get_str("ctcp_version_reply"));
176
static void ctcp_time(IRC_SERVER_REC *server, const char *data,
181
g_return_if_fail(server != NULL);
182
g_return_if_fail(nick != NULL);
184
reply = my_asctime(time(NULL));
185
str = g_strdup_printf("NOTICE %s :\001TIME %s\001", nick, reply);
186
ctcp_send_reply(server, str);
192
static void ctcp_userinfo(IRC_SERVER_REC *server, const char *data,
195
ctcp_send_parsed_reply(server, nick, "USERINFO",
196
settings_get_str("ctcp_userinfo_reply"));
199
/* CTCP clientinfo */
200
static void ctcp_clientinfo(IRC_SERVER_REC *server, const char *data,
206
g_return_if_fail(server != NULL);
207
g_return_if_fail(nick != NULL);
209
str = g_string_new(NULL);
210
g_string_sprintf(str, "NOTICE %s :\001CLIENTINFO", nick);
211
for (tmp = ctcp_cmds; tmp != NULL; tmp = tmp->next) {
212
CTCP_CMD_REC *rec = tmp->data;
214
g_string_append_c(str, ' ');
215
g_string_append(str, rec->name);
217
g_string_append_c(str, '\001');
219
ctcp_send_reply(server, str->str);
220
g_string_free(str, TRUE);
223
static void ctcp_msg(IRC_SERVER_REC *server, const char *data,
224
const char *nick, const char *addr, const char *target)
228
if (g_strncasecmp(data, "ACTION ", 7) == 0) {
229
/* special treatment for actions */
230
signal_emit("ctcp action", 5, server, data+7,
235
if (ignore_check(SERVER(server), nick, addr, target, data, MSGLEVEL_CTCPS))
238
str = g_strconcat("ctcp msg ", data, NULL);
239
args = strchr(str+9, ' ');
240
if (args != NULL) *args++ = '\0'; else args = "";
243
if (!signal_emit(str, 5, server, args, nick, addr, target)) {
244
signal_emit("default ctcp msg", 5,
245
server, data, nick, addr, target);
250
static void ctcp_reply(IRC_SERVER_REC *server, const char *data,
251
const char *nick, const char *addr, const char *target)
255
if (ignore_check(SERVER(server), nick, addr, target, data, MSGLEVEL_CTCPS))
258
str = g_strconcat("ctcp reply ", data, NULL);
259
args = strchr(str+11, ' ');
260
if (args != NULL) *args++ = '\0'; else args = "";
263
if (!signal_emit(str, 5, server, args, nick, addr, target)) {
264
signal_emit("default ctcp reply", 5,
265
server, data, nick, addr, target);
270
static void event_privmsg(IRC_SERVER_REC *server, const char *data,
271
const char *nick, const char *addr)
273
char *params, *target, *msg;
276
g_return_if_fail(data != NULL);
278
params = event_get_params(data, 2, &target, &msg);
280
/* handle only ctcp messages.. */
282
/* remove the \001 at beginning and end */
285
if (msg[len-1] == '\001')
288
signal_emit("ctcp msg", 5, server, msg, nick, addr, target);
295
static void event_notice(IRC_SERVER_REC *server, const char *data,
296
const char *nick, const char *addr)
298
char *params, *target, *ptr, *msg;
300
g_return_if_fail(data != NULL);
302
params = event_get_params(data, 2, &target, &msg);
304
/* handle only ctcp replies */
306
ptr = strrchr(++msg, 1);
307
if (ptr != NULL) *ptr = '\0';
309
signal_emit("ctcp reply", 5, server, msg, nick, addr, target);
316
static void sig_disconnected(IRC_SERVER_REC *server)
318
g_return_if_fail(server != NULL);
320
if (!IS_IRC_SERVER(server))
323
g_slist_free(server->ctcpqueue);
324
server->ctcpqueue = NULL;
331
settings_add_str("misc", "ctcp_version_reply",
332
PACKAGE" v$J - running on $sysname $sysarch");
333
settings_add_str("misc", "ctcp_userinfo_reply", "$Y");
334
settings_add_int("flood", "max_ctcp_queue", 5);
336
signal_add("server disconnected", (SIGNAL_FUNC) sig_disconnected);
337
signal_add_first("event privmsg", (SIGNAL_FUNC) event_privmsg);
338
signal_add_first("event notice", (SIGNAL_FUNC) event_notice);
339
signal_add("ctcp msg", (SIGNAL_FUNC) ctcp_msg);
340
signal_add("ctcp reply", (SIGNAL_FUNC) ctcp_reply);
341
signal_add("ctcp msg ping", (SIGNAL_FUNC) ctcp_ping);
342
signal_add("ctcp msg version", (SIGNAL_FUNC) ctcp_version);
343
signal_add("ctcp msg time", (SIGNAL_FUNC) ctcp_time);
344
signal_add("ctcp msg userinfo", (SIGNAL_FUNC) ctcp_userinfo);
345
signal_add("ctcp msg clientinfo", (SIGNAL_FUNC) ctcp_clientinfo);
347
ctcp_register("ping");
348
ctcp_register("version");
349
ctcp_register("time");
350
ctcp_register("userinfo");
351
ctcp_register("clientinfo");
354
void ctcp_deinit(void)
356
while (ctcp_cmds != NULL)
357
ctcp_cmd_destroy(ctcp_cmds->data);
359
signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected);
360
signal_remove("event privmsg", (SIGNAL_FUNC) event_privmsg);
361
signal_remove("event notice", (SIGNAL_FUNC) event_notice);
362
signal_remove("ctcp msg", (SIGNAL_FUNC) ctcp_msg);
363
signal_remove("ctcp reply", (SIGNAL_FUNC) ctcp_reply);
364
signal_remove("ctcp msg ping", (SIGNAL_FUNC) ctcp_ping);
365
signal_remove("ctcp msg version", (SIGNAL_FUNC) ctcp_version);
366
signal_remove("ctcp msg time", (SIGNAL_FUNC) ctcp_time);
367
signal_remove("ctcp msg userinfo", (SIGNAL_FUNC) ctcp_userinfo);
368
signal_remove("ctcp msg clientinfo", (SIGNAL_FUNC) ctcp_clientinfo);