--- a/ChangeLog Fri Nov 03 04:29:05 2017 +0000
+++ b/ChangeLog Fri Nov 03 01:22:04 2017 -0500
@@ -104,12 +104,22 @@
* A single jabber plugin provides XMPP, GTalk and Facebook protocols.
* A single yahoo plugin provides both Yahoo and Yahoo JAPAN protocols.
-version 2.12.1 (??/??/????):
+version 2.13.0 (??/??/????): * Unified string comparison. (PR #186) (Arkadiy Illarionov)
+ * Properlly shell escape URI's when opening them. (PR #271 Daniel Kamil Kozar) + * Fixed build against curses 6.0 with opaque structs set. (#16764 dimstar) + (PR #268 Daniel Kamil Kozar) + * Fixed a crash when resizing the window. (#16680 marcus) (PR #269 Daniel Kamil Kozar) + * Fixed bashism in autotools. (#16836 lameventanas) (PR #267 Daniel Kamil Kozar) * Show XEP-0066 OOB URLs in any message, not just headlines
+ * Fix a user after free (#17200 debarshiray) (PR #266 Ethan Blanton) * Fix "Registration timeout" on SASL auth with InspIRCd servers
@@ -117,6 +127,14 @@
* Fix issues with plugins that modify outgoing messages
(such as the custom PART/QUIT feature of the IRC More plugin)
+ * Better support for dark themes. (#12572 Alyssa Rosenzweig and Gary Kramlich) + * Fixed IPv6 links by not escaping []'s. (#16391 cyisfor) (PR #270 Daniel Kamil Kozar) + * Only write buddy icons to the cache if they're not already cached. (PR #276 David Woodhouse) + * Fix handling of search results (#17238 David Woodhouse) version 2.12.0 (03/09/2017):
* Fix an out of bounds memory write in purple_markup_unescape_entity.
--- a/finch/gntnotify.c Fri Nov 03 04:29:05 2017 +0000
+++ b/finch/gntnotify.c Fri Nov 03 01:22:04 2017 -0500
@@ -385,11 +385,12 @@
finch_notify_sr_new_rows(PurpleConnection *gc,
PurpleNotifySearchResults *results, void *data)
- GntTree *tree = GNT_TREE(data);
+ GntWindow *window = GNT_WINDOW(data); + GntTree *tree = GNT_TREE(g_object_get_data(G_OBJECT(window), "tree-widget")); - /* XXX: Do I need to empty the tree here? */
+ gnt_tree_remove_all(GNT_TREE(tree)); for (o = results->rows; o; o = o->next)
@@ -493,12 +494,16 @@
g_signal_connect(G_OBJECT(tree), "destroy",
G_CALLBACK(notify_sr_destroy_cb), NULL);
- finch_notify_sr_new_rows(gc, results, tree);
+ g_object_set_data(G_OBJECT(window), "tree-widget", tree); + finch_notify_sr_new_rows(gc, results, window); + g_signal_connect(G_OBJECT(window), "destroy", + G_CALLBACK(notify_msg_window_destroy_cb), GINT_TO_POINTER(PURPLE_NOTIFY_SEARCHRESULTS)); g_object_set_data(G_OBJECT(window), "notify-results", results);
--- a/finch/libgnt/gntmain.c Fri Nov 03 04:29:05 2017 +0000
+++ b/finch/libgnt/gntmain.c Fri Nov 03 01:22:04 2017 -0500
@@ -551,10 +551,11 @@
static void (*org_winch_handler)(int);
+static void (*org_winch_handler_sa)(int, siginfo_t *, void *);
+sighandler(int sig, siginfo_t *info, void *data) @@ -563,18 +564,17 @@
g_idle_add((GSourceFunc)refresh_screen, NULL);
- signal(SIGWINCH, sighandler);
+ if (org_winch_handler_sa) + org_winch_handler_sa(sig, info, data); - signal(SIGCHLD, sighandler);
- signal(SIGINT, sighandler);
@@ -602,6 +602,10 @@
@@ -654,14 +658,26 @@
+ act.sa_sigaction = sighandler; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_SIGINFO; - org_winch_handler = signal(SIGWINCH, sighandler);
+ org_winch_handler = NULL; + org_winch_handler_sa = NULL; + sigaction(SIGWINCH, &act, &oact); + if (oact.sa_flags & SA_SIGINFO) + org_winch_handler_sa = oact.sa_sigaction; + else if (oact.sa_handler != SIG_DFL && oact.sa_handler != SIG_IGN) + org_winch_handler = oact.sa_handler;
- signal(SIGCHLD, sighandler);
+ sigaction(SIGCHLD, &act, NULL); + sigaction(SIGINT, &act, NULL); signal(SIGPIPE, SIG_IGN);
- signal(SIGINT, sighandler);
#if !GLIB_CHECK_VERSION(2, 36, 0)
/* GLib type system is automaticaly initialized since 2.36. */
--- a/finch/libgnt/gntwm.c Fri Nov 03 04:29:05 2017 +0000
+++ b/finch/libgnt/gntwm.c Fri Nov 03 01:22:04 2017 -0500
@@ -166,37 +166,37 @@
- sx = panel->win->_begx;
- ex = panel->win->_maxx + sx;
- sy = panel->win->_begy;
- ey = panel->win->_maxy + sy;
+ sx = getbegx(panel->win); + ex = getmaxx(panel->win) + sx; + sy = getbegy(panel->win); + ey = getmaxy(panel->win) + sy; while ((below = panel_below(below)) != NULL) {
- if (sy > below->win->_begy + below->win->_maxy ||
- ey < below->win->_begy)
+ if (sy > getbegy(below->win) + getmaxy(below->win) || + ey < getbegy(below->win)) - if (sx > below->win->_begx + below->win->_maxx ||
- ex < below->win->_begx)
+ if (sx > getbegx(below->win) + getmaxx(below->win) || + ex < getbegx(below->win)) - for (y = MAX(sy, below->win->_begy); y <= MIN(ey, below->win->_begy + below->win->_maxy); y++) {
- if (mvwin_wch(below->win, y - below->win->_begy, sx - 1 - below->win->_begx, &ch) != OK)
+ for (y = MAX(sy, getbegy(below->win)); y <= MIN(ey, getbegy(below->win) + getmaxy(below->win)); y++) { + if (mvwin_wch(below->win, y - getbegy(below->win), sx - 1 - getbegx(below->win), &ch) != OK) w = widestringwidth(ch.chars);
if (w > 1 && (ch.attr & 1)) {
- mvwadd_wch(below->win, y - below->win->_begy, sx - 1 - below->win->_begx, &ch);
- touchline(below->win, y - below->win->_begy, 1);
+ mvwadd_wch(below->win, y - getbegy(below->win), sx - 1 - getbegx(below->win), &ch); + touchline(below->win, y - getbegy(below->win), 1); - if (mvwin_wch(below->win, y - below->win->_begy, ex + 1 - below->win->_begx, &ch) != OK)
+ if (mvwin_wch(below->win, y - getbegy(below->win), ex + 1 - getbegx(below->win), &ch) != OK) w = widestringwidth(ch.chars);
if (w > 1 && !(ch.attr & 1)) {
- mvwadd_wch(below->win, y - below->win->_begy, ex + 1 - below->win->_begx, &ch);
- touchline(below->win, y - below->win->_begy, 1);
+ mvwadd_wch(below->win, y - getbegy(below->win), ex + 1 - getbegx(below->win), &ch); + touchline(below->win, y - getbegy(below->win), 1); --- a/libpurple/buddyicon.c Fri Nov 03 04:29:05 2017 +0000
+++ b/libpurple/buddyicon.c Fri Nov 03 01:22:04 2017 -0500
@@ -176,6 +176,7 @@
if (!purple_image_save(img, path))
purple_debug_error("buddyicon", "failed to save icon %s", path);
--- a/libpurple/media.c Fri Nov 03 04:29:05 2017 +0000
+++ b/libpurple/media.c Fri Nov 03 01:22:04 2017 -0500
@@ -1458,20 +1458,12 @@
gchar dtmf, guint8 volume, guint16 duration)
- PurpleAccount *account = NULL;
- PurpleConnection *gc = NULL;
- PurpleProtocol *protocol = NULL;
PurpleMediaBackendIface *backend_iface = NULL;
- account = purple_media_get_account(media);
backend_iface = PURPLE_MEDIA_BACKEND_GET_INTERFACE(media->priv->backend);
- gc = purple_account_get_connection(account);
- protocol = purple_connection_get_protocol(gc);
@@ -1484,11 +1476,7 @@
g_return_val_if_fail(strchr("0123456789ABCD#*", dtmf), FALSE);
- if (PURPLE_PROTOCOL_IMPLEMENTS(protocol, MEDIA_IFACE, send_dtmf)
- && purple_protocol_media_iface_send_dtmf(protocol, media, dtmf, volume, duration))
- } else if (backend_iface && backend_iface->send_dtmf
+ if (backend_iface && backend_iface->send_dtmf && backend_iface->send_dtmf(media->priv->backend,
session_id, dtmf, volume, duration))
--- a/libpurple/media/backend-fs2.c Fri Nov 03 04:29:05 2017 +0000
+++ b/libpurple/media/backend-fs2.c Fri Nov 03 01:22:04 2017 -0500
@@ -1059,7 +1059,7 @@
FsParticipant *participant;
PurpleMediaBackendFs2Session *session;
PurpleMediaBackendFs2Stream *media_stream;
value = gst_structure_get_value(structure, "stream");
stream = g_value_get_object(value);
@@ -1073,8 +1073,7 @@
local_candidate->foundation);
g_object_get(stream, "participant", &participant, NULL);
- g_object_get(participant, "cname", &name, NULL);
- g_object_unref(participant);
+ name = g_object_get_data(G_OBJECT(participant), "purple-name"); media_stream = get_stream(self, session->id, name);
media_stream->local_candidates = g_list_append(
@@ -1085,24 +1084,25 @@
g_signal_emit_by_name(self, "new-candidate",
session->id, name, candidate);
g_object_unref(candidate);
+ g_object_unref(participant); } else if (gst_structure_has_name(structure,
"farstream-local-candidates-prepared")) {
FsParticipant *participant;
PurpleMediaBackendFs2Session *session;
value = gst_structure_get_value(structure, "stream");
stream = g_value_get_object(value);
session = get_session_from_fs_stream(self, stream);
g_object_get(stream, "participant", &participant, NULL);
- g_object_get(participant, "cname", &name, NULL);
- g_object_unref(participant);
g_signal_emit_by_name(self, "candidates-prepared",
+ g_object_get_data(G_OBJECT(participant), "purple-name")); + g_object_unref(participant); } else if (gst_structure_has_name(structure,
"farstream-new-active-candidate-pair")) {
@@ -1112,7 +1112,6 @@
FsParticipant *participant;
PurpleMediaBackendFs2Session *session;
PurpleMediaCandidate *lcandidate, *rcandidate;
value = gst_structure_get_value(structure, "stream");
stream = g_value_get_object(value);
@@ -1122,8 +1121,6 @@
remote_candidate = g_value_get_boxed(value);
g_object_get(stream, "participant", &participant, NULL);
- g_object_get(participant, "cname", &name, NULL);
- g_object_unref(participant);
session = get_session_from_fs_stream(self, stream);
@@ -1131,8 +1128,11 @@
rcandidate = candidate_from_fs(remote_candidate);
g_signal_emit_by_name(self, "active-candidate-pair",
- session->id, name, lcandidate, rcandidate);
+ g_object_get_data(G_OBJECT(participant), "purple-name"), + lcandidate, rcandidate); + g_object_unref(participant); g_object_unref(lcandidate);
g_object_unref(rcandidate);
} else if (gst_structure_has_name(structure,
--- a/libpurple/protocols/gg/blist.c Fri Nov 03 04:29:05 2017 +0000
+++ b/libpurple/protocols/gg/blist.c Fri Nov 03 01:22:04 2017 -0500
@@ -125,7 +125,7 @@
g = g_strdup("Gadu-Gadu");
- if ('\0' != data_tbl[F_GROUP]) {
+ if ('\0' != *(data_tbl[F_GROUP])) { /* XXX: Probably buddy should be added to all the groups. */
/* Hard limit to at most 50 groups */
gchar **group_tbl = g_strsplit(data_tbl[F_GROUP], ",", 50);
--- a/libpurple/protocols/jabber/jingle/rtp.c Fri Nov 03 04:29:05 2017 +0000
+++ b/libpurple/protocols/jabber/jingle/rtp.c Fri Nov 03 01:22:04 2017 -0500
@@ -819,6 +819,7 @@
JingleTransport *transport;
JabberBuddyResource *jbr;
const gchar *transport_type;
gchar *resource = NULL, *me = NULL, *sid = NULL;
@@ -827,16 +828,15 @@
jb = jabber_buddy_find(js, who, FALSE);
purple_debug_error("jingle-rtp", "Could not find Jabber buddy\n");
resource = jabber_get_resource(who);
jbr = jabber_buddy_find_resource(jb, resource);
purple_debug_error("jingle-rtp", "Could not find buddy's resource - %s\n", resource);
if (jabber_resource_has_capability(jbr, JINGLE_TRANSPORT_ICEUDP)) {
@@ -848,7 +848,7 @@
purple_debug_error("jingle-rtp", "Resource doesn't support "
"the same transport types\n");
/* set ourselves as initiator */
@@ -856,7 +856,6 @@
sid = jabber_get_next_id(js);
session = jingle_session_create(js, sid, me, who, TRUE);
if (type & PURPLE_MEDIA_AUDIO) {
@@ -878,13 +877,17 @@
g_object_notify_by_pspec(G_OBJECT(content), properties[PROP_MEDIA_TYPE]);
if (jingle_rtp_get_media(session) == NULL) {
--- a/libpurple/tests/test_util.c Fri Nov 03 04:29:05 2017 +0000
+++ b/libpurple/tests/test_util.c Fri Nov 03 01:22:04 2017 -0500
@@ -523,6 +523,30 @@
/******************************************************************************
+ *****************************************************************************/ +test_uri_escape_for_open(void) { + /* make sure shell stuff is escaped... */ + gchar *result = purple_uri_escape_for_open("https://$(xterm)"); + g_assert_cmpstr("https://%24%28xterm%29", ==, result); + result = purple_uri_escape_for_open("https://`xterm`"); + g_assert_cmpstr("https://%60xterm%60", ==, result); + result = purple_uri_escape_for_open("https://$((25 + 13))"); + g_assert_cmpstr("https://%24%28%2825%20+%2013%29%29", ==, result); + /* ...but keep brackets so that ipv6 links can be opened. */ + result = purple_uri_escape_for_open("https://[123:4567:89a::::]"); + g_assert_cmpstr("https://[123:4567:89a::::]", ==, result); +/****************************************************************************** *****************************************************************************/
@@ -570,5 +594,8 @@
g_test_add_func("/util/test_strdup_withhtml",
test_util_strdup_withhtml);
+ g_test_add_func("/util/test_uri_escape_for_open", + test_uri_escape_for_open); --- a/libpurple/util.c Fri Nov 03 04:29:05 2017 +0000
+++ b/libpurple/util.c Fri Nov 03 01:22:04 2017 -0500
@@ -1472,7 +1472,7 @@
pln = "\302\256"; /* or use g_unichar_to_utf8(0xae); */
else if(IS_ENTITY("'"))
- else if(text[1] == '#' && g_ascii_isxdigit(text[2])) {
+ else if(text[1] == '#' && (g_ascii_isxdigit(text[2]) || text[2] == 'x')) { const char *start = text + 2;
@@ -4271,6 +4271,17 @@
+purple_uri_escape_for_open(const char *unescaped) + /* Replace some special characters like $ with their percent-encoded value. + * This shouldn't be necessary because we shell-escape the entire arg before + * exec'ing the browser, however, we had a report that a URL containing + * $(xterm) was causing xterm to start on his system. This is obviously a + * bug on his system, but it's pretty easy for us to protect against it. */ + return g_uri_escape_string(unescaped, "[]:;/%#,+?=&@", FALSE); /**************************************************************************
**************************************************************************/
--- a/libpurple/util.h Fri Nov 03 04:29:05 2017 +0000
+++ b/libpurple/util.h Fri Nov 03 01:22:04 2017 -0500
@@ -1329,6 +1329,17 @@
GList *purple_uri_list_extract_filenames(const gchar *uri_list);
+ * This function escapes any characters that might be interpreted by the shell + * when executing a program to open a URI on some systems. + * @param unescaped The unescaped URI. + * @return A newly allocated string with any shell metacharacters replaced with + * their escaped equivalents. +char *purple_uri_escape_for_open(const char *unescaped); /**************************************************************************
**************************************************************************/
--- a/pidgin/gtkblist.c Fri Nov 03 04:29:05 2017 +0000
+++ b/pidgin/gtkblist.c Fri Nov 03 01:22:04 2017 -0500
@@ -55,6 +55,7 @@
#include "gtkstatusbox.h"
#include "gtkscrollbook.h"
#include "gtksmiley-manager.h"
#include "gtkblist-theme.h"
#include "gtkblist-theme-loader.h"
@@ -4251,7 +4252,7 @@
pidgin_blist_get_name_markup(PurpleBuddy *b, gboolean selected, gboolean aliased)
- const char *name, *name_color, *name_font, *status_color, *status_font;
+ const char *name, *name_color, *name_font, *status_color, *status_font, *dim_grey; PurpleProtocol *protocol = NULL;
@@ -4354,13 +4355,15 @@
theme = pidgin_blist_get_theme();
+ dim_grey = pidgin_style_is_dark(NULL) ? "light slate grey" : "dim grey"; if (purple_presence_is_idle(presence)) {
namefont = statusfont = pidgin_blist_theme_get_idle_text_info(theme);
- name_color = "dim grey";
} else if (!purple_presence_is_online(presence)) {
namefont = pidgin_blist_theme_get_offline_text_info(theme);
- name_color = "dim grey";
statusfont = pidgin_blist_theme_get_status_text_info(theme);
} else if (purple_presence_is_available(presence)) {
namefont = pidgin_blist_theme_get_online_text_info(theme);
@@ -4374,14 +4377,14 @@
&& (purple_presence_is_idle(presence)
|| !purple_presence_is_online(presence)))
- name_color = "dim grey";
name_color = theme_font_get_color_default(namefont, name_color);
name_font = theme_font_get_face_default(namefont, "");
- status_color = theme_font_get_color_default(statusfont, "dim grey");
+ status_color = theme_font_get_color_default(statusfont, dim_grey); status_font = theme_font_get_face_default(statusfont, "");
if (aliased && selected) {
@@ -6554,7 +6557,7 @@
textcolor = pidgin_theme_font_get_color_describe(pair);
/* If no theme them default to making idle buddy names grey */
- textcolor = "dim grey";
+ textcolor = pidgin_style_is_dark(NULL) ? "light slate grey" : "dim grey"; idle = g_strdup_printf("<span color='%s' font_desc='%s'>%d:%02d</span>",
--- a/pidgin/gtkconv.c Fri Nov 03 04:29:05 2017 +0000
+++ b/pidgin/gtkconv.c Fri Nov 03 01:22:04 2017 -0500
@@ -61,6 +61,7 @@
@@ -8940,6 +8941,57 @@
+/* Invalidate the first tab color set */ +static gboolean tab_color_fuse = TRUE; +pidgin_conversations_set_tab_colors(void) + /* Set default tab colors */ + GString *str = g_string_new(NULL); + GtkSettings *settings = gtk_settings_get_default(); + GtkStyle *parent = gtk_rc_get_style_by_paths(settings, "tab-container.tab-label*", NULL, G_TYPE_NONE), *now; + {"pidgin_tab_label_typing_default", "tab-label-typing", "#4e9a06"}, + {"pidgin_tab_label_typed_default", "tab-label-typed", "#c4a000"}, + {"pidgin_tab_label_attention_default", "tab-label-attention", "#006aff"}, + {"pidgin_tab_label_unreadchat_default", "tab-label-unreadchat", "#cc0000"}, + {"pidgin_tab_label_event_default", "tab-label-event", "#888a85"}, + tab_color_fuse = FALSE; + for (iter = 0; styles[iter].stylename; iter++) { + now = gtk_rc_get_style_by_paths(settings, styles[iter].labelname, NULL, G_TYPE_NONE); + (parent && now && parent->rc_style == now->rc_style)) { + gdk_color_parse(styles[iter].color, &color); + pidgin_style_adjust_contrast(gtk_widget_get_default_style(), &color); + g_string_append_printf(str, "style \"%s\" {\n" + "fg[ACTIVE] = \"%s\"\n" + "widget \"*%s\" style \"%s\"\n", + styles[iter].stylename, + gdk_color_to_string(&color), + styles[iter].labelname, styles[iter].stylename); + gtk_rc_parse_string(str->str); + g_string_free(str, TRUE); + gtk_rc_reset_styles(settings); pidgin_conversations_uninit(void)
@@ -10247,6 +10299,9 @@
purple_signal_emit(pidgin_conversations_get_handle(),
"conversation-window-created", win);
+ pidgin_conversations_set_tab_colors(); @@ -11210,6 +11265,9 @@
gdk_rgba_parse(&nick_highlight, DEFAULT_HIGHLIGHT_COLOR);
gdk_rgba_parse(&send_color, DEFAULT_SEND_COLOR);
+ pidgin_style_adjust_contrast(NULL, &nick_highlight); + pidgin_style_adjust_contrast(NULL, &send_color); srand(background.red * 65535 + background.green * 65535 + background.blue * 65535 + 1);
breakout_time = time(NULL) + 3;
--- a/pidgin/gtknotify.c Fri Nov 03 04:29:05 2017 +0000
+++ b/pidgin/gtknotify.c Fri Nov 03 01:22:04 2017 -0500
@@ -1336,13 +1336,7 @@
GSList *argv = NULL, *argv_remote = NULL;
gchar **usercmd_argv = NULL;
- /* Replace some special characters like $ with their percent-encoded
- value. This shouldn't be necessary because we shell-escape the entire
- arg before exec'ing the browser, however, we had a report that a URL
- containing $(xterm) was causing xterm to start on his system. This is
- obviously a bug on his system, but it's pretty easy for us to protect
- uri_escaped = g_uri_escape_string(uri, ":;/%#,+?=&@", FALSE);
+ uri_escaped = purple_uri_escape_for_open(uri); web_browser = purple_prefs_get_string(PIDGIN_PREFS_ROOT