From 91c9e871c78e203aed834edd1e1f558680a6ccfa Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 12 Jul 2016 13:59:46 +0200 Subject: [PATCH 01/21] Add an option to stop the connection when SASL fails. --- src/fe-common/irc/fe-sasl.c | 17 +++++++++++++++++ src/irc/core/irc-servers.h | 1 + src/irc/core/sasl.c | 7 +++++++ 3 files changed, 25 insertions(+) diff --git a/src/fe-common/irc/fe-sasl.c b/src/fe-common/irc/fe-sasl.c index 331b38b0..dfbfc84a 100644 --- a/src/fe-common/irc/fe-sasl.c +++ b/src/fe-common/irc/fe-sasl.c @@ -23,6 +23,9 @@ #include "signals.h" #include "levels.h" +#include "irc-servers.h" +#include "settings.h" + #include "printtext.h" static void sig_sasl_success(IRC_SERVER_REC *server) @@ -35,14 +38,28 @@ static void sig_sasl_failure(IRC_SERVER_REC *server, const char *reason) printformat(server, NULL, MSGLEVEL_CRAP, IRCTXT_SASL_ERROR, reason); } +static void sig_cap_end(IRC_SERVER_REC *server) +{ + /* The negotiation has now been terminated, if we didn't manage to + * authenticate successfully with the server just disconnect. */ + if (server->sasl_success == FALSE && + settings_get_bool("sasl_disconnect_on_failure")) + server_disconnect(SERVER(server)); + +} + void fe_sasl_init(void) { + settings_add_bool("server", "sasl_disconnect_on_failure", TRUE); + signal_add("server sasl success", (SIGNAL_FUNC) sig_sasl_success); signal_add("server sasl failure", (SIGNAL_FUNC) sig_sasl_failure); + signal_add_first("server cap end", (SIGNAL_FUNC) sig_cap_end); } void fe_sasl_deinit(void) { signal_remove("server sasl success", (SIGNAL_FUNC) sig_sasl_success); signal_remove("server sasl failure", (SIGNAL_FUNC) sig_sasl_failure); + signal_remove("server cap end", (SIGNAL_FUNC) sig_cap_end); } diff --git a/src/irc/core/irc-servers.h b/src/irc/core/irc-servers.h index bb100f86..09f3f81d 100644 --- a/src/irc/core/irc-servers.h +++ b/src/irc/core/irc-servers.h @@ -68,6 +68,7 @@ struct _IRC_SERVER_REC { unsigned int motd_got:1; /* We've received MOTD */ unsigned int isupport_sent:1; /* Server has sent us an isupport reply */ unsigned int cap_complete:1; /* We've done the initial CAP negotiation */ + unsigned int sasl_success:1; /* Did we authenticate successfully ? */ int max_kicks_in_cmd; /* max. number of people to kick with one /KICK command */ int max_modes_in_cmd; /* max. number of mode changes in one /MODE command */ diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c index a1c16cdd..1021bea4 100644 --- a/src/irc/core/sasl.c +++ b/src/irc/core/sasl.c @@ -48,6 +48,7 @@ static gboolean sasl_timeout(IRC_SERVER_REC *server) cap_finish_negotiation(server); server->sasl_timeout = 0; + server->sasl_success = FALSE; signal_emit("server sasl failure", 2, server, "The authentication timed out"); @@ -84,6 +85,8 @@ static void sasl_fail(IRC_SERVER_REC *server, const char *data, const char *from params = event_get_params(data, 2, NULL, &error); + server->sasl_success = FALSE; + signal_emit("server sasl failure", 2, server, error); /* Terminate the negotiation */ @@ -99,6 +102,8 @@ static void sasl_already(IRC_SERVER_REC *server, const char *data, const char *f server->sasl_timeout = 0; } + server->sasl_success = TRUE; + signal_emit("server sasl success", 1, server); /* We're already authenticated, do nothing */ @@ -112,6 +117,8 @@ static void sasl_success(IRC_SERVER_REC *server, const char *data, const char *f server->sasl_timeout = 0; } + server->sasl_success = TRUE; + signal_emit("server sasl success", 1, server); /* The authentication succeeded, time to finish the CAP negotiation */ From 4ccffd85ffd06325687546f78b78e3e7fce575c5 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Thu, 20 Oct 2016 21:41:36 +0200 Subject: [PATCH 02/21] Expose 'sasl_success' to the perl side. --- src/fe-common/irc/fe-sasl.c | 2 +- src/perl/irc/Irc.xs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fe-common/irc/fe-sasl.c b/src/fe-common/irc/fe-sasl.c index dfbfc84a..4c86f850 100644 --- a/src/fe-common/irc/fe-sasl.c +++ b/src/fe-common/irc/fe-sasl.c @@ -42,7 +42,7 @@ static void sig_cap_end(IRC_SERVER_REC *server) { /* The negotiation has now been terminated, if we didn't manage to * authenticate successfully with the server just disconnect. */ - if (server->sasl_success == FALSE && + if (!server->sasl_success && settings_get_bool("sasl_disconnect_on_failure")) server_disconnect(SERVER(server)); diff --git a/src/perl/irc/Irc.xs b/src/perl/irc/Irc.xs index 8b3b0c45..41690010 100644 --- a/src/perl/irc/Irc.xs +++ b/src/perl/irc/Irc.xs @@ -32,6 +32,7 @@ static void perl_irc_server_fill_hash(HV *hv, IRC_SERVER_REC *server) (void) hv_store(hv, "isupport_sent", 13, newSViv(server->isupport_sent), 0); (void) hv_store(hv, "cap_complete", 12, newSViv(server->cap_complete), 0); + (void) hv_store(hv, "sasl_success", 12, newSViv(server->sasl_success), 0); av = newAV(); for (tmp = server->cap_supported; tmp != NULL; tmp = tmp->next) From 560283ba4e4d355daa32dc970021845260d2dca9 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Mon, 12 Dec 2016 21:07:56 +0100 Subject: [PATCH 03/21] g_sequence backing for window list --- configure.ac | 2 +- src/fe-common/core/fe-windows.c | 204 ++++++++++++++++++++++---------- 2 files changed, 145 insertions(+), 61 deletions(-) diff --git a/configure.ac b/configure.ac index bf87f5aa..464f6288 100644 --- a/configure.ac +++ b/configure.ac @@ -237,7 +237,7 @@ for try in 1 2; do echo "*** trying without -lgmodule" glib_modules= fi - AM_PATH_GLIB_2_0(2.16.0,,, $glib_modules) + AM_PATH_GLIB_2_0(2.28.0,,, $glib_modules) if test "$GLIB_LIBS"; then if test $glib_modules = gmodule; then AC_DEFINE(HAVE_GMODULE) diff --git a/src/fe-common/core/fe-windows.c b/src/fe-common/core/fe-windows.c index 46c1593b..ff45f141 100644 --- a/src/fe-common/core/fe-windows.c +++ b/src/fe-common/core/fe-windows.c @@ -35,6 +35,7 @@ GSList *windows; /* first in the list is the active window, next is the last active, etc. */ +GSequence *windows_seq; WINDOW_REC *active_win; static int daytag; @@ -44,21 +45,23 @@ static int daycheck; /* 0 = don't check, 1 = time is 00:00, check, static int window_get_new_refnum(void) { WINDOW_REC *win; - GSList *tmp; + GSequenceIter *iter, *end; int refnum; refnum = 1; - tmp = windows; - while (tmp != NULL) { - win = tmp->data; + for (iter = g_sequence_get_begin_iter(windows_seq), + end = g_sequence_get_end_iter(windows_seq); + + iter != end; + + refnum++, + iter = g_sequence_iter_next(iter)) { + + win = g_sequence_get(iter); if (refnum != win->refnum) { - tmp = tmp->next; - continue; + return refnum; } - - refnum++; - tmp = windows; } return refnum; @@ -73,6 +76,7 @@ WINDOW_REC *window_create(WI_ITEM_REC *item, int automatic) rec->level = settings_get_level("window_default_level"); windows = g_slist_prepend(windows, rec); + g_sequence_insert_sorted(windows_seq, rec, (GCompareDataFunc)window_refnum_cmp, NULL); signal_emit("window created", 2, rec, GINT_TO_POINTER(automatic)); if (item != NULL) window_item_add(rec, item, automatic); @@ -84,6 +88,25 @@ WINDOW_REC *window_create(WI_ITEM_REC *item, int automatic) return rec; } +static void window_set_refnum0(WINDOW_REC *window, int refnum) +{ + int old_refnum; + + g_return_if_fail(window != NULL); + g_return_if_fail(refnum >= 1); + if (window->refnum == refnum) return; + + old_refnum = window->refnum; + window->refnum = refnum; + signal_emit("window refnum changed", 2, window, GINT_TO_POINTER(old_refnum)); +} + +static int window_refnum_lookup(WINDOW_REC *window, void *refnum_p) +{ + int refnum = GPOINTER_TO_INT(refnum_p); + return window->refnum == refnum ? 0 : window->refnum < refnum ? -1 : 1; +} + /* removed_refnum was removed from the windows list, pack the windows so there won't be any holes. If there is any holes after removed_refnum, leave the windows behind it alone. */ @@ -91,23 +114,34 @@ static void windows_pack(int removed_refnum) { WINDOW_REC *window; int refnum; + GSequenceIter *iter, *end; - for (refnum = removed_refnum+1;; refnum++) { - window = window_find_refnum(refnum); - if (window == NULL || window->sticky_refnum) + refnum = removed_refnum+1; + end = g_sequence_get_end_iter(windows_seq); + iter = g_sequence_lookup(windows_seq, GINT_TO_POINTER(refnum), (GCompareDataFunc)window_refnum_lookup, NULL); + if (iter == NULL) iter = end; + + for (; iter != end; refnum++, iter = g_sequence_iter_next(iter)) { + window = g_sequence_get(iter); + + if (window == NULL || window->sticky_refnum || window->refnum != refnum) break; - window_set_refnum(window, refnum-1); + window_set_refnum0(window, refnum-1); + g_sequence_sort_changed(iter, (GCompareDataFunc)window_refnum_cmp, NULL); } } void window_destroy(WINDOW_REC *window) { + GSequenceIter *iter; g_return_if_fail(window != NULL); if (window->destroying) return; window->destroying = TRUE; windows = g_slist_remove(windows, window); + iter = g_sequence_lookup(windows_seq, window, (GCompareDataFunc)window_refnum_cmp, NULL); + if (iter != NULL) g_sequence_remove(iter); if (active_win == window) { active_win = NULL; /* it's corrupted */ @@ -189,26 +223,32 @@ void window_change_server(WINDOW_REC *window, void *server) void window_set_refnum(WINDOW_REC *window, int refnum) { - GSList *tmp; + GSequenceIter *oiter, *witer; int old_refnum; g_return_if_fail(window != NULL); g_return_if_fail(refnum >= 1); if (window->refnum == refnum) return; - for (tmp = windows; tmp != NULL; tmp = tmp->next) { - WINDOW_REC *rec = tmp->data; + oiter = g_sequence_lookup(windows_seq, GINT_TO_POINTER(refnum), (GCompareDataFunc)window_refnum_lookup, NULL); + witer = g_sequence_lookup(windows_seq, GINT_TO_POINTER(window->refnum), (GCompareDataFunc)window_refnum_lookup, NULL); - if (rec->refnum == refnum) { - rec->refnum = window->refnum; - signal_emit("window refnum changed", 2, rec, GINT_TO_POINTER(refnum)); - break; - } + if (oiter != NULL) { + WINDOW_REC *rec = g_sequence_get(oiter); + + rec->refnum = window->refnum; + signal_emit("window refnum changed", 2, rec, GINT_TO_POINTER(refnum)); } old_refnum = window->refnum; window->refnum = refnum; signal_emit("window refnum changed", 2, window, GINT_TO_POINTER(old_refnum)); + + if (witer != NULL && oiter != NULL) { + g_sequence_swap(oiter, witer); + } else { + g_sequence_sort_changed(witer, (GCompareDataFunc)window_refnum_cmp, NULL); + } } void window_set_name(WINDOW_REC *window, const char *name) @@ -346,13 +386,13 @@ WINDOW_REC *window_find_closest(void *server, const char *name, int level) WINDOW_REC *window_find_refnum(int refnum) { - GSList *tmp; + GSequenceIter *iter; - for (tmp = windows; tmp != NULL; tmp = tmp->next) { - WINDOW_REC *rec = tmp->data; + iter = g_sequence_lookup(windows_seq, GINT_TO_POINTER(refnum), (GCompareDataFunc)window_refnum_lookup, NULL); + if (iter != NULL) { + WINDOW_REC *rec = g_sequence_get(iter); - if (rec->refnum == refnum) - return rec; + return rec; } return NULL; @@ -400,71 +440,112 @@ WINDOW_REC *window_find_item(SERVER_REC *server, const char *name) int window_refnum_prev(int refnum, int wrap) { - GSList *tmp; - int prev, max; + GSequenceIter *iter, *end; - max = prev = -1; - for (tmp = windows; tmp != NULL; tmp = tmp->next) { - WINDOW_REC *rec = tmp->data; + iter = g_sequence_search(windows_seq, GINT_TO_POINTER(refnum-1), (GCompareDataFunc)window_refnum_lookup, NULL); + end = g_sequence_get_end_iter(windows_seq); - if (rec->refnum < refnum && (prev == -1 || rec->refnum > prev)) - prev = rec->refnum; - if (wrap && (max == -1 || rec->refnum > max)) - max = rec->refnum; + if (iter != NULL) { + WINDOW_REC *rec; + if (iter != end) { + rec = g_sequence_get(iter); + + if (rec->refnum < refnum) + return rec->refnum; + } + + iter = g_sequence_iter_prev(iter); + rec = g_sequence_get(iter); + + if (rec->refnum < refnum) + return rec->refnum; } - return prev != -1 ? prev : max; + if (wrap) { + WINDOW_REC *rec; + iter = g_sequence_iter_prev(end); + if (iter != end) { + rec = g_sequence_get(iter); + + return rec->refnum; + } + } + + return -1; } int window_refnum_next(int refnum, int wrap) { - GSList *tmp; - int min, next; + GSequenceIter *iter, *end; - min = next = -1; - for (tmp = windows; tmp != NULL; tmp = tmp->next) { - WINDOW_REC *rec = tmp->data; + iter = g_sequence_search(windows_seq, GINT_TO_POINTER(refnum), (GCompareDataFunc)window_refnum_lookup, NULL); + end = g_sequence_get_end_iter(windows_seq); - if (rec->refnum > refnum && (next == -1 || rec->refnum < next)) - next = rec->refnum; - if (wrap && (min == -1 || rec->refnum < min)) - min = rec->refnum; + if (iter != NULL && iter != end) { + WINDOW_REC *rec = g_sequence_get(iter); + + if (rec->refnum > refnum) + return rec->refnum; + + iter = g_sequence_iter_next(iter); + if (iter != end) { + rec = g_sequence_get(iter); + + if (rec->refnum > refnum) + return rec->refnum; + } } - return next != -1 ? next : min; + if (wrap) { + WINDOW_REC *rec; + iter = g_sequence_get_begin_iter(windows_seq); + if (iter != end) { + rec = g_sequence_get(iter); + + return rec->refnum; + } + } + + return -1; } int windows_refnum_last(void) { - GSList *tmp; - int max; + GSequenceIter *end, *iter; + WINDOW_REC *rec; - max = -1; - for (tmp = windows; tmp != NULL; tmp = tmp->next) { - WINDOW_REC *rec = tmp->data; + end = g_sequence_get_end_iter(windows_seq); + iter = g_sequence_iter_prev(end); + if (iter != end) { + rec = g_sequence_get(iter); - if (rec->refnum > max) - max = rec->refnum; + return rec->refnum; } - return max; + return -1; } int window_refnum_cmp(WINDOW_REC *w1, WINDOW_REC *w2) { - return w1->refnum < w2->refnum ? -1 : 1; + return w1 == w2 ? 0 : w1->refnum < w2->refnum ? -1 : 1; } GSList *windows_get_sorted(void) { - GSList *tmp, *sorted; + GSequenceIter *iter, *begin; + GSList *sorted; sorted = NULL; - for (tmp = windows; tmp != NULL; tmp = tmp->next) { - WINDOW_REC *rec = tmp->data; + for (iter = g_sequence_get_end_iter(windows_seq), + begin = g_sequence_get_begin_iter(windows_seq); - sorted = g_slist_insert_sorted(sorted, rec, (GCompareFunc) - window_refnum_cmp); + iter != begin; + + ) { + iter = g_sequence_iter_prev(iter); + WINDOW_REC *rec = g_sequence_get(iter); + + sorted = g_slist_prepend(sorted, rec); } return sorted; @@ -709,6 +790,7 @@ static void read_settings(void) void windows_init(void) { active_win = NULL; + windows_seq = g_sequence_new(NULL); daycheck = 0; daytag = -1; settings_add_bool("lookandfeel", "window_auto_change", FALSE); settings_add_bool("lookandfeel", "windows_auto_renumber", TRUE); @@ -733,4 +815,6 @@ void windows_deinit(void) signal_remove("server disconnected", (SIGNAL_FUNC) sig_server_disconnected); signal_remove("server connect failed", (SIGNAL_FUNC) sig_server_disconnected); signal_remove("setup changed", (SIGNAL_FUNC) read_settings); + g_sequence_free(windows_seq); + windows_seq = NULL; } From 365097319f2bf57d7d01c2c4c912fca124fbedf9 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Tue, 13 Dec 2016 03:04:01 +0100 Subject: [PATCH 04/21] manually redraw the activity list on expose only might speed up /foreach query /unquery --- src/fe-text/statusbar-items.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/fe-text/statusbar-items.c b/src/fe-text/statusbar-items.c index 0db4f63a..de4499b4 100644 --- a/src/fe-text/statusbar-items.c +++ b/src/fe-text/statusbar-items.c @@ -143,16 +143,34 @@ static char *get_activity_list(MAIN_WINDOW_REC *window, int normal, int hilight) static void item_act(SBAR_ITEM_REC *item, int get_size_only) { char *actlist; + int max_size; - actlist = get_activity_list(item->bar->parent_window, TRUE, TRUE); - if (actlist == NULL) { - if (get_size_only) + if (get_size_only) { + if (activity_list == NULL) item->min_size = item->max_size = 0; + /* Skip activity calculation on regular trigger, only + set dirty */ return; } - statusbar_item_default_handler(item, get_size_only, + actlist = get_activity_list(item->bar->parent_window, TRUE, TRUE); + if (actlist == NULL) { + return; + } + + max_size = item->max_size; + statusbar_item_default_handler(item, TRUE, NULL, actlist, FALSE); + statusbar_item_default_handler(item, FALSE, + NULL, actlist, FALSE); + if (max_size != item->max_size) { + /* Due to above hack of skipping the calculation, we + need to manually trigger the redraw process now or + we won't see the item */ + item->bar->dirty = item->dirty = TRUE; + statusbar_redraw(item->bar, TRUE); + statusbar_redraw_dirty(); + } g_free_not_null(actlist); } From 59242cb595716bf34966ee71aca81e0c9a2a5284 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Thu, 15 Dec 2016 16:59:38 +0100 Subject: [PATCH 05/21] add assertion to statusbar_read_group fix #564 --- src/fe-text/statusbar-config.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/fe-text/statusbar-config.c b/src/fe-text/statusbar-config.c index a47a709e..48f4aa61 100644 --- a/src/fe-text/statusbar-config.c +++ b/src/fe-text/statusbar-config.c @@ -194,6 +194,8 @@ static void statusbar_read_group(CONFIG_NODE *node) STATUSBAR_GROUP_REC *group; GSList *tmp; + g_return_if_fail(is_node_list(node)); + group = statusbar_group_find(node->key); if (group == NULL) { group = statusbar_group_create(node->key); From 0d6add02cf1a1e0dc3905a482d259a8851b4939c Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Thu, 15 Dec 2016 15:22:30 +0100 Subject: [PATCH 06/21] Process the nick changes in queries before the PRIVMSG is handled. Otherwise we end up with the message in the status window since the frontend knows jack shit about the casemapping option when it tries to find the associated window for the query. --- src/fe-common/irc/fe-irc-queries.c | 7 +++++++ src/irc/core/irc-queries.c | 16 ---------------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/src/fe-common/irc/fe-irc-queries.c b/src/fe-common/irc/fe-irc-queries.c index b2faefbc..c928a94a 100644 --- a/src/fe-common/irc/fe-irc-queries.c +++ b/src/fe-common/irc/fe-irc-queries.c @@ -78,6 +78,13 @@ static void event_privmsg(SERVER_REC *server, const char *data, if (!server_has_nick(server, query->name)) query_change_nick(query, nick); } + } else { + /* process the changes to the query structure now, before the + * privmsg is dispatched. */ + if (g_strcmp0(query->name, nick) != 0) + query_change_nick(query, nick); + if (address != NULL && g_strcmp0(query->address, address) != 0) + query_change_address(query, address); } } diff --git a/src/irc/core/irc-queries.c b/src/irc/core/irc-queries.c index 12861744..b611e621 100644 --- a/src/irc/core/irc-queries.c +++ b/src/irc/core/irc-queries.c @@ -79,20 +79,6 @@ static void check_query_changes(IRC_SERVER_REC *server, const char *nick, } } -static void event_privmsg(IRC_SERVER_REC *server, const char *data, - const char *nick, const char *address) -{ - char *params, *target, *msg; - - g_return_if_fail(data != NULL); - if (nick == NULL) - return; - - params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg); - check_query_changes(server, nick, address, target); - g_free(params); -} - static void ctcp_action(IRC_SERVER_REC *server, const char *msg, const char *nick, const char *address, const char *target) @@ -117,14 +103,12 @@ static void event_nick(SERVER_REC *server, const char *data, void irc_queries_init(void) { - signal_add_last("event privmsg", (SIGNAL_FUNC) event_privmsg); signal_add_last("ctcp action", (SIGNAL_FUNC) ctcp_action); signal_add("event nick", (SIGNAL_FUNC) event_nick); } void irc_queries_deinit(void) { - signal_remove("event privmsg", (SIGNAL_FUNC) event_privmsg); signal_remove("ctcp action", (SIGNAL_FUNC) ctcp_action); signal_remove("event nick", (SIGNAL_FUNC) event_nick); } From 7a7f6abc168b571a0db4fa65c760fe6e46edf199 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Thu, 15 Dec 2016 22:41:57 +0100 Subject: [PATCH 07/21] Prevent a UaF by calling server_disconnect in a signal handler. --- src/fe-common/irc/fe-sasl.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/fe-common/irc/fe-sasl.c b/src/fe-common/irc/fe-sasl.c index 4c86f850..6cba1887 100644 --- a/src/fe-common/irc/fe-sasl.c +++ b/src/fe-common/irc/fe-sasl.c @@ -43,8 +43,15 @@ static void sig_cap_end(IRC_SERVER_REC *server) /* The negotiation has now been terminated, if we didn't manage to * authenticate successfully with the server just disconnect. */ if (!server->sasl_success && - settings_get_bool("sasl_disconnect_on_failure")) - server_disconnect(SERVER(server)); + settings_get_bool("sasl_disconnect_on_failure")) { + /* We can't use server_disconnect() here because we'd end up + * freeing the 'server' object and be guilty of a slew of UaF. */ + server->connection_lost = TRUE; + /* By setting connection_lost we make sure the communication is + * halted and when the control goes back to irc_parse_incoming + * the server object is safely destroyed. */ + signal_stop(); + } } From 2f59fe206233c0f45256e9e541c121f4d63385dd Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Mon, 19 Dec 2016 22:03:46 +0100 Subject: [PATCH 08/21] add some sequence helper functions --- src/fe-common/core/fe-windows.c | 85 +++++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 25 deletions(-) diff --git a/src/fe-common/core/fe-windows.c b/src/fe-common/core/fe-windows.c index ff45f141..d02048be 100644 --- a/src/fe-common/core/fe-windows.c +++ b/src/fe-common/core/fe-windows.c @@ -42,6 +42,16 @@ static int daytag; static int daycheck; /* 0 = don't check, 1 = time is 00:00, check, 2 = time is 00:00, already checked */ +static GSequenceIter *windows_seq_begin(void) +{ + return g_sequence_get_begin_iter(windows_seq); +} + +static GSequenceIter *windows_seq_end(void) +{ + return g_sequence_get_end_iter(windows_seq); +} + static int window_get_new_refnum(void) { WINDOW_REC *win; @@ -49,8 +59,8 @@ static int window_get_new_refnum(void) int refnum; refnum = 1; - for (iter = g_sequence_get_begin_iter(windows_seq), - end = g_sequence_get_end_iter(windows_seq); + for (iter = windows_seq_begin(), + end = windows_seq_end(); iter != end; @@ -67,6 +77,11 @@ static int window_get_new_refnum(void) return refnum; } +static GSequenceIter *windows_seq_insert(WINDOW_REC *rec) +{ + return g_sequence_insert_sorted(windows_seq, rec, (GCompareDataFunc)window_refnum_cmp, NULL); +} + WINDOW_REC *window_create(WI_ITEM_REC *item, int automatic) { WINDOW_REC *rec; @@ -76,7 +91,7 @@ WINDOW_REC *window_create(WI_ITEM_REC *item, int automatic) rec->level = settings_get_level("window_default_level"); windows = g_slist_prepend(windows, rec); - g_sequence_insert_sorted(windows_seq, rec, (GCompareDataFunc)window_refnum_cmp, NULL); + windows_seq_insert(rec); signal_emit("window created", 2, rec, GINT_TO_POINTER(automatic)); if (item != NULL) window_item_add(rec, item, automatic); @@ -107,6 +122,16 @@ static int window_refnum_lookup(WINDOW_REC *window, void *refnum_p) return window->refnum == refnum ? 0 : window->refnum < refnum ? -1 : 1; } +static GSequenceIter *windows_seq_refnum_lookup(int refnum) +{ + return g_sequence_lookup(windows_seq, GINT_TO_POINTER(refnum), (GCompareDataFunc)window_refnum_lookup, NULL); +} + +static void windows_seq_changed(GSequenceIter *iter) +{ + g_sequence_sort_changed(iter, (GCompareDataFunc)window_refnum_cmp, NULL); +} + /* removed_refnum was removed from the windows list, pack the windows so there won't be any holes. If there is any holes after removed_refnum, leave the windows behind it alone. */ @@ -117,9 +142,9 @@ static void windows_pack(int removed_refnum) GSequenceIter *iter, *end; refnum = removed_refnum+1; - end = g_sequence_get_end_iter(windows_seq); - iter = g_sequence_lookup(windows_seq, GINT_TO_POINTER(refnum), (GCompareDataFunc)window_refnum_lookup, NULL); - if (iter == NULL) iter = end; + end = windows_seq_end(); + iter = windows_seq_refnum_lookup(refnum); + if (iter == NULL) return; for (; iter != end; refnum++, iter = g_sequence_iter_next(iter)) { window = g_sequence_get(iter); @@ -128,10 +153,15 @@ static void windows_pack(int removed_refnum) break; window_set_refnum0(window, refnum-1); - g_sequence_sort_changed(iter, (GCompareDataFunc)window_refnum_cmp, NULL); + windows_seq_changed(iter); } } +static GSequenceIter *windows_seq_window_lookup(WINDOW_REC *rec) +{ + return g_sequence_lookup(windows_seq, rec, (GCompareDataFunc)window_refnum_cmp, NULL); +} + void window_destroy(WINDOW_REC *window) { GSequenceIter *iter; @@ -140,7 +170,7 @@ void window_destroy(WINDOW_REC *window) if (window->destroying) return; window->destroying = TRUE; windows = g_slist_remove(windows, window); - iter = g_sequence_lookup(windows_seq, window, (GCompareDataFunc)window_refnum_cmp, NULL); + iter = windows_seq_window_lookup(window); if (iter != NULL) g_sequence_remove(iter); if (active_win == window) { @@ -223,18 +253,18 @@ void window_change_server(WINDOW_REC *window, void *server) void window_set_refnum(WINDOW_REC *window, int refnum) { - GSequenceIter *oiter, *witer; + GSequenceIter *other_iter, *window_iter; int old_refnum; g_return_if_fail(window != NULL); g_return_if_fail(refnum >= 1); if (window->refnum == refnum) return; - oiter = g_sequence_lookup(windows_seq, GINT_TO_POINTER(refnum), (GCompareDataFunc)window_refnum_lookup, NULL); - witer = g_sequence_lookup(windows_seq, GINT_TO_POINTER(window->refnum), (GCompareDataFunc)window_refnum_lookup, NULL); + other_iter = windows_seq_refnum_lookup(refnum); + window_iter = windows_seq_refnum_lookup(window->refnum); - if (oiter != NULL) { - WINDOW_REC *rec = g_sequence_get(oiter); + if (other_iter != NULL) { + WINDOW_REC *rec = g_sequence_get(other_iter); rec->refnum = window->refnum; signal_emit("window refnum changed", 2, rec, GINT_TO_POINTER(refnum)); @@ -244,10 +274,10 @@ void window_set_refnum(WINDOW_REC *window, int refnum) window->refnum = refnum; signal_emit("window refnum changed", 2, window, GINT_TO_POINTER(old_refnum)); - if (witer != NULL && oiter != NULL) { - g_sequence_swap(oiter, witer); + if (window_iter != NULL && other_iter != NULL) { + g_sequence_swap(other_iter, window_iter); } else { - g_sequence_sort_changed(witer, (GCompareDataFunc)window_refnum_cmp, NULL); + windows_seq_changed(window_iter); } } @@ -388,7 +418,7 @@ WINDOW_REC *window_find_refnum(int refnum) { GSequenceIter *iter; - iter = g_sequence_lookup(windows_seq, GINT_TO_POINTER(refnum), (GCompareDataFunc)window_refnum_lookup, NULL); + iter = windows_seq_refnum_lookup(refnum); if (iter != NULL) { WINDOW_REC *rec = g_sequence_get(iter); @@ -438,12 +468,17 @@ WINDOW_REC *window_find_item(SERVER_REC *server, const char *name) return window_item_window(item); } +static GSequenceIter *windows_seq_refnum_search_right(int refnum) +{ + return g_sequence_search(windows_seq, GINT_TO_POINTER(refnum), (GCompareDataFunc)window_refnum_lookup, NULL); +} + int window_refnum_prev(int refnum, int wrap) { GSequenceIter *iter, *end; - iter = g_sequence_search(windows_seq, GINT_TO_POINTER(refnum-1), (GCompareDataFunc)window_refnum_lookup, NULL); - end = g_sequence_get_end_iter(windows_seq); + iter = windows_seq_refnum_search_right(refnum-1); + end = windows_seq_end(); if (iter != NULL) { WINDOW_REC *rec; @@ -478,8 +513,8 @@ int window_refnum_next(int refnum, int wrap) { GSequenceIter *iter, *end; - iter = g_sequence_search(windows_seq, GINT_TO_POINTER(refnum), (GCompareDataFunc)window_refnum_lookup, NULL); - end = g_sequence_get_end_iter(windows_seq); + iter = windows_seq_refnum_search_right(refnum); + end = windows_seq_end(); if (iter != NULL && iter != end) { WINDOW_REC *rec = g_sequence_get(iter); @@ -498,7 +533,7 @@ int window_refnum_next(int refnum, int wrap) if (wrap) { WINDOW_REC *rec; - iter = g_sequence_get_begin_iter(windows_seq); + iter = windows_seq_begin(); if (iter != end) { rec = g_sequence_get(iter); @@ -514,7 +549,7 @@ int windows_refnum_last(void) GSequenceIter *end, *iter; WINDOW_REC *rec; - end = g_sequence_get_end_iter(windows_seq); + end = windows_seq_end(); iter = g_sequence_iter_prev(end); if (iter != end) { rec = g_sequence_get(iter); @@ -536,8 +571,8 @@ GSList *windows_get_sorted(void) GSList *sorted; sorted = NULL; - for (iter = g_sequence_get_end_iter(windows_seq), - begin = g_sequence_get_begin_iter(windows_seq); + for (iter = windows_seq_end(), + begin = windows_seq_begin(); iter != begin; From 9004265e5417c509e55c5141d5880ebd1e1c3281 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Tue, 20 Dec 2016 21:01:16 +0100 Subject: [PATCH 09/21] clean up window_refnum_{prev,next} --- src/fe-common/core/fe-windows.c | 46 ++++++++++----------------------- 1 file changed, 14 insertions(+), 32 deletions(-) diff --git a/src/fe-common/core/fe-windows.c b/src/fe-common/core/fe-windows.c index d02048be..97034192 100644 --- a/src/fe-common/core/fe-windows.c +++ b/src/fe-common/core/fe-windows.c @@ -473,35 +473,29 @@ static GSequenceIter *windows_seq_refnum_search_right(int refnum) return g_sequence_search(windows_seq, GINT_TO_POINTER(refnum), (GCompareDataFunc)window_refnum_lookup, NULL); } +static GSequenceIter *windows_seq_refnum_search_left(int refnum) +{ + GSequenceIter *iter = windows_seq_refnum_search_right(refnum-1); + return iter == windows_seq_begin() ? NULL : g_sequence_iter_prev(iter); +} + int window_refnum_prev(int refnum, int wrap) { + WINDOW_REC *rec; GSequenceIter *iter, *end; - iter = windows_seq_refnum_search_right(refnum-1); + iter = windows_seq_refnum_search_left(refnum); end = windows_seq_end(); if (iter != NULL) { - WINDOW_REC *rec; - if (iter != end) { - rec = g_sequence_get(iter); - - if (rec->refnum < refnum) - return rec->refnum; - } - - iter = g_sequence_iter_prev(iter); rec = g_sequence_get(iter); - - if (rec->refnum < refnum) - return rec->refnum; + return rec->refnum; } if (wrap) { - WINDOW_REC *rec; iter = g_sequence_iter_prev(end); if (iter != end) { rec = g_sequence_get(iter); - return rec->refnum; } } @@ -511,32 +505,21 @@ int window_refnum_prev(int refnum, int wrap) int window_refnum_next(int refnum, int wrap) { + WINDOW_REC *rec; GSequenceIter *iter, *end; iter = windows_seq_refnum_search_right(refnum); end = windows_seq_end(); - if (iter != NULL && iter != end) { - WINDOW_REC *rec = g_sequence_get(iter); - - if (rec->refnum > refnum) - return rec->refnum; - - iter = g_sequence_iter_next(iter); - if (iter != end) { - rec = g_sequence_get(iter); - - if (rec->refnum > refnum) - return rec->refnum; - } + if (iter != end) { + rec = g_sequence_get(iter); + return rec->refnum; } if (wrap) { - WINDOW_REC *rec; iter = windows_seq_begin(); if (iter != end) { rec = g_sequence_get(iter); - return rec->refnum; } } @@ -546,14 +529,13 @@ int window_refnum_next(int refnum, int wrap) int windows_refnum_last(void) { - GSequenceIter *end, *iter; WINDOW_REC *rec; + GSequenceIter *end, *iter; end = windows_seq_end(); iter = g_sequence_iter_prev(end); if (iter != end) { rec = g_sequence_get(iter); - return rec->refnum; } From 03f5dc63fee7c60bb5d5c29698c975073e365b88 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Tue, 20 Dec 2016 21:33:51 +0100 Subject: [PATCH 10/21] nits --- src/fe-common/core/fe-windows.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/fe-common/core/fe-windows.c b/src/fe-common/core/fe-windows.c index 97034192..bd289d2f 100644 --- a/src/fe-common/core/fe-windows.c +++ b/src/fe-common/core/fe-windows.c @@ -59,19 +59,17 @@ static int window_get_new_refnum(void) int refnum; refnum = 1; - for (iter = windows_seq_begin(), - end = windows_seq_end(); - - iter != end; - - refnum++, - iter = g_sequence_iter_next(iter)) { + iter = windows_seq_begin(); + end = windows_seq_end(); + while (iter != end) { win = g_sequence_get(iter); - if (refnum != win->refnum) { + if (refnum != win->refnum) return refnum; - } + + refnum++; + iter = g_sequence_iter_next(iter); } return refnum; @@ -141,7 +139,7 @@ static void windows_pack(int removed_refnum) int refnum; GSequenceIter *iter, *end; - refnum = removed_refnum+1; + refnum = removed_refnum + 1; end = windows_seq_end(); iter = windows_seq_refnum_lookup(refnum); if (iter == NULL) return; @@ -152,7 +150,7 @@ static void windows_pack(int removed_refnum) if (window == NULL || window->sticky_refnum || window->refnum != refnum) break; - window_set_refnum0(window, refnum-1); + window_set_refnum0(window, refnum - 1); windows_seq_changed(iter); } } @@ -468,14 +466,19 @@ WINDOW_REC *window_find_item(SERVER_REC *server, const char *name) return window_item_window(item); } +/* search to the numerically right iterator of refnum */ static GSequenceIter *windows_seq_refnum_search_right(int refnum) { return g_sequence_search(windows_seq, GINT_TO_POINTER(refnum), (GCompareDataFunc)window_refnum_lookup, NULL); } +/* we want to find the numerically left iterator of refnum, so we + search the right of the previous refnum. but we need to figure out + the case where the iterator is already at the beginning, i.e + iter->refnum >= refnum */ static GSequenceIter *windows_seq_refnum_search_left(int refnum) { - GSequenceIter *iter = windows_seq_refnum_search_right(refnum-1); + GSequenceIter *iter = windows_seq_refnum_search_right(refnum - 1); return iter == windows_seq_begin() ? NULL : g_sequence_iter_prev(iter); } From 9a018a782c40ed9da88ae88a7f1c01265f3342de Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Tue, 20 Dec 2016 21:36:56 +0100 Subject: [PATCH 11/21] sort windows_seq helpers to top --- src/fe-common/core/fe-windows.c | 84 ++++++++++++++++----------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/src/fe-common/core/fe-windows.c b/src/fe-common/core/fe-windows.c index bd289d2f..248cd621 100644 --- a/src/fe-common/core/fe-windows.c +++ b/src/fe-common/core/fe-windows.c @@ -42,6 +42,12 @@ static int daytag; static int daycheck; /* 0 = don't check, 1 = time is 00:00, check, 2 = time is 00:00, already checked */ +static int window_refnum_lookup(WINDOW_REC *window, void *refnum_p) +{ + int refnum = GPOINTER_TO_INT(refnum_p); + return window->refnum == refnum ? 0 : window->refnum < refnum ? -1 : 1; +} + static GSequenceIter *windows_seq_begin(void) { return g_sequence_get_begin_iter(windows_seq); @@ -52,6 +58,42 @@ static GSequenceIter *windows_seq_end(void) return g_sequence_get_end_iter(windows_seq); } +static GSequenceIter *windows_seq_insert(WINDOW_REC *rec) +{ + return g_sequence_insert_sorted(windows_seq, rec, (GCompareDataFunc)window_refnum_cmp, NULL); +} + +static GSequenceIter *windows_seq_refnum_lookup(int refnum) +{ + return g_sequence_lookup(windows_seq, GINT_TO_POINTER(refnum), (GCompareDataFunc)window_refnum_lookup, NULL); +} + +static void windows_seq_changed(GSequenceIter *iter) +{ + g_sequence_sort_changed(iter, (GCompareDataFunc)window_refnum_cmp, NULL); +} + +static GSequenceIter *windows_seq_window_lookup(WINDOW_REC *rec) +{ + return g_sequence_lookup(windows_seq, rec, (GCompareDataFunc)window_refnum_cmp, NULL); +} + +/* search to the numerically right iterator of refnum */ +static GSequenceIter *windows_seq_refnum_search_right(int refnum) +{ + return g_sequence_search(windows_seq, GINT_TO_POINTER(refnum), (GCompareDataFunc)window_refnum_lookup, NULL); +} + +/* we want to find the numerically left iterator of refnum, so we + search the right of the previous refnum. but we need to figure out + the case where the iterator is already at the beginning, i.e + iter->refnum >= refnum */ +static GSequenceIter *windows_seq_refnum_search_left(int refnum) +{ + GSequenceIter *iter = windows_seq_refnum_search_right(refnum - 1); + return iter == windows_seq_begin() ? NULL : g_sequence_iter_prev(iter); +} + static int window_get_new_refnum(void) { WINDOW_REC *win; @@ -75,11 +117,6 @@ static int window_get_new_refnum(void) return refnum; } -static GSequenceIter *windows_seq_insert(WINDOW_REC *rec) -{ - return g_sequence_insert_sorted(windows_seq, rec, (GCompareDataFunc)window_refnum_cmp, NULL); -} - WINDOW_REC *window_create(WI_ITEM_REC *item, int automatic) { WINDOW_REC *rec; @@ -114,22 +151,6 @@ static void window_set_refnum0(WINDOW_REC *window, int refnum) signal_emit("window refnum changed", 2, window, GINT_TO_POINTER(old_refnum)); } -static int window_refnum_lookup(WINDOW_REC *window, void *refnum_p) -{ - int refnum = GPOINTER_TO_INT(refnum_p); - return window->refnum == refnum ? 0 : window->refnum < refnum ? -1 : 1; -} - -static GSequenceIter *windows_seq_refnum_lookup(int refnum) -{ - return g_sequence_lookup(windows_seq, GINT_TO_POINTER(refnum), (GCompareDataFunc)window_refnum_lookup, NULL); -} - -static void windows_seq_changed(GSequenceIter *iter) -{ - g_sequence_sort_changed(iter, (GCompareDataFunc)window_refnum_cmp, NULL); -} - /* removed_refnum was removed from the windows list, pack the windows so there won't be any holes. If there is any holes after removed_refnum, leave the windows behind it alone. */ @@ -155,11 +176,6 @@ static void windows_pack(int removed_refnum) } } -static GSequenceIter *windows_seq_window_lookup(WINDOW_REC *rec) -{ - return g_sequence_lookup(windows_seq, rec, (GCompareDataFunc)window_refnum_cmp, NULL); -} - void window_destroy(WINDOW_REC *window) { GSequenceIter *iter; @@ -466,22 +482,6 @@ WINDOW_REC *window_find_item(SERVER_REC *server, const char *name) return window_item_window(item); } -/* search to the numerically right iterator of refnum */ -static GSequenceIter *windows_seq_refnum_search_right(int refnum) -{ - return g_sequence_search(windows_seq, GINT_TO_POINTER(refnum), (GCompareDataFunc)window_refnum_lookup, NULL); -} - -/* we want to find the numerically left iterator of refnum, so we - search the right of the previous refnum. but we need to figure out - the case where the iterator is already at the beginning, i.e - iter->refnum >= refnum */ -static GSequenceIter *windows_seq_refnum_search_left(int refnum) -{ - GSequenceIter *iter = windows_seq_refnum_search_right(refnum - 1); - return iter == windows_seq_begin() ? NULL : g_sequence_iter_prev(iter); -} - int window_refnum_prev(int refnum, int wrap) { WINDOW_REC *rec; From 9151f87145e6c9ea40192e0e7c8266eacaaa335f Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Tue, 20 Dec 2016 21:40:18 +0100 Subject: [PATCH 12/21] remove some for loops --- src/fe-common/core/fe-windows.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/fe-common/core/fe-windows.c b/src/fe-common/core/fe-windows.c index 248cd621..0afa2914 100644 --- a/src/fe-common/core/fe-windows.c +++ b/src/fe-common/core/fe-windows.c @@ -165,7 +165,7 @@ static void windows_pack(int removed_refnum) iter = windows_seq_refnum_lookup(refnum); if (iter == NULL) return; - for (; iter != end; refnum++, iter = g_sequence_iter_next(iter)) { + while (iter != end) { window = g_sequence_get(iter); if (window == NULL || window->sticky_refnum || window->refnum != refnum) @@ -173,6 +173,9 @@ static void windows_pack(int removed_refnum) window_set_refnum0(window, refnum - 1); windows_seq_changed(iter); + + refnum++; + iter = g_sequence_iter_next(iter); } } @@ -556,12 +559,10 @@ GSList *windows_get_sorted(void) GSList *sorted; sorted = NULL; - for (iter = windows_seq_end(), - begin = windows_seq_begin(); + iter = windows_seq_end(); + begin = windows_seq_begin(); - iter != begin; - - ) { + while (iter != begin) { iter = g_sequence_iter_prev(iter); WINDOW_REC *rec = g_sequence_get(iter); From 0a46a1664ab2d5c914ab378d56e0d22825f06522 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Thu, 22 Dec 2016 15:38:43 +0100 Subject: [PATCH 13/21] Add myself to the core team members --- AUTHORS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index eea359cc..c1280552 100644 --- a/AUTHORS +++ b/AUTHORS @@ -13,6 +13,7 @@ Irssi staff (current maintainers) : Jase Thew (bazerka) dequis (dx) Ailin Nemui (Nei) + Giuseppe (TheLemonMan, lemonboy) Former developers: @@ -26,7 +27,6 @@ Large feature patches by: Heikki Orsila : DCC SEND queueing Mark Trumbull : DCC SERVER Francesco Fracassi : Passive DCC - Giuseppe (The Lemon Man) Other patches (grep for "patch" in ChangeLog) by: From 7e22d051ae699467575d1feeec6d8e2e2f16721f Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Fri, 23 Dec 2016 17:59:55 +0100 Subject: [PATCH 14/21] Make sure SASL was actually requested before failing. --- src/fe-common/irc/fe-sasl.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/fe-common/irc/fe-sasl.c b/src/fe-common/irc/fe-sasl.c index 6cba1887..fc8105fc 100644 --- a/src/fe-common/irc/fe-sasl.c +++ b/src/fe-common/irc/fe-sasl.c @@ -1,7 +1,7 @@ /* fe-sasl.c : irssi - Copyright (C) 2015 The Lemon Man + Copyright (C) 2015-2017 The Lemon Man This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,6 +22,8 @@ #include "module-formats.h" #include "signals.h" #include "levels.h" +#include "misc.h" +#include "sasl.h" #include "irc-servers.h" #include "settings.h" @@ -43,6 +45,7 @@ static void sig_cap_end(IRC_SERVER_REC *server) /* The negotiation has now been terminated, if we didn't manage to * authenticate successfully with the server just disconnect. */ if (!server->sasl_success && + server->connrec->sasl_mechanism != SASL_MECHANISM_NONE && settings_get_bool("sasl_disconnect_on_failure")) { /* We can't use server_disconnect() here because we'd end up * freeing the 'server' object and be guilty of a slew of UaF. */ From 8e5db471e4d8b052f072ce8a351222c6edb42d19 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Thu, 14 Jan 2016 14:10:00 +0100 Subject: [PATCH 15/21] Use GLib's regexp interface (backed by PCRE) --- src/core/ignore.c | 35 +++++++++++------------------ src/core/ignore.h | 8 +------ src/core/misc.c | 4 ---- src/fe-common/core/fe-ignore.c | 2 -- src/fe-common/core/hilight-text.c | 37 +++++++++++++------------------ src/fe-common/core/hilight-text.h | 8 +------ src/fe-text/textbuffer.c | 35 ++++++++++------------------- 7 files changed, 42 insertions(+), 87 deletions(-) diff --git a/src/core/ignore.c b/src/core/ignore.c index 2047dc9d..2b8299bd 100644 --- a/src/core/ignore.c +++ b/src/core/ignore.c @@ -67,12 +67,8 @@ static int ignore_match_pattern(IGNORE_REC *rec, const char *text) return FALSE; if (rec->regexp) { -#ifdef HAVE_REGEX_H return rec->regexp_compiled && - regexec(&rec->preg, text, 0, NULL, 0) == 0; -#else - return FALSE; -#endif + g_regex_match(rec->preg, text, 0, NULL); } return rec->fullword ? @@ -326,26 +322,23 @@ static void ignore_remove_config(IGNORE_REC *rec) static void ignore_init_rec(IGNORE_REC *rec) { -#ifdef HAVE_REGEX_H - char *errbuf; - int errcode, errbuf_len; + if (rec->regexp_compiled) { + g_regex_unref(rec->preg); + rec->regexp_compiled = FALSE; + } - if (rec->regexp_compiled) regfree(&rec->preg); - rec->regexp_compiled = FALSE; if (rec->regexp && rec->pattern != NULL) { - errcode = regcomp(&rec->preg, rec->pattern, - REG_EXTENDED|REG_ICASE|REG_NOSUB); - if (errcode != 0) { - errbuf_len = regerror(errcode, &rec->preg, 0, 0); - errbuf = g_malloc(errbuf_len); - regerror(errcode, &rec->preg, errbuf, errbuf_len); - g_warning("Failed to compile regexp '%s': %s", rec->pattern, errbuf); - g_free(errbuf); + GError *re_error; + + rec->preg = g_regex_new(rec->pattern, G_REGEX_CASELESS, 0, &re_error); + + if (rec->preg == NULL) { + g_warning("Failed to compile regexp '%s': %s", rec->pattern, re_error->message); + g_error_free(re_error); } else { rec->regexp_compiled = TRUE; } } -#endif } void ignore_add_rec(IGNORE_REC *rec) @@ -365,9 +358,7 @@ static void ignore_destroy(IGNORE_REC *rec, int send_signal) if (send_signal) signal_emit("ignore destroyed", 1, rec); -#ifdef HAVE_REGEX_H - if (rec->regexp_compiled) regfree(&rec->preg); -#endif + if (rec->regexp_compiled) g_regex_unref(rec->preg); if (rec->channels != NULL) g_strfreev(rec->channels); g_free_not_null(rec->mask); g_free_not_null(rec->servertag); diff --git a/src/core/ignore.h b/src/core/ignore.h index f889740f..6c9797f5 100644 --- a/src/core/ignore.h +++ b/src/core/ignore.h @@ -1,10 +1,6 @@ #ifndef __IGNORE_H #define __IGNORE_H -#ifdef HAVE_REGEX_H -# include -#endif - typedef struct _IGNORE_REC IGNORE_REC; struct _IGNORE_REC { @@ -20,10 +16,8 @@ struct _IGNORE_REC { unsigned int regexp:1; unsigned int fullword:1; unsigned int replies:1; /* ignore replies to nick in channel */ -#ifdef HAVE_REGEX_H unsigned int regexp_compiled:1; /* should always be TRUE, unless regexp is invalid */ - regex_t preg; -#endif + GRegex *preg; }; extern GSList *ignores; diff --git a/src/core/misc.c b/src/core/misc.c index 0bb1f7e6..c59eb126 100644 --- a/src/core/misc.c +++ b/src/core/misc.c @@ -22,10 +22,6 @@ #include "misc.h" #include "commands.h" -#ifdef HAVE_REGEX_H -# include -#endif - typedef struct { int condition; GInputFunction function; diff --git a/src/fe-common/core/fe-ignore.c b/src/fe-common/core/fe-ignore.c index 52b11e6b..addfa0b8 100644 --- a/src/fe-common/core/fe-ignore.c +++ b/src/fe-common/core/fe-ignore.c @@ -58,10 +58,8 @@ static void ignore_print(int index, IGNORE_REC *rec) g_string_append(options, "-regexp "); if (rec->pattern == NULL) g_string_append(options, "[INVALID! -pattern missing] "); -#ifdef HAVE_REGEX_H else if (!rec->regexp_compiled) g_string_append(options, "[INVALID!] "); -#endif } if (rec->fullword) g_string_append(options, "-full "); if (rec->replies) g_string_append(options, "-replies "); diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c index 4691a708..83b6f67e 100644 --- a/src/fe-common/core/hilight-text.c +++ b/src/fe-common/core/hilight-text.c @@ -101,9 +101,7 @@ static void hilight_destroy(HILIGHT_REC *rec) { g_return_if_fail(rec != NULL); -#ifdef HAVE_REGEX_H - if (rec->regexp_compiled) regfree(&rec->preg); -#endif + if (rec->regexp_compiled) g_regex_unref(rec->preg); if (rec->channels != NULL) g_strfreev(rec->channels); g_free_not_null(rec->color); g_free_not_null(rec->act_color); @@ -120,14 +118,15 @@ static void hilights_destroy_all(void) static void hilight_init_rec(HILIGHT_REC *rec) { -#ifdef HAVE_REGEX_H - if (rec->regexp_compiled) regfree(&rec->preg); - if (!rec->regexp) + if (rec->regexp_compiled) { + g_regex_unref(rec->preg); rec->regexp_compiled = FALSE; - else - rec->regexp_compiled = regcomp(&rec->preg, rec->text, - rec->case_sensitive ? REG_EXTENDED : (REG_EXTENDED|REG_ICASE)) == 0; -#endif + } + + rec->preg = g_regex_new(rec->text, G_REGEX_CASELESS, 0, NULL); + + if (rec->preg != NULL) + rec->regexp_compiled = TRUE; } void hilight_create(HILIGHT_REC *rec) @@ -200,19 +199,15 @@ static int hilight_match_text(HILIGHT_REC *rec, const char *text, char *match; if (rec->regexp) { -#ifdef HAVE_REGEX_H - regmatch_t rmatch[1]; + GMatchInfo *match; - if (rec->regexp_compiled && - regexec(&rec->preg, text, 1, rmatch, 0) == 0) { - if (rmatch[0].rm_so > 0 && - match_beg != NULL && match_end != NULL) { - *match_beg = rmatch[0].rm_so; - *match_end = rmatch[0].rm_eo; + if (rec->regexp_compiled) { + g_regex_match (rec->preg, text, 0, &match); + + if (g_match_info_matches(match)) { + return g_match_info_fetch_pos(match, 0, match_beg, match_end); } - return TRUE; } -#endif } else { if (rec->case_sensitive) { match = rec->fullword ? @@ -509,10 +504,8 @@ static void hilight_print(int index, HILIGHT_REC *rec) if (rec->case_sensitive) g_string_append(options, "-matchcase "); if (rec->regexp) { g_string_append(options, "-regexp "); -#ifdef HAVE_REGEX_H if (!rec->regexp_compiled) g_string_append(options, "[INVALID!] "); -#endif } if (rec->priority != 0) diff --git a/src/fe-common/core/hilight-text.h b/src/fe-common/core/hilight-text.h index ae05e1ca..a74c38b0 100644 --- a/src/fe-common/core/hilight-text.h +++ b/src/fe-common/core/hilight-text.h @@ -1,10 +1,6 @@ #ifndef __HILIGHT_TEXT_H #define __HILIGHT_TEXT_H -#ifdef HAVE_REGEX_H -# include -#endif - #include "formats.h" struct _HILIGHT_REC { @@ -24,10 +20,8 @@ struct _HILIGHT_REC { unsigned int fullword:1; /* match `text' only for full words */ unsigned int regexp:1; /* `text' is a regular expression */ unsigned int case_sensitive:1;/* `text' must match case */ -#ifdef HAVE_REGEX_H unsigned int regexp_compiled:1; /* should always be TRUE, unless regexp is invalid */ - regex_t preg; -#endif + GRegex *preg; char *servertag; }; diff --git a/src/fe-text/textbuffer.c b/src/fe-text/textbuffer.c index 24ee62bc..979b2a46 100644 --- a/src/fe-text/textbuffer.c +++ b/src/fe-text/textbuffer.c @@ -27,10 +27,6 @@ #include "textbuffer.h" -#ifdef HAVE_REGEX_H -# include -#endif - #define TEXT_CHUNK_USABLE_SIZE (LINE_TEXT_CHUNK_SIZE-2-(int)sizeof(char*)) TEXT_BUFFER_REC *textbuffer_create(void) @@ -537,9 +533,7 @@ GList *textbuffer_find_text(TEXT_BUFFER_REC *buffer, LINE_REC *startline, int before, int after, int regexp, int fullword, int case_sensitive) { -#ifdef HAVE_REGEX_H - regex_t preg; -#endif + GRegex *preg; LINE_REC *line, *pre_line; GList *matches; GString *str; @@ -550,14 +544,10 @@ GList *textbuffer_find_text(TEXT_BUFFER_REC *buffer, LINE_REC *startline, g_return_val_if_fail(text != NULL, NULL); if (regexp) { -#ifdef HAVE_REGEX_H - int flags = REG_EXTENDED | REG_NOSUB | - (case_sensitive ? 0 : REG_ICASE); - if (regcomp(&preg, text, flags) != 0) + preg = g_regex_new(text, (case_sensitive ? 0 : G_REGEX_CASELESS), 0, NULL); + + if (preg == NULL) return NULL; -#else - return NULL; -#endif } matches = NULL; match_after = 0; @@ -577,12 +567,11 @@ GList *textbuffer_find_text(TEXT_BUFFER_REC *buffer, LINE_REC *startline, if (*text != '\0') { textbuffer_line2text(line, FALSE, str); - if (line_matched) - line_matched = -#ifdef HAVE_REGEX_H - regexp ? regexec(&preg, str->str, 0, NULL, 0) == 0 : -#endif - match_func(str->str, text) != NULL; + if (line_matched) { + line_matched = regexp ? + g_regex_match(preg, str->str, 0, NULL) : + match_func(str->str, text) != NULL; + } } if (line_matched) { @@ -610,9 +599,9 @@ GList *textbuffer_find_text(TEXT_BUFFER_REC *buffer, LINE_REC *startline, matches = g_list_append(matches, NULL); } } -#ifdef HAVE_REGEX_H - if (regexp) regfree(&preg); -#endif + + if (regexp) + g_regex_unref(preg); g_string_free(str, TRUE); return matches; } From b5a727c87cf7db944ade9c6714385f1e8598d37e Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Fri, 29 Jan 2016 16:08:40 +0100 Subject: [PATCH 16/21] Remove unused references to regex.h Also remove the prototype for regex_match since it has been removed. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index bf87f5aa..7eb1bfe1 100644 --- a/configure.ac +++ b/configure.ac @@ -21,7 +21,7 @@ AC_PATH_PROG(perlpath, perl) AC_CHECK_HEADERS(unistd.h dirent.h sys/ioctl.h sys/resource.h) # check posix headers.. -AC_CHECK_HEADERS(sys/socket.h sys/time.h sys/utsname.h regex.h) +AC_CHECK_HEADERS(sys/socket.h sys/time.h sys/utsname.h) AC_SYS_LARGEFILE From 3fcd3cd2b9fae07a0b7cd3e5ba91049f19cc6501 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Fri, 29 Jan 2016 16:22:14 +0100 Subject: [PATCH 17/21] Remove the regexp_compiled field. It was made redundant by the introduction of the pointer to the GRegex structure. Silence the compiler warning in textbuffer.c about preg being initialized by setting it to NULL. --- src/core/ignore.c | 14 ++++---------- src/core/ignore.h | 1 - src/fe-common/core/fe-ignore.c | 2 +- src/fe-common/core/hilight-text.c | 13 ++++--------- src/fe-common/core/hilight-text.h | 1 - src/fe-text/textbuffer.c | 2 ++ 6 files changed, 11 insertions(+), 22 deletions(-) diff --git a/src/core/ignore.c b/src/core/ignore.c index 2b8299bd..30cb7cb8 100644 --- a/src/core/ignore.c +++ b/src/core/ignore.c @@ -66,10 +66,8 @@ static int ignore_match_pattern(IGNORE_REC *rec, const char *text) if (text == NULL) return FALSE; - if (rec->regexp) { - return rec->regexp_compiled && - g_regex_match(rec->preg, text, 0, NULL); - } + if (rec->regexp) + return rec->preg && g_regex_match(rec->preg, text, 0, NULL); return rec->fullword ? stristr_full(text, rec->pattern) != NULL : @@ -322,10 +320,8 @@ static void ignore_remove_config(IGNORE_REC *rec) static void ignore_init_rec(IGNORE_REC *rec) { - if (rec->regexp_compiled) { + if (rec->preg != NULL) g_regex_unref(rec->preg); - rec->regexp_compiled = FALSE; - } if (rec->regexp && rec->pattern != NULL) { GError *re_error; @@ -335,8 +331,6 @@ static void ignore_init_rec(IGNORE_REC *rec) if (rec->preg == NULL) { g_warning("Failed to compile regexp '%s': %s", rec->pattern, re_error->message); g_error_free(re_error); - } else { - rec->regexp_compiled = TRUE; } } } @@ -358,7 +352,7 @@ static void ignore_destroy(IGNORE_REC *rec, int send_signal) if (send_signal) signal_emit("ignore destroyed", 1, rec); - if (rec->regexp_compiled) g_regex_unref(rec->preg); + if (rec->preg != NULL) g_regex_unref(rec->preg); if (rec->channels != NULL) g_strfreev(rec->channels); g_free_not_null(rec->mask); g_free_not_null(rec->servertag); diff --git a/src/core/ignore.h b/src/core/ignore.h index 6c9797f5..f37f8b28 100644 --- a/src/core/ignore.h +++ b/src/core/ignore.h @@ -16,7 +16,6 @@ struct _IGNORE_REC { unsigned int regexp:1; unsigned int fullword:1; unsigned int replies:1; /* ignore replies to nick in channel */ - unsigned int regexp_compiled:1; /* should always be TRUE, unless regexp is invalid */ GRegex *preg; }; diff --git a/src/fe-common/core/fe-ignore.c b/src/fe-common/core/fe-ignore.c index addfa0b8..03fd4dd2 100644 --- a/src/fe-common/core/fe-ignore.c +++ b/src/fe-common/core/fe-ignore.c @@ -58,7 +58,7 @@ static void ignore_print(int index, IGNORE_REC *rec) g_string_append(options, "-regexp "); if (rec->pattern == NULL) g_string_append(options, "[INVALID! -pattern missing] "); - else if (!rec->regexp_compiled) + else if (rec->preg == NULL) g_string_append(options, "[INVALID!] "); } if (rec->fullword) g_string_append(options, "-full "); diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c index 83b6f67e..e3dcc2d9 100644 --- a/src/fe-common/core/hilight-text.c +++ b/src/fe-common/core/hilight-text.c @@ -101,7 +101,7 @@ static void hilight_destroy(HILIGHT_REC *rec) { g_return_if_fail(rec != NULL); - if (rec->regexp_compiled) g_regex_unref(rec->preg); + if (rec->preg != NULL) g_regex_unref(rec->preg); if (rec->channels != NULL) g_strfreev(rec->channels); g_free_not_null(rec->color); g_free_not_null(rec->act_color); @@ -118,15 +118,10 @@ static void hilights_destroy_all(void) static void hilight_init_rec(HILIGHT_REC *rec) { - if (rec->regexp_compiled) { + if (rec->preg != NULL) g_regex_unref(rec->preg); - rec->regexp_compiled = FALSE; - } rec->preg = g_regex_new(rec->text, G_REGEX_CASELESS, 0, NULL); - - if (rec->preg != NULL) - rec->regexp_compiled = TRUE; } void hilight_create(HILIGHT_REC *rec) @@ -201,7 +196,7 @@ static int hilight_match_text(HILIGHT_REC *rec, const char *text, if (rec->regexp) { GMatchInfo *match; - if (rec->regexp_compiled) { + if (rec->preg != NULL) { g_regex_match (rec->preg, text, 0, &match); if (g_match_info_matches(match)) { @@ -504,7 +499,7 @@ static void hilight_print(int index, HILIGHT_REC *rec) if (rec->case_sensitive) g_string_append(options, "-matchcase "); if (rec->regexp) { g_string_append(options, "-regexp "); - if (!rec->regexp_compiled) + if (rec->preg == NULL) g_string_append(options, "[INVALID!] "); } diff --git a/src/fe-common/core/hilight-text.h b/src/fe-common/core/hilight-text.h index a74c38b0..93c573c2 100644 --- a/src/fe-common/core/hilight-text.h +++ b/src/fe-common/core/hilight-text.h @@ -20,7 +20,6 @@ struct _HILIGHT_REC { unsigned int fullword:1; /* match `text' only for full words */ unsigned int regexp:1; /* `text' is a regular expression */ unsigned int case_sensitive:1;/* `text' must match case */ - unsigned int regexp_compiled:1; /* should always be TRUE, unless regexp is invalid */ GRegex *preg; char *servertag; }; diff --git a/src/fe-text/textbuffer.c b/src/fe-text/textbuffer.c index 979b2a46..7d0806d1 100644 --- a/src/fe-text/textbuffer.c +++ b/src/fe-text/textbuffer.c @@ -543,6 +543,8 @@ GList *textbuffer_find_text(TEXT_BUFFER_REC *buffer, LINE_REC *startline, g_return_val_if_fail(buffer != NULL, NULL); g_return_val_if_fail(text != NULL, NULL); + preg = NULL; + if (regexp) { preg = g_regex_new(text, (case_sensitive ? 0 : G_REGEX_CASELESS), 0, NULL); From 5eaead761f1812fb9d4058b2bc38468521794693 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sun, 19 Jun 2016 21:08:25 +0200 Subject: [PATCH 18/21] Rebase against master. --- src/core/ignore.c | 6 ++++-- src/fe-text/textbuffer.c | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/core/ignore.c b/src/core/ignore.c index 30cb7cb8..c91f6e4a 100644 --- a/src/core/ignore.c +++ b/src/core/ignore.c @@ -66,8 +66,10 @@ static int ignore_match_pattern(IGNORE_REC *rec, const char *text) if (text == NULL) return FALSE; - if (rec->regexp) - return rec->preg && g_regex_match(rec->preg, text, 0, NULL); + if (rec->regexp) { + return rec->preg != NULL && + g_regex_match(rec->preg, text, 0, NULL); + } return rec->fullword ? stristr_full(text, rec->pattern) != NULL : diff --git a/src/fe-text/textbuffer.c b/src/fe-text/textbuffer.c index 7d0806d1..f35848a2 100644 --- a/src/fe-text/textbuffer.c +++ b/src/fe-text/textbuffer.c @@ -570,7 +570,7 @@ GList *textbuffer_find_text(TEXT_BUFFER_REC *buffer, LINE_REC *startline, textbuffer_line2text(line, FALSE, str); if (line_matched) { - line_matched = regexp ? + line_matched = regexp ? g_regex_match(preg, str->str, 0, NULL) : match_func(str->str, text) != NULL; } From 5dcf291f2144564363f734dba15760d3a82b61c2 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Thu, 23 Jun 2016 13:25:23 +0200 Subject: [PATCH 19/21] Use the RAW flag when building the regexps. Also, plugged a memory leak when retrieving the match position. --- src/core/ignore.c | 2 +- src/fe-common/core/hilight-text.c | 23 +++++++++++++---------- src/fe-text/textbuffer.c | 4 ++-- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/core/ignore.c b/src/core/ignore.c index c91f6e4a..cfcbd792 100644 --- a/src/core/ignore.c +++ b/src/core/ignore.c @@ -328,7 +328,7 @@ static void ignore_init_rec(IGNORE_REC *rec) if (rec->regexp && rec->pattern != NULL) { GError *re_error; - rec->preg = g_regex_new(rec->pattern, G_REGEX_CASELESS, 0, &re_error); + rec->preg = g_regex_new(rec->pattern, G_REGEX_OPTIMIZE | G_REGEX_RAW | G_REGEX_CASELESS, 0, &re_error); if (rec->preg == NULL) { g_warning("Failed to compile regexp '%s': %s", rec->pattern, re_error->message); diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c index e3dcc2d9..7a7f473c 100644 --- a/src/fe-common/core/hilight-text.c +++ b/src/fe-common/core/hilight-text.c @@ -121,7 +121,7 @@ static void hilight_init_rec(HILIGHT_REC *rec) if (rec->preg != NULL) g_regex_unref(rec->preg); - rec->preg = g_regex_new(rec->text, G_REGEX_CASELESS, 0, NULL); + rec->preg = g_regex_new(rec->text, G_REGEX_OPTIMIZE | G_REGEX_RAW | G_REGEX_CASELESS, 0, NULL); } void hilight_create(HILIGHT_REC *rec) @@ -188,22 +188,25 @@ static HILIGHT_REC *hilight_find(const char *text, char **channels) return NULL; } -static int hilight_match_text(HILIGHT_REC *rec, const char *text, +static gboolean hilight_match_text(HILIGHT_REC *rec, const char *text, int *match_beg, int *match_end) { - char *match; + gboolean ret = FALSE; if (rec->regexp) { - GMatchInfo *match; - if (rec->preg != NULL) { + GMatchInfo *match; + g_regex_match (rec->preg, text, 0, &match); - if (g_match_info_matches(match)) { - return g_match_info_fetch_pos(match, 0, match_beg, match_end); - } + if (g_match_info_matches(match)) + ret = g_match_info_fetch_pos(match, 0, match_beg, match_end); + + g_match_info_free(match); } } else { + char *match; + if (rec->case_sensitive) { match = rec->fullword ? strstr_full(text, rec->text) : @@ -218,11 +221,11 @@ static int hilight_match_text(HILIGHT_REC *rec, const char *text, *match_beg = (int) (match-text); *match_end = *match_beg + strlen(rec->text); } - return TRUE; + ret = TRUE; } } - return FALSE; + return ret; } #define hilight_match_level(rec, level) \ diff --git a/src/fe-text/textbuffer.c b/src/fe-text/textbuffer.c index f35848a2..979a6104 100644 --- a/src/fe-text/textbuffer.c +++ b/src/fe-text/textbuffer.c @@ -546,7 +546,7 @@ GList *textbuffer_find_text(TEXT_BUFFER_REC *buffer, LINE_REC *startline, preg = NULL; if (regexp) { - preg = g_regex_new(text, (case_sensitive ? 0 : G_REGEX_CASELESS), 0, NULL); + preg = g_regex_new(text, G_REGEX_RAW | (case_sensitive ? 0 : G_REGEX_CASELESS), 0, NULL); if (preg == NULL) return NULL; @@ -602,7 +602,7 @@ GList *textbuffer_find_text(TEXT_BUFFER_REC *buffer, LINE_REC *startline, } } - if (regexp) + if (preg != NULL) g_regex_unref(preg); g_string_free(str, TRUE); return matches; From f5cbbebc2ee858e8792ab40eea6abc9fd7865a28 Mon Sep 17 00:00:00 2001 From: Ailin Nemui Date: Tue, 3 Jan 2017 12:04:56 +0100 Subject: [PATCH 20/21] switch for gregex and regex.h --- configure.ac | 16 ++++++++++++++++ src/core/ignore.c | 31 ++++++++++++++++++++++++++++++ src/core/ignore.h | 9 +++++++++ src/core/misc.c | 4 ++++ src/fe-common/core/fe-ignore.c | 5 +++++ src/fe-common/core/hilight-text.c | 32 +++++++++++++++++++++++++++++++ src/fe-common/core/hilight-text.h | 9 +++++++++ src/fe-text/textbuffer.c | 29 ++++++++++++++++++++++++++-- 8 files changed, 133 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 7eb1bfe1..8d588408 100644 --- a/configure.ac +++ b/configure.ac @@ -144,6 +144,15 @@ AC_ARG_ENABLE(true-color, fi, want_truecolor=no) +AC_ARG_ENABLE(gregex, +[ --disable-gregex Build without GRegex (fall back to regex.h)], + if test x$enableval = xno ; then + want_gregex=no + else + want_gregex=yes + fi, + want_gregex=yes) + dnl ** dnl ** just some generic stuff... dnl ** @@ -534,6 +543,12 @@ else want_truecolor=no fi +if test "x$want_gregex" = "xyes"; then + AC_DEFINE([USE_GREGEX], [], [use GRegex for regular expressions]) +else + want_gregex=no +fi + AH_TEMPLATE(HAVE_GMODULE) AH_TEMPLATE(HAVE_SOCKS_H, [misc..]) AH_TEMPLATE(HAVE_STATIC_PERL) @@ -648,6 +663,7 @@ echo echo "Building with 64bit DCC support .. : $offt_64bit" echo "Building with true color support.. : $want_truecolor" +echo "Building with GRegex ............. : $want_gregex" echo echo "If there are any problems, read the INSTALL file." diff --git a/src/core/ignore.c b/src/core/ignore.c index cfcbd792..bf8db04f 100644 --- a/src/core/ignore.c +++ b/src/core/ignore.c @@ -67,8 +67,13 @@ static int ignore_match_pattern(IGNORE_REC *rec, const char *text) return FALSE; if (rec->regexp) { +#ifdef USE_GREGEX return rec->preg != NULL && g_regex_match(rec->preg, text, 0, NULL); +#else + return rec->regexp_compiled && + regexec(&rec->preg, text, 0, NULL, 0) == 0; +#endif } return rec->fullword ? @@ -322,6 +327,7 @@ static void ignore_remove_config(IGNORE_REC *rec) static void ignore_init_rec(IGNORE_REC *rec) { +#ifdef USE_GREGEX if (rec->preg != NULL) g_regex_unref(rec->preg); @@ -335,6 +341,27 @@ static void ignore_init_rec(IGNORE_REC *rec) g_error_free(re_error); } } +#else + char *errbuf; + int errcode, errbuf_len; + + if (rec->regexp_compiled) regfree(&rec->preg); + rec->regexp_compiled = FALSE; + + if (rec->regexp && rec->pattern != NULL) { + errcode = regcomp(&rec->preg, rec->pattern, + REG_EXTENDED|REG_ICASE|REG_NOSUB); + if (errcode != 0) { + errbuf_len = regerror(errcode, &rec->preg, 0, 0); + errbuf = g_malloc(errbuf_len); + regerror(errcode, &rec->preg, errbuf, errbuf_len); + g_warning("Failed to compile regexp '%s': %s", rec->pattern, errbuf); + g_free(errbuf); + } else { + rec->regexp_compiled = TRUE; + } + } +#endif } void ignore_add_rec(IGNORE_REC *rec) @@ -354,7 +381,11 @@ static void ignore_destroy(IGNORE_REC *rec, int send_signal) if (send_signal) signal_emit("ignore destroyed", 1, rec); +#ifdef USE_GREGEX if (rec->preg != NULL) g_regex_unref(rec->preg); +#else + if (rec->regexp_compiled) regfree(&rec->preg); +#endif if (rec->channels != NULL) g_strfreev(rec->channels); g_free_not_null(rec->mask); g_free_not_null(rec->servertag); diff --git a/src/core/ignore.h b/src/core/ignore.h index f37f8b28..80ae1d12 100644 --- a/src/core/ignore.h +++ b/src/core/ignore.h @@ -1,6 +1,10 @@ #ifndef __IGNORE_H #define __IGNORE_H +#ifndef USE_GREGEX +# include +#endif + typedef struct _IGNORE_REC IGNORE_REC; struct _IGNORE_REC { @@ -16,7 +20,12 @@ struct _IGNORE_REC { unsigned int regexp:1; unsigned int fullword:1; unsigned int replies:1; /* ignore replies to nick in channel */ +#ifdef USE_GREGEX GRegex *preg; +#else + unsigned int regexp_compiled:1; /* should always be TRUE, unless regexp is invalid */ + regex_t preg; +#endif }; extern GSList *ignores; diff --git a/src/core/misc.c b/src/core/misc.c index c59eb126..1cfa15b6 100644 --- a/src/core/misc.c +++ b/src/core/misc.c @@ -22,6 +22,10 @@ #include "misc.h" #include "commands.h" +#ifndef USE_GREGEX +# include +#endif + typedef struct { int condition; GInputFunction function; diff --git a/src/fe-common/core/fe-ignore.c b/src/fe-common/core/fe-ignore.c index 03fd4dd2..800e881d 100644 --- a/src/fe-common/core/fe-ignore.c +++ b/src/fe-common/core/fe-ignore.c @@ -58,8 +58,13 @@ static void ignore_print(int index, IGNORE_REC *rec) g_string_append(options, "-regexp "); if (rec->pattern == NULL) g_string_append(options, "[INVALID! -pattern missing] "); +#ifdef USE_GREGEX else if (rec->preg == NULL) g_string_append(options, "[INVALID!] "); +#else + else if (!rec->regexp_compiled) + g_string_append(options, "[INVALID!] "); +#endif } if (rec->fullword) g_string_append(options, "-full "); if (rec->replies) g_string_append(options, "-replies "); diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c index 7a7f473c..037cde5c 100644 --- a/src/fe-common/core/hilight-text.c +++ b/src/fe-common/core/hilight-text.c @@ -101,7 +101,11 @@ static void hilight_destroy(HILIGHT_REC *rec) { g_return_if_fail(rec != NULL); +#ifdef USE_GREGEX if (rec->preg != NULL) g_regex_unref(rec->preg); +#else + if (rec->regexp_compiled) regfree(&rec->preg); +#endif if (rec->channels != NULL) g_strfreev(rec->channels); g_free_not_null(rec->color); g_free_not_null(rec->act_color); @@ -118,10 +122,19 @@ static void hilights_destroy_all(void) static void hilight_init_rec(HILIGHT_REC *rec) { +#ifdef USE_GREGEX if (rec->preg != NULL) g_regex_unref(rec->preg); rec->preg = g_regex_new(rec->text, G_REGEX_OPTIMIZE | G_REGEX_RAW | G_REGEX_CASELESS, 0, NULL); +#else + if (rec->regexp_compiled) regfree(&rec->preg); + if (!rec->regexp) + rec->regexp_compiled = FALSE; + else + rec->regexp_compiled = regcomp(&rec->preg, rec->text, + rec->case_sensitive ? REG_EXTENDED : (REG_EXTENDED|REG_ICASE)) == 0; +#endif } void hilight_create(HILIGHT_REC *rec) @@ -194,6 +207,7 @@ static gboolean hilight_match_text(HILIGHT_REC *rec, const char *text, gboolean ret = FALSE; if (rec->regexp) { +#ifdef USE_GREGEX if (rec->preg != NULL) { GMatchInfo *match; @@ -204,6 +218,19 @@ static gboolean hilight_match_text(HILIGHT_REC *rec, const char *text, g_match_info_free(match); } +#else + regmatch_t rmatch[1]; + + if (rec->regexp_compiled && + regexec(&rec->preg, text, 1, rmatch, 0) == 0) { + if (rmatch[0].rm_so > 0 && + match_beg != NULL && match_end != NULL) { + *match_beg = rmatch[0].rm_so; + *match_end = rmatch[0].rm_eo; + } + ret = TRUE; + } +#endif } else { char *match; @@ -502,8 +529,13 @@ static void hilight_print(int index, HILIGHT_REC *rec) if (rec->case_sensitive) g_string_append(options, "-matchcase "); if (rec->regexp) { g_string_append(options, "-regexp "); +#ifdef USE_GREGEX if (rec->preg == NULL) g_string_append(options, "[INVALID!] "); +#else + if (!rec->regexp_compiled) + g_string_append(options, "[INVALID!] "); +#endif } if (rec->priority != 0) diff --git a/src/fe-common/core/hilight-text.h b/src/fe-common/core/hilight-text.h index 93c573c2..76beec1f 100644 --- a/src/fe-common/core/hilight-text.h +++ b/src/fe-common/core/hilight-text.h @@ -1,6 +1,10 @@ #ifndef __HILIGHT_TEXT_H #define __HILIGHT_TEXT_H +#ifndef USE_GREGEX +# include +#endif + #include "formats.h" struct _HILIGHT_REC { @@ -20,7 +24,12 @@ struct _HILIGHT_REC { unsigned int fullword:1; /* match `text' only for full words */ unsigned int regexp:1; /* `text' is a regular expression */ unsigned int case_sensitive:1;/* `text' must match case */ +#ifdef USE_GREGEX GRegex *preg; +#else + unsigned int regexp_compiled:1; /* should always be TRUE, unless regexp is invalid */ + regex_t preg; +#endif char *servertag; }; diff --git a/src/fe-text/textbuffer.c b/src/fe-text/textbuffer.c index 979a6104..ae4636a5 100644 --- a/src/fe-text/textbuffer.c +++ b/src/fe-text/textbuffer.c @@ -27,6 +27,10 @@ #include "textbuffer.h" +#ifndef USE_GREGEX +# include +#endif + #define TEXT_CHUNK_USABLE_SIZE (LINE_TEXT_CHUNK_SIZE-2-(int)sizeof(char*)) TEXT_BUFFER_REC *textbuffer_create(void) @@ -533,7 +537,11 @@ GList *textbuffer_find_text(TEXT_BUFFER_REC *buffer, LINE_REC *startline, int before, int after, int regexp, int fullword, int case_sensitive) { +#ifdef USE_GREGEX GRegex *preg; +#else + regex_t preg; +#endif LINE_REC *line, *pre_line; GList *matches; GString *str; @@ -543,6 +551,7 @@ GList *textbuffer_find_text(TEXT_BUFFER_REC *buffer, LINE_REC *startline, g_return_val_if_fail(buffer != NULL, NULL); g_return_val_if_fail(text != NULL, NULL); +#ifdef USE_GREGEX preg = NULL; if (regexp) { @@ -551,6 +560,14 @@ GList *textbuffer_find_text(TEXT_BUFFER_REC *buffer, LINE_REC *startline, if (preg == NULL) return NULL; } +#else + if (regexp) { + int flags = REG_EXTENDED | REG_NOSUB | + (case_sensitive ? 0 : REG_ICASE); + if (regcomp(&preg, text, flags) != 0) + return NULL; + } +#endif matches = NULL; match_after = 0; str = g_string_new(NULL); @@ -571,8 +588,12 @@ GList *textbuffer_find_text(TEXT_BUFFER_REC *buffer, LINE_REC *startline, if (line_matched) { line_matched = regexp ? - g_regex_match(preg, str->str, 0, NULL) : - match_func(str->str, text) != NULL; +#ifdef USE_GREGEX + g_regex_match(preg, str->str, 0, NULL) +#else + regexec(&preg, str->str, 0, NULL, 0) == 0 +#endif + : match_func(str->str, text) != NULL; } } @@ -602,8 +623,12 @@ GList *textbuffer_find_text(TEXT_BUFFER_REC *buffer, LINE_REC *startline, } } +#ifdef USE_GREGEX if (preg != NULL) g_regex_unref(preg); +#else + if (regexp) regfree(&preg); +#endif g_string_free(str, TRUE); return matches; } From 1f72b8e66a06b484dde20b6031c766a2129e0bd2 Mon Sep 17 00:00:00 2001 From: Ailin Nemui Date: Tue, 3 Jan 2017 12:29:52 +0100 Subject: [PATCH 21/21] up abi version --- src/common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common.h b/src/common.h index 0a7b72f0..43596580 100644 --- a/src/common.h +++ b/src/common.h @@ -6,7 +6,7 @@ #define IRSSI_GLOBAL_CONFIG "irssi.conf" /* config file name in /etc/ */ #define IRSSI_HOME_CONFIG "config" /* config file name in ~/.irssi/ */ -#define IRSSI_ABI_VERSION 6 +#define IRSSI_ABI_VERSION 7 #define DEFAULT_SERVER_ADD_PORT 6667