From 40f26429f8e3466fb68af30076d1a297c84f5da6 Mon Sep 17 00:00:00 2001 From: Diogo Sousa Date: Thu, 28 Nov 2013 00:59:31 +0000 Subject: [PATCH] Print{,_attr} and server{,_attr} hooks were incorrectly handled when both version existed (regular and attrs). Specifically, the priority was not respected, and both versions were run even when EAT_PLUGIN was returned. Fixes #847. --- src/common/dcc.c | 3 +- src/common/plugin.c | 71 ++++++++++++++++++++++++------------------ src/common/plugin.h | 8 ++--- src/common/proto-irc.c | 20 +++--------- src/common/text.c | 7 +---- 5 files changed, 49 insertions(+), 60 deletions(-) diff --git a/src/common/dcc.c b/src/common/dcc.c index 57354ba9..ca1be140 100644 --- a/src/common/dcc.c +++ b/src/common/dcc.c @@ -557,8 +557,7 @@ dcc_chat_line (struct DCC *dcc, char *line) for (i = 5; i < PDIWORDS; i++) word[i] = "\000"; - ret = plugin_emit_print (sess, word) - + plugin_emit_print_attrs (sess, word, 0); + ret = plugin_emit_print (sess, word, 0); /* did the plugin close it? */ if (!g_slist_find (dcc_list, dcc)) diff --git a/src/common/plugin.c b/src/common/plugin.c index 45746777..ee3b26c8 100644 --- a/src/common/plugin.c +++ b/src/common/plugin.c @@ -102,16 +102,21 @@ enum LIST_USERS }; +/* We use binary flags here because it makes it possible for plugin_hook_find() + * to match several types of hooks. This is used so that plugin_hook_run() + * match both HOOK_SERVER and HOOK_SERVER_ATTRS hooks when plugin_emit_server() + * is called. + */ enum { - HOOK_COMMAND, /* /command */ - HOOK_SERVER, /* PRIVMSG, NOTICE, numerics */ - HOOK_SERVER_ATTRS, /* same as above, with attributes */ - HOOK_PRINT, /* All print events */ - HOOK_PRINT_ATTRS, /* same as above, with attributes */ - HOOK_TIMER, /* timeouts */ - HOOK_FD, /* sockets & fds */ - HOOK_DELETED /* marked for deletion */ + HOOK_COMMAND = 1 << 0, /* /command */ + HOOK_SERVER = 1 << 1, /* PRIVMSG, NOTICE, numerics */ + HOOK_SERVER_ATTRS = 1 << 2, /* same as above, with attributes */ + HOOK_PRINT = 1 << 3, /* All print events */ + HOOK_PRINT_ATTRS = 1 << 4, /* same as above, with attributes */ + HOOK_TIMER = 1 << 5, /* timeouts */ + HOOK_FD = 1 << 6, /* sockets & fds */ + HOOK_DELETED = 1 << 7 /* marked for deletion */ }; GSList *plugin_list = NULL; /* export for plugingui.c */ @@ -560,16 +565,14 @@ plugin_hook_find (GSList *list, int type, char *name) while (list) { hook = list->data; - if (hook && hook->type == type) + if (hook && (hook->type & type)) { if (g_ascii_strcasecmp (hook->name, name) == 0) return list; - if (type == HOOK_SERVER) - { - if (g_ascii_strcasecmp (hook->name, "RAW LINE") == 0) + if ((type & HOOK_SERVER) + && g_ascii_strcasecmp (hook->name, "RAW LINE") == 0) return list; - } } list = list->next; } @@ -599,7 +602,7 @@ plugin_hook_run (session *sess, char *name, char *word[], char *word_eol[], hook->pl->context = sess; /* run the plugin's callback function */ - switch (type) + switch (hook->type) { case HOOK_COMMAND: ret = ((hexchat_cmd_cb *)hook->callback) (word, word_eol, hook->userdata); @@ -676,39 +679,30 @@ hexchat_event_attrs_free (hexchat_plugin *ph, hexchat_event_attrs *attrs) } /* got a server PRIVMSG, NOTICE, numeric etc... */ -int -plugin_emit_server (session *sess, char *name, char *word[], char *word_eol[]) -{ - return plugin_hook_run (sess, name, word, word_eol, NULL, HOOK_SERVER); -} int -plugin_emit_server_attrs (session *sess, char *name, char *word[], char *word_eol[], - time_t server_time) +plugin_emit_server (session *sess, char *name, char *word[], char *word_eol[], + time_t server_time) { hexchat_event_attrs attrs; attrs.server_time_utc = server_time; - return plugin_hook_run (sess, name, word, word_eol, &attrs, HOOK_SERVER_ATTRS); + return plugin_hook_run (sess, name, word, word_eol, &attrs, + HOOK_SERVER | HOOK_SERVER_ATTRS); } /* see if any plugins are interested in this print event */ int -plugin_emit_print (session *sess, char *word[]) -{ - return plugin_hook_run (sess, word[0], word, NULL, NULL, HOOK_PRINT); -} - -int -plugin_emit_print_attrs (session *sess, char *word[], time_t server_time) +plugin_emit_print (session *sess, char *word[], time_t server_time) { hexchat_event_attrs attrs; attrs.server_time_utc = server_time; - return plugin_hook_run (sess, word[0], word, NULL, &attrs, HOOK_PRINT_ATTRS); + return plugin_hook_run (sess, word[0], word, NULL, &attrs, + HOOK_PRINT | HOOK_PRINT_ATTRS); } int @@ -783,12 +777,27 @@ plugin_insert_hook (hexchat_hook *new_hook) { GSList *list; hexchat_hook *hook; + int new_hook_type; + + switch (new_hook->type) + { + case HOOK_PRINT: + case HOOK_PRINT_ATTRS: + new_hook_type = HOOK_PRINT | HOOK_PRINT_ATTRS; + break; + case HOOK_SERVER: + case HOOK_SERVER_ATTRS: + new_hook_type = HOOK_SERVER | HOOK_PRINT_ATTRS; + break; + default: + new_hook_type = new_hook->type; + } list = hook_list; while (list) { hook = list->data; - if (hook && hook->type == new_hook->type && hook->pri <= new_hook->pri) + if (hook && (hook->type & new_hook_type) && hook->pri <= new_hook->pri) { hook_list = g_slist_insert_before (hook_list, list, new_hook); return; diff --git a/src/common/plugin.h b/src/common/plugin.h index ee9da8c1..cd3f70a8 100644 --- a/src/common/plugin.h +++ b/src/common/plugin.h @@ -170,11 +170,9 @@ int plugin_kill (char *name, int by_filename); void plugin_kill_all (void); void plugin_auto_load (session *sess); int plugin_emit_command (session *sess, char *name, char *word[], char *word_eol[]); -int plugin_emit_server (session *sess, char *name, char *word[], char *word_eol[]); -int plugin_emit_server_attrs (session *sess, char *name, char *word[], - char *word_eol[], time_t server_time); -int plugin_emit_print (session *sess, char *word[]); -int plugin_emit_print_attrs (session *sess, char *word[], time_t server_time); +int plugin_emit_server (session *sess, char *name, char *word[], char *word_eol[], + time_t server_time); +int plugin_emit_print (session *sess, char *word[], time_t server_time); int plugin_emit_dummy_print (session *sess, char *name); int plugin_emit_keypress (session *sess, unsigned int state, unsigned int keyval, int len, char *string); GList* plugin_command_list(GList *tmp_list); diff --git a/src/common/proto-irc.c b/src/common/proto-irc.c index eb60a2e6..6d7c7fc1 100644 --- a/src/common/proto-irc.c +++ b/src/common/proto-irc.c @@ -1503,9 +1503,6 @@ irc_inline (server *serv, char *buf, int len) if (buf[0] == ':') { - int eat1; - int eat2; - /* find a context for this message */ if (is_channel (serv, word[3])) { @@ -1520,11 +1517,8 @@ irc_inline (server *serv, char *buf, int len) word[0] = type; word_eol[1] = buf; /* keep the ":" for plugins */ - eat1 = plugin_emit_server (sess, type, word, word_eol); - eat2 = plugin_emit_server_attrs (sess, type, word, word_eol, - tags_data.timestamp); - - if (eat1 || eat2) + if (plugin_emit_server (sess, type, word, word_eol, + tags_data.timestamp)) goto xit; word[1]++; @@ -1532,16 +1526,10 @@ irc_inline (server *serv, char *buf, int len) } else { - int eat1; - int eat2; - word[0] = type = word[1]; - eat1 = plugin_emit_server (sess, type, word, word_eol); - eat2 = plugin_emit_server_attrs (sess, type, word, word_eol, - tags_data.timestamp); - - if (eat1 || eat2) + if (plugin_emit_server (sess, type, word, word_eol, + tags_data.timestamp)) goto xit; } diff --git a/src/common/text.c b/src/common/text.c index 58d3b45c..1afb0c18 100644 --- a/src/common/text.c +++ b/src/common/text.c @@ -2074,8 +2074,6 @@ text_emit (int index, session *sess, char *a, char *b, char *c, char *d, int i; unsigned int stripcolor_args = (chanopt_is_set (prefs.hex_text_stripcolor_msg, sess->text_strip) ? 0xFFFFFFFF : 0); char tbuf[NICKLEN + 4]; - int eat1; - int eat2; if (prefs.hex_text_color_nicks && (index == XP_TE_CHANACTION || index == XP_TE_CHANMSG)) { @@ -2092,10 +2090,7 @@ text_emit (int index, session *sess, char *a, char *b, char *c, char *d, for (i = 5; i < PDIWORDS; i++) word[i] = "\000"; - eat1 = plugin_emit_print (sess, word); - eat2 = plugin_emit_print_attrs (sess, word, timestamp); - - if (eat1 || eat2) + if (plugin_emit_print (sess, word, timestamp)) return; /* If a plugin's callback executes "/close", 'sess' may be invalid */