diff options
Diffstat (limited to 'src/irc')
-rw-r--r-- | src/irc/core/ctcp.c | 126 | ||||
-rw-r--r-- | src/irc/core/ctcp.h | 10 |
2 files changed, 125 insertions, 11 deletions
diff --git a/src/irc/core/ctcp.c b/src/irc/core/ctcp.c index 5231f53d..51738438 100644 --- a/src/irc/core/ctcp.c +++ b/src/irc/core/ctcp.c @@ -29,6 +29,59 @@ #include "servers-idle.h" #include "ignore.h" +typedef struct { + char *name; + int refcount; +} CTCP_CMD_REC; + +static GSList *ctcp_cmds; + +static CTCP_CMD_REC *ctcp_cmd_find(const char *name) +{ + GSList *tmp; + + for (tmp = ctcp_cmds; tmp != NULL; tmp = tmp->next) { + CTCP_CMD_REC *rec = tmp->data; + + if (g_strcasecmp(rec->name, name) == 0) + return rec; + } + + return NULL; +} + +void ctcp_register(const char *name) +{ + CTCP_CMD_REC *rec; + + rec = ctcp_cmd_find(name); + if (rec == NULL) { + rec = g_new0(CTCP_CMD_REC, 1); + rec->name = g_strdup(name); + g_strup(rec->name); + + ctcp_cmds = g_slist_append(ctcp_cmds, rec); + } + + rec->refcount++; +} + +static void ctcp_cmd_destroy(CTCP_CMD_REC *rec) +{ + ctcp_cmds = g_slist_remove(ctcp_cmds, rec); + g_free(rec->name); + g_free(rec); +} + +void ctcp_unregister(const char *name) +{ + CTCP_CMD_REC *rec; + + rec = ctcp_cmd_find(name); + if (rec != NULL && --rec->refcount == 0) + ctcp_cmd_destroy(rec); +} + static void ctcp_queue_clean(IRC_SERVER_REC *server) { GSList *tmp, *next; @@ -92,24 +145,33 @@ static void ctcp_ping(IRC_SERVER_REC *server, const char *data, g_free(str); } -/* CTCP version */ -static void ctcp_version(IRC_SERVER_REC *server, const char *data, - const char *nick) +static void ctcp_send_parsed_reply(IRC_SERVER_REC *server, const char *nick, + const char *cmd, const char *args) { - char *str, *reply; + char *str, *pstr; g_return_if_fail(server != NULL); g_return_if_fail(nick != NULL); - reply = parse_special_string(settings_get_str("ctcp_version_reply"), - SERVER(server), NULL, "", NULL, 0); - str = g_strdup_printf("NOTICE %s :\001VERSION %s\001", nick, reply); + if (*args == '\0') + return; + + pstr = parse_special_string(args, SERVER(server), NULL, "", NULL, 0); + str = g_strdup_printf("NOTICE %s :\001%s %s\001", nick, cmd, pstr); ctcp_send_reply(server, str); g_free(str); - g_free(reply); + g_free(pstr); } /* CTCP version */ +static void ctcp_version(IRC_SERVER_REC *server, const char *data, + const char *nick) +{ + ctcp_send_parsed_reply(server, nick, "VERSION", + settings_get_str("ctcp_version_reply")); +} + +/* CTCP time */ static void ctcp_time(IRC_SERVER_REC *server, const char *data, const char *nick) { @@ -125,6 +187,38 @@ static void ctcp_time(IRC_SERVER_REC *server, const char *data, g_free(reply); } +/* CTCP userinfo */ +static void ctcp_userinfo(IRC_SERVER_REC *server, const char *data, + const char *nick) +{ + ctcp_send_parsed_reply(server, nick, "USERINFO", + settings_get_str("ctcp_userinfo_reply")); +} + +/* CTCP clientinfo */ +static void ctcp_clientinfo(IRC_SERVER_REC *server, const char *data, + const char *nick) +{ + GString *str; + GSList *tmp; + + g_return_if_fail(server != NULL); + g_return_if_fail(nick != NULL); + + str = g_string_new(NULL); + g_string_sprintf(str, "NOTICE %s :\001CLIENTINFO", nick); + for (tmp = ctcp_cmds; tmp != NULL; tmp = tmp->next) { + CTCP_CMD_REC *rec = tmp->data; + + g_string_append_c(str, ' '); + g_string_append(str, rec->name); + } + g_string_append_c(str, '\001'); + + ctcp_send_reply(server, str->str); + g_string_free(str, TRUE); +} + static void ctcp_msg(IRC_SERVER_REC *server, const char *data, const char *nick, const char *addr, const char *target) { @@ -221,8 +315,11 @@ static void sig_disconnected(IRC_SERVER_REC *server) void ctcp_init(void) { + ctcp_cmds = NULL; + settings_add_str("misc", "ctcp_version_reply", PACKAGE" v$J - running on $sysname $sysarch"); + settings_add_str("misc", "ctcp_userinfo_reply", "$Y"); settings_add_int("flood", "max_ctcp_queue", 5); signal_add("server disconnected", (SIGNAL_FUNC) sig_disconnected); @@ -233,10 +330,21 @@ void ctcp_init(void) signal_add("ctcp msg ping", (SIGNAL_FUNC) ctcp_ping); signal_add("ctcp msg version", (SIGNAL_FUNC) ctcp_version); signal_add("ctcp msg time", (SIGNAL_FUNC) ctcp_time); + signal_add("ctcp msg userinfo", (SIGNAL_FUNC) ctcp_userinfo); + signal_add("ctcp msg clientinfo", (SIGNAL_FUNC) ctcp_clientinfo); + + ctcp_register("ping"); + ctcp_register("version"); + ctcp_register("time"); + ctcp_register("userinfo"); + ctcp_register("clientinfo"); } void ctcp_deinit(void) { + while (ctcp_cmds != NULL) + ctcp_cmd_destroy(ctcp_cmds->data); + signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected); signal_remove("event privmsg", (SIGNAL_FUNC) event_privmsg); signal_remove("event notice", (SIGNAL_FUNC) event_notice); @@ -245,4 +353,6 @@ void ctcp_deinit(void) signal_remove("ctcp msg ping", (SIGNAL_FUNC) ctcp_ping); signal_remove("ctcp msg version", (SIGNAL_FUNC) ctcp_version); signal_remove("ctcp msg time", (SIGNAL_FUNC) ctcp_time); + signal_remove("ctcp msg userinfo", (SIGNAL_FUNC) ctcp_userinfo); + signal_remove("ctcp msg clientinfo", (SIGNAL_FUNC) ctcp_clientinfo); } diff --git a/src/irc/core/ctcp.h b/src/irc/core/ctcp.h index cb326228..beab5711 100644 --- a/src/irc/core/ctcp.h +++ b/src/irc/core/ctcp.h @@ -1,10 +1,14 @@ #ifndef __CTCP_H #define __CTCP_H -void ctcp_init(void); -void ctcp_deinit(void); +/* Register/unregister CTCP command, so it shows in CTCP CLIENTINFO */ +void ctcp_register(const char *name); +void ctcp_unregister(const char *name); /* Send CTCP reply with flood protection */ -void ctcp_send_reply(SERVER_REC *server, gchar *data); +void ctcp_send_reply(SERVER_REC *server, const char *data); + +void ctcp_init(void); +void ctcp_deinit(void); #endif |