changeset 17733:d7b50cac1c7a

This is a patch from Chris Davies to make Bonjour work on Windows using the Apple Bonjour framework. It turns out that the actual DNS-SD library is (3 clause) BSD licensed, so we can use it. There are a few changes by me, mainly to fix the howl implementation. Fixes #1117 . There appear to be a few bugs, but I believe that they were also present previously. I'm hoping to do some more tweaking before the next release. The howl implementation will eventually be supersceded by a native avahi implementation, so I opted for a somewhat dirty hack to enable it instead of doing something with config.h.
author Daniel Atallah <daniel.atallah@gmail.com>
date Tue, 05 Jun 2007 03:38:22 +0000
parents 7e856734b712
children b87114cdd6ae
files COPYRIGHT libpurple/protocols/bonjour/Makefile.am libpurple/protocols/bonjour/Makefile.mingw libpurple/protocols/bonjour/bonjour.c libpurple/protocols/bonjour/bonjour.h libpurple/protocols/bonjour/buddy.c libpurple/protocols/bonjour/buddy.h libpurple/protocols/bonjour/dns_sd.c libpurple/protocols/bonjour/dns_sd.h libpurple/protocols/bonjour/dns_sd_proxy.h libpurple/protocols/bonjour/jabber.c libpurple/protocols/bonjour/mdns_common.c libpurple/protocols/bonjour/mdns_common.h libpurple/protocols/bonjour/mdns_howl.c libpurple/protocols/bonjour/mdns_howl.h libpurple/protocols/bonjour/mdns_types.h libpurple/protocols/bonjour/mdns_win32.c libpurple/protocols/bonjour/mdns_win32.h
diffstat 18 files changed, 1183 insertions(+), 526 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Tue Jun 05 03:13:02 2007 +0000
+++ b/COPYRIGHT	Tue Jun 05 03:38:22 2007 +0000
@@ -89,6 +89,7 @@
 Jeramey Crawford
 Michael Culbertson
 Steven Danna
+Chris Davies
 Martijn Dekker
 Vinicius Depizzol
 Philip Derrin
--- a/libpurple/protocols/bonjour/Makefile.am	Tue Jun 05 03:13:02 2007 +0000
+++ b/libpurple/protocols/bonjour/Makefile.am	Tue Jun 05 03:38:22 2007 +0000
@@ -1,4 +1,6 @@
 EXTRA_DIST = \
+		mdns_win32.c \
+		mdns_win32.h \
 		Makefile.mingw
 
 pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
@@ -8,12 +10,16 @@
 	bonjour.h \
 	buddy.c \
 	buddy.h \
-	dns_sd.c \
-	dns_sd.h \
+	dns_sd_proxy.h \
 	jabber.c \
-	jabber.h
+	jabber.h \
+	mdns_common.c \
+	mdns_common.h \
+	mdns_howl.c \
+	mdns_howl.h \
+	mdns_types.h
 
-AM_CFLAGS = $(st)
+AM_CFLAGS = $(st) -DUSE_BONJOUR_HOWL
 
 libbonjour_la_LDFLAGS = -module -avoid-version
 
--- a/libpurple/protocols/bonjour/Makefile.mingw	Tue Jun 05 03:13:02 2007 +0000
+++ b/libpurple/protocols/bonjour/Makefile.mingw	Tue Jun 05 03:38:22 2007 +0000
@@ -8,7 +8,6 @@
 include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
 
 TARGET = libbonjour
-NEEDED_DLLS = $(HOWL_TOP)/bin/libhowl-1.dll
 TYPE = PLUGIN
 
 # Static or Plugin...
@@ -24,17 +23,17 @@
 ##
 ## INCLUDE PATHS
 ##
-INCLUDE_PATHS +=	-I$(BONJOUR_ROOT) \
+INCLUDE_PATHS +=	-I. \
 			-I$(GTK_TOP)/include \
 			-I$(GTK_TOP)/include/glib-2.0 \
 			-I$(GTK_TOP)/lib/glib-2.0/include \
-			-I$(HOWL_TOP)/include \
+			-I$(BONJOUR_TOP)/include \
 			-I$(PURPLE_TOP) \
 			-I$(PURPLE_TOP)/win32 \
 			-I$(PIDGIN_TREE_TOP)
 
 LIB_PATHS +=		-L$(GTK_TOP)/lib \
-			-L$(HOWL_TOP)/lib \
+			-L$(BONJOUR_TOP)/lib \
 			-L$(PURPLE_TOP)
 
 ##
@@ -42,7 +41,8 @@
 ##
 C_SRC =			bonjour.c \
 			buddy.c \
-			dns_sd.c \
+			mdns_common.c \
+			mdns_win32.c \
 			jabber.c
 
 OBJECTS = $(C_SRC:%.c=%.o)
@@ -54,7 +54,7 @@
 			-lglib-2.0 \
 			-lws2_32 \
 			-lintl \
-			-lhowl \
+			-ldnssd \
 			-lpurple
 
 include $(PIDGIN_COMMON_RULES)
@@ -68,7 +68,6 @@
 
 install: all $(DLL_INSTALL_DIR)
 	cp $(TARGET).dll $(DLL_INSTALL_DIR)
-	cp $(NEEDED_DLLS) $(PURPLE_INSTALL_DIR)
 
 $(OBJECTS): $(PURPLE_CONFIG_H)
 
--- a/libpurple/protocols/bonjour/bonjour.c	Tue Jun 05 03:13:02 2007 +0000
+++ b/libpurple/protocols/bonjour/bonjour.c	Tue Jun 05 03:38:22 2007 +0000
@@ -37,7 +37,7 @@
 #include "version.h"
 
 #include "bonjour.h"
-#include "dns_sd.h"
+#include "mdns_common.h"
 #include "jabber.h"
 #include "buddy.h"
 
@@ -120,7 +120,7 @@
 
 	/* Connect to the mDNS daemon looking for buddies in the LAN */
 	bd->dns_sd_data = bonjour_dns_sd_new();
-	bd->dns_sd_data->name = (sw_string)purple_account_get_username(account);
+	bd->dns_sd_data->name = purple_account_get_username(account);
 	bd->dns_sd_data->txtvers = g_strdup("1");
 	bd->dns_sd_data->version = g_strdup("1");
 	bd->dns_sd_data->first = g_strdup(purple_account_get_string(account, "first", default_firstname));
@@ -491,8 +491,8 @@
 		LPUSER_INFO_10 user_info = NULL;
 		LPSERVER_INFO_100 server_info = NULL;
 		wchar_t *servername = NULL;
-		wchar_t username[UNLEN + 1] = {'\0'};
-		DWORD dwLenUsername = sizeof(username);
+		wchar_t username[UNLEN + 1];
+		DWORD dwLenUsername = UNLEN + 1;
 		FARPROC myNetServerEnum = wpurple_find_and_loadproc(
 			"Netapi32.dll", "NetServerEnum");
 		FARPROC myNetApiBufferFree = wpurple_find_and_loadproc(
@@ -517,7 +517,7 @@
 			}
 		}
 
-		if (!GetUserNameW(&username, &dwLenUsername)) {
+		if (!GetUserNameW((LPWSTR) &username, &dwLenUsername)) {
 			purple_debug_warning("bonjour",
 				"Unable to look up username\n");
 		}
@@ -553,7 +553,7 @@
 		 */
 		splitpoint = strchr(tmp, ',');
 		if (splitpoint != NULL)
-			default_lastname = g_strndup(tmp, splitpoint - tmp);			
+			default_lastname = g_strndup(tmp, splitpoint - tmp);
 		else
 			default_lastname = g_strdup(tmp);
 	}
