Mercurial > pidgin.yaz
changeset 18803:abb9aac69507
merge of '7ee71f1a32c4a5d7001c0049f2c7ec1e6cb54fa3'
and 'c896d38533c1a23a6748a75257104e1f501999e5'
author | Ka-Hing Cheung <khc@hxbc.us> |
---|---|
date | Sun, 05 Aug 2007 19:42:29 +0000 |
parents | 42161f9233bf (current diff) 355f24d20501 (diff) |
children | b839f427cbb2 1244b5f43661 b9a0b1bd321b |
files | libpurple/protocols/bonjour/mdns_howl.h libpurple/protocols/bonjour/mdns_win32.h pidgin/gtkconv.c |
diffstat | 14 files changed, 449 insertions(+), 375 deletions(-) [+] |
line wrap: on
line diff
--- a/libpurple/plugins/log_reader.c Sun Aug 05 19:41:08 2007 +0000 +++ b/libpurple/plugins/log_reader.c Sun Aug 05 19:42:29 2007 +0000 @@ -60,14 +60,14 @@ char *path; GDir *dir; - g_return_val_if_fail(sn != NULL, list); - g_return_val_if_fail(account != NULL, list); + g_return_val_if_fail(sn != NULL, NULL); + g_return_val_if_fail(account != NULL, NULL); logdir = purple_prefs_get_string("/plugins/core/log_reader/adium/log_directory"); /* By clearing the log directory path, this logger can be (effectively) disabled. */ - if (!*logdir) - return list; + if (!logdir || !*logdir) + return NULL; plugin = purple_find_prpl(purple_account_get_protocol_id(account)); if (!plugin) @@ -236,8 +236,8 @@ /* XXX: TODO: We probably want to set PURPLE_LOG_READ_NO_NEWLINE * XXX: TODO: for HTML logs. */ - if (flags != NULL) - *flags = 0; + if (flags != NULL) + *flags = 0; g_return_val_if_fail(log != NULL, g_strdup("")); @@ -626,17 +626,17 @@ const char *old_session_id = ""; struct msn_logger_data *data = NULL; - g_return_val_if_fail(sn != NULL, list); - g_return_val_if_fail(account != NULL, list); + g_return_val_if_fail(sn != NULL, NULL); + g_return_val_if_fail(account != NULL, NULL); if (strcmp(account->protocol_id, "prpl-msn")) - return list; + return NULL; logdir = purple_prefs_get_string("/plugins/core/log_reader/msn/log_directory"); /* By clearing the log directory path, this logger can be (effectively) disabled. */ - if (!*logdir) - return list; + if (!logdir || !*logdir) + return NULL; buddy = purple_find_buddy(account, sn); @@ -1121,7 +1121,7 @@ if (name_guessed != NAME_GUESS_UNKNOWN) text = g_string_append(text, "</span>"); - style = xmlnode_get_attrib(text_node, "Style"); + style = xmlnode_get_attrib(text_node, "Style"); tmp = xmlnode_get_data(text_node); if (style && *style) { @@ -1211,14 +1211,14 @@ gchar *line; gchar *c; - g_return_val_if_fail(sn != NULL, list); - g_return_val_if_fail(account != NULL, list); + g_return_val_if_fail(sn != NULL, NULL); + g_return_val_if_fail(account != NULL, NULL); logdir = purple_prefs_get_string("/plugins/core/log_reader/trillian/log_directory"); /* By clearing the log directory path, this logger can be (effectively) disabled. */ - if (!*logdir) - return list; + if (!logdir || !*logdir) + return NULL; plugin = purple_find_prpl(purple_account_get_protocol_id(account)); if (!plugin) @@ -1429,8 +1429,8 @@ char *c; const char *line; - if (flags != NULL) - *flags = PURPLE_LOG_READ_NO_NEWLINE; + if (flags != NULL) + *flags = PURPLE_LOG_READ_NO_NEWLINE; g_return_val_if_fail(log != NULL, g_strdup("")); @@ -1776,18 +1776,18 @@ int offset = 0; GError *error; - g_return_val_if_fail(sn != NULL, list); - g_return_val_if_fail(account != NULL, list); + g_return_val_if_fail(sn != NULL, NULL); + g_return_val_if_fail(account != NULL, NULL); /* QIP only supports ICQ. */ if (strcmp(account->protocol_id, "prpl-icq")) - return list; + return NULL; logdir = purple_prefs_get_string("/plugins/core/log_reader/qip/log_directory"); /* By clearing the log directory path, this logger can be (effectively) disabled. */ - if (!*logdir) - return list; + if (!logdir || !*logdir) + return NULL; plugin = purple_find_prpl(purple_account_get_protocol_id(account)); if (!plugin) @@ -1927,8 +1927,8 @@ char *utf8_string; FILE *file; - if (flags != NULL) - *flags = PURPLE_LOG_READ_NO_NEWLINE; + if (flags != NULL) + *flags = PURPLE_LOG_READ_NO_NEWLINE; g_return_val_if_fail(log != NULL, g_strdup(""));
--- a/libpurple/protocols/bonjour/Makefile.am Sun Aug 05 19:41:08 2007 +0000 +++ b/libpurple/protocols/bonjour/Makefile.am Sun Aug 05 19:42:29 2007 +0000 @@ -1,6 +1,5 @@ EXTRA_DIST = \ mdns_win32.c \ - mdns_win32.h \ Makefile.mingw pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION) @@ -16,7 +15,7 @@ mdns_common.c \ mdns_common.h \ mdns_howl.c \ - mdns_howl.h \ + mdns_interface.h \ mdns_types.h \ parser.c \ parser.h
--- a/libpurple/protocols/bonjour/buddy.c Sun Aug 05 19:41:08 2007 +0000 +++ b/libpurple/protocols/bonjour/buddy.c Sun Aug 05 19:42:29 2007 +0000 @@ -22,6 +22,7 @@ #include "account.h" #include "blist.h" #include "bonjour.h" +#include "mdns_interface.h" #include "debug.h" /** @@ -35,6 +36,8 @@ buddy->account = account; buddy->name = g_strdup(name); + _mdns_init_buddy(buddy); + return buddy; } @@ -102,8 +105,9 @@ { PurpleBuddy *buddy; PurpleGroup *group; - const char *status_id, *first, *last; - gchar *alias; + PurpleAccount *account = bonjour_buddy->account; + const char *status_id, *first, *last, *old_hash, *new_hash; + gchar *alias = NULL; /* Translate between the Bonjour status and the Purple status */ if (g_ascii_strcasecmp("dnd", bonjour_buddy->status) == 0) @@ -116,44 +120,55 @@ * field from the DNS SD. */ - /* Create the alias for the buddy using the first and the last name */ - first = bonjour_buddy->first; - last = bonjour_buddy->last; - alias = g_strdup_printf("%s%s%s", - (first && *first ? first : ""), - (first && *first && last && *last ? " " : ""), - (last && *last ? last : "")); - /* Make sure the Bonjour group exists in our buddy list */ group = purple_find_group(BONJOUR_GROUP_NAME); /* Use the buddy's domain, instead? */ - if (group == NULL) - { + if (group == NULL) { group = purple_group_new(BONJOUR_GROUP_NAME); purple_blist_add_group(group, NULL); } /* Make sure the buddy exists in our buddy list */ - buddy = purple_find_buddy(bonjour_buddy->account, bonjour_buddy->name); + buddy = purple_find_buddy(account, bonjour_buddy->name); - if (buddy == NULL) - { - buddy = purple_buddy_new(bonjour_buddy->account, bonjour_buddy->name, alias); + if (buddy == NULL) { + buddy = purple_buddy_new(account, bonjour_buddy->name, NULL); buddy->proto_data = bonjour_buddy; purple_blist_node_set_flags((PurpleBlistNode *)buddy, PURPLE_BLIST_NODE_FLAG_NO_SAVE); purple_blist_add_buddy(buddy, NULL, group, NULL); } + /* Create the alias for the buddy using the first and the last name */ + 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 : "")); + serv_got_alias(purple_account_get_connection(account), buddy->name, alias); + g_free(alias); + /* Set the user's status */ if (bonjour_buddy->msg != NULL) - purple_prpl_got_user_status(bonjour_buddy->account, buddy->name, status_id, - "message", bonjour_buddy->msg, - NULL); + purple_prpl_got_user_status(account, buddy->name, status_id, + "message", bonjour_buddy->msg, NULL); else - purple_prpl_got_user_status(bonjour_buddy->account, buddy->name, status_id, - NULL); - purple_prpl_got_user_idle(bonjour_buddy->account, buddy->name, FALSE, 0); + purple_prpl_got_user_status(account, buddy->name, status_id, NULL); + + purple_prpl_got_user_idle(account, buddy->name, FALSE, 0); + + /* 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. */ - g_free(alias); + /* 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; + if (new_hash && (!old_hash || strcmp(old_hash, new_hash) != 0)) { + /* Look up the new icon data */ + bonjour_dns_sd_retrieve_buddy_icon(bonjour_buddy); + } else + purple_buddy_icons_set_for_user(account, buddy->name, NULL, 0, NULL); } /** @@ -164,6 +179,7 @@ { g_free(buddy->name); g_free(buddy->ip); + g_free(buddy->full_service_name); g_free(buddy->first); g_free(buddy->phsh); @@ -182,13 +198,8 @@ bonjour_jabber_close_conversation(buddy->conversation); buddy->conversation = NULL; -#ifdef USE_BONJOUR_APPLE - if (buddy->txt_query != NULL) - { - purple_input_remove(buddy->txt_query_fd); - DNSServiceRefDeallocate(buddy->txt_query); - } -#endif + /* Clean up any mdns implementation data */ + _mdns_delete_buddy(buddy); g_free(buddy); }
--- a/libpurple/protocols/bonjour/buddy.h Sun Aug 05 19:41:08 2007 +0000 +++ b/libpurple/protocols/bonjour/buddy.h Sun Aug 05 19:42:29 2007 +0000 @@ -19,22 +19,17 @@ #include <glib.h> -#include "config.h" #include "account.h" #include "jabber.h" -#ifdef USE_BONJOUR_APPLE -#include "dns_sd_proxy.h" -#else /* USE_BONJOUR_HOWL */ -#include <howl.h> -#endif - typedef struct _BonjourBuddy { PurpleAccount *account; gchar *name; + /* TODO: Remove and just use the hostname */ gchar *ip; + gchar *full_service_name; gint port_p2pj; gchar *first; @@ -53,11 +48,7 @@ BonjourJabberConversation *conversation; -#ifdef USE_BONJOUR_APPLE - DNSServiceRef txt_query; - int txt_query_fd; -#endif - + gpointer mdns_impl_data; } BonjourBuddy; static const char *const buddy_TXT_records[] = {
--- a/libpurple/protocols/bonjour/mdns_common.c Sun Aug 05 19:41:08 2007 +0000 +++ b/libpurple/protocols/bonjour/mdns_common.c Sun Aug 05 19:42:29 2007 +0000 @@ -17,8 +17,8 @@ #include <string.h> #include "internal.h" -#include "config.h" #include "mdns_common.h" +#include "mdns_interface.h" #include "bonjour.h" #include "buddy.h" #include "debug.h" @@ -73,65 +73,28 @@ gboolean bonjour_dns_sd_start(BonjourDnsSd *data) { - PurpleAccount *account; PurpleConnection *gc; - gint dns_sd_socket; - gpointer opaque_data; -#ifdef USE_BONJOUR_HOWL - sw_discovery_oid session_id; -#endif - - account = data->account; - gc = purple_account_get_connection(account); + gc = purple_account_get_connection(data->account); /* Initialize the dns-sd data and session */ -#ifndef USE_BONJOUR_APPLE - if (sw_discovery_init(&data->session) != SW_OKAY) - { - purple_debug_error("bonjour", "Unable to initialize an mDNS session.\n"); - - /* In Avahi, sw_discovery_init frees data->session but doesn't clear it */ - data->session = NULL; - + if (!_mdns_init_session(data)) return FALSE; - } -#endif /* Publish our bonjour IM client at the mDNS daemon */ - - if (0 != _mdns_publish(data, PUBLISH_START)) - { + if (!_mdns_publish(data, PUBLISH_START)) return FALSE; - } /* Advise the daemon that we are waiting for connections */ - -#ifdef USE_BONJOUR_APPLE - if (DNSServiceBrowse(&data->browser, 0, 0, ICHAT_SERVICE, NULL, _mdns_service_browse_callback, account) - != kDNSServiceErr_NoError) -#else /* USE_BONJOUR_HOWL */ - if (sw_discovery_browse(data->session, 0, ICHAT_SERVICE, NULL, _browser_reply, - account, &session_id) != SW_OKAY) -#endif - { + if (!_mdns_browse(data)) { purple_debug_error("bonjour", "Unable to get service."); return FALSE; } + /* Get the socket that communicates with the mDNS daemon and bind it to a */ /* callback that will handle the dns_sd packets */ - -#ifdef USE_BONJOUR_APPLE - dns_sd_socket = DNSServiceRefSockFD(data->browser); - opaque_data = data->browser; -#else /* USE_BONJOUR_HOWL */ - dns_sd_socket = sw_discovery_socket(data->session); - opaque_data = data->session; -#endif - - gc->inpa = purple_input_add(dns_sd_socket, PURPLE_INPUT_READ, - _mdns_handle_event, opaque_data); + gc->inpa = _mdns_register_to_mainloop(data); return TRUE; } @@ -143,34 +106,10 @@ void bonjour_dns_sd_stop(BonjourDnsSd *data) { - PurpleAccount *account; PurpleConnection *gc; -#ifdef USE_BONJOUR_APPLE - if (data->advertisement == NULL || data->browser == NULL) -#else /* USE_BONJOUR_HOWL */ - if (data->session == NULL) -#endif - return; + _mdns_stop(data); -#ifdef USE_BONJOUR_HOWL - sw_discovery_cancel(data->session, data->session_id); -#endif - - account = data->account; - gc = purple_account_get_connection(account); + gc = purple_account_get_connection(data->account); purple_input_remove(gc->inpa); - -#ifdef USE_BONJOUR_APPLE - /* hack: for win32, we need to stop listening to the advertisement pipe too */ - purple_input_remove(data->advertisement_handler); - - DNSServiceRefDeallocate(data->advertisement); - DNSServiceRefDeallocate(data->browser); - data->advertisement = NULL; - data->browser = NULL; -#else /* USE_BONJOUR_HOWL */ - g_free(data->session); - data->session = NULL; -#endif }
--- a/libpurple/protocols/bonjour/mdns_common.h Sun Aug 05 19:41:08 2007 +0000 +++ b/libpurple/protocols/bonjour/mdns_common.h Sun Aug 05 19:42:29 2007 +0000 @@ -19,11 +19,7 @@ #include "mdns_types.h" -#ifdef USE_BONJOUR_APPLE -#include "mdns_win32.h" -#elif defined USE_BONJOUR_HOWL -#include "mdns_howl.h" -#endif +#include "buddy.h" /** * Allocate space for the dns-sd data. @@ -41,6 +37,11 @@ void bonjour_dns_sd_send_status(BonjourDnsSd *data, const char *status, const char *status_message); /** + * Retrieve the buddy icon blob + */ +void bonjour_dns_sd_retrieve_buddy_icon(BonjourBuddy* buddy); + +/** * Advertise our presence within the dns-sd daemon and start * browsing for other bonjour peers. */
--- a/libpurple/protocols/bonjour/mdns_howl.c Sun Aug 05 19:41:08 2007 +0000 +++ b/libpurple/protocols/bonjour/mdns_howl.c Sun Aug 05 19:42:29 2007 +0000 @@ -15,12 +15,20 @@ */ #include "internal.h" -#include "mdns_howl.h" +#include "mdns_interface.h" #include "debug.h" #include "buddy.h" -sw_result HOWL_API +#include <howl.h> + +/* data used by howl bonjour implementation */ +typedef struct _howl_impl_data { + sw_discovery session; + sw_discovery_oid session_id; +} HowlSessionImplData; + +static sw_result HOWL_API _publish_reply(sw_discovery discovery, sw_discovery_oid oid, sw_discovery_publish_status status, sw_opaque extra) { @@ -46,7 +54,7 @@ return SW_OKAY; } -sw_result HOWL_API +static sw_result HOWL_API _resolve_reply(sw_discovery discovery, sw_discovery_oid oid, sw_uint32 interface_index, sw_const_string name, sw_const_string type, sw_const_string domain, @@ -95,7 +103,7 @@ return SW_OKAY; } -sw_result HOWL_API +static sw_result HOWL_API _browser_reply(sw_discovery discovery, sw_discovery_oid oid, sw_discovery_browse_status status, sw_uint32 interface_index, sw_const_string name, @@ -154,19 +162,49 @@ return SW_OKAY; } -int -_mdns_publish(BonjourDnsSd *data, PublishType type) +static void +_mdns_handle_event(gpointer data, gint source, PurpleInputCondition condition) { + sw_discovery_read_socket((sw_discovery)data); +} + +/**************************** + * mdns_interface functions * + ****************************/ + +gboolean _mdns_init_session(BonjourDnsSd *data) { + HowlSessionImplData *idata = g_new0(HowlSessionImplData, 1); + + if (sw_discovery_init(&idata->session) != SW_OKAY) { + purple_debug_error("bonjour", "Unable to initialize an mDNS session.\n"); + + /* In Avahi, sw_discovery_init frees data->session but doesn't clear it */ + idata->session = NULL; + + g_free(idata); + + return FALSE; + } + + data->mdns_impl_data = idata; + + return TRUE; +} + + +gboolean _mdns_publish(BonjourDnsSd *data, PublishType type) { sw_text_record dns_data; sw_result publish_result = SW_OKAY; char portstring[6]; const char *jid, *aim, *email; + HowlSessionImplData *idata = data->mdns_impl_data; + + g_return_val_if_fail(idata != NULL, FALSE); /* Fill the data for the service */ - if (sw_text_record_init(&dns_data) != SW_OKAY) - { + if (sw_text_record_init(&dns_data) != SW_OKAY) { purple_debug_error("bonjour", "Unable to initialize the data for the mDNS.\n"); - return -1; + return FALSE; } /* Convert the port to a string */ @@ -208,32 +246,70 @@ /* TODO: ext, nick, node */ /* Publish the service */ - switch (type) - { + switch (type) { case PUBLISH_START: - publish_result = sw_discovery_publish(data->session, 0, purple_account_get_username(data->account), ICHAT_SERVICE, NULL, + publish_result = sw_discovery_publish(idata->session, 0, purple_account_get_username(data->account), ICHAT_SERVICE, NULL, NULL, data->port_p2pj, sw_text_record_bytes(dns_data), sw_text_record_len(dns_data), - _publish_reply, NULL, &data->session_id); + _publish_reply, NULL, &idata->session_id); break; case PUBLISH_UPDATE: - publish_result = sw_discovery_publish_update(data->session, data->session_id, + publish_result = sw_discovery_publish_update(idata->session, idata->session_id, sw_text_record_bytes(dns_data), sw_text_record_len(dns_data)); break; } - if (publish_result != SW_OKAY) - { + + if (publish_result != SW_OKAY) { purple_debug_error("bonjour", "Unable to publish or change the status of the _presence._tcp service.\n"); - return -1; + return FALSE; } /* Free the memory used by temp data */ sw_text_record_fina(dns_data); - return 0; + return TRUE; +} + +gboolean _mdns_browse(BonjourDnsSd *data) { + HowlSessionImplData *idata = data->mdns_impl_data; + /* TODO: don't we need to hang onto this to cancel later? */ + sw_discovery_oid session_id; + + g_return_val_if_fail(idata != NULL, FALSE); + + return (sw_discovery_browse(idata->session, 0, ICHAT_SERVICE, NULL, _browser_reply, + data->account, &session_id) == SW_OKAY); +} + +guint _mdns_register_to_mainloop(BonjourDnsSd *data) { + HowlSessionImplData *idata = data->mdns_impl_data; + + g_return_val_if_fail(idata != NULL, FALSE); + + return purple_input_add(sw_discovery_socket(idata->session), + PURPLE_INPUT_READ, _mdns_handle_event, idata->session); } -void -_mdns_handle_event(gpointer data, gint source, PurpleInputCondition condition) -{ - sw_discovery_read_socket((sw_discovery)data); +void _mdns_stop(BonjourDnsSd *data) { + HowlSessionImplData *idata = data->mdns_impl_data; + + if (idata == NULL || idata->session == NULL) + return; + + sw_discovery_cancel(idata->session, idata->session_id); + + /* TODO: should this really be g_free()'d ??? */ + g_free(idata->session); + + g_free(idata); + + data->mdns_impl_data = NULL; } + +void _mdns_init_buddy(BonjourBuddy *buddy) { +} + +void _mdns_delete_buddy(BonjourBuddy *buddy) { +} + +void bonjour_dns_sd_retrieve_buddy_icon(BonjourBuddy* buddy) { +}
--- a/libpurple/protocols/bonjour/mdns_howl.h Sun Aug 05 19:41:08 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef _BONJOUR_MDNS_HOWL -#define _BONJOUR_MDNS_HOWL - -#include "config.h" - -#ifdef USE_BONJOUR_HOWL - -#include <howl.h> -#include <glib.h> -#include "mdns_types.h" - -/* callback functions */ - -sw_result HOWL_API _publish_reply(sw_discovery discovery, sw_discovery_oid oid, sw_discovery_publish_status status, sw_opaque extra); - -sw_result HOWL_API _resolve_reply(sw_discovery discovery, sw_discovery_oid oid, sw_uint32 interface_index, sw_const_string name, - sw_const_string type, sw_const_string domain, sw_ipv4_address address, sw_port port, sw_octets text_record, - sw_ulong text_record_len, sw_opaque extra); - -sw_result HOWL_API _browser_reply(sw_discovery discovery, sw_discovery_oid oid, sw_discovery_browse_status status, - sw_uint32 interface_index, sw_const_string name, sw_const_string type, sw_const_string domain, sw_opaque_t extra); - - -/* interface functions */ - -int _mdns_publish(BonjourDnsSd *data, PublishType type); -void _mdns_handle_event(gpointer data, gint source, PurpleInputCondition condition); - -#endif - -#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/protocols/bonjour/mdns_interface.h Sun Aug 05 19:42:29 2007 +0000 @@ -0,0 +1,40 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _BONJOUR_MDNS_INTERFACE +#define _BONJOUR_MDNS_INTERFACE + +#include "mdns_types.h" +#include "buddy.h" + +gboolean _mdns_init_session(BonjourDnsSd *data); + +gboolean _mdns_publish(BonjourDnsSd *data, PublishType type); + +gboolean _mdns_browse(BonjourDnsSd *data); + +guint _mdns_register_to_mainloop(BonjourDnsSd *data); + +void _mdns_stop(BonjourDnsSd *data); + +void _mdns_init_buddy(BonjourBuddy *buddy); + +void _mdns_delete_buddy(BonjourBuddy *buddy); + +/* This doesn't quite belong here, but there really isn't any shared functionality */ +void bonjour_dns_sd_retrieve_buddy_icon(BonjourBuddy* buddy); + +#endif
--- a/libpurple/protocols/bonjour/mdns_types.h Sun Aug 05 19:41:08 2007 +0000 +++ b/libpurple/protocols/bonjour/mdns_types.h Sun Aug 05 19:42:29 2007 +0000 @@ -19,31 +19,14 @@ #include <glib.h> #include "account.h" -#include "config.h" - -#ifdef USE_BONJOUR_APPLE -#include "dns_sd_proxy.h" -#else /* USE_BONJOUR_HOWL */ -#include <howl.h> -#endif #define ICHAT_SERVICE "_presence._tcp." /** * Data to be used by the dns-sd connection. */ -typedef struct _BonjourDnsSd -{ -#ifdef USE_BONJOUR_APPLE - DNSServiceRef advertisement; - DNSServiceRef browser; - - int advertisement_handler; /* hack... windows bonjour is broken, so we have to have this */ -#else /* USE_BONJOUR_HOWL */ - sw_discovery session; - sw_discovery_oid session_id; -#endif - +typedef struct _BonjourDnsSd { + gpointer mdns_impl_data; PurpleAccount *account; gchar *first; gchar *last; @@ -59,5 +42,4 @@ PUBLISH_UPDATE } PublishType; - #endif
--- a/libpurple/protocols/bonjour/mdns_win32.c Sun Aug 05 19:41:08 2007 +0000 +++ b/libpurple/protocols/bonjour/mdns_win32.c Sun Aug 05 19:42:29 2007 +0000 @@ -15,22 +15,44 @@ */ #include "internal.h" -#include "mdns_win32.h" +#include "debug.h" -#include "debug.h" +#include "buddy.h" +#include "mdns_interface.h" +#include "dns_sd_proxy.h" +#include "dnsquery.h" + /* data structure for the resolve callback */ -typedef struct _ResolveCallbackArgs -{ +typedef struct _ResolveCallbackArgs { DNSServiceRef resolver; - int resolver_fd; + guint resolver_handler; PurpleDnsQueryData *query; - gchar *fqn; BonjourBuddy* buddy; } ResolveCallbackArgs; +/* data used by win32 bonjour implementation */ +typedef struct _win32_session_impl_data { + DNSServiceRef advertisement; + DNSServiceRef browser; + + guint advertisement_handler; /* hack... windows bonjour is broken, so we have to have this */ +} Win32SessionImplData; + +typedef struct _win32_buddy_impl_data { + DNSServiceRef txt_query; + guint txt_query_handler; + DNSServiceRef null_query; + guint null_query_handler; +} Win32BuddyImplData; + +static void +_mdns_handle_event(gpointer data, gint source, PurpleInputCondition condition) { + DNSServiceProcessResult((DNSServiceRef) data); +} + static void _mdns_parse_text_record(BonjourBuddy* buddy, const char* record, uint16_t record_len) { @@ -51,13 +73,32 @@ uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, const void *rdata, uint32_t ttl, void *context) { + if (kDNSServiceErr_NoError != errorCode) - purple_debug_error("bonjour", "text record query - callback error.\n"); + purple_debug_error("bonjour", "record query - callback error.\n"); else if (flags & kDNSServiceFlagsAdd) { - BonjourBuddy *buddy = (BonjourBuddy*)context; - _mdns_parse_text_record(buddy, rdata, rdlen); - bonjour_buddy_add_to_purple(buddy); + if (rrtype == kDNSServiceType_TXT) { + /* New Buddy */ + BonjourBuddy *buddy = (BonjourBuddy*) context; + _mdns_parse_text_record(buddy, rdata, rdlen); + bonjour_buddy_add_to_purple(buddy); + } else if (rrtype == kDNSServiceType_NULL) { + /* Buddy Icon response */ + BonjourBuddy *buddy = (BonjourBuddy*) context; + Win32BuddyImplData *idata = buddy->mdns_impl_data; + + g_return_if_fail(idata != NULL); + + purple_buddy_icons_set_for_user(buddy->account, buddy->name, + g_memdup(rdata, rdlen), rdlen, buddy->phsh); + + /* We've got what we need; stop listening */ + purple_input_remove(idata->null_query_handler); + idata->null_query_handler = -1; + DNSServiceRefDeallocate(idata->null_query); + idata->null_query = NULL; + } } } @@ -68,26 +109,26 @@ if (!hosts || !hosts->data) purple_debug_error("bonjour", "host resolution - callback error.\n"); - else - { + else { struct sockaddr_in *addr = (struct sockaddr_in*)g_slist_nth_data(hosts, 1); BonjourBuddy* buddy = args->buddy; + Win32BuddyImplData *idata = buddy->mdns_impl_data; + + g_return_if_fail(idata != NULL); buddy->ip = g_strdup(inet_ntoa(addr->sin_addr)); /* finally, set up the continuous txt record watcher, and add the buddy to purple */ - if (kDNSServiceErr_NoError == DNSServiceQueryRecord(&buddy->txt_query, 0, 0, args->fqn, - kDNSServiceType_TXT, kDNSServiceClass_IN, _mdns_text_record_query_callback, buddy)) - { - gint fd = DNSServiceRefSockFD(buddy->txt_query); - buddy->txt_query_fd = purple_input_add(fd, PURPLE_INPUT_READ, _mdns_handle_event, buddy->txt_query); + if (kDNSServiceErr_NoError == DNSServiceQueryRecord(&idata->txt_query, 0, 0, buddy->full_service_name, + kDNSServiceType_TXT, kDNSServiceClass_IN, _mdns_text_record_query_callback, buddy)) { + int fd = DNSServiceRefSockFD(idata->txt_query); + idata->txt_query_handler = purple_input_add(fd, PURPLE_INPUT_READ, _mdns_handle_event, idata->txt_query); bonjour_buddy_add_to_purple(buddy); purple_debug_info("bonjour", "Found buddy %s at %s:%d\n", buddy->name, buddy->ip, buddy->port_p2pj); - } - else + } else bonjour_buddy_delete(buddy); } @@ -97,7 +138,6 @@ /* free the remaining args memory */ purple_dnsquery_destroy(args->query); - g_free(args->fqn); g_free(args); } @@ -108,7 +148,7 @@ ResolveCallbackArgs *args = (ResolveCallbackArgs*)context; /* remove the input fd and destroy the service ref */ - purple_input_remove(args->resolver_fd); + purple_input_remove(args->resolver_handler); DNSServiceRefDeallocate(args->resolver); if (kDNSServiceErr_NoError != errorCode) @@ -125,14 +165,13 @@ _mdns_parse_text_record(args->buddy, txtRecord, txtLen); /* set more arguments, and start the host resolver */ - args->fqn = g_strdup(fullname); + args->buddy->full_service_name = g_strdup(fullname); if (!(args->query = purple_dnsquery_a(hosttarget, port, _mdns_resolve_host_callback, args))) { purple_debug_error("bonjour", "service resolver - host resolution failed.\n"); bonjour_buddy_delete(args->buddy); - g_free(args->fqn); g_free(args); } } @@ -150,7 +189,7 @@ purple_debug_info("bonjour", "service advertisement - callback.\n"); } -void DNSSD_API +static void DNSSD_API _mdns_service_browse_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context) { @@ -159,50 +198,52 @@ if (kDNSServiceErr_NoError != errorCode) purple_debug_error("bonjour", "service browser - callback error"); - else if (flags & kDNSServiceFlagsAdd) - { + else if (flags & kDNSServiceFlagsAdd) { /* A presence service instance has been discovered... check it isn't us! */ - if (g_ascii_strcasecmp(serviceName, account->username) != 0) - { + if (g_ascii_strcasecmp(serviceName, account->username) != 0) { /* OK, lets go ahead and resolve it to add to the buddy list */ ResolveCallbackArgs *args = g_new0(ResolveCallbackArgs, 1); args->buddy = bonjour_buddy_new(serviceName, account); - if (kDNSServiceErr_NoError != DNSServiceResolve(&args->resolver, 0, 0, serviceName, regtype, replyDomain, _mdns_service_resolve_callback, args)) - { + if (kDNSServiceErr_NoError != DNSServiceResolve(&args->resolver, 0, 0, serviceName, regtype, replyDomain, _mdns_service_resolve_callback, args)) { bonjour_buddy_delete(args->buddy); g_free(args); purple_debug_error("bonjour", "service browser - failed to resolve service.\n"); - } - else - { + } else { /* get a file descriptor for this service ref, and add it to the input list */ - gint resolver_fd = DNSServiceRefSockFD(args->resolver); - args->resolver_fd = purple_input_add(resolver_fd, PURPLE_INPUT_READ, _mdns_handle_event, args->resolver); + gint fd = DNSServiceRefSockFD(args->resolver); + args->resolver_handler = purple_input_add(fd, PURPLE_INPUT_READ, _mdns_handle_event, args->resolver); } } - } - else - { + } else { /* A peer has sent a goodbye packet, remove them from the buddy list */ purple_debug_info("bonjour", "service browser - remove notification\n"); gb = purple_find_buddy(account, serviceName); - if (gb != NULL) - { + if (gb != NULL) { bonjour_buddy_delete(gb->proto_data); purple_blist_remove_buddy(gb); } } } -int -_mdns_publish(BonjourDnsSd *data, PublishType type) -{ +/**************************** + * mdns_interface functions * + ****************************/ + +gboolean _mdns_init_session(BonjourDnsSd *data) { + data->mdns_impl_data = g_new0(Win32SessionImplData, 1); + return TRUE; +} + +gboolean _mdns_publish(BonjourDnsSd *data, PublishType type) { TXTRecordRef dns_data; char portstring[6]; - int ret = 0; + gboolean ret = TRUE; const char *jid, *aim, *email; DNSServiceErrorType set_ret; + Win32SessionImplData *idata = data->mdns_impl_data; + + g_return_val_if_fail(idata != NULL, FALSE); TXTRecordCreate(&dns_data, 256, NULL); @@ -250,41 +291,34 @@ /* TODO: ext, nick, node */ - if (set_ret != kDNSServiceErr_NoError) - { + if (set_ret != kDNSServiceErr_NoError) { purple_debug_error("bonjour", "Unable to allocate memory for text record.\n"); - ret = -1; - } - else - { + ret = FALSE; + } else { DNSServiceErrorType err = kDNSServiceErr_NoError; /* OK, we're done constructing the text record, (re)publish the service */ - switch (type) - { + switch (type) { case PUBLISH_START: purple_debug_info("bonjour", "Registering service on port %d\n", data->port_p2pj); - err = DNSServiceRegister(&data->advertisement, 0, 0, purple_account_get_username(data->account), ICHAT_SERVICE, + err = DNSServiceRegister(&idata->advertisement, 0, 0, purple_account_get_username(data->account), ICHAT_SERVICE, NULL, NULL, htons(data->port_p2pj), TXTRecordGetLength(&dns_data), TXTRecordGetBytesPtr(&dns_data), _mdns_service_register_callback, NULL); break; case PUBLISH_UPDATE: - err = DNSServiceUpdateRecord(data->advertisement, NULL, 0, TXTRecordGetLength(&dns_data), TXTRecordGetBytesPtr(&dns_data), 0); + err = DNSServiceUpdateRecord(idata->advertisement, NULL, 0, TXTRecordGetLength(&dns_data), TXTRecordGetBytesPtr(&dns_data), 0); break; } - if (kDNSServiceErr_NoError != err) - { + if (err != kDNSServiceErr_NoError) { purple_debug_error("bonjour", "Failed to publish presence service.\n"); - ret = -1; - } - else if (PUBLISH_START == type) - { + ret = FALSE; + } else if (type == PUBLISH_START) { /* hack: Bonjour on windows is broken. We don't care about the callback but we have to listen anyway */ - gint advertisement_fd = DNSServiceRefSockFD(data->advertisement); - data->advertisement_handler = purple_input_add(advertisement_fd, PURPLE_INPUT_READ, _mdns_handle_event, data->advertisement); + gint fd = DNSServiceRefSockFD(idata->advertisement); + idata->advertisement_handler = purple_input_add(fd, PURPLE_INPUT_READ, _mdns_handle_event, idata->advertisement); } } @@ -293,8 +327,84 @@ return ret; } -void -_mdns_handle_event(gpointer data, gint source, PurpleInputCondition condition) -{ - DNSServiceProcessResult((DNSServiceRef)data); +gboolean _mdns_browse(BonjourDnsSd *data) { + Win32SessionImplData *idata = data->mdns_impl_data; + + g_return_val_if_fail(idata != NULL, FALSE); + + return (DNSServiceBrowse(&idata->browser, 0, 0, ICHAT_SERVICE, NULL, + _mdns_service_browse_callback, data->account) + == kDNSServiceErr_NoError); +} + +guint _mdns_register_to_mainloop(BonjourDnsSd *data) { + Win32SessionImplData *idata = data->mdns_impl_data; + + g_return_val_if_fail(idata != NULL, FALSE); + + return purple_input_add(DNSServiceRefSockFD(idata->browser), + PURPLE_INPUT_READ, _mdns_handle_event, idata->browser); +} + +void _mdns_stop(BonjourDnsSd *data) { + Win32SessionImplData *idata = data->mdns_impl_data; + + if (idata == NULL || idata->advertisement == NULL || idata->browser == NULL) + return; + + /* hack: for win32, we need to stop listening to the advertisement pipe too */ + purple_input_remove(idata->advertisement_handler); + + DNSServiceRefDeallocate(idata->advertisement); + DNSServiceRefDeallocate(idata->browser); + + g_free(idata); + + data->mdns_impl_data = NULL; +} + +void _mdns_init_buddy(BonjourBuddy *buddy) { + buddy->mdns_impl_data = g_new0(Win32BuddyImplData, 1); } + +void _mdns_delete_buddy(BonjourBuddy *buddy) { + Win32BuddyImplData *idata = buddy->mdns_impl_data; + + g_return_if_fail(idata != NULL); + + if (idata->txt_query != NULL) { + purple_input_remove(idata->txt_query_handler); + DNSServiceRefDeallocate(idata->txt_query); + } + + if (idata->null_query != NULL) { + purple_input_remove(idata->null_query_handler); + DNSServiceRefDeallocate(idata->null_query); + } + + g_free(idata); + + buddy->mdns_impl_data = NULL; +} + +void bonjour_dns_sd_retrieve_buddy_icon(BonjourBuddy* buddy) { + Win32BuddyImplData *idata = buddy->mdns_impl_data; + + g_return_if_fail(idata != NULL); + + /* Cancel any existing query */ + if (idata->null_query != NULL) { + purple_input_remove(idata->null_query_handler); + idata->null_query_handler = 0; + DNSServiceRefDeallocate(idata->null_query); + idata->null_query = NULL; + } + + if (kDNSServiceErr_NoError == DNSServiceQueryRecord(&idata->null_query, 0, 0, buddy->full_service_name, + kDNSServiceType_NULL, kDNSServiceClass_IN, _mdns_text_record_query_callback, buddy)) { + int fd = DNSServiceRefSockFD(idata->null_query); + idata->null_query_handler = purple_input_add(fd, PURPLE_INPUT_READ, _mdns_handle_event, idata->null_query); + } + +} +
--- a/libpurple/protocols/bonjour/mdns_win32.h Sun Aug 05 19:41:08 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef _BONJOUR_MDNS_WIN32 -#define _BONJOUR_MDNS_WIN32 - -#ifdef USE_BONJOUR_APPLE - -#include <glib.h> -#include "mdns_types.h" -#include "buddy.h" -#include "dnsquery.h" -#include "dns_sd_proxy.h" - -/* Bonjour async callbacks */ - -void DNSSD_API _mdns_service_browse_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, - DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context); - -/* interface functions */ - -int _mdns_publish(BonjourDnsSd *data, PublishType type); -void _mdns_handle_event(gpointer data, gint source, PurpleInputCondition condition); - -#endif - -#endif
--- a/pidgin/gtkconv.c Sun Aug 05 19:41:08 2007 +0000 +++ b/pidgin/gtkconv.c Sun Aug 05 19:42:29 2007 +0000 @@ -6256,13 +6256,15 @@ (fields & PIDGIN_CONV_SET_TITLE) || (fields & PIDGIN_CONV_TOPIC)) { - char *title; + char *title, *truncate = NULL, truncchar; PurpleConvIm *im = NULL; PurpleAccount *account = purple_conversation_get_account(conv); + PurpleBuddy *buddy = NULL; + PurplePresence *p = NULL; char *markup = NULL; AtkObject *accessibility_obj; /* I think this is a little longer than it needs to be but I'm lazy. */ - char style[51]; + char *style, *status_style; if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) im = PURPLE_CONV_IM(conv); @@ -6275,12 +6277,20 @@ else title = g_strdup(purple_conversation_get_title(conv)); + if ((truncate = strchr(title, ' ')) || + (truncate = strchr(title, '@'))) { + truncchar = *truncate; + *truncate = '\0'; + } + if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { - PurpleBuddy *buddy = purple_find_buddy(account, conv->name); - if (buddy) + buddy = purple_find_buddy(account, conv->name); + if (buddy) { + p = purple_buddy_get_presence(buddy); markup = pidgin_blist_get_name_markup(buddy, FALSE, FALSE); - else + } else { markup = title; + } } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { PurpleConvChat *chat = PURPLE_CONV_CHAT(conv); const char *topic = purple_conv_chat_get_topic(chat); @@ -6296,54 +6306,56 @@ if (title != markup) g_free(markup); - *style = '\0'; - if (!GTK_WIDGET_REALIZED(gtkconv->tab_label)) gtk_widget_realize(gtkconv->tab_label); accessibility_obj = gtk_widget_get_accessible(gtkconv->tab_cont); if (im != NULL && - purple_conv_im_get_typing_state(im) == PURPLE_TYPING) - { + purple_conv_im_get_typing_state(im) == PURPLE_TYPING) { atk_object_set_description(accessibility_obj, _("Typing")); - strncpy(style, "color=\"#4e9a06\"", sizeof(style)); - } - else if (im != NULL && - purple_conv_im_get_typing_state(im) == PURPLE_TYPED) - { + style = "color=\"#4e9a06\""; + } else if (im != NULL && + purple_conv_im_get_typing_state(im) == PURPLE_TYPED) { atk_object_set_description(accessibility_obj, _("Stopped Typing")); - strncpy(style, "color=\"#c4a000\"", sizeof(style)); - } - else if (gtkconv->unseen_state == PIDGIN_UNSEEN_NICK) - { + style = "color=\"#c4a000\""; + } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_NICK) { atk_object_set_description(accessibility_obj, _("Nick Said")); - strncpy(style, "color=\"#204a87\" style=\"italic\" weight=\"bold\"", sizeof(style)); - } - else if (gtkconv->unseen_state == PIDGIN_UNSEEN_TEXT) - { + style = "color=\"#204a87\" style=\"italic\" weight=\"bold\""; + } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_TEXT) { atk_object_set_description(accessibility_obj, _("Unread Messages")); - strncpy(style, "color=\"#cc0000\" weight=\"bold\"", sizeof(style)); + style = "color=\"#cc0000\" weight=\"bold\""; + } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_EVENT) { + atk_object_set_description(accessibility_obj, _("New Event")); + style = "color=\"#888a85\" style=\"italic\""; + } else { + style = ""; } - else if (gtkconv->unseen_state == PIDGIN_UNSEEN_EVENT) - { - atk_object_set_description(accessibility_obj, _("New Event")); - strncpy(style, "color=\"#888a85\" style=\"italic\"", sizeof(style)); + + if (p && purple_presence_is_status_primitive_active(p, PURPLE_STATUS_OFFLINE)) { + status_style = "strikethrough='true'"; + } else if (p && !purple_presence_is_status_primitive_active(p, PURPLE_STATUS_AVAILABLE) && + !purple_presence_is_status_primitive_active(p, PURPLE_STATUS_INVISIBLE)) { + status_style = "style='italic'"; + } else { + status_style = ""; } - if (*style != '\0') + if (*style != '\0' || *status_style != '\0') { char *html_title,*label; html_title = g_markup_escape_text(title, -1); - - label = g_strdup_printf("<span %s>%s</span>", - style, html_title); + label = g_strdup_printf("<span %s %s>%s</span>", + style, status_style, html_title); g_free(html_title); gtk_label_set_markup(GTK_LABEL(gtkconv->tab_label), label); g_free(label); } else gtk_label_set_text(GTK_LABEL(gtkconv->tab_label), title); + + if (truncate) + *truncate = truncchar; if (pidgin_conv_window_is_active_conversation(conv)) update_typing_icon(gtkconv); @@ -8606,6 +8618,7 @@ gtk_misc_set_alignment(GTK_MISC(gtkconv->menu_label), 0, 0); gtk_widget_show(gtkconv->menu_tabby); + gtk_widget_set_size_request(gtkconv->menu_tabby, 0, -1); if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) pidgin_conv_update_buddy_icon(conv); @@ -8722,7 +8735,7 @@ TRUE, GTK_PACK_START); /* show the widgets */ - gtk_widget_show(gtkconv->icon); +/* gtk_widget_show(gtkconv->icon); */ gtk_widget_show(gtkconv->tab_label); if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/close_on_tabs")) gtk_widget_show(gtkconv->close);
--- a/pidgin/gtkimhtmltoolbar.c Sun Aug 05 19:41:08 2007 +0000 +++ b/pidgin/gtkimhtmltoolbar.c Sun Aug 05 19:42:29 2007 +0000 @@ -1109,7 +1109,6 @@ GtkWidget *font_menu; GtkWidget *insert_menu; GtkWidget *menuitem; - GtkWidget *button; GtkWidget *sep; int i; struct { @@ -1126,10 +1125,10 @@ #endif {_("_Smaller"), &toolbar->smaller_size, TRUE}, {_("_Font face"), &toolbar->font, TRUE}, - {_("_Foreground color"), &toolbar->fgcolor, TRUE}, - {_("_Background color"), &toolbar->bgcolor, TRUE}, + {_("Foreground _color"), &toolbar->fgcolor, TRUE}, + {_("Bac_kground color"), &toolbar->bgcolor, TRUE}, {_("_Reset formatting"), &toolbar->clear, FALSE}, - {NULL, NULL} + {NULL, NULL, FALSE} };