diff --git a/src/core/ignore.c b/src/core/ignore.c index 0cee82cd..0721d826 100644 --- a/src/core/ignore.c +++ b/src/core/ignore.c @@ -37,6 +37,8 @@ GSList *ignores; static NICKMATCH_REC *nickmatch; +static int unignore_timeout(IGNORE_REC *rec); + /* check if `text' contains ignored nick at the start of the line. */ static int ignore_check_replies_rec(IGNORE_REC *rec, CHANNEL_REC *channel, const char *text) @@ -258,6 +260,21 @@ IGNORE_REC *ignore_find(const char *servertag, const char *mask, return NULL; } +char *ignore_get_key(IGNORE_REC *rec) +{ + char *chans, *ret; + + if (rec->channels == NULL) + return rec->mask != NULL ? g_strdup(rec->mask) : NULL; + + chans = g_strjoinv(",", rec->channels); + if (rec->mask == NULL) return chans; + + ret = g_strdup_printf("%s %s", rec->mask, chans); + g_free(chans); + return ret; +} + static void ignore_set_config(IGNORE_REC *rec) { CONFIG_NODE *node; @@ -322,16 +339,25 @@ void ignore_add_rec(IGNORE_REC *rec) regcomp(&rec->preg, rec->pattern, REG_EXTENDED|REG_ICASE|REG_NOSUB) == 0; #endif + if (rec->time > 0) + rec->time_tag = g_timeout_add(rec->time*1000, (GSourceFunc) unignore_timeout, rec); + ignores = g_slist_append(ignores, rec); ignore_set_config(rec); - signal_emit("ignore created", 1, rec); + if (!rec->autoignore) + signal_emit("ignore created", 1, rec); + else + signal_emit("autoignore new", 1, rec); } static void ignore_destroy(IGNORE_REC *rec) { ignores = g_slist_remove(ignores, rec); - signal_emit("ignore destroyed", 1, rec); + if (!rec->autoignore) + signal_emit("ignore destroyed", 1, rec); + else + signal_emit("autoignore destroyed", 1, rec); #ifdef HAVE_REGEX_H if (rec->regexp_compiled) regfree(&rec->preg); @@ -365,6 +391,13 @@ void ignore_update_rec(IGNORE_REC *rec) } } +static int unignore_timeout(IGNORE_REC *rec) +{ + rec->level = 0; + ignore_update_rec(rec); + return FALSE; +} + static void read_ignores(void) { IGNORE_REC *rec; diff --git a/src/core/ignore.h b/src/core/ignore.h index f4aea3aa..a8e30ada 100644 --- a/src/core/ignore.h +++ b/src/core/ignore.h @@ -8,13 +8,14 @@ typedef struct { int level; /* ignore these levels */ char *mask; /* nick mask */ - char *servertag; /* this is for autoignoring */ + char *servertag; /* this is for autoignoring */ char **channels; /* ignore only in these channels */ char *pattern; /* text body must match this pattern */ int time; /* time in sec for temp ignores */ int time_tag; + unsigned int autoignore:1; unsigned int exception:1; /* *don't* ignore */ unsigned int regexp:1; unsigned int fullword:1; @@ -32,6 +33,8 @@ int ignore_check(SERVER_REC *server, const char *nick, const char *host, IGNORE_REC *ignore_find(const char *servertag, const char *mask, char **channels); +char *ignore_get_key(IGNORE_REC *rec); + void ignore_add_rec(IGNORE_REC *rec); void ignore_update_rec(IGNORE_REC *rec); diff --git a/src/fe-common/core/fe-ignore.c b/src/fe-common/core/fe-ignore.c index fdbc60d5..2af5f655 100644 --- a/src/fe-common/core/fe-ignore.c +++ b/src/fe-common/core/fe-ignore.c @@ -29,24 +29,6 @@ #include "ignore.h" #include "printtext.h" -static void fe_unignore(IGNORE_REC *rec); - -static char *ignore_get_key(IGNORE_REC *rec) -{ - char *chans, *ret; - - if (rec->channels == NULL) - return g_strdup(rec->mask == NULL ? "*" : rec->mask); - - chans = g_strjoinv(",", rec->channels); - if (rec->mask == NULL) return chans; - - ret = g_strdup_printf("%s %s", rec->mask == NULL ? - "*" : rec->mask, chans); - g_free(chans); - return ret; -} - static void ignore_print(int index, IGNORE_REC *rec) { GString *options; @@ -71,12 +53,6 @@ static void ignore_print(int index, IGNORE_REC *rec) g_free(levels); } -static int unignore_timeout(IGNORE_REC *rec) -{ - fe_unignore(rec); - return FALSE; -} - static void cmd_ignore_show(void) { GSList *tmp; @@ -98,9 +74,9 @@ static void cmd_ignore_show(void) [-time ] */ static void cmd_ignore(const char *data) { - GHashTable *optlist; + GHashTable *optlist; IGNORE_REC *rec; - char *patternarg, *chanarg, *mask, *levels, *key, *timestr; + char *patternarg, *chanarg, *mask, *levels, *timestr; char **channels; void *free_arg; int new_ignore; @@ -154,17 +130,8 @@ static void cmd_ignore(const char *data) if (rec->level == 0) { printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_UNIGNORED, rec->mask == NULL ? "*" : rec->mask); - } else { - key = ignore_get_key(rec); - levels = bits2level(rec->level); - printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_IGNORED, key, levels); - g_free(key); - g_free(levels); } - if (rec->time > 0) - rec->time_tag = g_timeout_add(rec->time*1000, (GSourceFunc) unignore_timeout, rec); - if (new_ignore) ignore_add_rec(rec); else @@ -173,18 +140,6 @@ static void cmd_ignore(const char *data) cmd_params_free(free_arg); } -static void fe_unignore(IGNORE_REC *rec) -{ - char *key; - - key = ignore_get_key(rec); - printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_UNIGNORED, key); - g_free(key); - - rec->level = 0; - ignore_update_rec(rec); -} - /* SYNTAX: UNIGNORE | */ static void cmd_unignore(const char *data) { @@ -210,10 +165,34 @@ static void cmd_unignore(const char *data) rec = ignore_find("*", data, (char **) chans); } - if (rec == NULL) - printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_IGNORE_NOT_FOUND, data); - else - fe_unignore(rec); + if (rec != NULL) { + rec->level = 0; + ignore_update_rec(rec); + } else { + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, + TXT_IGNORE_NOT_FOUND, data); + } +} + +static void sig_ignore_created(IGNORE_REC *rec) +{ + char *key, *levels; + + key = ignore_get_key(rec); + levels = bits2level(rec->level); + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, + TXT_IGNORED, key, levels); + g_free(key); + g_free(levels); +} + +static void sig_ignore_destroyed(IGNORE_REC *rec) +{ + char *key; + + key = ignore_get_key(rec); + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_UNIGNORED, key); + g_free(key); } void fe_ignore_init(void) @@ -221,6 +200,10 @@ void fe_ignore_init(void) command_bind("ignore", NULL, (SIGNAL_FUNC) cmd_ignore); command_bind("unignore", NULL, (SIGNAL_FUNC) cmd_unignore); + signal_add("ignore destroyed", (SIGNAL_FUNC) sig_ignore_destroyed); + signal_add("ignore created", (SIGNAL_FUNC) sig_ignore_created); + signal_add("ignore changed", (SIGNAL_FUNC) sig_ignore_created); + command_set_options("ignore", "regexp word except replies -time -pattern -channels"); } @@ -228,4 +211,8 @@ void fe_ignore_deinit(void) { command_unbind("ignore", (SIGNAL_FUNC) cmd_ignore); command_unbind("unignore", (SIGNAL_FUNC) cmd_unignore); + + signal_remove("ignore destroyed", (SIGNAL_FUNC) sig_ignore_destroyed); + signal_remove("ignore created", (SIGNAL_FUNC) sig_ignore_created); + signal_remove("ignore changed", (SIGNAL_FUNC) sig_ignore_created); } diff --git a/src/fe-common/irc/flood/fe-flood.c b/src/fe-common/irc/flood/fe-flood.c index 7f5a0ee5..0cd59208 100644 --- a/src/fe-common/irc/flood/fe-flood.c +++ b/src/fe-common/irc/flood/fe-flood.c @@ -24,38 +24,38 @@ #include "levels.h" #include "irc-servers.h" +#include "ignore.h" #include "irc/flood/autoignore.h" #include "themes.h" #include "printtext.h" -static void event_autoignore_new(IRC_SERVER_REC *server, AUTOIGNORE_REC *ignore) +static void event_autoignore_new(IGNORE_REC *rec) { - g_return_if_fail(ignore != NULL); + g_return_if_fail(rec != NULL); + + printformat(server_find_tag(rec->servertag), NULL, MSGLEVEL_CLIENTNOTICE, + IRCTXT_AUTOIGNORE, rec->mask, rec->time); +} - printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_AUTOIGNORE, - ignore->nick, (ignore->timeleft+59)/60); -} - -static void event_autoignore_remove(IRC_SERVER_REC *server, AUTOIGNORE_REC *ignore) +static void event_autoignore_destroyed(IGNORE_REC *rec) { - g_return_if_fail(ignore != NULL); - - printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_AUTOUNIGNORE, ignore->nick); -} - + g_return_if_fail(rec != NULL); + + printformat(server_find_tag(rec->servertag), NULL, MSGLEVEL_CLIENTNOTICE, + IRCTXT_AUTOUNIGNORE, rec->mask, rec->time); +} void fe_irc_flood_init(void) { - signal_add("autoignore new", (SIGNAL_FUNC) event_autoignore_new); - signal_add("autoignore remove", (SIGNAL_FUNC) event_autoignore_remove); + signal_add("autoignore new", (SIGNAL_FUNC) event_autoignore_new); + signal_add("autoignore destroyed", (SIGNAL_FUNC) event_autoignore_destroyed); - theme_register(fecommon_irc_flood_formats); + theme_register(fecommon_irc_flood_formats); } void fe_irc_flood_deinit(void) { - theme_unregister(); - signal_remove("autoignore new", (SIGNAL_FUNC) event_autoignore_new); - signal_remove("autoignore remove", (SIGNAL_FUNC) event_autoignore_remove); + signal_remove("autoignore destroyed", (SIGNAL_FUNC) event_autoignore_destroyed); + theme_unregister(); } diff --git a/src/fe-common/irc/flood/module-formats.c b/src/fe-common/irc/flood/module-formats.c index 29b76ace..c2ce4ae1 100644 --- a/src/fe-common/irc/flood/module-formats.c +++ b/src/fe-common/irc/flood/module-formats.c @@ -28,7 +28,7 @@ FORMAT_REC fecommon_irc_flood_formats[] = /* ---- */ { NULL, "Autoignore", 0 }, - { "autoignore", "Flood detected from {nick $0}, autoignoring for {hilight $1} minutes", 2, { 0, 1 } }, + { "autoignore", "Flood detected from {nick $0}, autoignoring for {hilight $1} seconds", 2, { 0, 1 } }, { "autounignore", "Removed autoignore from {nick $0}", 1, { 0 } }, { NULL, NULL, 0 } diff --git a/src/irc/flood/autoignore.c b/src/irc/flood/autoignore.c index 95967686..bc7be104 100644 --- a/src/irc/flood/autoignore.c +++ b/src/irc/flood/autoignore.c @@ -31,265 +31,62 @@ #include "autoignore.h" -/* How often to check if there's anyone to be unignored in autoignore list */ -#define AUTOIGNORE_TIMECHECK 10000 - -static int ignore_tag; - -GSList *server_autoignores(IRC_SERVER_REC *server) +void autoignore_update(IGNORE_REC *rec, int level) { - MODULE_SERVER_REC *rec; + rec->level |= level; + rec->time = settings_get_int("autoignore_time"); - g_return_val_if_fail(IS_IRC_SERVER(server), NULL); - - rec = MODULE_DATA(server); - return rec->ignorelist; + ignore_update_rec(rec); } -static void autoignore_remove_rec(IRC_SERVER_REC *server, AUTOIGNORE_REC *rec) +void autoignore_add(IRC_SERVER_REC *server, char *mask, int level) { - MODULE_SERVER_REC *mserver; + IGNORE_REC *rec; - g_return_if_fail(IS_IRC_SERVER(server)); - g_return_if_fail(rec != NULL); - - signal_emit("autoignore remove", 2, server, rec); - - g_free(rec->nick); - g_free(rec); - - mserver = MODULE_DATA(server); - mserver->ignorelist = g_slist_remove(mserver->ignorelist, rec); -} - -static AUTOIGNORE_REC *autoignore_find(IRC_SERVER_REC *server, const char *mask) -{ - MODULE_SERVER_REC *mserver; - GSList *tmp; - - g_return_val_if_fail(IS_IRC_SERVER(server), NULL); - g_return_val_if_fail(mask != NULL, NULL); - - mserver = MODULE_DATA(server); - for (tmp = mserver->ignorelist; tmp != NULL; tmp = tmp->next) { - AUTOIGNORE_REC *rec = tmp->data; - - if (g_strcasecmp(rec->nick, mask) == 0) - return rec; - } - - return NULL; -} - -/* timeout function: unignore old ignores.. */ -static void autoignore_timeout_server(IRC_SERVER_REC *server) -{ - MODULE_SERVER_REC *mserver; - GSList *tmp, *next; - time_t t; - - g_return_if_fail(server != NULL); - if (!IS_IRC_SERVER(server)) - return; - - mserver = MODULE_DATA(server); - t = time(NULL); - t -= mserver->ignore_lastcheck; - - for (tmp = mserver->ignorelist; tmp != NULL; tmp = next) { - AUTOIGNORE_REC *rec = tmp->data; - - next = tmp->next; - if (rec->timeleft > t) - rec->timeleft -= t; - else - autoignore_remove_rec(server, rec); - } - - mserver->ignore_lastcheck = time(NULL); -} - -static int autoignore_timeout(void) -{ - g_slist_foreach(servers, (GFunc) autoignore_timeout_server, NULL); - return 1; -} - -static void autoignore_init_server(IRC_SERVER_REC *server) -{ - MODULE_SERVER_REC *mserver; - - if (!IS_IRC_SERVER(server)) - return; - - mserver = MODULE_DATA(server); - mserver->ignorelist = NULL; - mserver->ignore_lastcheck = time(NULL)-AUTOIGNORE_TIMECHECK; -} - -static void autoignore_deinit_server(IRC_SERVER_REC *server) -{ - MODULE_SERVER_REC *mserver; - - if (!IS_IRC_SERVER(server)) - return; - - mserver = MODULE_DATA(server); - while (mserver->ignorelist != NULL) - autoignore_remove_rec(server, (AUTOIGNORE_REC *) mserver->ignorelist->data); -} - -IGNORE_REC *ignore_find_server(IRC_SERVER_REC *server, const char *mask) -{ - GSList *tmp; - - for (tmp = ignores; tmp != NULL; tmp = tmp->next) { - IGNORE_REC *rec = tmp->data; - - if (rec->servertag != NULL && - g_strcasecmp(rec->mask, mask) == 0 && - g_strcasecmp(rec->servertag, server->tag) == 0) - return rec; - } - - return NULL; -} - -void autoignore_add(IRC_SERVER_REC *server, const char *nick, int level) -{ - MODULE_SERVER_REC *mserver; - AUTOIGNORE_REC *rec; - IGNORE_REC *irec; - int igtime; - - g_return_if_fail(nick != NULL); - if (level == 0 || !IRC_SERVER(server)) return; - - igtime = settings_get_int("autoignore_time"); - if (igtime <= 0) return; - - irec = ignore_find_server(server, nick); - if (irec == NULL) { - irec = g_new0(IGNORE_REC, 1); - irec->servertag = g_strdup(server->tag); - irec->mask = g_strdup(nick); - irec->level = level; - ignore_add_rec(irec); - } else { - irec->level |= level; - ignore_update_rec(irec); - } - - rec = autoignore_find(server, nick); - if (rec != NULL) { - /* already being ignored */ - rec->timeleft = igtime; - return; - } - - rec = g_new(AUTOIGNORE_REC, 1); - rec->nick = g_strdup(nick); - rec->timeleft = igtime; + rec = g_new0(IGNORE_REC, 1); + + rec->mask = mask; + rec->servertag = g_strdup(server->tag); rec->level = level; - - mserver = MODULE_DATA(server); - mserver->ignorelist = g_slist_append(mserver->ignorelist, rec); - - signal_emit("autoignore new", 2, server, rec); -} - -int autoignore_remove(IRC_SERVER_REC *server, const char *mask, int level) -{ - AUTOIGNORE_REC *rec; - IGNORE_REC *irec; - - g_return_val_if_fail(mask != NULL, FALSE); - if (!IS_IRC_SERVER(server)) - return FALSE; - - irec = ignore_find_server(server, mask); - if (irec != NULL) { - irec->level &= ~level; - ignore_update_rec(irec); - } - - rec = autoignore_find(server, mask); - if (rec != NULL && (level & rec->level)) { - rec->level &= ~level; - if (rec->level == 0) autoignore_remove_rec(server, rec); - return TRUE; - } - - return FALSE; + rec->time = settings_get_int("autoignore_time"); + rec->autoignore = 1; + + ignore_add_rec(rec); } static void sig_flood(IRC_SERVER_REC *server, const char *nick, const char *host, gpointer levelp) { int level, check_level; + GString *mask; + IGNORE_REC *rec; + g_return_if_fail(IS_IRC_SERVER(server)); level = GPOINTER_TO_INT(levelp); check_level = level2bits(settings_get_str("autoignore_levels")); - if (level & check_level) - autoignore_add(server, nick, level); -} - -static void autoignore_remove_level(const char *nick, int level) -{ - AUTOIGNORE_REC *rec; - GSList *tmp; - - g_return_if_fail(nick != NULL); - - for (tmp = servers; tmp != NULL; tmp = tmp->next) { - IRC_SERVER_REC *server = tmp->data; - - if (!IS_IRC_SERVER(server)) - continue; - - rec = autoignore_find(server, nick); - if (rec != NULL && (rec->level & level)) { - rec->level &= ~level; - if (rec->level == 0) autoignore_remove_rec(server, rec); - } + mask = g_string_new(nick); + mask = g_string_append_c(mask, '!'); + mask = g_string_append(mask, host); + if (level & check_level) { + rec = ignore_find(server->tag, mask->str, NULL); + if (rec == NULL) + autoignore_add(server, mask->str, level); + else + autoignore_update(rec, level); } } -static void sig_ignore_destroyed(IGNORE_REC *ignore) -{ - if (ignore->mask != NULL) - autoignore_remove_level(ignore->mask, MSGLEVEL_ALL); -} - -static void sig_ignore_changed(IGNORE_REC *ignore) -{ - if (ignore->mask != NULL) - autoignore_remove_level(ignore->mask, ~ignore->level); -} - void autoignore_init(void) { settings_add_int("flood", "autoignore_time", 300); settings_add_str("flood", "autoignore_levels", ""); - ignore_tag = g_timeout_add(AUTOIGNORE_TIMECHECK, (GSourceFunc) autoignore_timeout, NULL); - - signal_add("server connected", (SIGNAL_FUNC) autoignore_init_server); - signal_add("server disconnected", (SIGNAL_FUNC) autoignore_deinit_server); - signal_add("flood", (SIGNAL_FUNC) sig_flood); - signal_add("ignore destroyed", (SIGNAL_FUNC) sig_ignore_destroyed); - signal_add("ignore changed", (SIGNAL_FUNC) sig_ignore_changed); + signal_add("flood", (SIGNAL_FUNC) sig_flood); } void autoignore_deinit(void) { - g_source_remove(ignore_tag); - - signal_remove("server connected", (SIGNAL_FUNC) autoignore_init_server); - signal_remove("server disconnected", (SIGNAL_FUNC) autoignore_deinit_server); signal_remove("flood", (SIGNAL_FUNC) sig_flood); - signal_remove("ignore destroyed", (SIGNAL_FUNC) sig_ignore_destroyed); - signal_remove("ignore changed", (SIGNAL_FUNC) sig_ignore_changed); } diff --git a/src/irc/flood/autoignore.h b/src/irc/flood/autoignore.h index efa01d27..b00829a1 100644 --- a/src/irc/flood/autoignore.h +++ b/src/irc/flood/autoignore.h @@ -1,16 +1,7 @@ #ifndef __AUTOIGNORE_H #define __AUTOIGNORE_H -typedef struct { - char *nick; - int timeleft; - int level; -} AUTOIGNORE_REC; - -GSList *server_autoignores(IRC_SERVER_REC *server); - -void autoignore_add(IRC_SERVER_REC *server, const char *nick, int level); -int autoignore_remove(IRC_SERVER_REC *server, const char *mask, int level); +void autoignore_add(IRC_SERVER_REC *server, char *nick, int level); void autoignore_init(void); void autoignore_deinit(void); diff --git a/src/irc/flood/flood.c b/src/irc/flood/flood.c index 0c4dc7ab..a1d4dd91 100644 --- a/src/irc/flood/flood.c +++ b/src/irc/flood/flood.c @@ -63,6 +63,7 @@ static int flood_hash_check_remove(const char *key, FLOOD_REC *flood, gpointer n flood->items = g_slist_remove(flood->items, rec); g_free(rec->target); g_free(rec); + rec->msgcount--; } }