--- a/libpurple/protocols/bonjour/bonjour.h	Tue Jun 05 03:13:02 2007 +0000
+++ b/libpurple/protocols/bonjour/bonjour.h	Tue Jun 05 03:38:22 2007 +0000
@@ -26,9 +26,7 @@
 #ifndef _BONJOUR_H_
 #define _BONJOUR_H_
 
-#include <howl.h>
-
-#include "dns_sd.h"
+#include "mdns_common.h"
 #include "internal.h"
 #include "jabber.h"
 
--- a/libpurple/protocols/bonjour/buddy.c	Tue Jun 05 03:13:02 2007 +0000
+++ b/libpurple/protocols/bonjour/buddy.c	Tue Jun 05 03:38:22 2007 +0000
@@ -27,49 +27,109 @@
  * Creates a new buddy.
  */
 BonjourBuddy *
-bonjour_buddy_new(const gchar *name, const gchar *first, gint port_p2pj,
-	const gchar *phsh, const gchar *status, const gchar *email,
-	const gchar *last, const gchar *jid, const gchar *AIM,
-	const gchar *vc, const gchar *ip, const gchar *msg)
+bonjour_buddy_new(const gchar *name, PurpleAccount* account)
 {
 	BonjourBuddy *buddy = malloc(sizeof(BonjourBuddy));
 
+	buddy->account = account;
 	buddy->name = g_strdup(name);
-	buddy->first = g_strdup(first);
-	buddy->port_p2pj = port_p2pj;
-	buddy->phsh = g_strdup(phsh);
-	buddy->status = g_strdup(status);
-	buddy->email = g_strdup(email);
-	buddy->last = g_strdup(last);
-	buddy->jid = g_strdup(jid);
-	buddy->AIM = g_strdup(AIM);
-	buddy->vc = g_strdup(vc);
-	buddy->ip = g_strdup(ip);
-	buddy->msg = g_strdup(msg);
+	buddy->first = NULL;
+	buddy->port_p2pj = 0;
+	buddy->phsh = NULL;
+	buddy->status = NULL;
+	buddy->email = NULL;
+	buddy->last = NULL;
+	buddy->jid = NULL;
+	buddy->AIM = NULL;
+	buddy->vc = NULL;
+	buddy->ip = NULL;
+	buddy->msg = NULL;
 	buddy->conversation = NULL;
+	
+#ifdef USE_BONJOUR_APPLE
+	buddy->txt_query = NULL;
+	buddy->txt_query_fd = 0;
+#endif
 
 	return buddy;
 }
 
