pidgin/pidgin

Parents a401fa6276ac
Children a836808f9c60
Convert the bonjour protocol plugin to the new status api and contacts

This has been tested on linux and windows. Apparently we don't build for mac right now. I didn't test file transfers at all though.

Testing Done:
Created and account and sent some messages to my Pidgin2 account.

Bugs closed: PIDGIN-17791

Reviewed at https://reviews.imfreedom.org/r/2427/
--- a/libpurple/protocols/bonjour/bonjour.c Tue May 23 00:21:15 2023 -0500
+++ b/libpurple/protocols/bonjour/bonjour.c Tue May 23 00:23:33 2023 -0500
@@ -363,20 +363,30 @@
bonjour_convo_closed(G_GNUC_UNUSED PurpleProtocolClient *client,
PurpleConnection *connection, const char *who)
{
- PurpleBuddy *buddy = purple_blist_find_buddy(purple_connection_get_account(connection), who);
+ PurpleAccount *account = NULL;
+ PurpleContact *contact = NULL;
+ PurpleContactManager *manager = NULL;
BonjourBuddy *bb;
- if (buddy == NULL || (bb = purple_buddy_get_protocol_data(buddy)) == NULL)
+ account = purple_connection_get_account(connection);
+ manager = purple_contact_manager_get_default();
+ contact = purple_contact_manager_find_with_username(manager, account, who);
+
+ if(!PURPLE_IS_CONTACT(contact) ||
+ (bb = g_object_get_data(G_OBJECT(contact), "bonjour-buddy")) == NULL)
{
/*
* This buddy is not in our buddy list, and therefore does not really
* exist, so we won't have any data about them.
*/
+ g_clear_object(&contact);
+
return;
}
bonjour_xmpp_close_conversation(bb->conversation);
bb->conversation = NULL;
+ g_clear_object(&contact);
}
static void
@@ -430,9 +440,24 @@
bonjour_can_receive_file(G_GNUC_UNUSED PurpleProtocolXfer *prplxfer,
PurpleConnection *connection, const char *who)
{
- PurpleBuddy *buddy = purple_blist_find_buddy(purple_connection_get_account(connection), who);
+ PurpleAccount *account = NULL;
+ PurpleContact *contact = NULL;
+ PurpleContactManager *manager = NULL;
+ gboolean ret = FALSE;
+
+ account = purple_connection_get_account(connection);
+ manager = purple_contact_manager_get_default();
+ contact = purple_contact_manager_find_with_username(manager, account, who);
- return (buddy != NULL && purple_buddy_get_protocol_data(buddy) != NULL);
+ if(PURPLE_IS_CONTACT(contact)) {
+ BonjourBuddy *bb = g_object_get_data(G_OBJECT(contact), "bonjour-buddy");
+
+ ret = (bb != NULL);
+ }
+
+ g_clear_object(&contact);
+
+ return ret;
}
static gssize
--- a/libpurple/protocols/bonjour/bonjour_ft.c Tue May 23 00:21:15 2023 -0500
+++ b/libpurple/protocols/bonjour/bonjour_ft.c Tue May 23 00:23:33 2023 -0500
@@ -64,7 +64,7 @@
char *proxy_host;
int proxy_port;
PurpleXmlNode *streamhost;
- PurpleBuddy *pb;
+ PurpleContact *contact;
};
G_DEFINE_DYNAMIC_TYPE(XepXfer, xep_xfer, PURPLE_TYPE_XFER);
@@ -360,7 +360,8 @@
static void
bonjour_xfer_init(PurpleXfer *xfer)
{
- PurpleBuddy *buddy;
+ PurpleContact *contact = NULL;
+ PurpleContactManager *manager = NULL;
BonjourBuddy *bb;
XepXfer *xf;
@@ -368,10 +369,19 @@
purple_debug_info("bonjour", "Bonjour-xfer-init.\n");
- buddy = purple_blist_find_buddy(purple_xfer_get_account(xfer), purple_xfer_get_remote_user(xfer));
+ manager = purple_contact_manager_get_default();
+ contact = purple_contact_manager_find_with_username(manager,
+ purple_xfer_get_account(xfer),
+ purple_xfer_get_remote_user(xfer));
+
/* this buddy is offline. */
- if (buddy == NULL || (bb = purple_buddy_get_protocol_data(buddy)) == NULL)
+ if(!PURPLE_IS_CONTACT(contact) ||
+ (bb = g_object_get_data(G_OBJECT(contact), "bonjour-buddy")) == NULL)
+ {
+ g_clear_object(&contact);
+
return;
+ }
/* Assume it is the first IP. We could do something like keep track of which one is in use or something. */
if (bb->ips)
@@ -385,10 +395,13 @@
xep_ft_si_result(xfer, purple_xfer_get_remote_user(xfer));
purple_debug_info("bonjour", "Bonjour xfer type is PURPLE_XFER_TYPE_RECEIVE.\n");
}
+
+ g_clear_object(&contact);
}
void
-xep_si_parse(PurpleConnection *pc, PurpleXmlNode *packet, PurpleBuddy *pb)
+xep_si_parse(PurpleConnection *pc, PurpleXmlNode *packet,
+ PurpleContact *contact)
{
const char *type, *id;
BonjourData *bd;
@@ -397,15 +410,16 @@
g_return_if_fail(pc != NULL);
g_return_if_fail(packet != NULL);
- g_return_if_fail(pb != NULL);
+ g_return_if_fail(PURPLE_IS_CONTACT(contact));
bd = purple_connection_get_protocol_data(pc);
- if(bd == NULL)
+ if(bd == NULL) {
return;
+ }
purple_debug_info("bonjour", "xep-si-parse.\n");
- name = purple_buddy_get_name(pb);
+ name = purple_contact_info_get_username(PURPLE_CONTACT_INFO(contact));
type = purple_xmlnode_get_attrib(packet, "type");
id = purple_xmlnode_get_attrib(packet, "id");
@@ -574,7 +588,7 @@
*/
static gboolean
add_ipv6_link_local_ifaces(PurpleXmlNode *cur_streamhost, const char *host,
- PurpleBuddy *pb)
+ PurpleContact *contact)
{
PurpleXmlNode *new_streamhost = NULL;
GInetAddress *addr;
@@ -592,7 +606,7 @@
}
g_clear_object(&addr);
- bb = purple_buddy_get_protocol_data(pb);
+ bb = g_object_get_data(G_OBJECT(contact), "bonjour-buddy");
for (ip_elem = bb->ips;
(ip_elem = g_slist_find_custom(ip_elem, host, (GCompareFunc)&xep_addr_differ));
@@ -611,8 +625,8 @@
}
static gboolean
-__xep_bytestreams_parse(PurpleBuddy *pb, PurpleXfer *xfer, PurpleXmlNode *streamhost,
- const char *iq_id)
+__xep_bytestreams_parse(PurpleContact *contact, PurpleXfer *xfer,
+ PurpleXmlNode *streamhost, const char *iq_id)
{
char *tmp_iq_id;
const char *jid, *host, *port;
@@ -630,7 +644,7 @@
/* skip IPv6 link local addresses with no interface scope
* (but try to add a new one with an interface scope then) */
- if(add_ipv6_link_local_ifaces(streamhost, host, pb))
+ if(add_ipv6_link_local_ifaces(streamhost, host, contact))
continue;
tmp_iq_id = g_strdup(iq_id);
@@ -643,7 +657,7 @@
xf->proxy_host = g_strdup(host);
xf->proxy_port = portnum;
xf->streamhost = streamhost;
- xf->pb = pb;
+ xf->contact = contact;
purple_debug_info("bonjour", "bytestream offer parse"
"jid=%s host=%s port=%d.\n", jid, host, portnum);
bonjour_bytestreams_connect(xfer);
@@ -654,7 +668,8 @@
}
void
-xep_bytestreams_parse(PurpleConnection *pc, PurpleXmlNode *packet, PurpleBuddy *pb)
+xep_bytestreams_parse(PurpleConnection *pc, PurpleXmlNode *packet,
+ PurpleContact *contact)
{
const char *type, *from, *iq_id, *sid;
PurpleXmlNode *query, *streamhost;
@@ -663,16 +678,17 @@
g_return_if_fail(pc != NULL);
g_return_if_fail(packet != NULL);
- g_return_if_fail(pb != NULL);
+ g_return_if_fail(PURPLE_IS_CONTACT(contact));
bd = purple_connection_get_protocol_data(pc);
- if(bd == NULL)
+ if(bd == NULL) {
return;
+ }
purple_debug_info("bonjour", "xep-bytestreams-parse.\n");
type = purple_xmlnode_get_attrib(packet, "type");
- from = purple_buddy_get_name(pb);
+ from = purple_contact_info_get_username(PURPLE_CONTACT_INFO(contact));
query = purple_xmlnode_get_child(packet,"query");
if(!type)
return;
@@ -694,7 +710,7 @@
xfer = bonjour_si_xfer_find(bd, sid, from);
streamhost = purple_xmlnode_get_child(query, "streamhost");
- if(xfer && streamhost && __xep_bytestreams_parse(pb, xfer, streamhost, iq_id))
+ if(xfer && streamhost && __xep_bytestreams_parse(contact, xfer, streamhost, iq_id))
return; /* success */
purple_debug_error("bonjour", "Didn't find an acceptable streamhost.\n");
@@ -966,7 +982,7 @@
xf->proxy_host, error_message);
tmp_node = purple_xmlnode_get_next_twin(xf->streamhost);
- ret = __xep_bytestreams_parse(xf->pb, xfer, tmp_node, xf->iq_id);
+ ret = __xep_bytestreams_parse(xf->contact, xfer, tmp_node, xf->iq_id);
if (!ret) {
xep_ft_si_reject(xf->data, xf->iq_id, purple_xfer_get_remote_user(xfer),
@@ -1046,7 +1062,7 @@
GSocketAddress *addr;
GInetSocketAddress *inet_addr;
GSocketAddress *proxy_addr;
- PurpleBuddy *pb;
+ PurpleContact *contact = NULL;
gchar *hash_input;
gchar *dstaddr;
GError *error = NULL;
@@ -1089,9 +1105,10 @@
return;
}
- pb = xf->pb;
- hash_input = g_strdup_printf("%s%s%s", xf->sid, purple_buddy_get_name(pb),
- bonjour_get_jid(purple_buddy_get_account(pb)));
+ contact = xf->contact;
+ hash_input = g_strdup_printf("%s%s%s", xf->sid,
+ purple_contact_info_get_username(PURPLE_CONTACT_INFO(contact)),
+ bonjour_get_jid(purple_contact_get_account(contact)));
dstaddr = g_compute_checksum_for_string(G_CHECKSUM_SHA1, hash_input, -1);
g_free(hash_input);
@@ -1128,7 +1145,7 @@
purple_debug_info("bonjour", "bonjour-bytestreams-connect.");
xf = XEP_XFER(xfer);
- account = purple_buddy_get_account(xf->pb);
+ account = purple_contact_get_account(xf->contact);
xf->client = purple_gio_socket_client_new(account, &error);
if (xf->client == NULL) {
--- a/libpurple/protocols/bonjour/bonjour_ft.h Tue May 23 00:21:15 2023 -0500
+++ b/libpurple/protocols/bonjour/bonjour_ft.h Tue May 23 00:23:33 2023 -0500
@@ -52,8 +52,8 @@
*/
void bonjour_send_file(PurpleProtocolXfer *prplxfer, PurpleConnection *gc, const char *who, const char *file);
-void xep_si_parse(PurpleConnection *pc, PurpleXmlNode *packet, PurpleBuddy *pb);
-void xep_bytestreams_parse(PurpleConnection *pc, PurpleXmlNode *packet, PurpleBuddy *pb);
+void xep_si_parse(PurpleConnection *pc, PurpleXmlNode *packet, PurpleContact *contact);
+void xep_bytestreams_parse(PurpleConnection *pc, PurpleXmlNode *packet, PurpleContact *contact);
void xep_xfer_register(GTypeModule *module);
--- a/libpurple/protocols/bonjour/buddy.c Tue May 23 00:21:15 2023 -0500
+++ b/libpurple/protocols/bonjour/buddy.c Tue May 23 00:23:33 2023 -0500
@@ -119,73 +119,108 @@
* the buddy.
*/
void
-bonjour_buddy_add_to_purple(BonjourBuddy *bonjour_buddy, PurpleBuddy *buddy)
+bonjour_buddy_add_to_purple(BonjourBuddy *bonjour_buddy)
{
- PurpleGroup *group;
PurpleAccount *account = bonjour_buddy->account;
- const char *status_id, *old_hash, *new_hash, *name;
+ PurpleContact *contact = NULL;
+ PurpleContactManager *manager = NULL;
+ PurplePerson *person = NULL;
+ PurplePresence *presence = NULL;
+ PurplePresencePrimitive primitive = PURPLE_PRESENCE_PRIMITIVE_AVAILABLE;
/* Translate between the Bonjour status and the Purple status */
- if (bonjour_buddy->status != NULL && g_ascii_strcasecmp("dnd", bonjour_buddy->status) == 0)
- status_id = BONJOUR_STATUS_ID_AWAY;
- else
- status_id = BONJOUR_STATUS_ID_AVAILABLE;
+ if(bonjour_buddy->status != NULL &&
+ g_ascii_strcasecmp("dnd", bonjour_buddy->status) == 0)
+ {
+ primitive = PURPLE_PRESENCE_PRIMITIVE_AWAY;
+ }
/*
* TODO: Figure out the idle time by getting the "away"
* field from the DNS SD.
*/
- /* Make sure the Bonjour group exists in our buddy list */
- group = purple_blist_find_group(BONJOUR_GROUP_NAME); /* Use the buddy's domain, instead? */
- if (group == NULL) {
- group = purple_group_new(BONJOUR_GROUP_NAME);
- purple_blist_add_group(group, NULL);
- }
+ /* Determine if we already know about this contact. */
+ manager = purple_contact_manager_get_default();
+ contact = purple_contact_manager_find_with_username(manager, account,
+ bonjour_buddy->name);
+
+ /* If not, create the contact and add them to the manager. */
+ if(!PURPLE_IS_CONTACT(contact)) {
+ PurpleTags *tags = NULL;
- /* Make sure the buddy exists in our buddy list */
- if (buddy == NULL)
- buddy = purple_blist_find_buddy(account, bonjour_buddy->name);
+ contact = purple_contact_new(account, NULL);
+ purple_contact_manager_add(manager, contact);
- if (buddy == NULL) {
- buddy = purple_buddy_new(account, bonjour_buddy->name, NULL);
- purple_blist_node_set_transient(PURPLE_BLIST_NODE(buddy), TRUE);
- purple_blist_add_buddy(buddy, NULL, group, NULL);
+ purple_contact_info_set_username(PURPLE_CONTACT_INFO(contact),
+ bonjour_buddy->name);
+
+ tags = purple_contact_info_get_tags(PURPLE_CONTACT_INFO(contact));
+ purple_tags_add_with_value(tags, "group", BONJOUR_GROUP_NAME);
}
- name = purple_buddy_get_name(buddy);
- purple_buddy_set_protocol_data(buddy, bonjour_buddy);
+ /* Make sure we have a person for this contact as we want them to appear in
+ * the contact list.
+ */
+ person = purple_contact_info_get_person(PURPLE_CONTACT_INFO(contact));
+ if(!PURPLE_IS_PERSON(person)) {
+ person = g_object_new(PURPLE_TYPE_PERSON, "id", bonjour_buddy->name,
+ NULL);
+ purple_contact_info_set_person(PURPLE_CONTACT_INFO(contact), person);
+ purple_person_add_contact_info(person, PURPLE_CONTACT_INFO(contact));
- /* Create the alias for the buddy using the first and the last name */
- if (bonjour_buddy->nick && *bonjour_buddy->nick)
- purple_serv_got_alias(purple_account_get_connection(account), name, bonjour_buddy->nick);
- else {
+ /* We remove our reference as the pointer is valid and we're treating
+ * it just like if we had called _get_person above but with the new
+ * instance.
+ */
+ g_object_unref(person);
+ }
+
+ /* Set the alias. */
+ if(!purple_strempty(bonjour_buddy->nick)) {
+ purple_contact_info_set_alias(PURPLE_CONTACT_INFO(contact),
+ bonjour_buddy->nick);
+ } else {
+ GStrvBuilder *builder = NULL;
+ GStrv parts = NULL;
gchar *alias = NULL;
- const char *first, *last;
- first = bonjour_buddy->first;
- last = bonjour_buddy->last;
- if ((first && *first) || (last && *last))
- alias = g_strdup_printf("%s%s%s",
- (first && *first ? first : ""),
- (first && *first && last && *last ? " " : ""),
- (last && *last ? last : ""));
- purple_serv_got_alias(purple_account_get_connection(account), name, alias);
+
+ builder = g_strv_builder_new();
+
+ if(!purple_strempty(bonjour_buddy->first)) {
+ g_strv_builder_add(builder, bonjour_buddy->first);
+ }
+
+ if(!purple_strempty(bonjour_buddy->last)) {
+ g_strv_builder_add(builder, bonjour_buddy->last);
+ }
+
+ parts = g_strv_builder_end(builder);
+
+ alias = g_strjoinv(" ", parts);
+ g_strfreev(parts);
+
+ if(!purple_strempty(alias)) {
+ purple_contact_info_set_alias(PURPLE_CONTACT_INFO(contact), alias);
+ } else {
+ purple_contact_info_set_alias(PURPLE_CONTACT_INFO(contact), NULL);
+ }
g_free(alias);
}
+ g_object_set_data(G_OBJECT(contact), "bonjour-buddy", bonjour_buddy);
+
/* Set the user's status */
- if (bonjour_buddy->msg != NULL)
- purple_protocol_got_user_status(account, name, status_id,
- "message", bonjour_buddy->msg, NULL);
- else
- purple_protocol_got_user_status(account, name, status_id, NULL);
-
- purple_protocol_got_user_idle(account, name, FALSE, 0);
+ presence = purple_contact_info_get_presence(PURPLE_CONTACT_INFO(contact));
+ purple_presence_set_primitive(presence, primitive);
+ purple_presence_set_message(presence, bonjour_buddy->msg);
+ purple_presence_set_idle(presence, FALSE, NULL);
/* TODO: Because we don't save Bonjour buddies in blist.xml,
* we will always have to look up the buddy icon at login time.
* I think we should figure out a way to do something about this. */
+#if 0
/* Deal with the buddy icon */
old_hash = purple_buddy_icons_get_checksum_for_user(buddy);
new_hash = (bonjour_buddy->phsh && *(bonjour_buddy->phsh)) ? bonjour_buddy->phsh : NULL;
@@ -196,22 +231,27 @@
bonjour_dns_sd_retrieve_buddy_icon(bonjour_buddy);
} else if (!new_hash)
purple_buddy_icons_set_for_user(account, name, NULL, 0, NULL);
+#endif
+
+ g_clear_object(&contact);
}
/**
* The buddy has signed off Bonjour.
* If the buddy is being saved, mark as offline, otherwise delete
*/
-void bonjour_buddy_signed_off(PurpleBuddy *pb) {
- if (purple_blist_node_is_transient(PURPLE_BLIST_NODE(pb))) {
- purple_account_remove_buddy(purple_buddy_get_account(pb), pb, NULL);
- purple_blist_remove_buddy(pb);
- } else {
- purple_protocol_got_user_status(purple_buddy_get_account(pb),
- purple_buddy_get_name(pb), "offline", NULL);
- bonjour_buddy_delete(purple_buddy_get_protocol_data(pb));
- purple_buddy_set_protocol_data(pb, NULL);
+void bonjour_buddy_signed_off(PurpleContact *contact) {
+ BonjourBuddy *bb = NULL;
+ PurplePresence *presence = NULL;
+
+ presence = purple_contact_info_get_presence(PURPLE_CONTACT_INFO(contact));
+ purple_presence_set_primitive(presence, PURPLE_PRESENCE_PRIMITIVE_OFFLINE);
+
+ bb = g_object_get_data(G_OBJECT(contact), "bonjour-buddy");
+ if(bb != NULL) {
+ bonjour_buddy_delete(bb);
}
+ g_object_set_data(G_OBJECT(contact), "bonjour-buddy", NULL);
}
/**
--- a/libpurple/protocols/bonjour/buddy.h Tue May 23 00:21:15 2023 -0500
+++ b/libpurple/protocols/bonjour/buddy.h Tue May 23 00:23:33 2023 -0500
@@ -91,16 +91,15 @@
gboolean bonjour_buddy_check(BonjourBuddy *buddy);
/**
- * If the buddy doesn't previously exists, it is created. Else, its data is changed (???)
- * purple_buddy is optional; it saves an additional lookup if we already have it
+ * If the buddy doesn't previously exists, it is created.
*/
-void bonjour_buddy_add_to_purple(BonjourBuddy *bonjour_buddy, PurpleBuddy *purple_buddy);
+void bonjour_buddy_add_to_purple(BonjourBuddy *bonjour_buddy);
/**
* The buddy has signed off Bonjour.
* If the buddy is being saved, mark as offline, otherwise delete
*/
-void bonjour_buddy_signed_off(PurpleBuddy *purple_buddy);
+void bonjour_buddy_signed_off(PurpleContact *contact);
/**
* We got the buddy icon data; deal with it
--- a/libpurple/protocols/bonjour/mdns_avahi.c Tue May 23 00:21:15 2023 -0500
+++ b/libpurple/protocols/bonjour/mdns_avahi.c Tue May 23 00:23:33 2023 -0500
@@ -109,9 +109,10 @@
uint16_t port, AvahiStringList *txt,
G_GNUC_UNUSED AvahiLookupResultFlags flags, void *userdata)
{
- PurpleBuddy *pb;
- BonjourBuddy *bb;
+ BonjourBuddy *bb = NULL;
PurpleAccount *account = userdata;
+ PurpleContactManager *manager = NULL;
+ PurpleContact *contact = NULL;
AvahiStringList *l;
size_t size;
char *key, *value;
@@ -122,8 +123,12 @@
g_return_if_fail(r != NULL);
- pb = purple_blist_find_buddy(account, name);
- bb = (pb != NULL) ? purple_buddy_get_protocol_data(pb) : NULL;
+ manager = purple_contact_manager_get_default();
+ contact = purple_contact_manager_find_with_username(manager, account,
+ name);
+ if(PURPLE_IS_CONTACT(contact)) {
+ bb = g_object_get_data(G_OBJECT(contact), "bonjour-buddy");
+ }
switch (event) {
case AVAHI_RESOLVER_FAILURE:
@@ -143,8 +148,9 @@
_cleanup_resolver_data(rd);
/* If this was the last resolver, remove the buddy */
- if (b_impl->resolvers == NULL)
- bonjour_buddy_signed_off(pb);
+ if (b_impl->resolvers == NULL) {
+ bonjour_buddy_signed_off(contact);
+ }
}
}
break;
@@ -219,20 +225,23 @@
_cleanup_resolver_data(rd);
/* If this was the last resolver, remove the buddy */
if (b_impl->resolvers == NULL) {
- if (pb != NULL)
- bonjour_buddy_signed_off(pb);
- else
+ if (PURPLE_IS_CONTACT(contact)) {
+ bonjour_buddy_signed_off(contact);
+ } else {
bonjour_buddy_delete(bb);
+ }
}
- } else
+ } else {
/* Add or update the buddy in our buddy list */
- bonjour_buddy_add_to_purple(bb, pb);
+ bonjour_buddy_add_to_purple(bb);
+ }
break;
default:
purple_debug_info("bonjour", "Unrecognized Service Resolver event: %d.\n", event);
}
+ g_clear_object(&contact);
}
static void
@@ -242,7 +251,6 @@
G_GNUC_UNUSED AvahiLookupResultFlags flags, void *userdata)
{
PurpleAccount *account = userdata;
- PurpleBuddy *pb = NULL;
switch (event) {
case AVAHI_BROWSER_FAILURE:
@@ -263,15 +271,22 @@
}
}
break;
- case AVAHI_BROWSER_REMOVE:
+ case AVAHI_BROWSER_REMOVE: {
+ PurpleContact *contact = NULL;
+ PurpleContactManager *manager = NULL;
+
purple_debug_info("bonjour", "_browser_callback - Remove service\n");
- pb = purple_blist_find_buddy(account, name);
- if (pb != NULL) {
- BonjourBuddy *bb = purple_buddy_get_protocol_data(pb);
+
+ manager = purple_contact_manager_get_default();
+ contact = purple_contact_manager_find_with_username(manager,
+ account, name);
+ if (PURPLE_IS_CONTACT(contact)) {
+ BonjourBuddy *bb = NULL;
AvahiBuddyImplData *b_impl;
GSList *l;
AvahiSvcResolverData *rd_search;
+ bb = g_object_get_data(G_OBJECT(contact), "bonjour-buddy");
g_return_if_fail(bb != NULL);
b_impl = bb->mdns_impl_data;
@@ -301,11 +316,16 @@
_cleanup_resolver_data(rd);
/* If this was the last resolver, remove the buddy */
- if (b_impl->resolvers == NULL)
- bonjour_buddy_signed_off(pb);
+ if (b_impl->resolvers == NULL) {
+ bonjour_buddy_signed_off(contact);
+ }
}
}
+
+ g_clear_object(&contact);
+
break;
+ }
case AVAHI_BROWSER_ALL_FOR_NOW:
case AVAHI_BROWSER_CACHE_EXHAUSTED:
break;
--- a/libpurple/protocols/bonjour/mdns_dns_sd.c Tue May 23 00:21:15 2023 -0500
+++ b/libpurple/protocols/bonjour/mdns_dns_sd.c Tue May 23 00:23:33 2023 -0500
@@ -151,7 +151,7 @@
/* New Buddy */
BonjourBuddy *bb = (BonjourBuddy*) context;
_mdns_parse_text_record(bb, rdata, rdlen);
- bonjour_buddy_add_to_purple(bb, NULL);
+ bonjour_buddy_add_to_purple(bb);
} else if (rrtype == kDNSServiceType_NULL) {
/* Buddy Icon response */
BonjourBuddy *bb = (BonjourBuddy*) context;
@@ -181,16 +181,21 @@
{
ResolveCallbackArgs *args = (ResolveCallbackArgs*) context;
Win32BuddyImplData *idata = args->bb->mdns_impl_data;
+ PurpleContact *contact = NULL;
+ PurpleContactManager *manager = NULL;
gboolean delete_buddy = FALSE;
- PurpleBuddy *pb = NULL;
g_source_remove(args->resolver_query->input_handler);
DNSServiceRefDeallocate(args->resolver_query->sdRef);
g_free(args->resolver_query);
args->resolver_query = NULL;
- if ((pb = purple_blist_find_buddy(args->account, args->res_data->name))) {
- if (purple_buddy_get_protocol_data(pb) != args->bb) {
+ manager = purple_contact_manager_get_default();
+ contact = purple_contact_manager_find_with_username(manager, args->account,
+ args->res_data->name);
+
+ if (PURPLE_IS_CONTACT(contact)) {
+ if (g_object_get_data(G_OBJECT(contact), "bonjour-buddy") != args->bb) {
purple_debug_error("bonjour", "Found purple buddy for %s not matching bonjour buddy record.",
args->res_data->name);
goto cleanup;
@@ -236,7 +241,7 @@
args->res_data->txt_query->input_handler = purple_input_add(DNSServiceRefSockFD(txt_query_sr),
PURPLE_INPUT_READ, _mdns_handle_event, args->res_data->txt_query);
- bonjour_buddy_add_to_purple(args->bb, NULL);
+ bonjour_buddy_add_to_purple(args->bb);
} else {
purple_debug_error("bonjour", "Unable to set up record watcher for buddy %s (%d)\n", args->bb->name, errorCode);
delete_buddy = TRUE;
@@ -251,10 +256,11 @@
/* If this was the last resolver, remove the buddy */
if (idata->resolvers == NULL) {
- if (pb)
- bonjour_buddy_signed_off(pb);
- else
+ if (PURPLE_IS_CONTACT(contact)) {
+ bonjour_buddy_signed_off(contact);
+ } else {
bonjour_buddy_delete(args->bb);
+ }
/* Remove from the pending list */
pending_buddies = g_slist_remove(pending_buddies, args->bb);
@@ -267,6 +273,8 @@
/* free the remaining args memory */
g_free(args->full_service_name);
g_free(args);
+
+ g_clear_object(&contact);
}
static void DNSSD_API
@@ -319,15 +327,24 @@
/* If this was the last resolver, remove the buddy */
if (idata->resolvers == NULL) {
- PurpleBuddy *pb;
- /* See if this is now attached to a PurpleBuddy */
- if ((pb = purple_blist_find_buddy(args->account, args->bb->name)))
- bonjour_buddy_signed_off(pb);
- else {
+ PurpleContact *contact = NULL;
+ PurpleContactManager *manager = NULL;
+
+ manager = purple_contact_manager_get_default();
+ contact = purple_contact_manager_find_with_username(manager,
+ args->account,
+ args->bb->name);
+
+ /* See if this is now attached to a PurpleContact */
+ if(PURPLE_IS_CONTACT(contact)) {
+ bonjour_buddy_signed_off(contact);
+ } else {
/* Remove from the pending list */
pending_buddies = g_slist_remove(pending_buddies, args->bb);
bonjour_buddy_delete(args->bb);
}
+
+ g_clear_object(&contact);
}
g_free(args);
@@ -432,19 +449,23 @@
}
}
} else {
- PurpleBuddy *pb = NULL;
+ PurpleContact *contact = NULL;
+ PurpleContactManager *manager = NULL;
+
+ manager = purple_contact_manager_get_default();
+ contact = purple_contact_manager_find_with_username(manager, account,
+ serviceName);
/* A peer has sent a goodbye packet, remove them from the buddy list */
purple_debug_info("bonjour", "Received remove notification for '%s' on iface %u (%s, %s)\n",
serviceName, interfaceIndex, regtype ? regtype : "",
replyDomain ? replyDomain : "");
- pb = purple_blist_find_buddy(account, serviceName);
- if (pb != NULL) {
+ if(PURPLE_IS_CONTACT(contact)) {
GSList *l;
/* There may be multiple presences, we should only get rid of this one */
Win32SvcResolverData *rd_search;
- BonjourBuddy *bb = purple_buddy_get_protocol_data(pb);
+ BonjourBuddy *bb = g_object_get_data(G_OBJECT(contact), "bonjour-buddy");
Win32BuddyImplData *idata;
g_return_if_fail(bb != NULL);
@@ -475,13 +496,15 @@
if (idata->resolvers == NULL) {
purple_debug_info("bonjour", "Removed last presence for buddy '%s'; signing off buddy.\n",
serviceName);
- bonjour_buddy_signed_off(pb);
+ bonjour_buddy_signed_off(contact);
}
}
} else {
- purple_debug_warning("bonjour", "Unable to find buddy (%s) to remove\n", serviceName ? serviceName : "(null)");
+ purple_debug_warning("bonjour", "Unable to find contact (%s) to remove\n", serviceName ? serviceName : "(null)");
/* TODO: Should we look in the pending buddies list? */
}
+
+ g_clear_object(&contact);
}
}
--- a/libpurple/protocols/bonjour/parser.c Tue May 23 00:21:15 2023 -0500
+++ b/libpurple/protocols/bonjour/parser.c Tue May 23 00:23:33 2023 -0500
@@ -38,7 +38,7 @@
bconv->buddy_name = g_strndup((char *)attributes[i+3], len);
bonjour_xmpp_conv_match_by_name(bconv);
- return (bconv->pb != NULL);
+ return (PURPLE_IS_CONTACT(bconv->contact));
}
}
@@ -67,8 +67,9 @@
if(!bconv->recv_stream_start) {
bconv->recv_stream_start = TRUE;
- if (bconv->pb == NULL)
+ if(!PURPLE_IS_CONTACT(bconv->contact)) {
parse_from_attrib_and_find_buddy(bconv, nb_attributes, attributes);
+ }
bonjour_xmpp_stream_started(bconv);
}
@@ -76,14 +77,16 @@
/* If we haven't yet attached a buddy and this isn't "<stream:features />",
* try to get a "from" attribute as a last resort to match our buddy. */
- if(bconv->pb == NULL
+ if(!PURPLE_IS_CONTACT(bconv->contact)
&& !(prefix && !xmlStrcmp(prefix, (xmlChar*) "stream")
&& !xmlStrcmp(element_name, (xmlChar*) "features"))
&& !parse_from_attrib_and_find_buddy(bconv, nb_attributes, attributes))
+ {
/* We've run out of options for finding who the conversation is from
using explicitly specified stuff; see if we can make a good match
by using the IP */
bonjour_xmpp_conv_match_by_ip(bconv);
+ }
if(bconv->current)
node = purple_xmlnode_new_child(bconv->current, (const char*) element_name);
@@ -136,7 +139,7 @@
} else {
PurpleXmlNode *packet = bconv->current;
bconv->current = NULL;
- bonjour_xmpp_process_packet(bconv->pb, packet);
+ bonjour_xmpp_process_packet(bconv->contact, packet);
purple_xmlnode_free(packet);
}
}
--- a/libpurple/protocols/bonjour/xmpp.c Tue May 23 00:21:15 2023 -0500
+++ b/libpurple/protocols/bonjour/xmpp.c Tue May 23 00:23:33 2023 -0500
@@ -49,17 +49,19 @@
};
static void
-xep_iq_parse(PurpleXmlNode *packet, PurpleBuddy *pb);
+xep_iq_parse(PurpleXmlNode *packet, PurpleContact *contact);
static BonjourXMPPConversation *
-bonjour_xmpp_conv_new(PurpleBuddy *pb, PurpleAccount *account, const char *ip) {
+bonjour_xmpp_conv_new(PurpleContact *contact, PurpleAccount *account,
+ const char *ip)
+{
BonjourXMPPConversation *bconv = g_new0(BonjourXMPPConversation, 1);
bconv->cancellable = g_cancellable_new();
bconv->tx_buf = purple_circular_buffer_new(512);
bconv->tx_handler = 0;
bconv->rx_handler = 0;
- bconv->pb = pb;
+ bconv->contact = contact;
bconv->account = account;
bconv->ip = g_strdup(ip);
@@ -111,11 +113,17 @@
}
static void
-_xmpp_parse_and_write_message_to_ui(PurpleXmlNode *message_node, PurpleBuddy *pb)
+_xmpp_parse_and_write_message_to_ui(PurpleXmlNode *message_node,
+ PurpleContact *contact)
{
PurpleXmlNode *body_node, *html_node, *events_node;
- PurpleConnection *gc = purple_account_get_connection(purple_buddy_get_account(pb));
+ PurpleAccount *account = NULL;
+ PurpleConnection *gc = NULL;
gchar *body = NULL;
+ const char *username = NULL;
+
+ account = purple_contact_get_account(contact);
+ gc = purple_account_get_connection(account);
body_node = purple_xmlnode_get_child(message_node, "body");
html_node = purple_xmlnode_get_child(message_node, "html");
@@ -196,61 +204,53 @@
}
/* Send the message to the UI */
- purple_serv_got_im(gc, purple_buddy_get_name(pb), body, 0, time(NULL));
+ username = purple_contact_info_get_username(PURPLE_CONTACT_INFO(contact));
+ purple_serv_got_im(gc, username, body, 0, time(NULL));
g_free(body);
}
-struct _match_buddies_by_address {
- const char *address;
- GSList *matched_buddies;
-};
-
-static void
-_match_buddies_by_address(gpointer value, gpointer data)
-{
- PurpleBuddy *pb = value;
- struct _match_buddies_by_address *mbba = data;
- BonjourBuddy *bb = purple_buddy_get_protocol_data(pb);
-
- if (!bb) {
- return;
- }
-
- /*
- * If the current PurpleBuddy's data is not null, then continue to determine
- * whether one of the buddies IPs matches the target IP.
- */
- if (g_slist_find_custom(bb->ips, mbba->address, (GCompareFunc)g_ascii_strcasecmp)) {
- mbba->matched_buddies = g_slist_prepend(mbba->matched_buddies, pb);
- }
-}
-
static GSList *
_find_match_buddies_by_address(const BonjourXMPP *jdata, const char *address)
{
- struct _match_buddies_by_address mbba = {
- .address = address,
- .matched_buddies = NULL
- };
- GSList *buddies = purple_blist_find_buddies(jdata->account, NULL);
+ PurpleContactManager *manager = NULL;
+ GListModel *contacts = NULL;
+ GSList *ret = NULL;
+
+ manager = purple_contact_manager_get_default();
+ contacts = purple_contact_manager_get_all(manager, jdata->account);
+ for(guint i = 0; i < g_list_model_get_n_items(contacts); i++) {
+ PurpleContact *contact = NULL;
+ BonjourBuddy *bb = NULL;
- g_slist_foreach(buddies, _match_buddies_by_address, &mbba);
- g_slist_free(buddies);
+ contact = g_list_model_get_item(contacts, i);
+ bb = g_object_get_data(G_OBJECT(contact), "bonjour-buddy");
+ if(bb != NULL) {
+ if(g_slist_find_custom(bb->ips, address,
+ (GCompareFunc)g_ascii_strcasecmp))
+ {
+ ret = g_slist_prepend(ret, contact);
+ }
+ }
- return mbba.matched_buddies;
+ g_clear_object(&contact);
+ }
+
+ return ret;
}
static void
_send_data_write_cb(GObject *stream, gpointer data)
{
- PurpleBuddy *pb = data;
- BonjourBuddy *bb = purple_buddy_get_protocol_data(pb);
- BonjourXMPPConversation *bconv = bb->conversation;
+ PurpleContact *contact = data;
+ BonjourBuddy *bb = NULL;
+ BonjourXMPPConversation *bconv = NULL;
gsize writelen;
gssize ret;
GError *error = NULL;
+ bb = g_object_get_data(G_OBJECT(contact), "bonjour-buddy");
+ bconv = bb->conversation;
writelen = purple_circular_buffer_get_max_read(bconv->tx_buf);
if (writelen == 0) {
@@ -276,10 +276,10 @@
purple_debug_error(
"bonjour",
"Error sending message to buddy %s error: %s",
- purple_buddy_get_name(pb),
+ purple_contact_info_get_username(PURPLE_CONTACT_INFO(contact)),
error ? error->message : "(null)");
- account = purple_buddy_get_account(pb);
+ account = purple_contact_get_account(contact);
conv = purple_conversation_manager_find_im(manager, account, bb->name);
if (conv != NULL) {
@@ -291,6 +291,7 @@
bonjour_xmpp_close_conversation(bb->conversation);
bb->conversation = NULL;
g_clear_error(&error);
+
return;
}
@@ -298,9 +299,9 @@
}
static gint
-_send_data(PurpleBuddy *pb, char *message)
+_send_data(PurpleContact *contact, char *message)
{
- BonjourBuddy *bb = purple_buddy_get_protocol_data(pb);
+ BonjourBuddy *bb = g_object_get_data(G_OBJECT(contact), "bonjour-buddy");
BonjourXMPPConversation *bconv = bb->conversation;
gsize len = strlen(message);
gssize ret;
@@ -333,10 +334,10 @@
purple_debug_error(
"bonjour",
"Error sending message to buddy %s error: %s",
- purple_buddy_get_name(pb),
+ purple_contact_info_get_username(PURPLE_CONTACT_INFO(contact)),
error ? error->message : "(null)");
- account = purple_buddy_get_account(pb);
+ account = purple_contact_get_account(contact);
conv = purple_conversation_manager_find_im(manager, account, bb->name);
if (conv != NULL) {
@@ -361,7 +362,7 @@
bconv->cancellable);
g_source_set_callback(source,
G_SOURCE_FUNC(_send_data_write_cb),
- pb, NULL);
+ g_object_ref(contact), g_object_unref);
bconv->tx_handler = g_source_attach(source, NULL);
g_source_unref(source);
}
@@ -371,36 +372,41 @@
return ret;
}
-void bonjour_xmpp_process_packet(PurpleBuddy *pb, PurpleXmlNode *packet) {
-
+void
+bonjour_xmpp_process_packet(PurpleContact *contact, PurpleXmlNode *packet) {
+ g_return_if_fail(PURPLE_IS_CONTACT(contact));
g_return_if_fail(packet != NULL);
- g_return_if_fail(pb != NULL);
- if (purple_strequal(packet->name, "message"))
- _xmpp_parse_and_write_message_to_ui(packet, pb);
- else if (purple_strequal(packet->name, "iq"))
- xep_iq_parse(packet, pb);
- else {
+ if (purple_strequal(packet->name, "message")) {
+ _xmpp_parse_and_write_message_to_ui(packet, contact);
+ } else if (purple_strequal(packet->name, "iq")) {
+ xep_iq_parse(packet, contact);
+ } else {
purple_debug_warning("bonjour", "Unknown packet: %s\n",
packet->name ? packet->name : "(null)");
}
}
-static void bonjour_xmpp_stream_ended(BonjourXMPPConversation *bconv) {
-
+static void
+bonjour_xmpp_stream_ended(BonjourXMPPConversation *bconv) {
/* Inform the user that the conversation has been closed */
BonjourBuddy *bb = NULL;
- const gchar *name = bconv->pb ? purple_buddy_get_name(bconv->pb) : "(unknown)";
+ const gchar *name = "(unknown)";
+
+ if(PURPLE_IS_CONTACT(bconv->contact)) {
+ PurpleContactInfo *info = PURPLE_CONTACT_INFO(bconv->contact);
+
+ name = purple_contact_info_get_username(info);
+ bb = g_object_get_data(G_OBJECT(bconv->contact), "bonjour-buddy");
+ }
purple_debug_info("bonjour", "Received conversation close notification from %s.\n", name);
- if(bconv->pb != NULL)
- bb = purple_buddy_get_protocol_data(bconv->pb);
-
/* Close the socket, clear the watcher and free memory */
bonjour_xmpp_close_conversation(bconv);
- if(bb)
+ if(bb != NULL) {
bb->conversation = NULL;
+ }
}
static gboolean
@@ -425,11 +431,14 @@
len, error ? error->message : "(null)");
bonjour_xmpp_close_conversation(bconv);
- if (bconv->pb != NULL) {
- BonjourBuddy *bb = purple_buddy_get_protocol_data(bconv->pb);
+ if(PURPLE_IS_CONTACT(bconv->contact)) {
+ BonjourBuddy *bb = NULL;
- if(bb != NULL)
+ bb = g_object_get_data(G_OBJECT(bconv->contact),
+ "bonjour-buddy");
+ if(bb != NULL) {
bb->conversation = NULL;
+ }
}
/* I guess we really don't need to notify the user.
@@ -438,7 +447,8 @@
g_clear_error(&error);
return FALSE;
} else if (len == 0) { /* The other end has closed the socket */
- const gchar *name = purple_buddy_get_name(bconv->pb);
+ const gchar *name = NULL;
+ name = purple_contact_info_get_username(PURPLE_CONTACT_INFO(bconv->contact));
purple_debug_warning("bonjour", "Connection closed (without stream end) by %s.\n", (name) ? name : "(unknown)");
bonjour_xmpp_stream_ended(bconv);
return FALSE;
@@ -483,9 +493,9 @@
manager = purple_conversation_manager_get_default();
- if(bconv->pb) {
- bb = purple_buddy_get_protocol_data(bconv->pb);
- bname = purple_buddy_get_name(bconv->pb);
+ if(PURPLE_IS_CONTACT(bconv->contact)) {
+ bb = g_object_get_data(G_OBJECT(bconv->contact), "bonjour-buddy");
+ bname = purple_contact_info_get_username(PURPLE_CONTACT_INFO(bconv->contact));
}
purple_debug_error(
@@ -541,8 +551,9 @@
g_return_val_if_fail(error != NULL, FALSE);
- if (bconv->pb != NULL)
- bname = purple_buddy_get_name(bconv->pb);
+ if(PURPLE_IS_CONTACT(bconv->contact)) {
+ bname = purple_contact_info_get_username(PURPLE_CONTACT_INFO(bconv->contact));
+ }
/* If we have no idea who "to" is, use an empty string.
* If we don't know now, it is because the other side isn't playing nice, so they can't complain. */
@@ -568,7 +579,7 @@
(*bname) ? bname : "(unknown)", bconv->ip,
*error ? (*error)->message : "(null)");
- if (bconv->pb) {
+ if(PURPLE_IS_CONTACT(bconv->contact)) {
PurpleConversation *conv;
PurpleConversationManager *manager;
@@ -628,8 +639,9 @@
!bonjour_xmpp_send_stream_init(bconv, &error)) {
const char *bname = bconv->buddy_name;
- if (bconv->pb)
- bname = purple_buddy_get_name(bconv->pb);
+ if(PURPLE_IS_CONTACT(bconv->contact)) {
+ bname = purple_contact_info_get_username(PURPLE_CONTACT_INFO(bconv->contact));
+ }
purple_debug_error(
"bonjour",
@@ -637,7 +649,7 @@
bname ? bname : "(unknown)", bconv->ip,
error ? error->message : "(null)");
- if (bconv->pb) {
+ if(PURPLE_IS_CONTACT(bconv->contact)) {
PurpleConversation *conv;
PurpleConversationManager *manager;
@@ -670,18 +682,22 @@
/* If the stream has been completely started and we know who we're talking to, we can start doing stuff. */
/* I don't think the circ_buffer can actually contain anything without a buddy being associated, but lets be explicit. */
- if (bconv->sent_stream_start == FULLY_SENT && bconv->recv_stream_start
- && bconv->pb && purple_circular_buffer_get_max_read(bconv->tx_buf) > 0) {
+ if(bconv->sent_stream_start == FULLY_SENT && bconv->recv_stream_start &&
+ PURPLE_IS_CONTACT(bconv->contact) &&
+ purple_circular_buffer_get_max_read(bconv->tx_buf) > 0)
+ {
/* Watch for when we can write the buffered messages */
GSource *source = g_pollable_output_stream_create_source(
G_POLLABLE_OUTPUT_STREAM(bconv->output),
bconv->cancellable);
g_source_set_callback(source, G_SOURCE_FUNC(_send_data_write_cb),
- bconv->pb, NULL);
+ g_object_ref(bconv->contact), g_object_unref);
bconv->tx_handler = g_source_attach(source, NULL);
g_source_unref(source);
/* We can probably write the data right now. */
- _send_data_write_cb(G_OBJECT(bconv->output), bconv->pb);
+ g_object_ref(bconv->contact);
+ _send_data_write_cb(G_OBJECT(bconv->output), bconv->contact);
+ g_object_unref(bconv->contact);
}
}
@@ -699,7 +715,7 @@
GInetAddress *their_inet_addr;
gchar *address_text;
BonjourXMPPConversation *bconv;
- GSList *buddies;
+ GSList *contacts;
GSource *source;
their_addr = g_socket_connection_get_remote_address(connection, NULL);
@@ -725,14 +741,14 @@
purple_debug_info("bonjour", "Received incoming connection from %s.\n", address_text);
- buddies = _find_match_buddies_by_address(jdata, address_text);
- if (buddies == NULL) {
+ contacts = _find_match_buddies_by_address(jdata, address_text);
+ if (contacts == NULL) {
purple_debug_info("bonjour", "We don't like invisible buddies, this is not a superheroes comic\n");
g_free(address_text);
return;
}
- g_slist_free(buddies);
+ g_slist_free(contacts);
/* We've established that this *could* be from one of our buddies.
* Wait for the stream open to see if that matches too before assigning it.
@@ -795,17 +811,21 @@
static void
_connected_to_buddy(GObject *source, GAsyncResult *res, gpointer user_data)
{
- PurpleBuddy *pb = user_data;
- BonjourBuddy *bb = purple_buddy_get_protocol_data(pb);
+ BonjourBuddy *bb = NULL;
+ PurpleAccount *account = NULL;
+ PurpleContact *contact = user_data;
GSocketConnection *conn;
GSource *rx_source;
GError *error = NULL;
+ const char *username = NULL;
+ bb = g_object_get_data(G_OBJECT(contact), "bonjour-buddy");
conn = g_socket_client_connect_to_host_finish(G_SOCKET_CLIENT(source),
res, &error);
+ username = purple_contact_info_get_username(PURPLE_CONTACT_INFO(contact));
+ account = purple_contact_get_account(contact);
if (conn == NULL) {
- PurpleAccount *account = NULL;
PurpleConversation *conv = NULL;
PurpleConversationManager *manager = NULL;
GSList *tmp;
@@ -813,13 +833,15 @@
if (error && error->code == G_IO_ERROR_CANCELLED) {
/* This conversation was closed before it started. */
g_error_free(error);
+ g_clear_object(&contact);
+
return;
}
purple_debug_error("bonjour",
"Error connecting to buddy %s at %s:%d "
"(%s); Trying next IP address",
- purple_buddy_get_name(pb),
+ username,
bb->conversation->ip, bb->port_p2pj,
error ? error->message : "(unknown)");
g_clear_error(&error);
@@ -832,8 +854,6 @@
if (tmp)
tmp = g_slist_next(tmp);
- account = purple_buddy_get_account(pb);
-
if (tmp != NULL) {
const gchar *ip;
GSocketClient *client;
@@ -841,23 +861,26 @@
bb->conversation->ip_link = ip = tmp->data;
purple_debug_info("bonjour", "Starting conversation with %s at %s:%d\n",
- purple_buddy_get_name(pb), ip, bb->port_p2pj);
+ username, ip, bb->port_p2pj);
/* Make sure to connect without a proxy. */
client = g_socket_client_new();
if (client != NULL) {
g_free(bb->conversation->ip);
bb->conversation->ip = g_strdup(ip);
+ /* We pass our reference on contact to the callback. */
g_socket_client_connect_to_host_async(
client, ip, bb->port_p2pj,
bb->conversation->cancellable,
- _connected_to_buddy, pb);
+ _connected_to_buddy, contact);
g_object_unref(client);
return;
}
}
- purple_debug_error("bonjour", "No more addresses for buddy %s. Aborting", purple_buddy_get_name(pb));
+ purple_debug_error("bonjour",
+ "No more addresses for buddy %s. Aborting",
+ username);
manager = purple_conversation_manager_get_default();
@@ -870,6 +893,9 @@
bonjour_xmpp_close_conversation(bb->conversation);
bb->conversation = NULL;
+
+ g_clear_object(&contact);
+
return;
}
@@ -880,19 +906,16 @@
g_object_ref(g_io_stream_get_output_stream(G_IO_STREAM(conn)));
if (!bonjour_xmpp_send_stream_init(bb->conversation, &error)) {
- PurpleAccount *account = NULL;
PurpleConversation *conv = NULL;
PurpleConversationManager *manager = NULL;
purple_debug_error("bonjour",
"Error starting stream with buddy %s at "
"%s:%d error: %s",
- purple_buddy_get_name(pb),
+ username,
bb->conversation->ip, bb->port_p2pj,
error ? error->message : "(null)");
- account = purple_buddy_get_account(pb);
-
manager = purple_conversation_manager_get_default();
conv = purple_conversation_manager_find_im(manager, account, bb->name);
@@ -905,6 +928,8 @@
bonjour_xmpp_close_conversation(bb->conversation);
bb->conversation = NULL;
g_clear_error(&error);
+ g_clear_object(&contact);
+
return;
}
@@ -916,20 +941,31 @@
bb->conversation, NULL);
bb->conversation->rx_handler = g_source_attach(rx_source, NULL);
g_source_unref(rx_source);
+ g_clear_object(&contact);
}
void
bonjour_xmpp_conv_match_by_name(BonjourXMPPConversation *bconv) {
- PurpleBuddy *pb = NULL;
BonjourBuddy *bb = NULL;
+ PurpleContact *contact = NULL;
+ PurpleContactManager *manager = NULL;
g_return_if_fail(bconv->ip != NULL);
- g_return_if_fail(bconv->pb == NULL);
+ g_return_if_fail(!PURPLE_IS_CONTACT(bconv->contact));
+
+ manager = purple_contact_manager_get_default();
+ contact = purple_contact_manager_find_with_username(manager,
+ bconv->account,
+ bconv->buddy_name);
- pb = purple_blist_find_buddy(bconv->account, bconv->buddy_name);
- if (pb && (bb = purple_buddy_get_protocol_data(pb))) {
- purple_debug_info("bonjour", "Found buddy %s for incoming conversation \"from\" attrib.\n",
- purple_buddy_get_name(pb));
+ if(contact && (bb = g_object_get_data(G_OBJECT(contact), "bonjour-buddy"))) {
+ const char *username = NULL;
+
+ username = purple_contact_info_get_username(PURPLE_CONTACT_INFO(contact));
+
+ purple_debug_info("bonjour",
+ "Found buddy %s for incoming conversation \"from\" attrib.\n",
+ username);
/* Check that one of the buddy's IPs matches */
if (g_slist_find_custom(bb->ips, bconv->ip, (GCompareFunc)g_ascii_strcasecmp)) {
@@ -938,7 +974,7 @@
BonjourXMPP *jdata = bd->xmpp_data;
purple_debug_info("bonjour", "Matched buddy %s to incoming conversation \"from\" attrib and IP (%s)",
- purple_buddy_get_name(pb), bconv->ip);
+ username, bconv->ip);
/* Attach conv. to buddy and remove from pending list */
jdata->pending_conversations = g_slist_remove(jdata->pending_conversations, bconv);
@@ -948,18 +984,20 @@
bonjour_xmpp_close_conversation(bb->conversation);
}
- bconv->pb = pb;
+ bconv->contact = contact;
bb->conversation = bconv;
}
}
/* We've failed to match a buddy - give up */
- if (bconv->pb == NULL) {
+ if(!PURPLE_IS_CONTACT(bconv->contact)) {
/* This must be asynchronous because it destroys the parser and we
* may be in the middle of parsing.
*/
async_bonjour_xmpp_close_conversation(bconv);
}
+
+ g_clear_object(&contact);
}
@@ -968,21 +1006,22 @@
PurpleConnection *pc = purple_account_get_connection(bconv->account);
BonjourData *bd = purple_connection_get_protocol_data(pc);
BonjourXMPP *jdata = bd->xmpp_data;
- GSList *buddies;
+ GSList *contacts;
- buddies = _find_match_buddies_by_address(jdata, bconv->ip);
+ contacts = _find_match_buddies_by_address(jdata, bconv->ip);
/* If there is exactly one match, use it */
- if (!buddies) {
+ if (!contacts) {
purple_debug_error("bonjour", "No buddies matched for ip %s.", bconv->ip);
- } else if (buddies->next != NULL) {
+ } else if (contacts->next != NULL) {
purple_debug_error("bonjour", "More than one buddy matched for ip %s.", bconv->ip);
} else {
- PurpleBuddy *pb = buddies->data;
- BonjourBuddy *bb = purple_buddy_get_protocol_data(pb);
+ PurpleContact *contact = contacts->data;
+ BonjourBuddy *bb = g_object_get_data(G_OBJECT(contact), "bonjour-buddy");
purple_debug_info("bonjour", "Matched buddy %s to incoming conversation using IP (%s)",
- purple_buddy_get_name(pb), bconv->ip);
+ purple_contact_info_get_username(PURPLE_CONTACT_INFO(contact)),
+ bconv->ip);
/* Attach conv. to buddy and remove from pending list */
jdata->pending_conversations = g_slist_remove(jdata->pending_conversations, bconv);
@@ -992,34 +1031,44 @@
bonjour_xmpp_close_conversation(bb->conversation);
}
- bconv->pb = pb;
+ bconv->contact = contact;
bb->conversation = bconv;
}
/* We've failed to match a buddy - give up */
- if (bconv->pb == NULL) {
+ if(!PURPLE_IS_CONTACT(bconv->contact)) {
/* This must be asynchronous because it destroys the parser and we
* may be in the middle of parsing.
*/
async_bonjour_xmpp_close_conversation(bconv);
}
- g_slist_free(buddies);
+ g_slist_free(contacts);
}
-static PurpleBuddy *
+static PurpleContact *
_find_or_start_conversation(BonjourXMPP *jdata, const gchar *to)
{
- PurpleBuddy *pb = NULL;
+ PurpleContact *contact = NULL;
+ PurpleContactManager *manager = NULL;
BonjourBuddy *bb = NULL;
g_return_val_if_fail(jdata != NULL, NULL);
g_return_val_if_fail(to != NULL, NULL);
- pb = purple_blist_find_buddy(jdata->account, to);
- if (pb == NULL || (bb = purple_buddy_get_protocol_data(pb)) == NULL)
- /* You can not send a message to an offline buddy */
+ manager = purple_contact_manager_get_default();
+ contact = purple_contact_manager_find_with_username(manager,
+ jdata->account, to);
+
+ if(!PURPLE_IS_CONTACT(contact)) {
return NULL;
+ }
+
+ bb = g_object_get_data(G_OBJECT(contact), "bonjour-buddy");
+ if(bb == NULL) {
+ g_clear_object(&contact);
+ return NULL;
+ }
/* Check if there is a previously open conversation */
if (bb->conversation == NULL) {
@@ -1037,18 +1086,20 @@
purple_debug_error("bonjour",
"Unable to connect to buddy (%s).",
to);
+ g_clear_object(&contact);
return NULL;
}
- bb->conversation = bonjour_xmpp_conv_new(pb, jdata->account, ip);
+ bb->conversation = bonjour_xmpp_conv_new(contact, jdata->account, ip);
bb->conversation->ip_link = ip;
g_socket_client_connect_to_host_async(
client, ip, bb->port_p2pj,
- bb->conversation->cancellable, _connected_to_buddy, pb);
+ bb->conversation->cancellable, _connected_to_buddy,
+ g_object_ref(contact));
g_object_unref(client);
}
- return pb;
+ return contact;
}
int
@@ -1056,13 +1107,16 @@
{
PurpleXmlNode *message_node, *node, *node2;
gchar *message, *xhtml;
- PurpleBuddy *pb;
+ PurpleContact *contact = NULL;
BonjourBuddy *bb;
int ret;
- pb = _find_or_start_conversation(jdata, to);
- if (pb == NULL || (bb = purple_buddy_get_protocol_data(pb)) == NULL) {
+ contact = _find_or_start_conversation(jdata, to);
+ if(!PURPLE_IS_CONTACT(contact) ||
+ (bb = g_object_get_data(G_OBJECT(contact), "bonjour-buddy")) == NULL)
+ {
purple_debug_info("bonjour", "Can't send a message to an offline buddy (%s).\n", to);
+ g_clear_object(&contact);
/* You can not send a message to an offline buddy */
return -10000;
}
@@ -1096,10 +1150,12 @@
message = purple_xmlnode_to_str(message_node, NULL);
purple_xmlnode_free(message_node);
- ret = _send_data(pb, message) >= 0;
+ ret = _send_data(contact, message) >= 0;
g_free(message);
+ g_clear_object(&contact);
+
return ret;
}
@@ -1119,8 +1175,8 @@
jdata->pending_conversations = g_slist_remove(jdata->pending_conversations, bconv);
/* Disconnect this conv. from the buddy here so it can't be disposed of twice.*/
- if(bconv->pb != NULL) {
- BonjourBuddy *bb = purple_buddy_get_protocol_data(bconv->pb);
+ if(PURPLE_IS_CONTACT(bconv->contact)) {
+ BonjourBuddy *bb = g_object_get_data(G_OBJECT(bconv->contact), "bonjour-buddy");
if (bb->conversation == bconv)
bb->conversation = NULL;
}
@@ -1149,17 +1205,24 @@
/* Cancel any file transfers that are waiting to begin */
/* There won't be any transfers if it hasn't been attached to a buddy */
- if (bconv->pb != NULL && bd != NULL) {
+ if (PURPLE_IS_CONTACT(bconv->contact) && bd != NULL) {
GSList *xfers, *tmp_next;
+ const char *username = NULL;
+
xfers = bd->xfer_lists;
+ username = purple_contact_info_get_username(PURPLE_CONTACT_INFO(bconv->contact));
+
while (xfers != NULL) {
PurpleXfer *xfer = xfers->data;
+
tmp_next = xfers->next;
+
/* We only need to cancel this if it hasn't actually started transferring. */
/* This will change if we ever support IBB transfers. */
- if (purple_strequal(purple_xfer_get_remote_user(xfer), purple_buddy_get_name(bconv->pb))
+ if (purple_strequal(purple_xfer_get_remote_user(xfer), username)
&& (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_NOT_STARTED
- || purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_UNKNOWN)) {
+ || purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_UNKNOWN))
+ {
purple_xfer_cancel_remote(xfer);
}
xfers = tmp_next;
@@ -1229,20 +1292,26 @@
/* Close all the conversation sockets and remove all the watchers after sending end streams */
if (!purple_account_is_disconnected(jdata->account)) {
- GSList *buddies, *l;
+ PurpleContactManager *manager = NULL;
+ GListModel *model = NULL;
+
+ manager = purple_contact_manager_get_default();
+ model = purple_contact_manager_get_all(manager, jdata->account);
- buddies = purple_blist_find_buddies(jdata->account, NULL);
- for (l = buddies; l; l = l->next) {
- BonjourBuddy *bb = purple_buddy_get_protocol_data((PurpleBuddy*) l->data);
- if (bb && bb->conversation) {
+ for(guint i = 0; i < g_list_model_get_n_items(model); i++) {
+ PurpleContact *contact = g_list_model_get_item(model, i);
+ BonjourBuddy *bb = g_object_get_data(G_OBJECT(contact),
+ "bonjour-buddy");
+
+ if(bb != NULL && bb->conversation != NULL) {
/* Any ongoing connection attempt is cancelled
* when a connection is destroyed */
bonjour_xmpp_close_conversation(bb->conversation);
bb->conversation = NULL;
}
+
+ g_clear_object(&contact);
}
-
- g_slist_free(buddies);
}
g_slist_free_full(jdata->pending_conversations, (GDestroyNotify)bonjour_xmpp_close_conversation);
@@ -1292,34 +1361,37 @@
}
static void
-xep_iq_parse(PurpleXmlNode *packet, PurpleBuddy *pb)
-{
+xep_iq_parse(PurpleXmlNode *packet, PurpleContact *contact) {
PurpleAccount *account;
PurpleConnection *gc;
- account = purple_buddy_get_account(pb);
+ account = purple_contact_get_account(contact);
gc = purple_account_get_connection(account);
- if (purple_xmlnode_get_child(packet, "si") != NULL || purple_xmlnode_get_child(packet, "error") != NULL)
- xep_si_parse(gc, packet, pb);
- else
- xep_bytestreams_parse(gc, packet, pb);
+ if(purple_xmlnode_get_child(packet, "si") != NULL ||
+ purple_xmlnode_get_child(packet, "error") != NULL)
+ {
+ xep_si_parse(gc, packet, contact);
+ } else {
+ xep_bytestreams_parse(gc, packet, contact);
+ }
}
int
xep_iq_send_and_free(XepIq *iq)
{
int ret = -1;
- PurpleBuddy *pb = NULL;
+ PurpleContact *contact = NULL;
/* start the talk, reuse the message socket */
- pb = _find_or_start_conversation((BonjourXMPP*) iq->data, iq->to);
+ contact = _find_or_start_conversation((BonjourXMPP*) iq->data, iq->to);
/* Send the message */
- if (pb != NULL) {
+ if(PURPLE_IS_CONTACT(contact)) {
/* Convert xml node into stream */
gchar *msg = purple_xmlnode_to_str(iq->node, NULL);
- ret = _send_data(pb, msg);
+ ret = _send_data(contact, msg);
g_free(msg);
+ g_clear_object(&contact);
}
purple_xmlnode_free(iq->node);
--- a/libpurple/protocols/bonjour/xmpp.h Tue May 23 00:21:15 2023 -0500
+++ b/libpurple/protocols/bonjour/xmpp.h Tue May 23 00:23:33 2023 -0500
@@ -53,7 +53,7 @@
gpointer stream_data;
xmlParserCtxt *context;
PurpleXmlNode *current;
- PurpleBuddy *pb;
+ PurpleContact *contact;
PurpleAccount *account;
/* The following are only needed before attaching to a PurpleBuddy */
@@ -79,7 +79,7 @@
void bonjour_xmpp_stream_started(BonjourXMPPConversation *bconv);
-void bonjour_xmpp_process_packet(PurpleBuddy *pb, PurpleXmlNode *packet);
+void bonjour_xmpp_process_packet(PurpleContact *contact, PurpleXmlNode *packet);
void bonjour_xmpp_stop(BonjourXMPP *data);