Sophie

Sophie

distrib > Mandriva > 2009.0 > x86_64 > by-pkgid > a4e51422fe1b8d073f47c12205a319a3 > files > 14

kdelibs-3.5.10-4.4mdv2009.0.src.rpm

--- dnssd/Makefile.am.old	2007-10-07 23:05:05.000000000 +0200
+++ dnssd/Makefile.am	2007-10-07 23:05:34.000000000 +0200
@@ -1,20 +1,21 @@
 # set the include path for X, qt and KDE
-INCLUDES = -I$(top_srcdir) $(all_includes)
+INCLUDES = -I$(top_srcdir) $(all_includes) $(AVAHI_CFLAGS)
 
 # these are the headers for your project
-noinst_HEADERS = sdevent.h
 
 # let automoc handle all of the meta source files (moc)
 METASOURCES = AUTO
 
 lib_LTLIBRARIES =  libkdnssd.la
+noinst_HEADERS = sdevent.h
 
 libkdnssd_la_SOURCES = remoteservice.cpp responder.cpp servicebase.cpp \
 				settings.kcfgc publicservice.cpp query.cpp domainbrowser.cpp servicebrowser.cpp
 dnssdincludedir = $(includedir)/dnssd
 dnssdinclude_HEADERS = domainbrowser.h query.h remoteservice.h \
 	publicservice.h servicebase.h servicebrowser.h settings.h
-libkdnssd_la_LIBADD = ../kdecore/libkdecore.la $(LIB_DNSSD)
+libkdnssd_la_CXXFLAGS = $(INCLUDES)
+libkdnssd_la_LIBADD = $(LIB_KDECORE) $(AVAHI_LIBS)
 libkdnssd_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) -version-info 1:0
 
 #kde_kcfg_DATA = kcm_kdnssd.kcfg
--- dnssd/configure.in.in.old	2005-09-10 10:27:49.000000000 +0200
+++ dnssd/configure.in.in	2007-10-07 23:07:29.000000000 +0200
@@ -1,38 +1,18 @@
 #MIN_CONFIG
 
-AC_ARG_ENABLE(dnssd, [  --disable-dnssd     don't require libdns_sd (browsing and publishing DNS-SD services will not be possible) ],  with_dnssd=$enableval, with_dnssd=yes)
-if test "$with_dnssd" = "yes"; then
-AC_MSG_CHECKING(for DNS-SD support)
-save_dnssdtest_LIBS="$LIBS"
-save_dnssdtest_LDFLAGS="$LDFLAGS"
-save_dnssdtest_CPPFLAGS="$CPPFLAGS"
-LDFLAGS="$all_libraries $LDFLAGS"
-CPPFLAGS="$CPPFLAGS $all_includes"
-case $host_os in
-  darwin*) LIBS="" ;;
-  *) LIBS="-ldns_sd" ;;
-esac
-have_libdns_sd="no"
-AC_TRY_LINK(	[
-			#include <dns_sd.h>
-		],[
-			DNSServiceRefDeallocate( (DNSServiceRef) 0);
-			TXTRecordDeallocate( (TXTRecordRef*) 0);
-		],[
-			AC_DEFINE(HAVE_DNSSD,1,[Define if dns-sd is available])
-			case $host_os in
-				darwin*) LIB_DNSSD="" ;;
-				*) LIB_DNSSD="-ldns_sd" ;;
-			esac
-			have_libdns_sd="yes"
-			AC_MSG_RESULT(yes)
-		],[
-			AC_MSG_RESULT(no)
-                        LIB_DNSSD=""
-])
-CPPFLAGS=$save_dnssdtest_CPPFLAGS
-LDFLAGS=$save_dnssdtest_LDFLAGS
-LIBS=$save_dnssdtest_LIBS
+# Check for pkg-config manually first, as if its not installed the
+# PKG_PROG_PKG_CONFIG macro won't be defined.
+m4_pattern_allow(PKG_CONFIG_MIN_VERSION)
+PKG_PROG_PKG_CONFIG
+
+avahi_found=no
+KDE_PKG_CHECK_MODULES(AVAHI, [avahi-qt3 >= 0.4 , avahi-client >= 0.4],
+	[avahi_found=yes],[:])
+AC_MSG_RESULT($avahi_found)
+AC_SUBST(AVAHI_CFLAGS)
+AC_SUBST(AVAHI_LIBS)
+PKG_CHECK_EXISTS( [ avahi-client >= 0.6], AC_DEFINE(AVAHI_API_0_6,1,[Avahi API 0.6] ) )
+
+if test x$avahi_found = xno; then
+   DO_NOT_COMPILE="$DO_NOT_COMPILE kdnssd-avahi"
 fi
-AC_SUBST(LIB_DNSSD)
-AM_CONDITIONAL(HAVE_DNSSD, test "$have_libdns_sd" = "yes")
--- dnssd/domainbrowser.cpp.old	2005-11-08 23:39:39.000000000 +0100
+++ dnssd/domainbrowser.cpp	2007-10-07 23:10:18.000000000 +0200
@@ -27,46 +27,56 @@
 #include "query.h"
 #include "servicebrowser.h"
 #include <kapplication.h>
