--- 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 @@
PurpleXmlNode *streamhost;
+ PurpleContact *contact; G_DEFINE_DYNAMIC_TYPE(XepXfer, xep_xfer, PURPLE_TYPE_XFER);
@@ -360,7 +360,8 @@
bonjour_xfer_init(PurpleXfer *xfer)
+ PurpleContact *contact = NULL; + PurpleContactManager *manager = NULL; @@ -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); /* Assume it is the first IP. We could do something like keep track of which one is in use or something. */
@@ -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); -xep_si_parse(PurpleConnection *pc, PurpleXmlNode *packet, PurpleBuddy *pb)
+xep_si_parse(PurpleConnection *pc, PurpleXmlNode *packet, + PurpleContact *contact) @@ -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);
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 @@
add_ipv6_link_local_ifaces(PurpleXmlNode *cur_streamhost, const char *host,
+ PurpleContact *contact) PurpleXmlNode *new_streamhost = NULL;
@@ -592,7 +606,7 @@
- bb = purple_buddy_get_protocol_data(pb);
+ bb = g_object_get_data(G_OBJECT(contact), "bonjour-buddy"); (ip_elem = g_slist_find_custom(ip_elem, host, (GCompareFunc)&xep_addr_differ));
@@ -611,8 +625,8 @@
-__xep_bytestreams_parse(PurpleBuddy *pb, PurpleXfer *xfer, PurpleXmlNode *streamhost,
+__xep_bytestreams_parse(PurpleContact *contact, PurpleXfer *xfer, + PurpleXmlNode *streamhost, const char *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)) tmp_iq_id = g_strdup(iq_id);
@@ -643,7 +657,7 @@
xf->proxy_host = g_strdup(host);
xf->proxy_port = portnum;
xf->streamhost = streamhost;
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 @@
-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);
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");
@@ -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)) 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); xep_ft_si_reject(xf->data, xf->iq_id, purple_xfer_get_remote_user(xfer),
@@ -1046,7 +1062,7 @@
GInetSocketAddress *inet_addr;
GSocketAddress *proxy_addr;
+ PurpleContact *contact = NULL; @@ -1089,9 +1105,10 @@
- hash_input = g_strdup_printf("%s%s%s", xf->sid, purple_buddy_get_name(pb),
- bonjour_get_jid(purple_buddy_get_account(pb)));
+ 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);
@@ -1128,7 +1145,7 @@
purple_debug_info("bonjour", "bonjour-bytestreams-connect.");
- 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/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 @@
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, + 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.",
@@ -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); purple_debug_error("bonjour", "Unable to set up record watcher for buddy %s (%d)\n", args->bb->name, errorCode);
@@ -251,10 +256,11 @@
/* If this was the last resolver, remove the buddy */
if (idata->resolvers == NULL) {
- bonjour_buddy_signed_off(pb);
+ if (PURPLE_IS_CONTACT(contact)) { + bonjour_buddy_signed_off(contact); 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_clear_object(&contact); @@ -319,15 +327,24 @@
/* If this was the last resolver, remove the buddy */
if (idata->resolvers == NULL) {
- /* 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);
+ PurpleContact *contact = NULL; + PurpleContactManager *manager = NULL; + manager = purple_contact_manager_get_default(); + contact = purple_contact_manager_find_with_username(manager, + /* See if this is now attached to a PurpleContact */ + if(PURPLE_IS_CONTACT(contact)) { + bonjour_buddy_signed_off(contact); /* Remove from the pending list */
pending_buddies = g_slist_remove(pending_buddies, args->bb);
bonjour_buddy_delete(args->bb);
+ g_clear_object(&contact); @@ -432,19 +449,23 @@
- PurpleBuddy *pb = NULL;
+ PurpleContact *contact = NULL; + PurpleContactManager *manager = NULL; + manager = purple_contact_manager_get_default(); + contact = purple_contact_manager_find_with_username(manager, account, /* 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(PURPLE_IS_CONTACT(contact)) { /* 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",
- bonjour_buddy_signed_off(pb);
+ bonjour_buddy_signed_off(contact); - 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/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 @@
-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, BonjourXMPPConversation *bconv = g_new0(BonjourXMPPConversation, 1);
bconv->cancellable = g_cancellable_new();
bconv->tx_buf = purple_circular_buffer_new(512);
+ bconv->contact = contact; bconv->account = account;
bconv->ip = g_strdup(ip);
@@ -111,11 +113,17 @@
-_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; + 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)); -struct _match_buddies_by_address {
- GSList *matched_buddies;
-_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 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);
_find_match_buddies_by_address(const BonjourXMPP *jdata, const char *address)
- struct _match_buddies_by_address mbba = {
- .matched_buddies = NULL
- GSList *buddies = purple_blist_find_buddies(jdata->account, NULL);
+ PurpleContactManager *manager = NULL; + GListModel *contacts = 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);
+ contact = g_list_model_get_item(contacts, i); + bb = g_object_get_data(G_OBJECT(contact), "bonjour-buddy"); + 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); _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; + bb = g_object_get_data(G_OBJECT(contact), "bonjour-buddy"); + bconv = bb->conversation; writelen = purple_circular_buffer_get_max_read(bconv->tx_buf);
@@ -276,10 +276,10 @@
"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);
@@ -291,6 +291,7 @@
bonjour_xmpp_close_conversation(bb->conversation);
@@ -298,9 +299,9 @@
-_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);
@@ -333,10 +334,10 @@
"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);
@@ -361,7 +362,7 @@
g_source_set_callback(source,
G_SOURCE_FUNC(_send_data_write_cb),
+ g_object_ref(contact), g_object_unref); bconv->tx_handler = g_source_attach(source, NULL);
@@ -371,36 +372,41 @@
-void bonjour_xmpp_process_packet(PurpleBuddy *pb, PurpleXmlNode *packet) {
+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);
+ 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); purple_debug_warning("bonjour", "Unknown packet: %s\n",
packet->name ? packet->name : "(null)");
-static void bonjour_xmpp_stream_ended(BonjourXMPPConversation *bconv) {
+bonjour_xmpp_stream_ended(BonjourXMPPConversation *bconv) { /* Inform the user that the conversation has been closed */
- 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);
- bb = purple_buddy_get_protocol_data(bconv->pb);
/* Close the socket, clear the watcher and free memory */
bonjour_xmpp_close_conversation(bconv);
@@ -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;
+ bb = g_object_get_data(G_OBJECT(bconv->contact), /* I guess we really don't need to notify the user.
@@ -438,7 +447,8 @@
} 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);
@@ -483,9 +493,9 @@
manager = purple_conversation_manager_get_default();
- 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)); @@ -541,8 +551,9 @@
g_return_val_if_fail(error != NULL, FALSE);
- 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(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;
- bname = purple_buddy_get_name(bconv->pb);
+ if(PURPLE_IS_CONTACT(bconv->contact)) { + bname = purple_contact_info_get_username(PURPLE_CONTACT_INFO(bconv->contact)); @@ -637,7 +649,7 @@
bname ? bname : "(unknown)", bconv->ip,
error ? error->message : "(null)");
+ 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),
g_source_set_callback(source, G_SOURCE_FUNC(_send_data_write_cb),
+ g_object_ref(bconv->contact), g_object_unref); bconv->tx_handler = g_source_attach(source, NULL);
/* 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;
BonjourXMPPConversation *bconv;
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);
+ 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_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 @@
_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; + 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),
+ username = purple_contact_info_get_username(PURPLE_CONTACT_INFO(contact)); + account = purple_contact_get_account(contact); - PurpleAccount *account = NULL;
PurpleConversation *conv = NULL;
PurpleConversationManager *manager = NULL;
@@ -813,13 +833,15 @@
if (error && error->code == G_IO_ERROR_CANCELLED) {
/* This conversation was closed before it started. */
+ g_clear_object(&contact); purple_debug_error("bonjour",
"Error connecting to buddy %s at %s:%d "
"(%s); Trying next IP address",
- purple_buddy_get_name(pb),
bb->conversation->ip, bb->port_p2pj,
error ? error->message : "(unknown)");
@@ -832,8 +854,6 @@
- account = purple_buddy_get_account(pb);
@@ -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();
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); - 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", manager = purple_conversation_manager_get_default();
@@ -870,6 +893,9 @@
bonjour_xmpp_close_conversation(bb->conversation);
+ g_clear_object(&contact); @@ -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 "
- purple_buddy_get_name(pb),
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);
+ g_clear_object(&contact); @@ -916,20 +941,31 @@
bb->conversation->rx_handler = g_source_attach(rx_source, NULL);
g_source_unref(rx_source);
+ g_clear_object(&contact); bonjour_xmpp_conv_match_by_name(BonjourXMPPConversation *bconv) {
- PurpleBuddy *pb = 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, - 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", /* 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);
/* 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->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;
- 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 */
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);
- 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)), /* 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->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(contacts);
_find_or_start_conversation(BonjourXMPP *jdata, const gchar *to)
- PurpleBuddy *pb = NULL;
+ PurpleContact *contact = NULL; + PurpleContactManager *manager = 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, + if(!PURPLE_IS_CONTACT(contact)) { + bb = g_object_get_data(G_OBJECT(contact), "bonjour-buddy"); + g_clear_object(&contact); /* 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).",
+ g_clear_object(&contact); - 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));
@@ -1056,13 +1107,16 @@
PurpleXmlNode *message_node, *node, *node2;
+ PurpleContact *contact = NULL; - 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 */
@@ -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_clear_object(&contact); @@ -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)
@@ -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; + username = purple_contact_info_get_username(PURPLE_CONTACT_INFO(bconv->contact)); PurpleXfer *xfer = xfers->data;
/* 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);
@@ -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)) {
+ 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), + if(bb != NULL && bb->conversation != NULL) { /* Any ongoing connection attempt is cancelled
* when a connection is destroyed */
bonjour_xmpp_close_conversation(bb->conversation);
+ g_clear_object(&contact);
g_slist_free_full(jdata->pending_conversations, (GDestroyNotify)bonjour_xmpp_close_conversation);
@@ -1292,34 +1361,37 @@
-xep_iq_parse(PurpleXmlNode *packet, PurpleBuddy *pb)
+xep_iq_parse(PurpleXmlNode *packet, PurpleContact *contact) { - 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);
- 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); + xep_bytestreams_parse(gc, packet, contact); xep_iq_send_and_free(XepIq *iq)
- 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);
+ 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_clear_object(&contact); purple_xmlnode_free(iq->node);