From 01d56c0c47f4d4642be4224b43c403918f3d4372 Mon Sep 17 00:00:00 2001 From: dequis Date: Sat, 8 Oct 2016 03:32:08 -0300 Subject: purple: Fix handling of empty, immediate roomlist results Two issues here: 1. SIPE called in_progress(FALSE) immediately (which decreases refcount), before purple_roomlist_get_list() could return (which would normally increase refcount). The first refcount decrease steals it from the prpl, and bad things happen. Added an initialized flag to only do that decrease after it was increased first. This is similar to how pidgin sets a 'dialog' attribute after the purple_roomlist_get_list() call, and skips the unref if it's not set. 2. The code assumed that NULL return value means room listing not supported. That's not quite true, so now it checks in the prpl info to see if roomlist_get_list is defined. Also, made purple_roomlist_data more private. --- protocols/purple/bpurple.h | 6 ------ protocols/purple/purple.c | 26 ++++++++++++++++++++++---- 2 files changed, 22 insertions(+), 10 deletions(-) (limited to 'protocols') diff --git a/protocols/purple/bpurple.h b/protocols/purple/bpurple.h index ca7cf70e..39677b86 100644 --- a/protocols/purple/bpurple.h +++ b/protocols/purple/bpurple.h @@ -14,10 +14,4 @@ struct purple_data guint next_request_id; }; -struct purple_roomlist_data -{ - GSList *chats; - gint topic; -}; - #endif /* !BPURPLE_H */ diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 374b826b..6b043101 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -53,6 +53,13 @@ struct request_input_data { guint id; }; +struct purple_roomlist_data { + GSList *chats; + gint topic; + gboolean initialized; +}; + + struct im_connection *purple_ic_by_pa(PurpleAccount *pa) { GSList *i; @@ -770,13 +777,21 @@ void purple_chat_list(struct im_connection *ic, const char *server) { PurpleRoomlist *list; struct purple_data *pd = ic->proto_data; + PurplePlugin *prpl = purple_plugins_find_with_id(pd->account->protocol_id); + PurplePluginProtocolInfo *pi = prpl->info->extra_info; + + if (!pi || !pi->roomlist_get_list) { + imcb_log(ic, "Room listing unsupported by this purple plugin"); + return; + } list = purple_roomlist_get_list(pd->account->gc); if (list) { + struct purple_roomlist_data *rld = list->ui_data; + rld->initialized = TRUE; + purple_roomlist_ref(list); - } else { - imcb_log(ic, "Room listing unsupported by this purple plugin"); } } @@ -1381,7 +1396,7 @@ static void prplcb_roomlist_in_progress(PurpleRoomlist *list, gboolean in_progre struct im_connection *ic; struct purple_roomlist_data *rld = list->ui_data; - if (in_progress) { + if (in_progress || !rld) { return; } @@ -1392,7 +1407,10 @@ static void prplcb_roomlist_in_progress(PurpleRoomlist *list, gboolean in_progre rld->chats = NULL; bee_chat_list_finish(ic); - purple_roomlist_unref(list); + + if (rld->initialized) { + purple_roomlist_unref(list); + } } static void prplcb_roomlist_destroy(PurpleRoomlist *list) -- cgit v1.2.3 From 9698fc0a190f958fa28a8e54b2bfd6ccfdb2aa18 Mon Sep 17 00:00:00 2001 From: dequis Date: Wed, 12 Oct 2016 05:07:25 -0300 Subject: jabber: Don't pass a readonly empty string to imcb_chat_topic() Fixes crashes when a topic is unset and strip_html is set to always. Turns out that the strip_html() function does a strcpy at the end which may write a single null byte over the null byte of the empty string, and if it's not in writable memory, that blows up. Thanks to iamthemcmaster / mcm for pointing this out --- protocols/jabber/conference.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'protocols') diff --git a/protocols/jabber/conference.c b/protocols/jabber/conference.c index 3a6cff7c..593e4233 100644 --- a/protocols/jabber/conference.c +++ b/protocols/jabber/conference.c @@ -465,7 +465,8 @@ void jabber_chat_pkt_message(struct im_connection *ic, struct jabber_buddy *bud, } if (subject && chat) { - char *subject_text = subject->text_len > 0 ? subject->text : ""; + char empty[1] = ""; + char *subject_text = subject->text_len > 0 ? subject->text : empty; if (g_strcmp0(chat->topic, subject_text) != 0) { bare_jid = (bud) ? jabber_get_bare_jid(bud->ext_jid) : NULL; imcb_chat_topic(chat, bare_jid, subject_text, -- cgit v1.2.3 From a08b2db9575b276d7e6008e794fa728518671ec4 Mon Sep 17 00:00:00 2001 From: dequis Date: Sun, 16 Oct 2016 03:45:28 -0300 Subject: Rename bee_chat_list_finish() to imcb_chat_list_finish() bee_chat_list_finish is still available as a deprecated function but it will be removed before the next stable release It has never been part of any release, just keeping it for a while for the sake of being polite to the users of the discord plugin who may be using the experimental chat list branch. --- protocols/bee.h | 3 ++- protocols/bee_chat.c | 8 +++++++- protocols/purple/purple.c | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) (limited to 'protocols') diff --git a/protocols/bee.h b/protocols/bee.h index 5f47e464..93027d59 100644 --- a/protocols/bee.h +++ b/protocols/bee.h @@ -189,6 +189,7 @@ G_MODULE_EXPORT int bee_chat_msg(bee_t *bee, struct groupchat *c, const char *ms G_MODULE_EXPORT struct groupchat *bee_chat_by_title(bee_t *bee, struct im_connection *ic, const char *title); G_MODULE_EXPORT void imcb_chat_invite(struct im_connection *ic, const char *name, const char *who, const char *msg); -G_MODULE_EXPORT void bee_chat_list_finish(struct im_connection *ic); +G_GNUC_DEPRECATED G_MODULE_EXPORT void bee_chat_list_finish(struct im_connection *ic); +G_MODULE_EXPORT void imcb_chat_list_finish(struct im_connection *ic); #endif /* __BEE_H__ */ diff --git a/protocols/bee_chat.c b/protocols/bee_chat.c index 76ed7f85..c5f2b262 100644 --- a/protocols/bee_chat.c +++ b/protocols/bee_chat.c @@ -274,7 +274,13 @@ void imcb_chat_invite(struct im_connection *ic, const char *name, const char *wh } } -void bee_chat_list_finish(struct im_connection *ic) +void imcb_chat_list_finish(struct im_connection *ic) { cmd_chat_list_finish(ic); } + +void bee_chat_list_finish(struct im_connection *ic) +{ + imcb_log(ic, "Warning: using deprecated bee_chat_list_finish. This will be removed in the stable release."); + imcb_chat_list_finish(ic); +} diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index 6b043101..bd84966e 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -1406,7 +1406,7 @@ static void prplcb_roomlist_in_progress(PurpleRoomlist *list, gboolean in_progre ic->chatlist = g_slist_reverse(rld->chats); rld->chats = NULL; - bee_chat_list_finish(ic); + imcb_chat_list_finish(ic); if (rld->initialized) { purple_roomlist_unref(list); -- cgit v1.2.3 From 6e991a9464ce13fb742dcd50a37d5e00084b4233 Mon Sep 17 00:00:00 2001 From: dequis Date: Sun, 16 Oct 2016 03:50:49 -0300 Subject: Turn purple_chatlist_free() into a imcb_chat_list_free() I found myself copypasting this to jabber. Might as well make it part of the API. --- protocols/bee.h | 1 + protocols/bee_chat.c | 17 +++++++++++++++++ protocols/purple/purple.c | 19 ++----------------- 3 files changed, 20 insertions(+), 17 deletions(-) (limited to 'protocols') diff --git a/protocols/bee.h b/protocols/bee.h index 93027d59..56c34210 100644 --- a/protocols/bee.h +++ b/protocols/bee.h @@ -191,5 +191,6 @@ G_MODULE_EXPORT void imcb_chat_invite(struct im_connection *ic, const char *name G_GNUC_DEPRECATED G_MODULE_EXPORT void bee_chat_list_finish(struct im_connection *ic); G_MODULE_EXPORT void imcb_chat_list_finish(struct im_connection *ic); +G_MODULE_EXPORT void imcb_chat_list_free(struct im_connection *ic); #endif /* __BEE_H__ */ diff --git a/protocols/bee_chat.c b/protocols/bee_chat.c index c5f2b262..31b37737 100644 --- a/protocols/bee_chat.c +++ b/protocols/bee_chat.c @@ -284,3 +284,20 @@ void bee_chat_list_finish(struct im_connection *ic) imcb_log(ic, "Warning: using deprecated bee_chat_list_finish. This will be removed in the stable release."); imcb_chat_list_finish(ic); } + +void imcb_chat_list_free(struct im_connection *ic) +{ + bee_chat_info_t *ci; + GSList *l = ic->chatlist; + + while (l) { + ci = l->data; + l = g_slist_delete_link(l, l); + + g_free(ci->title); + g_free(ci->topic); + g_free(ci); + } + + ic->chatlist = NULL; +} diff --git a/protocols/purple/purple.c b/protocols/purple/purple.c index bd84966e..71b495db 100644 --- a/protocols/purple/purple.c +++ b/protocols/purple/purple.c @@ -360,21 +360,6 @@ static void purple_login(account_t *acc) } } -static void purple_chatlist_free(struct im_connection *ic) -{ - bee_chat_info_t *ci; - GSList *l = ic->chatlist; - - while (l) { - ci = l->data; - l = g_slist_delete_link(l, l); - - g_free(ci->title); - g_free(ci->topic); - g_free(ci); - } -} - static void purple_logout(struct im_connection *ic) { struct purple_data *pd = ic->proto_data; @@ -390,7 +375,7 @@ static void purple_logout(struct im_connection *ic) purple_account_set_enabled(pd->account, "BitlBee", FALSE); purple_connections = g_slist_remove(purple_connections, ic); purple_accounts_remove(pd->account); - purple_chatlist_free(ic); + imcb_chat_list_free(ic); g_hash_table_destroy(pd->input_requests); g_free(pd); } @@ -1401,7 +1386,7 @@ static void prplcb_roomlist_in_progress(PurpleRoomlist *list, gboolean in_progre } ic = purple_ic_by_pa(list->account); - purple_chatlist_free(ic); + imcb_chat_list_free(ic); ic->chatlist = g_slist_reverse(rld->chats); rld->chats = NULL; -- cgit v1.2.3