+void 
+set_bonjour_buddy_value(BonjourBuddy* buddy, bonjour_buddy_member member, const char* value, uint32_t len)
+{
+	gchar **key = NULL;
+	switch (member)
+	{
+		case E_BUDDY_FIRST:
+			key = &buddy->first;
+			break;
+			
+		case E_BUDDY_LAST:
+			key = &buddy->last;
+			break;
+			
+		case E_BUDDY_STATUS:
+			key = &buddy->status;
+			break;
+			
+		case E_BUDDY_EMAIL:
+			key = &buddy->email;
+			break;
+			
+		case E_BUDDY_PHSH:
+			key = &buddy->phsh;
+			break;
+	
+		case E_BUDDY_JID:
+			key = &buddy->jid;
+			break;
+			
+		case E_BUDDY_AIM:
+			key = &buddy->AIM;
+			break;
+			
+		case E_BUDDY_VC:
+			key = &buddy->vc;
+			break;
+			
+		case E_BUDDY_MSG:
+			key = &buddy->msg;
+			break;
+	}
+	
+	g_free(*key);
+	*key = NULL;
+	*key = g_strndup(value, len);
+}
+
 /**
  * Check if all the compulsory buddy data is present.
  */
 gboolean
 bonjour_buddy_check(BonjourBuddy *buddy)
 {
-	if (buddy->name == NULL) {
+	if (buddy->account == NULL)
+	{
+		return FALSE;
+	}
+	
+	if (buddy->name == NULL)
+	{
+		return FALSE;
+	}
+	
+	if (buddy->first == NULL)
+	{
 		return FALSE;
 	}
 
-	if (buddy->first == NULL) {
+	if (buddy->last == NULL)
+	{
 		return FALSE;
 	}
 
-	if (buddy->last == NULL) {
-		return FALSE;
-	}
-
-	if (buddy->status == NULL) {
+	if (buddy->status == NULL)
+	{
 		return FALSE;
 	}
 
@@ -82,13 +142,13 @@
  * the buddy.
  */
 void
-bonjour_buddy_add_to_purple(PurpleAccount *account, BonjourBuddy *bonjour_buddy)
+bonjour_buddy_add_to_purple(BonjourBuddy *bonjour_buddy)
 {
 	PurpleBuddy *buddy;
 	PurpleGroup *group;
 	const char *status_id, *first, *last;
 	char *alias;
-
+	
 	/* Translate between the Bonjour status and the Purple status */
 	if (g_ascii_strcasecmp("dnd", bonjour_buddy->status) == 0)
 		status_id = BONJOUR_STATUS_ID_AWAY;
@@ -108,6 +168,7 @@
 							(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)
@@ -117,10 +178,11 @@
 	}
 
 	/* Make sure the buddy exists in our buddy list */
-	buddy = purple_find_buddy(account, bonjour_buddy->name);
+	buddy = purple_find_buddy(bonjour_buddy->account, bonjour_buddy->name);
+	
 	if (buddy == NULL)
 	{
-		buddy = purple_buddy_new(account, bonjour_buddy->name, alias);
+		buddy = purple_buddy_new(bonjour_buddy->account, bonjour_buddy->name, alias);
 		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);
@@ -128,13 +190,14 @@
 
 	/* Set the user's status */
 	if (bonjour_buddy->msg != NULL)
-		purple_prpl_got_user_status(account, buddy->name, status_id,
+		purple_prpl_got_user_status(bonjour_buddy->account, buddy->name, status_id,
 								  "message", bonjour_buddy->msg,
 								  NULL);
 	else
-		purple_prpl_got_user_status(account, buddy->name, status_id,
+		purple_prpl_got_user_status(bonjour_buddy->account, buddy->name, status_id,
 								  NULL);
-	purple_prpl_got_user_idle(account, buddy->name, FALSE, 0);
+	purple_prpl_got_user_idle(bonjour_buddy->account, buddy->name, FALSE, 0);
+
 
 	g_free(alias);
 }
@@ -162,6 +225,14 @@
 		g_free(buddy->conversation->buddy_name);
 		g_free(buddy->conversation);
 	}
+	
+#ifdef USE_BONJOUR_APPLE
+	if (NULL != buddy->txt_query)
+		{
+		purple_input_remove(buddy->txt_query_fd);
+		DNSServiceRefDeallocate(buddy->txt_query);
+		}
+#endif
 
 	free(buddy);
 }
--- a/libpurple/protocols/bonjour/buddy.h	Tue Jun 05 03:13:02 2007 +0000
+++ b/libpurple/protocols/bonjour/buddy.h	Tue Jun 05 03:38:22 2007 +0000
@@ -17,14 +17,22 @@
 #ifndef _BONJOUR_BUDDY
 #define _BONJOUR_BUDDY
 
-#include <howl.h>
 #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;
 	gchar *first;
 	gint port_p2pj;
@@ -37,16 +45,38 @@
 	gchar *vc;
 	gchar *ip;
 	gchar *msg;
+	
 	BonjourJabberConversation *conversation;
+	
+#ifdef USE_BONJOUR_APPLE
+	DNSServiceRef txt_query;
+	int txt_query_fd;
+#endif
+	
 } BonjourBuddy;
 
+typedef enum _bonjour_buddy_member
+{
+	E_BUDDY_FIRST,
+	E_BUDDY_LAST,
+	E_BUDDY_STATUS,
+	E_BUDDY_EMAIL,
+	E_BUDDY_PHSH,
+	E_BUDDY_JID,
+	E_BUDDY_AIM,
+	E_BUDDY_VC,
+	E_BUDDY_MSG
+} bonjour_buddy_member;
+
 /**
  * Creates a new buddy.
  */
-BonjourBuddy *bonjour_buddy_new(const gchar *name, const gchar *first,
-	gint port_p2pj, const gchar *phsh, const gchar *status,
-	const gchar *email, const gchar *last, const gchar *jid,
-	const gchar *AIM, const gchar *vc, const gchar *ip, const gchar *msg);
+BonjourBuddy *bonjour_buddy_new(const gchar *name, PurpleAccount* account);
+
+/**
+ * Sets a value in the BonjourBuddy struct, destroying the old value
+ */
+void set_bonjour_buddy_value(BonjourBuddy* buddy, bonjour_buddy_member member, const char* value, uint32_t len);
 
 /**
  * Check if all the compulsory buddy data is present.
@@ -56,7 +86,7 @@
 /**
  * If the buddy doesn't previoulsy exists, it is created. Else, its data is changed (???)
  */
-void bonjour_buddy_add_to_purple(PurpleAccount *account, BonjourBuddy *buddy);
+void bonjour_buddy_add_to_purple(BonjourBuddy *buddy);
 
 /**
  * Deletes a buddy from memory.
--- a/libpurple/protocols/bonjour/dns_sd.c	Tue Jun 05 03:13:02 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,387 +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.
- */
-
-#include <string.h>
-
-#include "dns_sd.h"
-#include "bonjour.h"
-#include "buddy.h"
-#include "debug.h"
-
-/* Private functions */
-
-static sw_result HOWL_API
-_publish_reply(sw_discovery discovery, sw_discovery_oid oid,
-			   sw_discovery_publish_status status, sw_opaque extra)
-{
-	purple_debug_warning("bonjour", "_publish_reply --> Start\n");
-
-	/* Check the answer from the mDNS daemon */
-	switch (status)
-	{
-		case SW_DISCOVERY_PUBLISH_STARTED :
-			purple_debug_info("bonjour", "_publish_reply --> Service started\n");
-			break;
-		case SW_DISCOVERY_PUBLISH_STOPPED :
-			purple_debug_info("bonjour", "_publish_reply --> Service stopped\n");
-			break;
-		case SW_DISCOVERY_PUBLISH_NAME_COLLISION :
-			purple_debug_info("bonjour", "_publish_reply --> Name collision\n");
-			break;
-		case SW_DISCOVERY_PUBLISH_INVALID :
-			purple_debug_info("bonjour", "_publish_reply --> Service invalid\n");
-			break;
-	}
-
-	return SW_OKAY;
-}
-
-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,
-			   sw_ipv4_address address, sw_port port,
-			   sw_octets text_record, sw_ulong text_record_len,
-			   sw_opaque extra)
-{
-	BonjourBuddy *buddy;
-	PurpleAccount *account = (PurpleAccount*)extra;
-	gchar *txtvers = NULL;
-	gchar *version = NULL;
-	gchar *first = NULL;
-	gchar *phsh = NULL;
-	gchar *status = NULL;
-	gchar *email = NULL;
-	gchar *last = NULL;
-	gchar *jid = NULL;
-	gchar *AIM = NULL;
-	gchar *vc = NULL;
-	gchar *msg = NULL;
-	gint address_length = 16;
-	gchar *ip = NULL;
-	sw_text_record_iterator iterator;
-	char key[SW_TEXT_RECORD_MAX_LEN];
-	char value[SW_TEXT_RECORD_MAX_LEN];
-	sw_uint32 value_length;
-
-	sw_discovery_cancel(discovery, oid);
-
-	/* Get the ip as a string */
-	ip = malloc(address_length);
-	sw_ipv4_address_name(address, ip, address_length);
-
-	/* Obtain the parameters from the text_record */
-	if ((text_record_len > 0) && (text_record) && (*text_record != '\0'))
-	{
-		sw_text_record_iterator_init(&iterator, text_record, text_record_len);
-		while (sw_text_record_iterator_next(iterator, key, (sw_octet *)value, &value_length) == SW_OKAY)
-		{
-			/* Compare the keys with the possible ones and save them on */
-			/* the appropiate place of the buddy_list */
-			if (strcmp(key, "txtvers") == 0) {
-				txtvers = g_strdup(value);
-			} else if (strcmp(key, "version") == 0) {
-				version = g_strdup(value);
-			} else if (strcmp(key, "1st") == 0) {
-				first = g_strdup(value);
-			} else if (strcmp(key, "status") == 0) {
-				status = g_strdup(value);
-			} else if (strcmp(key, "email") == 0) {
-				email = g_strdup(value);
-			} else if (strcmp(key, "last") == 0) {
-				last = g_strdup(value);
-			} else if (strcmp(key, "jid") == 0) {
-				jid = g_strdup(value);
-			} else if (strcmp(key, "AIM") == 0) {
-				AIM = g_strdup(value);
-			} else if (strcmp(key, "vc") == 0) {
-				vc = g_strdup(value);
-			} else if (strcmp(key, "phsh") == 0) {
-				phsh = g_strdup(value);
-			} else if (strcmp(key, "msg") == 0) {
-				msg = g_strdup(value);
-			}
-		}
-	}
-
-	/* Put the parameters of the text_record in a buddy and add the buddy to */
-	/* the buddy list */
-	buddy = bonjour_buddy_new(name, first, port, phsh,
-							  status, email, last, jid, AIM, vc, ip, msg);
-
-	if (bonjour_buddy_check(buddy) == FALSE)
-	{
-		bonjour_buddy_delete(buddy);
-		return SW_DISCOVERY_E_UNKNOWN;
-	}
-
-	/* Add or update the buddy in our buddy list */
-	bonjour_buddy_add_to_purple(account, buddy);
-
-	/* Free all the temporal strings */
-	g_free(txtvers);
-	g_free(version);
-	g_free(first);
-	g_free(last);
-	g_free(status);
-	g_free(email);
-	g_free(jid);
-	g_free(AIM);
-	g_free(vc);
-	g_free(phsh);
-	g_free(msg);
-
-	return SW_OKAY;
-}
-
-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,
-			   sw_const_string type, sw_const_string domain,
-			   sw_opaque_t extra)
-{
-	sw_discovery_resolve_id rid;
-	PurpleAccount *account = (PurpleAccount*)extra;
-	PurpleBuddy *gb = NULL;
-
-	switch (status)
-	{
-		case SW_DISCOVERY_BROWSE_INVALID:
-			purple_debug_warning("bonjour", "_browser_reply --> Invalid\n");
-			break;
-		case SW_DISCOVERY_BROWSE_RELEASE:
-			purple_debug_warning("bonjour", "_browser_reply --> Release\n");
-			break;
-		case SW_DISCOVERY_BROWSE_ADD_DOMAIN:
-			purple_debug_warning("bonjour", "_browser_reply --> Add domain\n");
-			break;
-		case SW_DISCOVERY_BROWSE_ADD_DEFAULT_DOMAIN:
-			purple_debug_warning("bonjour", "_browser_reply --> Add default domain\n");
-			break;
-		case SW_DISCOVERY_BROWSE_REMOVE_DOMAIN:
-			purple_debug_warning("bonjour", "_browser_reply --> Remove domain\n");
-			break;
-		case SW_DISCOVERY_BROWSE_ADD_SERVICE:
-			/* A new peer has joined the network and uses iChat bonjour */
-			purple_debug_info("bonjour", "_browser_reply --> Add service\n");
-			if (g_ascii_strcasecmp(name, account->username) != 0)
-			{
-				if (sw_discovery_resolve(discovery, interface_index, name, type,
-						domain, _resolve_reply, extra, &rid) != SW_OKAY)
-				{
-					purple_debug_warning("bonjour", "_browser_reply --> Cannot send resolve\n");
-				}
-			}
-			break;
-		case SW_DISCOVERY_BROWSE_REMOVE_SERVICE:
-			purple_debug_info("bonjour", "_browser_reply --> Remove service\n");
-			gb = purple_find_buddy((PurpleAccount*)extra, name);
-			if (gb != NULL)
-			{
-				bonjour_buddy_delete(gb->proto_data);
-				purple_blist_remove_buddy(gb);
-			}
-			break;
-		case SW_DISCOVERY_BROWSE_RESOLVED:
-			purple_debug_info("bonjour", "_browse_reply --> Resolved\n");
-			break;
-		default:
-			break;
-	}
-
-	return SW_OKAY;
-}
-
-static int
-_dns_sd_publish(BonjourDnsSd *data, PublishType type)
-{
-	sw_text_record dns_data;
-	sw_result publish_result = SW_OKAY;
-	char portstring[6];
-
-	/* Fill the data for the service */
-	if (sw_text_record_init(&dns_data) != SW_OKAY)
-	{
-		purple_debug_error("bonjour", "Unable to initialize the data for the mDNS.\n");
-		return -1;
-	}
-
-	/* Convert the port to a string */
-	snprintf(portstring, sizeof(portstring), "%d", data->port_p2pj);
-
-	/* Publish standard records */
-	sw_text_record_add_key_and_string_value(dns_data, "txtvers", data->txtvers);
-	sw_text_record_add_key_and_string_value(dns_data, "version", data->version);
-	sw_text_record_add_key_and_string_value(dns_data, "1st", data->first);
-	sw_text_record_add_key_and_string_value(dns_data, "last", data->last);
-	sw_text_record_add_key_and_string_value(dns_data, "port.p2pj", portstring);
-	sw_text_record_add_key_and_string_value(dns_data, "phsh", data->phsh);
-	sw_text_record_add_key_and_string_value(dns_data, "status", data->status);
-	sw_text_record_add_key_and_string_value(dns_data, "vc", data->vc);
-
-	/* Publish extra records */
-	if ((data->email != NULL) && (*data->email != '\0'))
-		sw_text_record_add_key_and_string_value(dns_data, "email", data->email);
-
-	if ((data->jid != NULL) && (*data->jid != '\0'))
-		sw_text_record_add_key_and_string_value(dns_data, "jid", data->jid);
-
-	if ((data->AIM != NULL) && (*data->AIM != '\0'))
-		sw_text_record_add_key_and_string_value(dns_data, "AIM", data->AIM);
-
-	if ((data->msg != NULL) && (*data->msg != '\0'))
-		sw_text_record_add_key_and_string_value(dns_data, "msg", data->msg);
-
-	/* Publish the service */
-	switch (type)
-	{
-		case PUBLISH_START:
-			publish_result = sw_discovery_publish(data->session, 0, data->name, 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);
-			break;
-		case PUBLISH_UPDATE:
-			publish_result = sw_discovery_publish_update(data->session, data->session_id,
-								sw_text_record_bytes(dns_data), sw_text_record_len(dns_data));
-			break;
-	}
-	if (publish_result != SW_OKAY)
-	{
-		purple_debug_error("bonjour", "Unable to publish or change the status of the _presence._tcp service.\n");
-		return -1;
-	}
-
-	/* Free the memory used by temp data */
-	sw_text_record_fina(dns_data);
-
-	return 0;
-}
-
-static void
-_dns_sd_handle_packets(gpointer data, gint source, PurpleInputCondition condition)
-{
-	sw_discovery_read_socket((sw_discovery)data);
-}
-
-/* End private functions */
-
-/**
- * Allocate space for the dns-sd data.
- */
-BonjourDnsSd *
-bonjour_dns_sd_new()
-{
-	BonjourDnsSd *data = g_new0(BonjourDnsSd, 1);
-
-	return data;
-}
-
-/**
- * Deallocate the space of the dns-sd data.
- */
-void
-bonjour_dns_sd_free(BonjourDnsSd *data)
-{
-	g_free(data->first);
-	g_free(data->last);
-	g_free(data->email);
-	g_free(data);
-}
-
-/**
- * Send a new dns-sd packet updating our status.
- */
-void
-bonjour_dns_sd_send_status(BonjourDnsSd *data, const char *status, const char *status_message)
-{
-	g_free(data->status);
-	g_free(data->msg);
-
-	data->status = g_strdup(status);
-	data->msg = g_strdup(status_message);
-
-	/* Update our text record with the new status */
-	_dns_sd_publish(data, PUBLISH_UPDATE); /* <--We must control the errors */
-}
-
-/**
- * Advertise our presence within the dns-sd daemon and start browsing
- * for other bonjour peers.
- */
-gboolean
-bonjour_dns_sd_start(BonjourDnsSd *data)
-{
-	PurpleAccount *account;
-	PurpleConnection *gc;
-	gint dns_sd_socket;
-	sw_discovery_oid session_id;
-
-	account = data->account;
-	gc = purple_account_get_connection(account);
-
-	/* Initialize the dns-sd data and session */
-	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;
-
-		return FALSE;
-	}
-
-	/* Publish our bonjour IM client at the mDNS daemon */
-	_dns_sd_publish(data, PUBLISH_START); /* <--We must control the errors */
-
-	/* Advise the daemon that we are waiting for connections */
-	if (sw_discovery_browse(data->session, 0, ICHAT_SERVICE, NULL, _browser_reply,
-			data->account, &session_id) != SW_OKAY)
-	{
-		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 */
-	dns_sd_socket = sw_discovery_socket(data->session);
-	gc->inpa = purple_input_add(dns_sd_socket, PURPLE_INPUT_READ,
-									_dns_sd_handle_packets, data->session);
-
-	return TRUE;
-}
-
-/**
- * Unregister the "_presence._tcp" service at the mDNS daemon.
- */
-void
-bonjour_dns_sd_stop(BonjourDnsSd *data)
-{
-	PurpleAccount *account;
-	PurpleConnection *gc;
-
-	if (data->session == NULL)
-		return;
-
-	sw_discovery_cancel(data->session, data->session_id);
-
-	account = data->account;
-	gc = purple_account_get_connection(account);
-	purple_input_remove(gc->inpa);
-
-	g_free(data->session);
-	data->session = NULL;
-}
--- a/libpurple/protocols/bonjour/dns_sd.h	Tue Jun 05 03:13:02 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +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_DNS_SD
-#define _BONJOUR_DNS_SD
-
-#include <howl.h>
-#include <glib.h>
-#include "account.h"
-
-#define ICHAT_SERVICE "_presence._tcp."
-
-/**
- * Data to be used by the dns-sd connection.
- */
-typedef struct _BonjourDnsSd
-{
-	sw_discovery session;
-	sw_discovery_oid session_id;
-	PurpleAccount *account;
-	gchar *name;
-	gchar *txtvers;
-	gchar *version;
-	gchar *first;
-	gchar *last;
-	gint port_p2pj;
-	gchar *phsh;
-	gchar *status;
-	gchar *email;
-	gchar *vc;
-	gchar *jid;
-	gchar *AIM;
-	gchar *msg;
-	GHashTable *buddies;
-} BonjourDnsSd;
-
-typedef enum _PublishType {
-	PUBLISH_START,
-	PUBLISH_UPDATE
-} PublishType;
-
-/**
- * Allocate space for the dns-sd data.
- */
-BonjourDnsSd *bonjour_dns_sd_new(void);
-
-/**
- * Deallocate the space of the dns-sd data.
- */
-void bonjour_dns_sd_free(BonjourDnsSd *data);
-
-/**
- * Send a new dns-sd packet updating our status.
- */
-void bonjour_dns_sd_send_status(BonjourDnsSd *data, const char *status, const char *status_message);
-
-/**
- * Advertise our presence within the dns-sd daemon and start
- * browsing for other bonjour peers.
- */
-gboolean bonjour_dns_sd_start(BonjourDnsSd *data);
-
-/**
- * Unregister the "_presence._tcp" service at the mDNS daemon.
- */
-void bonjour_dns_sd_stop(BonjourDnsSd *data);
-
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/bonjour/dns_sd_proxy.h	Tue Jun 05 03:38:22 2007 +0000
@@ -0,0 +1,19 @@
+#ifndef _DNS_SD_PROXY
+#define _DNS_SD_PROXY
+
+#include <stdint.h>
+
+/* fixup to make pidgin compile against win32 bonjour */
+#ifdef _WIN32
+#define _MSL_STDINT_H
+#undef bzero
+#endif
+
+#include <dns_sd.h>
+
+/* dns_sd.h defines bzero and we also do in libc_internal.h */
+#ifdef _WIN32
+#undef bzero
+#endif
+
+#endif
--- a/libpurple/protocols/bonjour/jabber.c	Tue Jun 05 03:13:02 2007 +0000
+++ b/libpurple/protocols/bonjour/jabber.c	Tue Jun 05 03:38:22 2007 +0000
@@ -51,18 +51,19 @@
 	gint socket_fd;
 	gint retorno = 0;
 	struct sockaddr_in buddy_address;