+#ifdef AVAHI_API_0_6
+#include <avahi-client/lookup.h>
+#endif
 
 namespace DNSSD
 {
 
-#ifdef HAVE_DNSSD
-void domain_callback(DNSServiceRef, DNSServiceFlags flags, uint32_t, DNSServiceErrorType errorCode, 
-	const char *replyDomain, void *context);
+#ifdef AVAHI_API_0_6
+void domains_callback(AvahiDomainBrowser*,  AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* replyDomain,
+     AvahiLookupResultFlags, void* context);
+#else
+void domains_callback(AvahiDomainBrowser*,  AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* replyDomain,
+     void* context);
 #endif
 
-class DomainBrowserPrivate : public Responder
+
+class DomainBrowserPrivate 
 {
 public:
-	DomainBrowserPrivate(DomainBrowser* owner) : Responder(), m_browseLAN(false), m_started(false), m_owner(owner) {}
+	DomainBrowserPrivate(DomainBrowser* owner) : m_browseLAN(false), m_started(false), 
+	    m_browser(0), m_owner(owner) {}
+	~DomainBrowserPrivate() { if (m_browser) avahi_domain_browser_free(m_browser); }
 	QStringList m_domains;
 	virtual void customEvent(QCustomEvent* event);
 	bool m_browseLAN;
 	bool m_started;
+	AvahiDomainBrowser* m_browser;
 	DomainBrowser* m_owner;
 };		
 
 void DomainBrowserPrivate::customEvent(QCustomEvent* event)
 {
-	if (event->type()==QEvent::User+SD_ERROR) stop();
 	if (event->type()==QEvent::User+SD_ADDREMOVE) {
 		AddRemoveEvent *aev = static_cast<AddRemoveEvent*>(event);
 		if (aev->m_op==AddRemoveEvent::Add) m_owner->gotNewDomain(aev->m_domain);
 			else m_owner->gotRemoveDomain(aev->m_domain);
 	}
 }
+
 	
 DomainBrowser::DomainBrowser(QObject *parent) : QObject(parent)
 {
 	d = new DomainBrowserPrivate(this);
-	d->m_domains = Configuration::domainList();
+ 	d->m_domains = Configuration::domainList();
 	if (Configuration::browseLocal()) {
 		d->m_domains+="local.";
 		d->m_browseLAN=true;
 	}
-	connect(KApplication::kApplication(),SIGNAL(kipcMessage(int,int)),this,
-	        SLOT(domainListChanged(int,int)));
+ 	connect(KApplication::kApplication(),SIGNAL(kipcMessage(int,int)),this,
+ 	        SLOT(domainListChanged(int,int)));
 }
 
 DomainBrowser::DomainBrowser(const QStringList& domains, bool recursive, QObject *parent) : QObject(parent)
@@ -88,14 +98,15 @@
 	if (d->m_started) return;
 	d->m_started=true;
 	if (ServiceBrowser::isAvailable()!=ServiceBrowser::Working) return;
-	QStringList::const_iterator itEnd = d->m_domains.end();
+ 	QStringList::const_iterator itEnd = d->m_domains.end();
 	for (QStringList::const_iterator it=d->m_domains.begin(); it!=itEnd; ++it ) emit domainAdded(*it);
-#ifdef HAVE_DNSSD		
-	if (d->m_browseLAN) {
-		DNSServiceRef ref;
-		if (DNSServiceEnumerateDomains(&ref,kDNSServiceFlagsBrowseDomains,0,domain_callback,
-		reinterpret_cast<void*>(d))==kDNSServiceErr_NoError) d->setRef(ref);
-	}
+	if (d->m_browseLAN) 
+#ifdef AVAHI_API_0_6
+	    d->m_browser = avahi_domain_browser_new(Responder::self().client(), AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
+		"local.", AVAHI_DOMAIN_BROWSER_BROWSE, (AvahiLookupFlags)0, domains_callback, this);
+#else
+	    d->m_browser = avahi_domain_browser_new(Responder::self().client(), AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
+		"local.", AVAHI_DOMAIN_BROWSER_BROWSE, domains_callback, this);
 #endif
 }
 
@@ -115,9 +126,14 @@
 void DomainBrowser::domainListChanged(int message,int)
 {
 	if (message!=KIPCDomainsChanged) return;
+
 	bool was_started = d->m_started;
-	if (d->isRunning()) d->stop(); // LAN query
+	if (d->m_browser) { 
+	    avahi_domain_browser_free(d->m_browser);  // LAN query
+	    d->m_browser=0;
+	}
 	d->m_started = false;
+
 	// remove all domains and resolvers
 	if (was_started) {
 		QStringList::const_iterator itEnd = d->m_domains.end();
@@ -129,7 +145,7 @@
 	Configuration::self()->readConfig();
 	d->m_browseLAN = Configuration::browseLocal();
 	d->m_domains = Configuration::domainList();
-	if (Configuration::browseLocal()) d->m_domains+="local.";
+	if (Configuration::browseLocal()) d->m_domains+="local";
 	// this will emit domainAdded() for every domain if necessary
 	if (was_started) startBrowse();
 }
@@ -147,22 +163,21 @@
 void DomainBrowser::virtual_hook(int, void*)
 {}
 
-#ifdef HAVE_DNSSD
-void domain_callback(DNSServiceRef, DNSServiceFlags flags, uint32_t, DNSServiceErrorType errorCode, 
-	const char *replyDomain, void *context)
+#ifdef AVAHI_API_0_6
+void domains_callback(AvahiDomainBrowser*,  AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* replyDomain,
+     AvahiLookupResultFlags,void* context)
+#else
+void domains_callback(AvahiDomainBrowser*,  AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* replyDomain,
+     void* context)
+#endif
 {
 	QObject *obj = reinterpret_cast<QObject*>(context);
-	if (errorCode != kDNSServiceErr_NoError) {
-		ErrorEvent err;
-		QApplication::sendEvent(obj, &err);
-	} else {
-		AddRemoveEvent arev((flags & kDNSServiceFlagsAdd) ? AddRemoveEvent::Add :
+	AddRemoveEvent* arev=new AddRemoveEvent((event==AVAHI_BROWSER_NEW) ? AddRemoveEvent::Add :
 			AddRemoveEvent::Remove, QString::null, QString::null, 
-			DNSToDomain(replyDomain), !(flags & kDNSServiceFlagsMoreComing));
-		QApplication::sendEvent(obj, &arev);
-	}
+			DNSToDomain(replyDomain));
+		QApplication::postEvent(obj, arev);
 }
-#endif
+
 
 }
 #include "domainbrowser.moc"
--- dnssd/publicservice.cpp.old	2005-10-10 17:06:42.000000000 +0200
+++ dnssd/publicservice.cpp	2007-10-07 23:16:11.000000000 +0200
@@ -27,9 +27,15 @@
 #include <netinet/in.h>
 #include <sys/socket.h>
 #include <qapplication.h>
-#include <network/ksocketaddress.h>
+#include <ksocketaddress.h>
 #include <kurl.h>
 #include <unistd.h>