+	BonjourBuddy *bb = gb->proto_data;
 
 	/* Create a socket and make it non-blocking */
 	socket_fd = socket(PF_INET, SOCK_STREAM, 0);
 
 	buddy_address.sin_family = PF_INET;
-	buddy_address.sin_port = htons(((BonjourBuddy*)(gb->proto_data))->port_p2pj);
-	inet_aton(((BonjourBuddy*)(gb->proto_data))->ip, &(buddy_address.sin_addr));
+	buddy_address.sin_port = htons(bb->port_p2pj);
+	inet_aton(bb->ip, &(buddy_address.sin_addr));
 	memset(&(buddy_address.sin_zero), '\0', 8);
 
 	retorno = connect(socket_fd, (struct sockaddr*)&buddy_address, sizeof(struct sockaddr));
 	if (retorno == -1) {
-		purple_debug_warning("bonjour", "connect error: %s\n", strerror(errno));
+		purple_debug_warning("bonjour", "Error connecting to buddy %s at %s:%d error: %s\n", purple_buddy_get_name(gb), bb->ip ? bb->ip : "(null)", buddy_address.sin_port, strerror(errno));
 	}
 	fcntl(socket_fd, F_SETFL, O_NONBLOCK);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/bonjour/mdns_common.c	Tue Jun 05 03:38:22 2007 +0000
@@ -0,0 +1,174 @@
+/*
+ *  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.
+ */
+
+#include <string.h>
+
+#include "config.h"
+#include "mdns_common.h"
+#include "bonjour.h"
+#include "buddy.h"
+#include "debug.h"
+
+
+/**
+ * Allocate space for the dns-sd data.
+ */
+BonjourDnsSd *
+bonjour_dns_sd_new()
+{
+	BonjourDnsSd *data = g_new0(BonjourDnsSd, 1);
+
+	return data;
+}
+
+/**
+ * Deallocate the space of the dns-sd data.
+ */
+void
+bonjour_dns_sd_free(BonjourDnsSd *data)
+{
+	g_free(data->first);
+	g_free(data->last);
+	g_free(data->email);
+	g_free(data);
+}
+
+/**
+ * Send a new dns-sd packet updating our status.
+ */
+void
+bonjour_dns_sd_send_status(BonjourDnsSd *data, const char *status, const char *status_message)
+{
+	g_free(data->status);
+	g_free(data->msg);
+
+	data->status = g_strdup(status);
+	data->msg = g_strdup(status_message);
+
+	/* Update our text record with the new status */
+	_mdns_publish(data, PUBLISH_UPDATE); /* <--We must control the errors */
+}
+
+/**
+ * Advertise our presence within the dns-sd daemon and start browsing
+ * for other bonjour peers.
+ */
+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);
+
+	/* 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;
+
+		return FALSE;
+	}
+#endif
+
+	/* Publish our bonjour IM client at the mDNS daemon */
+
+	if (0 != _mdns_publish(data, PUBLISH_START))
+	{
+		return FALSE;
+	}
+
+	/* Advise the daemon that we are waiting for connections */
+	
+#ifdef USE_BONJOUR_APPLE
+	printf("account pointer here is %x\n,", account);
+	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
+	{
+		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);
+
+	return TRUE;
+}
+
+/**
+ * Unregister the "_presence._tcp" service at the mDNS daemon.
+ */
+
+void
+bonjour_dns_sd_stop(BonjourDnsSd *data)
+{
+	PurpleAccount *account;
+	PurpleConnection *gc;
+
+#ifdef USE_BONJOUR_APPLE 
+	if (NULL == data->advertisement || NULL == data->browser)
+#else /* USE_BONJOUR_HOWL */
+	if (data->session == NULL)
+#endif
+		return;
+
+#ifdef USE_BONJOUR_HOWL 
+	sw_discovery_cancel(data->session, data->session_id);
+#endif
+
+	account = data->account;
+	gc = purple_account_get_connection(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_fd);
+
+	DNSServiceRefDeallocate(data->advertisement);
+	DNSServiceRefDeallocate(data->browser);
+	data->advertisement = NULL;
+	data->browser = NULL;
+#else /* USE_BONJOUR_HOWL */
+	g_free(data->session);
+	data->session = NULL;
+#endif
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/bonjour/mdns_common.h	Tue Jun 05 03:38:22 2007 +0000
@@ -0,0 +1,51 @@
+/*
+ *  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_COMMON
+#define _BONJOUR_MDNS_COMMON
+
+#include "mdns_types.h"
+
+#include "mdns_win32.h"
+#include "mdns_howl.h"
+
+/**
+ * Allocate space for the dns-sd data.
+ */
+BonjourDnsSd *bonjour_dns_sd_new(void);
+
+/**
+ * Deallocate the space of the dns-sd data.
+ */
+void bonjour_dns_sd_free(BonjourDnsSd *data);
+
+/**
+ * Send a new dns-sd packet updating our status.
+ */
+void bonjour_dns_sd_send_status(BonjourDnsSd *data, const char *status, const char *status_message);
+
+/**
+ * Advertise our presence within the dns-sd daemon and start
+ * browsing for other bonjour peers.
+ */
+gboolean bonjour_dns_sd_start(BonjourDnsSd *data);
+
+/**
+ * Unregister the "_presence._tcp" service at the mDNS daemon.
+ */
+void bonjour_dns_sd_stop(BonjourDnsSd *data);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/bonjour/mdns_howl.c	Tue Jun 05 03:38:22 2007 +0000
@@ -0,0 +1,264 @@
+/*
+ *  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.
+ */
+
+#include "mdns_howl.h"
+
+#include "debug.h"
+#include "buddy.h"
+
+sw_result HOWL_API
+_publish_reply(sw_discovery discovery, sw_discovery_oid oid,
+			   sw_discovery_publish_status status, sw_opaque extra)
+{
+	purple_debug_warning("bonjour", "_publish_reply --> Start\n");
+
+	/* Check the answer from the mDNS daemon */
+	switch (status)
+	{
+		case SW_DISCOVERY_PUBLISH_STARTED :
+			purple_debug_info("bonjour", "_publish_reply --> Service started\n");
+			break;
+		case SW_DISCOVERY_PUBLISH_STOPPED :
+			purple_debug_info("bonjour", "_publish_reply --> Service stopped\n");
+			break;
+		case SW_DISCOVERY_PUBLISH_NAME_COLLISION :
+			purple_debug_info("bonjour", "_publish_reply --> Name collision\n");
+			break;
+		case SW_DISCOVERY_PUBLISH_INVALID :
+			purple_debug_info("bonjour", "_publish_reply --> Service invalid\n");
+			break;
+	}
+
+	return SW_OKAY;
+}
+
+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)
+{
+	BonjourBuddy *buddy;
+	PurpleAccount *account = (PurpleAccount*)extra;
+	/*gchar *txtvers = NULL;*/
+	/*gchar *version = NULL;*/
+	gint address_length = 16;
+	sw_text_record_iterator iterator;
+	char key[SW_TEXT_RECORD_MAX_LEN];
+	char value[SW_TEXT_RECORD_MAX_LEN];
+	sw_uint32 value_length;
+
+	sw_discovery_cancel(discovery, oid);
+
+	/* create a buddy record */
+	buddy = bonjour_buddy_new(name, account);
+
+	/* Get the ip as a string */
+	buddy->ip = g_malloc(address_length);
+	sw_ipv4_address_name(address, buddy->ip, address_length);
+
+	buddy->port_p2pj = port;
+
+	/* Obtain the parameters from the text_record */
+	if ((text_record_len > 0) && (text_record) && (*text_record != '\0'))
+	{
+		sw_text_record_iterator_init(&iterator, text_record, text_record_len);
+		while (sw_text_record_iterator_next(iterator, key, (sw_octet *)value, &value_length) == SW_OKAY)
+		{
+			/* Compare the keys with the possible ones and save them on */
+			/* the appropiate place of the buddy_list */
+			if (strcmp(key, "txtvers") == 0) {
+				/*txtvers = g_strdup(value);*/
+			} else if (strcmp(key, "version") == 0) {
+				/*version = g_strdup(value);*/
+			} else if (strcmp(key, "1st") == 0) {
+				g_free(buddy->first);
+				buddy->first = g_strdup(value);
+			} else if (strcmp(key, "status") == 0) {
+				g_free(buddy->status);
+				buddy->status = g_strdup(value);
+			} else if (strcmp(key, "email") == 0) {
+				g_free(buddy->email);
+				buddy->email = g_strdup(value);
+			} else if (strcmp(key, "last") == 0) {
+				g_free(buddy->last);
+				buddy->last = g_strdup(value);
+			} else if (strcmp(key, "jid") == 0) {
+				g_free(buddy->jid);
+				buddy->jid = g_strdup(value);
+			} else if (strcmp(key, "AIM") == 0) {
+				g_free(buddy->AIM);
+				buddy->AIM = g_strdup(value);
+			} else if (strcmp(key, "vc") == 0) {
+				g_free(buddy->vc);
+				buddy->vc = g_strdup(value);
+			} else if (strcmp(key, "phsh") == 0) {
+				g_free(buddy->phsh);
+				buddy->phsh = g_strdup(value);
+			} else if (strcmp(key, "msg") == 0) {
+				g_free(buddy->msg);
+				buddy->msg = g_strdup(value);
+			}
+		}
+	}
+
+	if (!bonjour_buddy_check(buddy))
+	{
+		bonjour_buddy_delete(buddy);
+		return SW_DISCOVERY_E_UNKNOWN;
+	}
+
+	/* Add or update the buddy in our buddy list */
+	bonjour_buddy_add_to_purple(buddy);
+
+	/* Free all the temporal strings */
+	/*g_free(txtvers);*/
+	/*g_free(version);*/
+
+	return SW_OKAY;
+}
+
+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)
+{
+	sw_discovery_resolve_id rid;
+	PurpleAccount *account = (PurpleAccount*)extra;
+	PurpleBuddy *gb = NULL;
+
+	switch (status)
+	{
+		case SW_DISCOVERY_BROWSE_INVALID:
+			purple_debug_warning("bonjour", "_browser_reply --> Invalid\n");
+			break;
+		case SW_DISCOVERY_BROWSE_RELEASE:
+			purple_debug_warning("bonjour", "_browser_reply --> Release\n");
+			break;
+		case SW_DISCOVERY_BROWSE_ADD_DOMAIN:
+			purple_debug_warning("bonjour", "_browser_reply --> Add domain\n");
+			break;
+		case SW_DISCOVERY_BROWSE_ADD_DEFAULT_DOMAIN:
+			purple_debug_warning("bonjour", "_browser_reply --> Add default domain\n");
+			break;
+		case SW_DISCOVERY_BROWSE_REMOVE_DOMAIN:
+			purple_debug_warning("bonjour", "_browser_reply --> Remove domain\n");
+			break;
+		case SW_DISCOVERY_BROWSE_ADD_SERVICE:
+			/* A new peer has joined the network and uses iChat bonjour */
+			purple_debug_info("bonjour", "_browser_reply --> Add service\n");
+			if (g_ascii_strcasecmp(name, account->username) != 0)
+			{
+				if (sw_discovery_resolve(discovery, interface_index, name, type,
+						domain, _resolve_reply, extra, &rid) != SW_OKAY)
+				{
+					purple_debug_warning("bonjour", "_browser_reply --> Cannot send resolve\n");
+				}
+			}
+			break;
+		case SW_DISCOVERY_BROWSE_REMOVE_SERVICE:
+			purple_debug_info("bonjour", "_browser_reply --> Remove service\n");
+			gb = purple_find_buddy((PurpleAccount*)extra, name);
+			if (gb != NULL)
+			{
+				bonjour_buddy_delete(gb->proto_data);
+				purple_blist_remove_buddy(gb);
+			}
+			break;
+		case SW_DISCOVERY_BROWSE_RESOLVED:
+			purple_debug_info("bonjour", "_browse_reply --> Resolved\n");
+			break;
+		default:
+			break;
+	}
+
+	return SW_OKAY;
+}
+
+int
+_mdns_publish(BonjourDnsSd *data, PublishType type)
+{
+	sw_text_record dns_data;
+	sw_result publish_result = SW_OKAY;
+	char portstring[6];
+
+	/* Fill the data for the service */
+	if (sw_text_record_init(&dns_data) != SW_OKAY)
+	{
+		purple_debug_error("bonjour", "Unable to initialize the data for the mDNS.\n");
+		return -1;
+	}
+
+	/* Convert the port to a string */
+	snprintf(portstring, sizeof(portstring), "%d", data->port_p2pj);
+
+	/* Publish standard records */
+	sw_text_record_add_key_and_string_value(dns_data, "txtvers", data->txtvers);
+	sw_text_record_add_key_and_string_value(dns_data, "version", data->version);
+	sw_text_record_add_key_and_string_value(dns_data, "1st", data->first);
+	sw_text_record_add_key_and_string_value(dns_data, "last", data->last);
+	sw_text_record_add_key_and_string_value(dns_data, "port.p2pj", portstring);
+	sw_text_record_add_key_and_string_value(dns_data, "phsh", data->phsh);
+	sw_text_record_add_key_and_string_value(dns_data, "status", data->status);
+	sw_text_record_add_key_and_string_value(dns_data, "vc", data->vc);
+
+	/* Publish extra records */
+	if ((data->email != NULL) && (*data->email != '\0'))
+		sw_text_record_add_key_and_string_value(dns_data, "email", data->email);
+
+	if ((data->jid != NULL) && (*data->jid != '\0'))
+		sw_text_record_add_key_and_string_value(dns_data, "jid", data->jid);
+
+	if ((data->AIM != NULL) && (*data->AIM != '\0'))
+		sw_text_record_add_key_and_string_value(dns_data, "AIM", data->AIM);
+
+	if ((data->msg != NULL) && (*data->msg != '\0'))
+		sw_text_record_add_key_and_string_value(dns_data, "msg", data->msg);
+
+	/* Publish the service */
+	switch (type)
+	{
+		case PUBLISH_START:
+			publish_result = sw_discovery_publish(data->session, 0, data->name, 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);
+			break;
+		case PUBLISH_UPDATE:
+			publish_result = sw_discovery_publish_update(data->session, data->session_id,
+								sw_text_record_bytes(dns_data), sw_text_record_len(dns_data));
+			break;
+	}
+	if (publish_result != SW_OKAY)
+	{
+		purple_debug_error("bonjour", "Unable to publish or change the status of the _presence._tcp service.\n");
+		return -1;
+	}
+
+	/* Free the memory used by temp data */
+	sw_text_record_fina(dns_data);
+
+	return 0;
+}
+
+void
+_mdns_handle_event(gpointer data, gint source, PurpleInputCondition condition)
+{
+	sw_discovery_read_socket((sw_discovery)data);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/bonjour/mdns_howl.h	Tue Jun 05 03:38:22 2007 +0000
@@ -0,0 +1,47 @@
+/*
+ *  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_types.h	Tue Jun 05 03:38:22 2007 +0000
@@ -0,0 +1,70 @@
+/*
+ *  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_TYPES
+#define _BONJOUR_MDNS_TYPES
+
+#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_fd; /* hack... windows bonjour is broken, so we have to have this */
+#else /* USE_BONJOUR_HOWL */
+	sw_discovery session;
+	sw_discovery_oid session_id;
+#endif
+
+	PurpleAccount *account;
+	const char *name;
+	gchar *txtvers;
+	gchar *version;
+	gchar *first;
+	gchar *last;
+	gint port_p2pj;
+	gchar *phsh;
+	gchar *status;
+	gchar *email;
+	gchar *vc;
+	gchar *jid;
+	gchar *AIM;
+	gchar *msg;
+	GHashTable *buddies;
+} BonjourDnsSd;
+
+typedef enum _PublishType {
+	PUBLISH_START,
+	PUBLISH_UPDATE
+} PublishType;
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/bonjour/mdns_win32.c	Tue Jun 05 03:38:22 2007 +0000
@@ -0,0 +1,323 @@
+/*
+ *  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.
+ */
+
+#include "mdns_win32.h"
+
+#include "debug.h"
+
+void 
+_mdns_resolve_host_callback(GSList *hosts, gpointer data, const char *error_message)
+{
+	ResolveCallbackArgs* args = (ResolveCallbackArgs*)data;
+
+	if (!hosts || !hosts->data)
+	{
+		purple_debug_error("bonjour", "host resolution - callback error.\n");	
+	}
+	else
+	{
+		struct sockaddr_in *addr = (struct sockaddr_in*)g_slist_nth_data(hosts, 1);
+		BonjourBuddy* buddy = args->buddy;
+		
+		buddy->ip = 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);
+			
+			bonjour_buddy_add_to_purple(buddy);
+		}
+		else
+		{
+			bonjour_buddy_delete(buddy);
+		}
+		
+	}
+	
+	/* free the hosts list*/
+	g_slist_free(hosts);
+	
+	/* free the remaining args memory */				
+	purple_dnsquery_destroy(args->query);
+	g_free(args->fqn);
+	free(args);
+}
+
+void DNSSD_API 
+_mdns_text_record_query_callback(DNSServiceRef DNSServiceRef, DNSServiceFlags flags, uint32_t interfaceIndex,
+    DNSServiceErrorType errorCode, const char *fullname, 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");
+	}
+	else if (flags & kDNSServiceFlagsAdd)
+	{
+		BonjourBuddy *buddy = (BonjourBuddy*)context;	
+		_mdns_parse_text_record(buddy, rdata, rdlen);
+		bonjour_buddy_add_to_purple(buddy);
+	}
+}
+
+void DNSSD_API 
+_mdns_service_resolve_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, 
+    const char *fullname, const char *hosttarget, uint16_t port, uint16_t txtLen, const char *txtRecord, void *context)
+{
+	ResolveCallbackArgs *args = (ResolveCallbackArgs*)context;
+
+	/* remove the input fd and destroy the service ref */
+	purple_input_remove(args->resolver_fd);
+	DNSServiceRefDeallocate(args->resolver);
+
+	if (kDNSServiceErr_NoError != errorCode)
+	{
+		purple_debug_error("bonjour", "service resolver - callback error.\n");
+		bonjour_buddy_delete(args->buddy);
+		free(args);
+	}
+	else
+	{
+		args->buddy->port_p2pj = port;
+				
+		/* parse the text record */
+		_mdns_parse_text_record(args->buddy, txtRecord, txtLen);
+		
+		/* set more arguments, and start the host resolver */
+		args->fqn = g_strdup(fullname);
+		
+		if (NULL == (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);
+			free(args);
+		}
+	}
+	
+}
+
+void DNSSD_API 
+_mdns_service_register_callback(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode,
+    const char *name, const char *regtype, const char *domain, void *context)
+{
+	/* we don't actually care about anything said in this callback - this is only here because Bonjour for windows is broken */
+	if (kDNSServiceErr_NoError != errorCode)
+		{
+		purple_debug_error("bonjour", "service advertisement - callback error.\n");
+		}
+	else
+		{
+		purple_debug_info("bonjour", "service advertisement - callback.\n");
+		}
+}
+
+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)
+{
+	PurpleAccount *account = (PurpleAccount*)context;
+	PurpleBuddy *gb = NULL;
+	
+	if (kDNSServiceErr_NoError != errorCode)
+	{
+		purple_debug_error("bonjour", "service browser - callback error");
+	}
+	else if (flags & kDNSServiceFlagsAdd)
+	{
+		/* A presence service instance has been discovered... check it isn't us! */
+		if (0 != g_ascii_strcasecmp(serviceName, account->username))
+		{
+			/* OK, lets go ahead and resolve it to add to the buddy list */
+			ResolveCallbackArgs *args = malloc(sizeof(ResolveCallbackArgs));
+			args->buddy = bonjour_buddy_new(serviceName, account);
+			
+			if (kDNSServiceErr_NoError != DNSServiceResolve(&args->resolver, 0, 0, serviceName, regtype, replyDomain, _mdns_service_resolve_callback, args))
+			{
+				bonjour_buddy_delete(args->buddy);
+				free(args);
+				purple_debug_error("bonjour", "service browser - failed to resolve service.\n");
+			}
+			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);
+			}
+		}
+	}
+	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)
+		{
+			bonjour_buddy_delete(gb->proto_data);
+			purple_blist_remove_buddy(gb);
+		}
+	}
+}
+
+void 
+_mdns_parse_text_record(BonjourBuddy* buddy, const char* record, uint16_t record_len)
+{
+	char *txt_entry;
+	uint8_t txt_len;
+
+	if (NULL != (txt_entry = (char*)TXTRecordGetValuePtr(record_len, record, "1st", &txt_len)))
+	{
+		set_bonjour_buddy_value(buddy, E_BUDDY_FIRST, txt_entry, txt_len);
+	}
+		
+	if (NULL != (txt_entry = (char*)TXTRecordGetValuePtr(record_len, record, "last", &txt_len)))
+	{
+		set_bonjour_buddy_value(buddy, E_BUDDY_LAST, txt_entry, txt_len);
+	}
+			
+	if (NULL != (txt_entry = (char*)TXTRecordGetValuePtr(record_len, record, "status", &txt_len)))
+	{
+		set_bonjour_buddy_value(buddy, E_BUDDY_STATUS, txt_entry, txt_len);
+	}
+				
+	if (NULL != (txt_entry = (char*)TXTRecordGetValuePtr(record_len, record, "email", &txt_len)))
+	{
+		set_bonjour_buddy_value(buddy, E_BUDDY_EMAIL, txt_entry, txt_len);
+	}
+		
+	if (NULL != (txt_entry = (char*)TXTRecordGetValuePtr(record_len, record, "jid", &txt_len)))
+	{
+		set_bonjour_buddy_value(buddy, E_BUDDY_JID, txt_entry, txt_len);
+	}
+		
+	if (NULL != (txt_entry = (char*)TXTRecordGetValuePtr(record_len, record, "AIM", &txt_len)))
+	{
+		set_bonjour_buddy_value(buddy, E_BUDDY_AIM, txt_entry, txt_len);
+	}
+	
+	if (NULL != (txt_entry = (char*)TXTRecordGetValuePtr(record_len, record, "VC", &txt_len)))
+	{
+		set_bonjour_buddy_value(buddy, E_BUDDY_VC, txt_entry, txt_len);
+	}
+	
+	if (NULL != (txt_entry = (char*)TXTRecordGetValuePtr(record_len, record, "phsh", &txt_len)))
+	{
+		set_bonjour_buddy_value(buddy, E_BUDDY_PHSH, txt_entry, txt_len);
+	}
+	
+	if (NULL != (txt_entry = (char*)TXTRecordGetValuePtr(record_len, record, "msg", &txt_len)))
+	{
+		set_bonjour_buddy_value(buddy, E_BUDDY_MSG, txt_entry, txt_len);
+	}	
+}
+
+int
+_mdns_publish(BonjourDnsSd *data, PublishType type)
+{
+	TXTRecordRef dns_data;
+	char portstring[6];
+	int ret = 0;
+	
+	TXTRecordCreate(&dns_data, 256, NULL);
+
+	/* Convert the port to a string */
+	snprintf(portstring, sizeof(portstring), "%d", data->port_p2pj);
+	
+	/* Publish standard records */
+
+	if (kDNSServiceErr_NoError != TXTRecordSetValue(&dns_data, "txtvers", strlen(data->txtvers), data->txtvers) ||
+			kDNSServiceErr_NoError != TXTRecordSetValue(&dns_data, "version", strlen(data->version), data->version) ||
+			kDNSServiceErr_NoError != TXTRecordSetValue(&dns_data, "1st", strlen(data->first), data->first) ||
+			kDNSServiceErr_NoError != TXTRecordSetValue(&dns_data, "last", strlen(data->last), data->last) ||
+			kDNSServiceErr_NoError != TXTRecordSetValue(&dns_data, "port", strlen(portstring), portstring) ||
+			kDNSServiceErr_NoError != TXTRecordSetValue(&dns_data, "phsh", strlen(data->phsh), data->phsh) ||
+			kDNSServiceErr_NoError != TXTRecordSetValue(&dns_data, "status", strlen(data->status), data->status) ||
+			kDNSServiceErr_NoError != TXTRecordSetValue(&dns_data, "vc", strlen(data->vc), data->vc))
+	{
+		purple_debug_error("bonjour", "Unable to allocate memory for text record.\n");
+		ret = -1;
+	}
+	else if ((data->email != NULL) && (*data->email != '\0') &&
+		kDNSServiceErr_NoError != TXTRecordSetValue(&dns_data, "email", strlen(data->email), data->email))
+	{
+		purple_debug_error("bonjour", "Unable to allocate memory for text record.\n");
+		ret = -1;
+	}
+	else if ((data->jid != NULL) && (*data->jid != '\0') &&
+		kDNSServiceErr_NoError != TXTRecordSetValue(&dns_data, "email", strlen(data->jid), data->jid))
+	{
+		purple_debug_error("bonjour", "Unable to allocate memory for text record.\n");
+		ret = -1;
+	}
+	else if ((data->AIM != NULL) && (*data->AIM != '\0') &&
+		kDNSServiceErr_NoError != TXTRecordSetValue(&dns_data, "AIM", strlen(data->AIM), data->AIM))
+	{
+		purple_debug_error("bonjour", "Unable to allocate memory for text record.\n");
+		ret = -1;
+	}
+	else if ((data->msg != NULL) && (*data->msg != '\0') &&
+		kDNSServiceErr_NoError != TXTRecordSetValue(&dns_data, "msg", strlen(data->msg), data->msg))
+	{
+		purple_debug_error("bonjour", "Unable to allocate memory for text record.\n");
+		ret = -1;
+	}
+	else
+	{
+		DNSServiceErrorType err = kDNSServiceErr_NoError;
+	
+		/* OK, we're done constructing the text record, (re)publish the service */
+		
+		switch (type)
+		{
+			case PUBLISH_START:
+				err = DNSServiceRegister(&data->advertisement, 0, 0, data->name, ICHAT_SERVICE,
+					NULL, NULL, 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);
+				break;
+		}
+		
+		if (kDNSServiceErr_NoError != err)
+		{
+			purple_debug_error("bonjour", "Failed to publish presence service.\n");
+			ret = -1;
+		}
+		else if (PUBLISH_START == type)
+		{
+			/* 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_fd = purple_input_add(advertisement_fd, PURPLE_INPUT_READ, _mdns_handle_event, data->advertisement);
+		}
+	}
+	
+	/* Free the memory used by temp data */
+	TXTRecordDeallocate(&dns_data);
+	return ret;
+}
+
+void 
+_mdns_handle_event(gpointer data, gint source, PurpleInputCondition condition)
+{
+	DNSServiceProcessResult((DNSServiceRef)data);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/bonjour/mdns_win32.h	Tue Jun 05 03:38:22 2007 +0000
@@ -0,0 +1,71 @@
+/*
+ *  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
+
+#include "config.h"
+
+#ifdef USE_BONJOUR_APPLE 
+
+#include <glib.h>
+#include "mdns_types.h"
+#include "buddy.h"
+#include "dnsquery.h"
+#include "dns_sd_proxy.h"
+
+/* data structure for the resolve callback */
+typedef struct _ResolveCallbackArgs
+{
+	DNSServiceRef resolver;
+	int resolver_fd;
+	
+	PurpleDnsQueryData *query;
+	gchar *fqn; 
+	
+	BonjourBuddy* buddy;
+} ResolveCallbackArgs;
+
+
+/* Bonjour async callbacks */
+
+void _mdns_resolve_host_callback(GSList *hosts, gpointer data, const char *error_message);
+
+void DNSSD_API _mdns_text_record_query_callback(DNSServiceRef DNSServiceRef, DNSServiceFlags flags, uint32_t interfaceIndex,
+    DNSServiceErrorType errorCode, const char *fullname, uint16_t rrtype, uint16_t rrclass, uint16_t rdlen,
+    const void *rdata, uint32_t ttl, void *context);
+
+void DNSSD_API _mdns_service_resolve_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, 
+    const char *fullname, const char *hosttarget, uint16_t port, uint16_t txtLen, const char *txtRecord, void *context);
+
+void DNSSD_API _mdns_service_register_callback(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode,
+    const char *name, const char *regtype, const char *domain, void *context);
+
+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);
+
+
+/* utility functions */
+void _mdns_parse_text_record(BonjourBuddy* buddy, const char* record, uint16_t record_len);
+
+/* interface functions */
+
+int _mdns_publish(BonjourDnsSd *data, PublishType type);
+void _mdns_handle_event(gpointer data, gint source, PurpleInputCondition condition);
+
+#endif
+
+#endif