+#include <avahi-client/client.h>
+#ifdef AVAHI_API_0_6
+#include <avahi-client/publish.h>
+#endif
+#include <avahi-common/alternative.h>
+#include <avahi-common/strlst.h>
 #include "sdevent.h"
 #include "responder.h"
 #include "servicebrowser.h"
@@ -38,16 +44,23 @@
 namespace DNSSD
 {
 static unsigned long publicIP();
-#ifdef HAVE_DNSSD
-void publish_callback (DNSServiceRef, DNSServiceFlags, DNSServiceErrorType errorCode, const char *name,
-		       const char*, const char*, void *context);
-#endif
-class PublicServicePrivate : public Responder
+
+void publish_callback (AvahiEntryGroup*, AvahiEntryGroupState s,  void *context);
+
+class PublicServicePrivate 
 {
 public:
-	PublicServicePrivate() : m_published(false)
+	PublicServicePrivate() : m_published(false), m_running(false), m_collision(false), m_group(false)
 	{}
 	bool m_published;
+	bool m_running;
+	bool m_collision;
+	AvahiEntryGroup* m_group;
+	void commit()
+	{
+	    if (!m_collision) avahi_entry_group_commit(m_group);
+	}    
+	
 };
 
 PublicService::PublicService(const QString& name, const QString& type, unsigned int port,
@@ -55,6 +68,10 @@
   		: QObject(), ServiceBase(name, type, QString::null, domain, port)
 {
 	d = new PublicServicePrivate;
+	if (Responder::self().client()) { 
+		d->m_group = avahi_entry_group_new(Responder::self().client(), publish_callback,this);
+		connect(&Responder::self(),SIGNAL(stateChanged(AvahiClientState)),this,SLOT(clientState(AvahiClientState)));
+	}
 	if (domain.isNull())
 		if (Configuration::publishType()==Configuration::EnumPublishType::LAN) m_domain="local.";
 		else m_domain=Configuration::publishDomain();
@@ -63,114 +80,148 @@
 
 PublicService::~PublicService()
 {
-	stop();
+	if (d->m_group) avahi_entry_group_free(d->m_group);
 	delete d;
 }
 
+void PublicService::tryApply()
+{
+    if (fillEntryGroup()) d->commit();
+    else {
+	stop();
+	emit published(false);
+    }
+}
+
 void PublicService::setServiceName(const QString& serviceName)
 {
 	m_serviceName = serviceName;
-	if (d->isRunning()) {
-		stop();
-		publishAsync();
-	}
+	if (d->m_running) {
+	    avahi_entry_group_reset(d->m_group);
+	    tryApply();
+	} 
 }
 
 void PublicService::setDomain(const QString& domain)
 {
 	m_domain = domain;
-	if (d->isRunning()) {
-	stop();
-	publishAsync();
-	}
+	if (d->m_running) {
+	    avahi_entry_group_reset(d->m_group);
+	    tryApply();
+	} 
 }
 
 
 void PublicService::setType(const QString& type)
 {
 	m_type = type;
-	if (d->isRunning()) {
-		stop();
-		publishAsync();
-	}
+	if (d->m_running) {
+	    avahi_entry_group_reset(d->m_group);
+	    tryApply();
+	} 
 }
 
 void PublicService::setPort(unsigned short port)
 {
 	m_port = port;
-	if (d->isRunning()) {
-		stop();
-		publishAsync();
-	}
+	if (d->m_running) {
+	    avahi_entry_group_reset(d->m_group);
+	    tryApply();
+    	} 
 }
 
-bool PublicService::isPublished() const
+void PublicService::setTextData(const QMap<QString,QString>& textData)
 {
-	return d->m_published;
+	m_textData = textData;
+	if (d->m_running) {
+	    avahi_entry_group_reset(d->m_group);
+	    tryApply();
+	} 
 }
 
-void PublicService::setTextData(const QMap<QString,QString>& textData)
+bool PublicService::isPublished() const
 {
-	m_textData = textData;
-	if (d->isRunning()) {
-		stop();
-		publishAsync();
-	}
+	return d->m_published;
 }
 
 bool PublicService::publish()
 {
 	publishAsync();
-	while (d->isRunning() && !d->m_published) d->process();
+	while (d->m_running && !d->m_published) Responder::self().process();
 	return d->m_published;
 }
 
 void PublicService::stop()
 {
-	d->stop();
-	d->m_published = false;
+    if (d->m_group) avahi_entry_group_reset(d->m_group);
+    d->m_published = false;
+}
+bool PublicService::fillEntryGroup()
+{
+    AvahiStringList *s=0;
+    QMap<QString,QString>::ConstIterator itEnd = m_textData.end();
+    for (QMap<QString,QString>::ConstIterator it = m_textData.begin(); it!=itEnd ; ++it) 
+	s = avahi_string_list_add_pair(s, it.key().utf8(),it.data().utf8());
+#ifdef AVAHI_API_0_6
+    bool res = (!avahi_entry_group_add_service_strlst(d->m_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, (AvahiPublishFlags)0, 
+	m_serviceName.isNull() ? avahi_client_get_host_name(Responder::self().client()) : m_serviceName.utf8().data(),
+	m_type.ascii(),domainToDNS(m_domain),m_hostName.utf8(),m_port,s));
+#else
+    bool res = (!avahi_entry_group_add_service_strlst(d->m_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 
+	m_serviceName.isNull() ? avahi_client_get_host_name(Responder::self().client()) : m_serviceName.utf8().data(),
+	m_type.ascii(),m_domain.utf8(),m_hostName.utf8(),m_port,s));
+#endif
+    avahi_string_list_free(s);
+    return res;
 }
 
-void PublicService::publishAsync()
+void PublicService::clientState(AvahiClientState s)
 {
-	if (d->isRunning()) stop();
-#ifdef HAVE_DNSSD
-	if (ServiceBrowser::isAvailable()==ServiceBrowser::Working) {
-		TXTRecordRef txt;
-		TXTRecordCreate(&txt,0,0);
-		QMap<QString,QString>::ConstIterator itEnd = m_textData.end();
-		for (QMap<QString,QString>::ConstIterator it = m_textData.begin(); it!=itEnd ; ++it) {
-			QCString value = it.data().utf8();
-			if (TXTRecordSetValue(&txt,it.key().utf8(),value.length(),value)!=kDNSServiceErr_NoError) {
-				TXTRecordDeallocate(&txt);
-				emit published(false);
-				return;
-			}
-		}
-		DNSServiceRef ref;
-		if (DNSServiceRegister(&ref,0,0,m_serviceName.utf8(),m_type.ascii(),domainToDNS(m_domain),NULL,
-		    htons(m_port),TXTRecordGetLength(&txt),TXTRecordGetBytesPtr(&txt),publish_callback,
-		    reinterpret_cast<void*>(this)) == kDNSServiceErr_NoError) d->setRef(ref);
-		TXTRecordDeallocate(&txt);
-	}
+    if (!d->m_running) return;
+    switch (s) {
+#ifdef AVAHI_API_0_6
+	case AVAHI_CLIENT_FAILURE:
+#else
+	case AVAHI_CLIENT_S_INVALID:
+	case AVAHI_CLIENT_DISCONNECTED:
 #endif
-	if (!d->isRunning()) emit published(false);
+	    stop();
+	    emit published(false);
+	    break;
+	case AVAHI_CLIENT_S_REGISTERING:
+	case AVAHI_CLIENT_S_COLLISION:
+	    avahi_entry_group_reset(d->m_group);
+	    d->m_collision=true;
+	    break;
+	case AVAHI_CLIENT_S_RUNNING:
+	    if (d->m_collision) {
+		d->m_collision=false;
+		tryApply();
+	    }
+    }
+}				    
+
+void PublicService::publishAsync()
+{
+	if (d->m_running) stop();
+	
+	if (!d->m_group) {
+	    emit published(false);
+	    return;
+	}
+	AvahiClientState s=Responder::self().state();
+	d->m_running=true; 
+	d->m_collision=true; // make it look like server is getting out of collision to force registering
+	clientState(s);
 }
 
-#ifdef HAVE_DNSSD
-void publish_callback (DNSServiceRef, DNSServiceFlags, DNSServiceErrorType errorCode, const char *name,
-		       const char*, const char*, void *context)
+void publish_callback (AvahiEntryGroup*, AvahiEntryGroupState s,  void *context)
 {
 	QObject *obj = reinterpret_cast<QObject*>(context);
-	if (errorCode != kDNSServiceErr_NoError) {
-		ErrorEvent err;
-		QApplication::sendEvent(obj, &err);
-	} else {
-		PublishEvent pev(QString::fromUtf8(name));
-		QApplication::sendEvent(obj, &pev);
-	}
+	if (s!=AVAHI_ENTRY_GROUP_ESTABLISHED && s!=AVAHI_ENTRY_GROUP_COLLISION) return;
+	PublishEvent* pev=new PublishEvent(s==AVAHI_ENTRY_GROUP_ESTABLISHED);
+	QApplication::postEvent(obj, pev);
 }
-#endif
 
 const KURL PublicService::toInvitation(const QString& host)
 {
@@ -194,14 +245,13 @@
 
 void PublicService::customEvent(QCustomEvent* event)
 {
-	if (event->type()==QEvent::User+SD_ERROR) {
-		stop();
-		emit published(false);
-	}
 	if (event->type()==QEvent::User+SD_PUBLISH) {
+		if (!static_cast<PublishEvent*>(event)->m_ok) {
+		    setServiceName(QString::fromUtf8(avahi_alternative_service_name(m_serviceName.utf8())));
+		    return;
+		}
 		d->m_published=true;
 		emit published(true);
-		m_serviceName = static_cast<PublishEvent*>(event)->m_name;
 	}
 }
 
--- dnssd/publicservice.h.old	2005-10-10 17:06:42.000000000 +0200
+++ dnssd/publicservice.h	2007-10-07 23:18:17.000000000 +0200
@@ -23,6 +23,7 @@
 
 #include <qobject.h>
 #include <dnssd/servicebase.h>
+#include <avahi-client/client.h>
 
 class KURL;
 namespace DNSSD
@@ -137,6 +138,10 @@
 	void published(bool);
 private:
 	PublicServicePrivate *d;
+	bool fillEntryGroup();
+	void tryApply();
+private slots:
+	void clientState(AvahiClientState);
 
 protected:
 	virtual void customEvent(QCustomEvent* event);
--- dnssd/query.cpp.old	2005-11-08 23:39:39.000000000 +0100
+++ dnssd/query.cpp	2007-10-07 23:19:46.000000000 +0200
@@ -22,26 +22,46 @@
 #include "responder.h"
 #include "remoteservice.h"
 #include "sdevent.h"
-#include <kdebug.h>
+#include <qdatetime.h>
 #include <qapplication.h>
 #include <qtimer.h>
 
-#define TIMEOUT_WAN 2000
+#include <avahi-client/client.h>
+#ifdef AVAHI_API_0_6
+#include <avahi-client/lookup.h>
+#endif
+
 #define TIMEOUT_LAN 200
 
 namespace DNSSD
 {
-#ifdef HAVE_DNSSD  
-void query_callback (DNSServiceRef, DNSServiceFlags flags, uint32_t, DNSServiceErrorType errorCode,
-		     const char *serviceName, const char *regtype, const char *replyDomain, void *context);
+#ifdef AVAHI_API_0_6
+
+void services_callback(AvahiServiceBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* name,
+    const char* regtype, const char* domain, AvahiLookupResultFlags, void* context);
+void types_callback(AvahiServiceTypeBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* regtype,
+    const char* replyDomain, AvahiLookupResultFlags, void* context);
+#else
+void services_callback(AvahiServiceBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* name,
+    const char* regtype, const char* domain, void* context);
+void types_callback(AvahiServiceTypeBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* regtype,
+    const char* replyDomain, void* context);
+void domains_callback(AvahiDomainBrowser*,  AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* replyDomain,
+     void* context);
 #endif
-class QueryPrivate : public Responder
+
+enum BrowserType { Types, Services };
+
+class QueryPrivate 
 {
 public:
-	QueryPrivate(const QString& type, const QString& domain) : Responder(), m_finished(false),
-	m_domain(domain), m_type(type)
-	{};
+	QueryPrivate(const QString& type, const QString& domain) : m_finished(false), m_browser(0),
+	m_running(false), m_domain(domain), m_type(type) {}
+
 	bool m_finished;
+	BrowserType m_browserType;
+	void* m_browser;
+	bool m_running;
 	QString m_domain;
 	QTimer timeout;
 	QString m_type;
@@ -56,12 +76,18 @@
 
 Query::~Query()
 {
+	if (d->m_browser) {
+	    switch (d->m_browserType) {
+		case Services: avahi_service_browser_free((AvahiServiceBrowser*)d->m_browser); break;
+		case Types: avahi_service_type_browser_free((AvahiServiceTypeBrowser*)d->m_browser); break;
+	    }
+	}		    
 	delete d;
 }
 
 bool Query::isRunning() const
 {
-	return d->isRunning();
+	return d->m_running;
 }
 
 bool Query::isFinished() const
@@ -76,16 +102,31 @@
 
 void Query::startQuery()
 {
-	if (d->isRunning()) return;
+	if (d->m_running) return;
 	d->m_finished = false;
-#ifdef HAVE_DNSSD
-	DNSServiceRef ref;
-	if (DNSServiceBrowse(&ref,0,0, d->m_type.ascii(), 
-	    domainToDNS(d->m_domain),query_callback,reinterpret_cast<void*>(this))
-		   == kDNSServiceErr_NoError) d->setRef(ref);
+	if (d->m_type=="_services._dns-sd._udp") {
+	    d->m_browserType = Types;
+#ifdef AVAHI_API_0_6
+	    d->m_browser = avahi_service_type_browser_new(Responder::self().client(), AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
+		domainToDNS(d->m_domain), (AvahiLookupFlags)0, types_callback, this);
+#else
+	    d->m_browser = avahi_service_type_browser_new(Responder::self().client(), AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
+		d->m_domain.utf8(), types_callback, this);
 #endif
-	if (!d->isRunning()) emit finished();
-		else d->timeout.start(domainIsLocal(d->m_domain) ? TIMEOUT_LAN : TIMEOUT_WAN,true);
+	} else {
+	    d->m_browserType = Services;
+#ifdef AVAHI_API_0_6
+	    d->m_browser = avahi_service_browser_new(Responder::self().client(), AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
+	    d->m_type.ascii(),domainToDNS(d->m_domain),  (AvahiLookupFlags)0, services_callback,this);
+#else
+	    d->m_browser = avahi_service_browser_new(Responder::self().client(), AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
+	    d->m_type.ascii(),d->m_domain.utf8(),services_callback,this);
+#endif
+	}
+	if (d->m_browser) {
+		d->m_running=true;
+		d->timeout.start(TIMEOUT_LAN,true);
+	} else emit finished();
 }
 void Query::virtual_hook(int, void*)
 {
@@ -93,24 +134,15 @@
 
 void Query::customEvent(QCustomEvent* event)
 {
-	if (event->type()==QEvent::User+SD_ERROR) {
-		d->stop();
-		d->m_finished=false;
-		emit finished();
-	}
 	if (event->type()==QEvent::User+SD_ADDREMOVE) {
-		RemoteService* svr;
+		d->timeout.start(TIMEOUT_LAN,true);
+		d->m_finished=false;
 		AddRemoveEvent *aev = static_cast<AddRemoveEvent*>(event);
 		// m_type has useless trailing dot
-		QString type=aev->m_type.left(aev->m_type.length()-1);
-		// label is badly splitted here - _http   _tcp.local. . - rely on decode()
-		if (d->m_type=="_services._dns-sd._udp") svr = new RemoteService(aev->m_name+"."+
-			type+"."+aev->m_domain);
-		else svr = new RemoteService(aev->m_name, type, aev->m_domain);
+		RemoteService*  svr = new RemoteService(aev->m_name,
+		    	aev->m_type,aev->m_domain);
 		if (aev->m_op==AddRemoveEvent::Add) emit serviceAdded(svr);
 			else emit serviceRemoved(svr);
-		d->m_finished = aev->m_last;
-		if (d->m_finished) emit finished();
 	}
 }
 
@@ -119,22 +151,36 @@
 	d->m_finished=true;
 	emit finished();
 }
-#ifdef HAVE_DNSSD
-void query_callback (DNSServiceRef, DNSServiceFlags flags, uint32_t, DNSServiceErrorType errorCode,
-		     const char *serviceName, const char *regtype, const char *replyDomain,
-		     void *context)
+
+#ifdef AVAHI_API_0_6
+void services_callback (AvahiServiceBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, 
+    const char* serviceName, const char* regtype, const char* replyDomain, AvahiLookupResultFlags, void* context)
+#else
+void services_callback (AvahiServiceBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, 
+    const char* serviceName, const char* regtype, const char* replyDomain, void* context)
+#endif
 {
 	QObject *obj = reinterpret_cast<QObject*>(context);
-	if (errorCode != kDNSServiceErr_NoError) {
-		ErrorEvent err;
-		QApplication::sendEvent(obj, &err);
-	} else {
-		AddRemoveEvent arev((flags & kDNSServiceFlagsAdd) ? AddRemoveEvent::Add :
+	AddRemoveEvent* arev = new AddRemoveEvent((event==AVAHI_BROWSER_NEW) ? AddRemoveEvent::Add :
 			AddRemoveEvent::Remove, QString::fromUtf8(serviceName), regtype, 
-			DNSToDomain(replyDomain), !(flags & kDNSServiceFlagsMoreComing));
-		QApplication::sendEvent(obj, &arev);
-	}
+			DNSToDomain(replyDomain));
+		QApplication::postEvent(obj, arev);
 }
+
+#ifdef AVAHI_API_0_6
+void types_callback(AvahiServiceTypeBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* regtype,
+    const char* replyDomain, AvahiLookupResultFlags, void* context)
+#else
+void types_callback(AvahiServiceTypeBrowser*, AvahiIfIndex, AvahiProtocol, AvahiBrowserEvent event, const char* regtype,
+    const char* replyDomain, void* context)
 #endif
+{
+	QObject *obj = reinterpret_cast<QObject*>(context);
+	AddRemoveEvent* arev = new AddRemoveEvent((event==AVAHI_BROWSER_NEW) ? AddRemoveEvent::Add :
+			AddRemoveEvent::Remove, QString::null, regtype, 
+			DNSToDomain(replyDomain));
+		QApplication::postEvent(obj, arev);
+}
+
 }
 #include "query.moc"
--- dnssd/remoteservice.cpp.old	2007-01-15 12:34:23.000000000 +0100
+++ dnssd/remoteservice.cpp	2007-10-07 23:23:43.000000000 +0200
@@ -27,33 +27,39 @@
 #include <sys/types.h>
 #endif
 #include <netinet/in.h>
+#include <avahi-client/client.h>
+#include <avahi-common/strlst.h>
+#ifdef AVAHI_API_0_6
+#include <avahi-client/lookup.h>
+#endif
 #include "remoteservice.h"
 #include "responder.h"
 #include "sdevent.h"
-#include <kdebug.h>
 
 namespace DNSSD
 {
-#ifdef HAVE_DNSSD
-void resolve_callback    (    DNSServiceRef,
-				DNSServiceFlags,
-				uint32_t,
-				DNSServiceErrorType                 errorCode,
-				const char*,
-				const char                          *hosttarget,
-				uint16_t                            port,
-				uint16_t                            txtLen,
-				const unsigned char                 *txtRecord,
-				void                                *context
-			 );
-
+#ifdef AVAHI_API_0_6
+void resolve_callback(AvahiServiceResolver*, AvahiIfIndex, AvahiProtocol proto, AvahiResolverEvent e,
+    const char* name, const char* type, const char* domain, const char* hostname, const AvahiAddress* a,
+    uint16_t port, AvahiStringList* txt, AvahiLookupResultFlags, void* context);
+#else
+void resolve_callback(AvahiServiceResolver*, AvahiIfIndex, AvahiProtocol proto, AvahiResolverEvent e,
+    const char* name, const char* type, const char* domain, const char* hostname, const AvahiAddress* a,
+    uint16_t port, AvahiStringList* txt, void* context);
 #endif
+
 class RemoteServicePrivate : public Responder
 {
 public:
-	RemoteServicePrivate() : Responder(), m_resolved(false)
-	{};
+	RemoteServicePrivate() :  m_resolved(false), m_running(false), m_resolver(0) {}
 	bool m_resolved;
+	bool m_running;
+	AvahiServiceResolver* m_resolver;
+	void stop() {
+	    m_running = false;
+	    if (m_resolver) avahi_service_resolver_free(m_resolver);
+	    m_resolver=0;
+	}
 };
 
 RemoteService::RemoteService(const QString& label)
@@ -83,29 +89,33 @@
 
 RemoteService::~RemoteService()
 {
+	if (d->m_resolver) avahi_service_resolver_free(d->m_resolver);
 	delete d;
 }
 
 bool RemoteService::resolve()
 {
 	resolveAsync();
-	while (d->isRunning() && !d->m_resolved) d->process();
+	while (d->m_running && !d->m_resolved) Responder::self().process();
 	d->stop();
 	return d->m_resolved;
 }
 
 void RemoteService::resolveAsync()
 {
-	if (d->isRunning()) return;
+	if (d->m_running) return;
 	d->m_resolved = false;
-	kdDebug() << this << ":Starting resolve of : " << m_serviceName << " " << m_type << " " << m_domain << "\n";
-#ifdef HAVE_DNSSD
-	DNSServiceRef ref;
-	if (DNSServiceResolve(&ref,0,0,m_serviceName.utf8(), m_type.ascii(), 
-		domainToDNS(m_domain),(DNSServiceResolveReply)resolve_callback,reinterpret_cast<void*>(this))
-		== kDNSServiceErr_NoError) d->setRef(ref);
+	// FIXME: first protocol should be set?
+#ifdef AVAHI_API_0_6
+	d->m_resolver = avahi_service_resolver_new(Responder::self().client(),AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
+	    m_serviceName.utf8(), m_type.ascii(), domainToDNS(m_domain), AVAHI_PROTO_UNSPEC, AVAHI_LOOKUP_NO_ADDRESS,
+	    resolve_callback, this);
+#else
+	d->m_resolver = avahi_service_resolver_new(Responder::self().client(),AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
+	    m_serviceName.utf8(), m_type.ascii(), m_domain.utf8(), AVAHI_PROTO_UNSPEC, resolve_callback, this);
 #endif
-	if (!d->isRunning()) emit resolved(false);
+	if (d->m_resolver) d->m_running=true;
+	    else  emit resolved(false);
 }
 
 bool RemoteService::isResolved() const
@@ -154,42 +164,33 @@
 	return s;
 }
 
-
-#ifdef HAVE_DNSSD
-void resolve_callback    (    DNSServiceRef,
-			      DNSServiceFlags,
-			      uint32_t,
-			      DNSServiceErrorType                 errorCode,
-			      const char*,
-			      const char                          *hosttarget,
-			      uint16_t                            port,
-			      uint16_t                            txtLen,
-			      const unsigned char                 *txtRecord,
-			      void                                *context
-			 )
+#ifdef AVAHI_API_0_6
+void resolve_callback(AvahiServiceResolver*, AvahiIfIndex, AvahiProtocol, AvahiResolverEvent e,
+    const char*, const char*, const char*, const char* hostname, const AvahiAddress*,
+    uint16_t port, AvahiStringList* txt, AvahiLookupResultFlags, void* context)
+#else
+void resolve_callback(AvahiServiceResolver*, AvahiIfIndex, AvahiProtocol, AvahiResolverEvent e,
+    const char*, const char*, const char*, const char* hostname, const AvahiAddress*,
+    uint16_t port, AvahiStringList* txt, void* context)
+#endif
 {
 	QObject *obj = reinterpret_cast<QObject*>(context);
-	if (errorCode != kDNSServiceErr_NoError) {
+	if (e != AVAHI_RESOLVER_FOUND) {
 		ErrorEvent err;
 		QApplication::sendEvent(obj, &err);	
 		return;
 	}
-	char key[256];
-	int index=0;
-	unsigned char valueLen;
-	kdDebug() << "Resolve callback\n";
 	QMap<QString,QString> map;
-        const void *voidValue = 0;
-	while (TXTRecordGetItemAtIndex(txtLen,txtRecord,index++,256,key,&valueLen,
-		&voidValue) == kDNSServiceErr_NoError)  
-        {
-		if (voidValue) map[QString::fromUtf8(key)]=QString::fromUtf8((const char*)voidValue,valueLen);
-			else map[QString::fromUtf8(key)]=QString::null;
-        }
-	ResolveEvent rev(DNSToDomain(hosttarget),ntohs(port),map);
+	while (txt) {
+	    char *key, *value;
+	    size_t size;
+	    if (avahi_string_list_get_pair(txt,&key,&value,&size)) break;
+	    map[QString::fromUtf8(key)]=(value) ? QString::fromUtf8(value) : QString::null;
+	    txt = txt->next;
+	}
+	ResolveEvent rev(DNSToDomain(hostname),port,map);
 	QApplication::sendEvent(obj, &rev);
 }
-#endif
 
 
 }
--- dnssd/responder.cpp.old	2005-10-10 17:06:42.000000000 +0200
+++ dnssd/responder.cpp	2007-10-07 23:25:47.000000000 +0200
@@ -20,62 +20,61 @@
 
 #include "responder.h"
 #include <qapplication.h>
+#include <qeventloop.h>
+#include <kstaticdeleter.h>
 #include <kidna.h>
+#include <kdebug.h>
+#include <avahi-qt3/qt-watch.h>
 
-// dns_sd.h API should care about proper encoding of non-latin1 characters
-// but for now it does not
-#define IDN_BROKEN_IN_MDNSRESPONDER
 
 namespace DNSSD
 {
 
-Responder::Responder(DNSServiceRef ref,QObject *parent, const char *name)
-		: QObject(parent, name), m_ref(0), m_socket(0)
+static KStaticDeleter<Responder> responder_sd;
+Responder* Responder::m_self = 0;
+
+void client_callback(AvahiClient *, AvahiClientState s, void* u) 
 {
-	setRef(ref);
+    Responder *r = reinterpret_cast<Responder*>(u);    
+    emit (r->stateChanged(s));
 }
- 
-void Responder::setRef(DNSServiceRef ref)
+
+
+Responder::Responder()
 {
-	if (m_socket || m_ref) stop();	
-	m_running = false;
-	m_ref = ref;
-	if (m_ref == 0 ) return;
-#ifdef HAVE_DNSSD
-	int fd = DNSServiceRefSockFD(ref);
-	if (fd == -1) return;
-	m_socket = new QSocketNotifier(fd,QSocketNotifier::Read,this);
-	connect(m_socket,SIGNAL(activated(int)),this,SLOT(process()));
-	m_running = true;
+    int error;
+    const AvahiPoll* poll = avahi_qt_poll_get();
+#ifdef AVAHI_API_0_6
+    m_client = avahi_client_new(poll, AVAHI_CLIENT_IGNORE_USER_CONFIG,client_callback, this,  &error);
+#else
+    m_client = avahi_client_new(poll, client_callback, this,  &error);
 #endif
+    if (!m_client) kdWarning() << "Failed to create avahi client" << endl;
 }
+ 
 Responder::~Responder()
 {
-	stop();
+    if (m_client) avahi_client_free(m_client);
 }
 
-void Responder::stop()
+Responder& Responder::self()
 {
-	if (m_socket) delete m_socket;
-	m_socket = 0;
-#ifdef HAVE_DNSSD
-	if (m_ref) DNSServiceRefDeallocate(m_ref);
-#endif
-	m_ref = 0;
-	m_running = false;
-}	
-
+    if (!m_self) responder_sd.setObject(m_self, new Responder);
+    return *m_self;
+}
 
 void Responder::process()
 {
-#ifdef HAVE_DNSSD
-	if ( DNSServiceProcessResult(m_ref) != kDNSServiceErr_NoError) stop();
-#endif
+    qApp->eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
 }
 
-bool Responder::isRunning() const
+AvahiClientState Responder::state() const
 {
-	return m_running;
+#ifdef AVAHI_API_0_6
+	return (m_client) ? (avahi_client_get_state(m_client)) : AVAHI_CLIENT_FAILURE;
+#else
+	return (m_client) ? (avahi_client_get_state(m_client)) : AVAHI_CLIENT_DISCONNECTED;
+#endif
 }
 
 bool domainIsLocal(const QString& domain)
@@ -85,22 +84,14 @@
 
 QCString domainToDNS(const QString &domain)
 {
-#ifdef IDN_BROKEN_IN_MDNSRESPONDER
 	if (domainIsLocal(domain)) return domain.utf8();
 		else return KIDNA::toAsciiCString(domain);
-#else
-	return domain.utf8();       
-#endif
 }
 
 QString DNSToDomain(const char* domain)
 {
-#ifdef IDN_BROKEN_IN_MDNSRESPONDER
 	if (domainIsLocal(domain)) return QString::fromUtf8(domain);
 		else return KIDNA::toUnicode(domain);
-#else
-	return QString::fromUtf8(domain);
-#endif
 }
 
 
--- dnssd/responder.h.old	2005-10-10 17:06:42.000000000 +0200
+++ dnssd/responder.h	2007-10-07 23:29:06.000000000 +0200
@@ -25,12 +25,7 @@
 #include <qsocketnotifier.h>
 #include <qsignal.h>
 #include <config.h>
-#ifdef HAVE_DNSSD
-#include <dns_sd.h>
-#else
-#define DNSServiceRef void*
-#endif
-
+#include <avahi-client/client.h>
 namespace DNSSD
 {
 
@@ -38,30 +33,28 @@
 This class should not be used directly.
  
 @author Jakub Stachowski
-@short Internal class wrapping dns_sd.h interface
+@short Internal class wrapping avahi client
  */
 class Responder : public QObject
 {
 	Q_OBJECT
 
 public:
-	Responder(DNSServiceRef ref=0,QObject *parent = 0, const char *name = 0);
+	Responder();
 
 	~Responder();
 
-	/**
-	Returns true if it is possible to use mDNS service publishing and discovery. 
-	It needs mDNSResponder running.
-	 */
-	bool isRunning() const;
-	void setRef(DNSServiceRef ref);
-	void stop();
-public slots:
+	static Responder& self();
+	AvahiClientState state() const;
+	AvahiClient* client() const { return m_client; }
 	void process();
-protected:
-	DNSServiceRef m_ref;
-	bool m_running;
-	QSocketNotifier *m_socket;
+signals:
+	void stateChanged(AvahiClientState);
+private:
+	AvahiClient* m_client;
+	static Responder* m_self;
+	friend void client_callback(AvahiClient*, AvahiClientState, void*);
+
 };
 
 /* Utils functions */
@@ -71,6 +64,7 @@
 QCString domainToDNS(const QString &domain);
 QString DNSToDomain(const char* domain);
 
+
 }
 
 #endif
--- dnssd/sdevent.h.old	2005-10-10 17:06:42.000000000 +0200
+++ dnssd/sdevent.h	2007-10-07 23:30:17.000000000 +0200
@@ -41,24 +41,23 @@
 public:
 	enum Operation { Add, Remove };
 	AddRemoveEvent(Operation op,const QString& name,const QString& type,
-		const QString& domain, bool last) : QCustomEvent(QEvent::User+SD_ADDREMOVE),
-	m_op(op), m_name(name), m_type(type), m_domain(domain), m_last(last) 
+		const QString& domain) : QCustomEvent(QEvent::User+SD_ADDREMOVE),
+	m_op(op), m_name(name), m_type(type), m_domain(domain) 
 	{}
 
 	const Operation m_op;
 	const QString m_name;
 	const QString m_type;
 	const QString m_domain;
-	const bool m_last;
 };
 
 class PublishEvent : public QCustomEvent
 {
 public:
-	PublishEvent(const QString& name) : QCustomEvent(QEvent::User+SD_PUBLISH), m_name(name)
+	PublishEvent(bool ok) : QCustomEvent(QEvent::User+SD_PUBLISH), m_ok(ok)
 	{}
 
-	const QString m_name;
+	bool m_ok;
 };
 
 class ResolveEvent : public QCustomEvent
--- dnssd/servicebase.cpp.old	2005-11-08 23:39:39.000000000 +0100
+++ dnssd/servicebase.cpp	2007-10-07 23:31:30.000000000 +0200
@@ -34,7 +34,7 @@
 
 QString ServiceBase::encode()
 {
-	return  m_serviceName.replace("\\","\\\\").replace(".","\\.") + QString(".") + m_type +
+	return  m_serviceName.replace(".","\\.").replace("\\","\\\\") + QString(".") + m_type +
 			 QString(".") + m_domain;
 }
 
--- dnssd/servicebrowser.cpp.old	2005-10-10 17:06:42.000000000 +0200
+++ dnssd/servicebrowser.cpp	2007-10-07 23:33:36.000000000 +0200
@@ -23,14 +23,11 @@
 #include <qstringlist.h>
 #include <qfile.h>
 #include "domainbrowser.h"
+#include "responder.h"
 #include "query.h"
 #include "servicebrowser.h"
+#include <avahi-client/client.h>
 #include <config.h>
-#ifdef HAVE_DNSSD
-#include <dns_sd.h>
-#endif
-
-#define MDNSD_PID "/var/run/mdnsd.pid"
 
 namespace DNSSD
 {
@@ -85,20 +82,12 @@
 
 const ServiceBrowser::State ServiceBrowser::isAvailable()
 {
-#ifdef HAVE_DNSSD
-	QFile f(MDNSD_PID);
-	if (!f.open(IO_ReadOnly)) return Stopped; // no pidfile
-	QString line;
-	if (f.readLine(line,16)<1) return Stopped;
-	unsigned int pid = line.toUInt();
-	if (pid==0) return Stopped;           // not a pid
-	return (kill(pid,0)==0 || errno==EPERM) ? Working : Stopped; 
-	// signal 0 only checks if process is running, mdnsd is probably owned by 'nobody' so we will
-	// get EPERM, if mdnsd is not running error will be ESRCH
-	
+	AvahiClientState s = Responder::self().state();
+#ifdef AVAHI_API_0_6
+	return (s==AVAHI_CLIENT_FAILURE) ? Stopped : Working;
 #else
-	return Unsupported;
-#endif
+	return (s==AVAHI_CLIENT_S_INVALID || s==AVAHI_CLIENT_DISCONNECTED) ? Stopped : Working;
+#endif 
 }
 ServiceBrowser::~ ServiceBrowser()
 {
--- dnssd/README.old	2005-09-10 10:27:49.000000000 +0200
+++ dnssd/README	2007-10-07 23:36:38.000000000 +0200
@@ -1,12 +1,11 @@
 Checklist to ensure that zeroconf will work:
 
-1) Install Apple's mdnsd, at least version 85
-2) kdelibs (and kdebase for ksysguard) should be configured and compiled with dns_sd sdk (part
-of mdnsd installation) present - config.h should contain '#define HAVE_DNSSD 1'
+1) Install Avahi, at least version 0.3
+2) compile kdnssd-avahi and install it to replace 'stub' libkdnssd.so provided by kdelibs
 3) check /etc/nsswitch.conf and ensure that there is 'mdns' before 'dns' in
 line starting with 'host:'. It should be something like:
 host: files mdns dns
-4) ensure that mdnsd is being started in initscripts
+4) ensure that avahi-daemon is being started in initscripts
 5) for testing: use kpf kicker applet to publish a directory, then open 'zeroconf:/'
 URL in konqueror. You should be able to see a local webserver with that published dir.