summaryrefslogtreecommitdiffstats
path: root/kdnssd/ioslave
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commitbcb704366cb5e333a626c18c308c7e0448a8e69f (patch)
treef0d6ab7d78ecdd9207cf46536376b44b91a1ca71 /kdnssd/ioslave
downloadtdenetwork-bcb704366cb5e333a626c18c308c7e0448a8e69f.tar.gz
tdenetwork-bcb704366cb5e333a626c18c308c7e0448a8e69f.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdenetwork@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kdnssd/ioslave')
-rw-r--r--kdnssd/ioslave/CONFIG_FORMAT53
-rw-r--r--kdnssd/ioslave/Makefile.am21
-rw-r--r--kdnssd/ioslave/_ftp._tcp5
-rw-r--r--kdnssd/ioslave/_http._tcp5
-rw-r--r--kdnssd/ioslave/_ldap._tcp2
-rw-r--r--kdnssd/ioslave/_nfs._tcp3
-rw-r--r--kdnssd/ioslave/_ssh._tcp4
-rw-r--r--kdnssd/ioslave/_telnet._tcp4
-rw-r--r--kdnssd/ioslave/_webdav._tcp5
-rw-r--r--kdnssd/ioslave/dnssd.cpp369
-rw-r--r--kdnssd/ioslave/dnssd.h87
-rw-r--r--kdnssd/ioslave/invitation.protocol62
-rw-r--r--kdnssd/ioslave/zeroconf.desktop56
-rw-r--r--kdnssd/ioslave/zeroconf.protocol63
14 files changed, 739 insertions, 0 deletions
diff --git a/kdnssd/ioslave/CONFIG_FORMAT b/kdnssd/ioslave/CONFIG_FORMAT
new file mode 100644
index 00000000..43e34001
--- /dev/null
+++ b/kdnssd/ioslave/CONFIG_FORMAT
@@ -0,0 +1,53 @@
+Every DNS-SD service type used with zeroconf:/ ioslave needs
+configuration file in $DATADIR/zeroconf with name matching service type.
+Used entries:
+
+Type - obligatory, must match file name
+Name - obligarory, specifies user friendly name shown in konqueror/ file dialog
+Name[language] - optional, contains the localized friendly name. E.g. Name[gb]=Colour server
+Exec - optional, specifies executable for helper service - used if service has no
+ corresponding helper protocol
+Protocol - optional, specifies real protocol name, will be taken from service name
+ if not set (for example _ssh._tcp => ssh://)
+Icon - optional, if not set will be taken from protocol
+PathEntry - optional, contains name of attribute carrying path
+UserEntry - optional, contains name of attribute carrying user name
+PasswdEntry - optional, contains name of attribute carrying password
+
+
+Examples:
+
+Name=FTP servers
+Type=_ftp._tcp
+PathEntry=path
+UserEntry=u
+PasswordEntry=p
+
+Protocol is taken from service type (ftp), if service is announced with attributes path, u or p, it
+will be inserted into resolved URL.
+Service published with: Name="Public files", type="_ftp._tcp", port=7773, attributes: path=/home/test/public_files,
+u=test, p=public on hostname "Storage" will be resolved into ftp://test:[email protected]/home/test/public_files
+
+-----
+
+
+Name=Remote shell (ssh)
+Type=_ssh._tcp
+UserEntry=u
+PasswordEntry=p
+
+
+Resolved URL will be ssh://user:password@machine:port/ . ssh is helper protocol so ktelnetservice will be launched for
+this URL.
+
+
+
+-----------
+
+Name=Battleship games
+Type=_kbattleship._tcp
+Exec=kbattleship %u
+
+URL will be resolved into kbattleship://host:port, then "kbattleship kbattleship://host:port" will be launched
+
+
diff --git a/kdnssd/ioslave/Makefile.am b/kdnssd/ioslave/Makefile.am
new file mode 100644
index 00000000..7b2cbb9a
--- /dev/null
+++ b/kdnssd/ioslave/Makefile.am
@@ -0,0 +1,21 @@
+INCLUDES = $(all_includes)
+
+kde_module_LTLIBRARIES = kio_zeroconf.la
+
+kio_zeroconf_la_SOURCES = dnssd.cpp
+kio_zeroconf_la_LIBADD = $(LIB_KDNSSD) $(LIB_KIO)
+kio_zeroconf_la_LDFLAGS = -avoid-version -module $(all_libraries) $(KDE_PLUGIN)
+
+protocol_DATA = zeroconf.protocol invitation.protocol
+protocoldir = $(kde_servicesdir)
+
+services_DATA = _http._tcp _ftp._tcp _ldap._tcp _webdav._tcp _nfs._tcp _ssh._tcp
+servicesdir = $(kde_datadir)/zeroconf
+
+remote_DATA = zeroconf.desktop
+remotedir = $(kde_datadir)/remoteview
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp -o $(podir)/kio_zeroconf.pot
+
+METASOURCES = AUTO
diff --git a/kdnssd/ioslave/_ftp._tcp b/kdnssd/ioslave/_ftp._tcp
new file mode 100644
index 00000000..27655cb4
--- /dev/null
+++ b/kdnssd/ioslave/_ftp._tcp
@@ -0,0 +1,5 @@
+Name=FTP servers
+Type=_ftp._tcp
+PathEntry=path
+UserEntry=u
+PasswordEntry=p
diff --git a/kdnssd/ioslave/_http._tcp b/kdnssd/ioslave/_http._tcp
new file mode 100644
index 00000000..8ce740b7
--- /dev/null
+++ b/kdnssd/ioslave/_http._tcp
@@ -0,0 +1,5 @@
+Name=WWW servers
+Type=_http._tcp
+PathEntry=path
+UserEntry=u
+PasswordEntry=p
diff --git a/kdnssd/ioslave/_ldap._tcp b/kdnssd/ioslave/_ldap._tcp
new file mode 100644
index 00000000..74a3a0cf
--- /dev/null
+++ b/kdnssd/ioslave/_ldap._tcp
@@ -0,0 +1,2 @@
+Name=Lightweight Directory Access Protocol
+Type=_ldap._tcp
diff --git a/kdnssd/ioslave/_nfs._tcp b/kdnssd/ioslave/_nfs._tcp
new file mode 100644
index 00000000..4748fe5b
--- /dev/null
+++ b/kdnssd/ioslave/_nfs._tcp
@@ -0,0 +1,3 @@
+Name=NFS Remote directory
+Type=_nfs._tcp
+PathEntry=path
diff --git a/kdnssd/ioslave/_ssh._tcp b/kdnssd/ioslave/_ssh._tcp
new file mode 100644
index 00000000..9deadb3c
--- /dev/null
+++ b/kdnssd/ioslave/_ssh._tcp
@@ -0,0 +1,4 @@
+Name=Remote shell (ssh)
+Type=_ssh._tcp
+UserEntry=u
+PasswordEntry=p
diff --git a/kdnssd/ioslave/_telnet._tcp b/kdnssd/ioslave/_telnet._tcp
new file mode 100644
index 00000000..4a8c676b
--- /dev/null
+++ b/kdnssd/ioslave/_telnet._tcp
@@ -0,0 +1,4 @@
+Name=Remote shell (telnet)
+Type=_telnet._tcp
+UserEntry=u
+PasswordEntry=p
diff --git a/kdnssd/ioslave/_webdav._tcp b/kdnssd/ioslave/_webdav._tcp
new file mode 100644
index 00000000..3c99b54a
--- /dev/null
+++ b/kdnssd/ioslave/_webdav._tcp
@@ -0,0 +1,5 @@
+Name=WebDav remote directory
+Type=_webdav._tcp
+PathEntry=path
+UserEntry=u
+PasswordEntry=p
diff --git a/kdnssd/ioslave/dnssd.cpp b/kdnssd/ioslave/dnssd.cpp
new file mode 100644
index 00000000..650a37ff
--- /dev/null
+++ b/kdnssd/ioslave/dnssd.cpp
@@ -0,0 +1,369 @@
+/***************************************************************************
+ * Copyright (C) 2004, 2005 by Jakub Stachowski *
+ * *
+ * 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 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 <qcstring.h>
+#include <qsocket.h>
+#include <qdatetime.h>
+#include <qbitarray.h>
+
+#include <stdlib.h>
+#include <math.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <kinstance.h>
+#include <kglobal.h>
+#include <kstandarddirs.h>
+#include <ksocketaddress.h>
+#include <kprotocolinfo.h>
+#include <kcmdlineargs.h>
+#include <klocale.h>
+#include <kurl.h>
+#include <ksock.h>
+#include <qmap.h>
+#include <kapplication.h>
+#include <qeventloop.h>
+#include <dnssd/domainbrowser.h>
+#include <krun.h>
+
+
+#include "dnssd.h"
+
+static const KCmdLineOptions options[] =
+{
+ { "+protocol", I18N_NOOP( "Protocol name" ), 0 },
+ { "+pool", I18N_NOOP( "Socket name" ), 0 },
+ { "+app", I18N_NOOP( "Socket name" ), 0 },
+ KCmdLineLastOption
+};
+
+ZeroConfProtocol::ZeroConfProtocol(const QCString& protocol, const QCString &pool_socket, const QCString &app_socket)
+ : SlaveBase(protocol, pool_socket, app_socket), browser(0),toResolve(0),
+ configData(0)
+{}
+
+ZeroConfProtocol::~ZeroConfProtocol()
+{
+ delete configData;
+}
+
+void ZeroConfProtocol::get(const KURL& url )
+{
+ if (!dnssdOK()) return;
+ UrlType t = checkURL(url);
+ switch (t) {
+ case HelperProtocol:
+ {
+ resolveAndRedirect(url,true);
+ mimeType("text/html");
+ QString reply= "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n";
+ reply+="</head>\n<body>\n<h2>"+i18n("Requested service has been launched in separate window.");
+ reply+="</h2>\n</body></html>";
+ data(reply.utf8());
+ data(QByteArray());
+ finished();
+ break;
+ }
+ case Service:
+ resolveAndRedirect(url);
+ break;
+ default:
+ error(ERR_MALFORMED_URL,i18n("invalid URL"));
+ }
+}
+void ZeroConfProtocol::mimetype(const KURL& url )
+{
+ resolveAndRedirect(url);
+}
+
+UrlType ZeroConfProtocol::checkURL(const KURL& url)
+{
+ if (url.path()=="/") return RootDir;
+ QString service, type, domain;
+ dissect(url,service,type,domain);
+ const QString& proto = type.section('.',1,-1);
+ if (type[0]!='_' || (proto!="_udp" && proto!="_tcp")) return Invalid;
+ if (service.isEmpty()) return ServiceDir;
+ if (!domain.isEmpty()) {
+ if (!setConfig(type)) return Invalid;
+ if (!configData->readEntry("Exec").isNull()) return HelperProtocol;
+ return (KProtocolInfo::isHelperProtocol( configData->readEntry( "Protocol",
+ type.section(".",0,0).mid(1)))) ? HelperProtocol : Service;
+ }
+ return Invalid;
+}
+
+// URL zeroconf://domain/_http._tcp/some%20service
+// URL invitation://host:port/_http._tcp/some%20service?u=username&root=directory
+void ZeroConfProtocol::dissect(const KURL& url,QString& name,QString& type,QString& domain)
+{
+ type = url.path().section("/",1,1);
+ domain = url.host();
+ name = url.path().section("/",2,-1);
+
+}
+
+bool ZeroConfProtocol::dnssdOK()
+{
+ switch(ServiceBrowser::isAvailable()) {
+ case ServiceBrowser::Stopped:
+ error(KIO::ERR_UNSUPPORTED_ACTION,
+ i18n("The Zeroconf daemon (mdnsd) is not running."));
+ return false;
+ case ServiceBrowser::Unsupported:
+ error(KIO::ERR_UNSUPPORTED_ACTION,
+ i18n("KDE has been built without Zeroconf support."));
+ return false;
+ default:
+ return true;
+ }
+}
+
+void ZeroConfProtocol::stat(const KURL& url)
+{
+ UDSEntry entry;
+ if (!dnssdOK()) return;
+ UrlType t = checkURL(url);
+ switch (t) {
+ case RootDir:
+ case ServiceDir:
+ buildDirEntry(entry,"");
+ statEntry(entry);
+ finished();
+ break;
+ case Service:
+ resolveAndRedirect(url);
+ break;
+ case HelperProtocol:
+ {
+ QString name,type,domain;
+ dissect(url,name,type,domain);
+ buildServiceEntry(entry,name,type,domain);
+ statEntry(entry);
+ finished();
+ break;
+ }
+ default:
+ error(ERR_MALFORMED_URL,i18n("invalid URL"));
+ }
+}
+QString ZeroConfProtocol::getAttribute(const QString& name)
+{
+ QString entry = configData->readEntry(name);
+ return (entry.isNull()) ? QString::null : toResolve->textData()[entry];
+}
+
+void ZeroConfProtocol::resolveAndRedirect(const KURL& url, bool useKRun)
+{
+ QString name,type,domain;
+ dissect(url,name,type,domain);
+ if (url.protocol()=="invitation") {
+ delete toResolve;
+ toResolve=0;
+ toResolve= new RemoteService(url);
+ if (!toResolve->isResolved()) error(ERR_MALFORMED_URL,i18n("Invalid URL"));
+ } else {
+ kdDebug() << "Resolve for " << name << ", " << type << ", " << domain << "\n";
+ if (toResolve!=0)
+ if (toResolve->serviceName()==name && toResolve->type()==type &&
+ toResolve->domain()==domain && toResolve->isResolved()) {
+ } else {
+ delete toResolve;
+ toResolve = 0;
+ }
+ if (toResolve==0) {
+ toResolve = new RemoteService(name,type,domain);
+ // or maybe HOST_NOT_FOUND?
+ if (!toResolve->resolve()) error(ERR_SERVICE_NOT_AVAILABLE,i18n("Unable to resolve service"));
+ }
+ }
+ KURL destUrl;
+ kdDebug() << "Resolved: " << toResolve->hostName() << "\n";
+ destUrl.setProtocol(getProtocol(type));
+ destUrl.setUser(getAttribute("UserEntry"));
+ destUrl.setPass(getAttribute("PasswordEntry"));
+ destUrl.setPath(getAttribute("PathEntry"));
+ destUrl.setHost(toResolve->hostName());
+ destUrl.setPort(toResolve->port());
+ // get exec from config or try getting it from helper protocol
+ if (useKRun) KRun::run(configData->readEntry("Exec",KProtocolInfo::exec(getProtocol(type))),destUrl);
+ else {
+ redirection(destUrl);
+ finished();
+ }
+}
+
+bool ZeroConfProtocol::setConfig(const QString& type)
+{
+ kdDebug() << "Setting config for " << type << endl;
+ if (configData)
+ {
+ if (configData->readEntry("Type")!=type)
+ {
+ delete configData;
+ configData=0L;
+ }
+ else
+ return true;
+ }
+ configData = new KConfig("zeroconf/"+type,false,false,"data");
+ return (configData->readEntry("Type")==type);
+}
+
+inline void buildAtom(UDSEntry& entry,UDSAtomTypes type, const QString& data)
+{
+ UDSAtom atom;
+ atom.m_uds=type;
+ atom.m_str=data;
+ entry.append(atom);
+}
+inline void buildAtom(UDSEntry& entry,UDSAtomTypes type, long data)
+{
+ UDSAtom atom;
+ atom.m_uds=type;
+ atom.m_long=data;
+ entry.append(atom);
+}
+
+
+void ZeroConfProtocol::buildDirEntry(UDSEntry& entry,const QString& name,const QString& type, const QString& host)
+{
+ entry.clear();
+ buildAtom(entry,UDS_NAME,name);
+ buildAtom(entry,UDS_ACCESS,0555);
+ buildAtom(entry,UDS_SIZE,0);
+ buildAtom(entry,UDS_FILE_TYPE,S_IFDIR);
+ buildAtom(entry,UDS_MIME_TYPE,"inode/directory");
+ if (!type.isNull()) buildAtom(entry,UDS_URL,"zeroconf:/"+((!host.isNull()) ? "/"+host+"/" : "" )+type+"/");
+}
+QString ZeroConfProtocol::getProtocol(const QString& type)
+{
+ setConfig(type);
+ return configData->readEntry("Protocol",type.section(".",0,0).mid(1));
+}
+
+void ZeroConfProtocol::buildServiceEntry(UDSEntry& entry,const QString& name,const QString& type,const QString& domain)
+{
+ setConfig(type);
+ entry.clear();
+ buildAtom(entry,UDS_NAME,name);
+ buildAtom(entry,UDS_ACCESS,0666);
+ QString icon=configData->readEntry("Icon",KProtocolInfo::icon(getProtocol(type)));
+ if (!icon.isNull()) buildAtom(entry,UDS_ICON_NAME,icon);
+ KURL protourl;
+ protourl.setProtocol(getProtocol(type));
+ QString encname = "zeroconf://" + domain +"/" +type+ "/" + name;
+ if (KProtocolInfo::supportsListing(protourl)) {
+ buildAtom(entry,UDS_FILE_TYPE,S_IFDIR);
+ encname+="/";
+ } else buildAtom(entry,UDS_FILE_TYPE,S_IFREG);
+ buildAtom(entry,UDS_URL,encname);
+}
+
+void ZeroConfProtocol::listDir(const KURL& url )
+{
+
+ if (!dnssdOK()) return;
+ UrlType t = checkURL(url);
+ UDSEntry entry;
+ switch (t) {
+ case RootDir:
+ if (allDomains=url.host().isEmpty())
+ browser = new ServiceBrowser(ServiceBrowser::AllServices);
+ else browser = new ServiceBrowser(ServiceBrowser::AllServices,url.host());
+ connect(browser,SIGNAL(serviceAdded(DNSSD::RemoteService::Ptr)),
+ this,SLOT(newType(DNSSD::RemoteService::Ptr)));
+ break;
+ case ServiceDir:
+ if (url.host().isEmpty())
+ browser = new ServiceBrowser(url.path(-1).section("/",1,-1));
+ else browser = new ServiceBrowser(url.path(-1).section("/",1,-1),url.host());
+ connect(browser,SIGNAL(serviceAdded(DNSSD::RemoteService::Ptr)),
+ this,SLOT(newService(DNSSD::RemoteService::Ptr)));
+ break;
+ case Service:
+ resolveAndRedirect(url);
+ return;
+ default:
+ error(ERR_MALFORMED_URL,i18n("invalid URL"));
+ return;
+ }
+ connect(browser,SIGNAL(finished()),this,SLOT(allReported()));
+ browser->startBrowse();
+ kapp->eventLoop()->enterLoop();
+}
+void ZeroConfProtocol::allReported()
+{
+ UDSEntry entry;
+ listEntry(entry,true);
+ finished();
+ delete browser;
+ browser=0;
+ mergedtypes.clear();
+ kapp->eventLoop()->exitLoop();
+}
+void ZeroConfProtocol::newType(DNSSD::RemoteService::Ptr srv)
+{
+ if (mergedtypes.contains(srv->type())>0) return;
+ mergedtypes << srv->type();
+ UDSEntry entry;
+ kdDebug() << "Got new entry " << srv->type() << endl;
+ if (!setConfig(srv->type())) return;
+ QString name = configData->readEntry("Name");
+ if (!name.isNull()) {
+ buildDirEntry(entry,name,srv->type(), (allDomains) ? QString::null :
+ browser->browsedDomains()->domains()[0]);
+ listEntry(entry,false);
+ }
+}
+void ZeroConfProtocol::newService(DNSSD::RemoteService::Ptr srv)
+{
+ UDSEntry entry;
+ buildServiceEntry(entry,srv->serviceName(),srv->type(),srv->domain());
+ listEntry(entry,false);
+}
+
+
+extern "C"
+{
+ int KDE_EXPORT kdemain( int argc, char **argv )
+ {
+ // KApplication is necessary to use other ioslaves
+ putenv(strdup("SESSION_MANAGER="));
+ KCmdLineArgs::init(argc, argv, "kio_zeroconf", 0, 0, 0, 0);
+ KCmdLineArgs::addCmdLineOptions( options );
+ KApplication::disableAutoDcopRegistration();
+ KApplication app;
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+ ZeroConfProtocol slave( args->arg(0), args->arg(1), args->arg(2) );
+ slave.dispatchLoop();
+ return 0;
+ }
+}
+
+
+#include "dnssd.moc"
+
diff --git a/kdnssd/ioslave/dnssd.h b/kdnssd/ioslave/dnssd.h
new file mode 100644
index 00000000..0f24dbee
--- /dev/null
+++ b/kdnssd/ioslave/dnssd.h
@@ -0,0 +1,87 @@
+/***************************************************************************
+ * Copyright (C) 2004, 2005 by Jakub Stachowski *
+ * *
+ * 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 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 _dnssd_H_
+#define _dnssd_H_
+
+#include <qstring.h>
+#include <qcstring.h>
+#include <qobject.h>
+
+#include <kurl.h>
+#include <kio/global.h>
+#include <kio/slavebase.h>
+#include <dnssd/servicebrowser.h>
+#include <dnssd/remoteservice.h>
+#include <qstringlist.h>
+
+
+class QCString;
+using namespace KIO;
+using namespace DNSSD;
+
+enum UrlType { RootDir, ServiceDir, Service, HelperProtocol, Invalid };
+
+class ZeroConfProtocol : public QObject, public KIO::SlaveBase
+{
+ Q_OBJECT
+public:
+ ZeroConfProtocol(const QCString& protocol, const QCString &pool_socket, const QCString &app_socket);
+ ~ZeroConfProtocol();
+ virtual void get(const KURL& url);
+ virtual void mimetype(const KURL& url);
+ virtual void stat(const KURL& url);
+ virtual void listDir(const KURL& url );
+private:
+ // Create UDSEntry for zeroconf:/ or zeroconf:/type/ paths
+ void buildDirEntry(UDSEntry& entry,const QString& name,const QString& type=QString::null,
+ const QString& host=QString::null);
+ // Create UDSEntry for single services: dnssd:/type/service
+ void buildServiceEntry(UDSEntry& entry,const QString& name,const QString& type,
+ const QString& domain);
+ // Returns root dir, service dir, service or invalid
+ UrlType checkURL(const KURL& url);
+ // extract name, type and domain from URL
+ void dissect(const KURL& url,QString& name,QString& type,QString& domain);
+ // resolve given service and redirect() to it or use KRun on it (used for helper protocols)
+ void resolveAndRedirect(const KURL& url, bool useKRun = false);
+ bool dnssdOK();
+ QString getAttribute(const QString& name);
+ QString getProtocol(const QString& type);
+ // try to load config file for given service type (or just return if already loaded)
+ bool setConfig(const QString& type);
+
+ ServiceBrowser* browser;
+ // service types merged from all domains - to avoid duplicates
+ QStringList mergedtypes;
+ // last resolved or still being resolved services - acts as one-entry cache
+ RemoteService *toResolve;
+ // Config file for service - also acts as one-entry cache
+ KConfig *configData;
+ // listDir for all domains (zeroconf:/) or one specified (zeroconf://domain/)
+ bool allDomains;
+private slots:
+ void newType(DNSSD::RemoteService::Ptr);
+ void newService(DNSSD::RemoteService::Ptr);
+ void allReported();
+
+};
+
+#endif
diff --git a/kdnssd/ioslave/invitation.protocol b/kdnssd/ioslave/invitation.protocol
new file mode 100644
index 00000000..ef6b068c
--- /dev/null
+++ b/kdnssd/ioslave/invitation.protocol
@@ -0,0 +1,62 @@
+[Protocol]
+exec=kio_zeroconf
+protocol=invitation
+
+input=none
+output=filesystem
+listing=Name,Link,Type
+reading=true
+writing=false
+makedir=false
+deleting=false
+linking=false
+moving=false
+Icon=network_local
+Description=SD invitations
+Description[be]=Запрашэнні SD
+Description[bg]=Покани SD
+Description[bn]=এসডি আমন্ত্রণ
+Description[bs]=SD pozivi
+Description[ca]=Invitacions SD
+Description[cs]=SD pozvánky
+Description[da]=SD-invitationer
+Description[de]=SD-Einladungen
+Description[el]=Προσκλήσεις SD
+Description[es]=Invitaciones SD
+Description[et]=SD kutsed
+Description[eu]=SD gonbidapenak
+Description[fa]=دعوتهای SD
+Description[fi]=SD-kutsut
+Description[fr]=Invitations SD
+Description[gl]=Invitacións SD
+Description[hu]=SD meghívók
+Description[is]=SD boð
+Description[it]=Inviti SD
+Description[ja]=SD 招待
+Description[ka]=SD მოწვევა
+Description[kk]=SD шақырулар
+Description[km]=លិខិត​អញ្ជើញ SD
+Description[lt]=SD pakvietimai
+Description[nb]=SD invitasjoner
+Description[nds]=SD-Inladen
+Description[ne]=SD निमन्त्रणा
+Description[nl]=SD-uitnodigingen
+Description[nn]=SD-innbydingar
+Description[pa]=SD ਸੱਦਾ
+Description[pl]=Zaproszenia SD
+Description[pt]=Convites de SD
+Description[pt_BR]=solicitações SD
+Description[ru]=Приглашения SD
+Description[sk]=SD pozvánky
+Description[sl]=Povabila SD
+Description[sr]=SD позивнице
+Description[sr@Latn]=SD pozivnice
+Description[sv]=SD-inbjudningar
+Description[tr]=SD davetleri
+Description[uk]=Запрошення SD
+Description[zh_CN]=SD 邀请
+Description[zh_HK]=SD 邀請
+Description[zh_TW]=SD 邀請
+maxInstances=4
+Class=:remote
+
diff --git a/kdnssd/ioslave/zeroconf.desktop b/kdnssd/ioslave/zeroconf.desktop
new file mode 100644
index 00000000..abc41151
--- /dev/null
+++ b/kdnssd/ioslave/zeroconf.desktop
@@ -0,0 +1,56 @@
+[Desktop Entry]
+Icon=network_local
+Name=Network Services
+Name[be]=Сеткавыя сервісы
+Name[bg]=Мрежови услуги
+Name[bn]=নেটওয়ার্ক সার্ভিস
+Name[br]=Servijoù rouedad
+Name[bs]=Mrežni servisi
+Name[ca]=Serveis de xarxa
+Name[cs]=Síťové služby
+Name[da]=Netværkstjenester
+Name[de]=Netzwerkdienste
+Name[el]=Υπηρεσίες δικτύου
+Name[eo]=Retservoj
+Name[es]=Servicios de red
+Name[et]=Võrguteenused
+Name[eu]=Sare zerbitzuak
+Name[fa]=خدمات شبکه
+Name[fi]=Lähiverkkopalvelut
+Name[fr]=Services réseaux
+Name[ga]=Seirbhísí Líonra
+Name[gl]=Servicios de Rede
+Name[he]=שרותי רשת
+Name[hu]=Hálózati szolgáltatások
+Name[is]=Netþjónustur
+Name[it]=Servizi di rete
+Name[ja]=ネットワークサービス
+Name[ka]=ქსელის სერვისები
+Name[kk]=Желі қызметтері
+Name[km]=សេវា​បណ្ដាញ
+Name[lt]=Tinklo tarnybos
+Name[nb]=Nettverkstjenester
+Name[nds]=Nettwarkdeensten
+Name[ne]=सञ्जाल सेवा
+Name[nl]=Netwerkdiensten
+Name[nn]=Nettverkstenester
+Name[pa]=ਨੈੱਟਵਰਕ ਸੇਵਾਵਾਂ
+Name[pl]=Usługi sieciowe
+Name[pt]=Serviços de Rede
+Name[pt_BR]=Serviços de Rede
+Name[ro]=Servicii de reţea
+Name[ru]=Сетевые службы
+Name[sk]=Sieťové služby
+Name[sl]=Omrežne storitve
+Name[sr]=Мрежни сервиси
+Name[sr@Latn]=Mrežni servisi
+Name[sv]=Nätverkstjänster
+Name[tr]=Ağ Servisleri
+Name[uk]=Мережеві служби
+Name[uz]=Tarmoq xizmatlari
+Name[uz@cyrillic]=Тармоқ хизматлари
+Name[zh_CN]=网络服务
+Name[zh_HK]=網絡服務
+Name[zh_TW]=網路服務
+Type=Link
+URL=zeroconf:/
diff --git a/kdnssd/ioslave/zeroconf.protocol b/kdnssd/ioslave/zeroconf.protocol
new file mode 100644
index 00000000..5343b282
--- /dev/null
+++ b/kdnssd/ioslave/zeroconf.protocol
@@ -0,0 +1,63 @@
+[Protocol]
+exec=kio_zeroconf
+protocol=zeroconf
+
+input=none
+output=filesystem
+listing=Name,Link,Type
+reading=true
+writing=false
+makedir=false
+deleting=false
+linking=false
+moving=false
+Icon=network_local
+Description=A kioslave for ZeroConf
+Description[be]=Модуль kioslave для ZeroConf
+Description[bn]=জিরো-কন্ফ এর জন্য একটি কে-আই-ও স্লেভ
+Description[br]=Ur c'hioslave evit ZeroConf
+Description[bs]=kioslave za ZeroConf
+Description[ca]=Un kioslave per ZeroConf
+Description[cs]=Pomocný protokol pro Zeroconf
+Description[da]=En kioslave for Zeroconf
+Description[de]=Ein Ein-/Ausgabemodul für ZeroConf
+Description[el]=Ένα kioslave για το ZeroConf
+Description[es]=Un «kioslave» para ZeroConf
+Description[et]=ZeroConfi I/O-moodul
+Description[eu]= kioslave bat ZeroConf-erako
+Description[fa]=یک kioslave برای ZeroConf
+Description[fi]=Siirräntätyöskentelijä ZeroConfille
+Description[fr]=Un module d'entrée / sortie pour ZeroConf
+Description[gl]=Un kioslabe para ZeroConf
+Description[he]=kioslave בשביל ZeroConf
+Description[hu]=KDE-protokoll a Zeroconf használatához
+Description[is]=kioslave fyrir ZeroConf
+Description[it]=Un kioslave per Zeroconf
+Description[ja]=ZeroConf の kioslave
+Description[ka]= kioslave ZeroConfსთვის
+Description[kk]=ZeroConf-тың kioslave-і
+Description[km]=kioslave មួយ​សម្រាប់ ZeroConf
+Description[lt]=Antrinė KDE programa skirta ZeroConf
+Description[nb]=En kioslave for ZeroConf
+Description[nds]=In-/Utgaavmoduul för ZeroConf
+Description[ne]=जेरोकन्फका लागि कियोस्लाभ
+Description[nl]=Een kioslave voor ZeroConf
+Description[nn]=Ein kio-slave for ZeroConf
+Description[pl]=Wtyczka protokołu ZeroConf
+Description[pt]=Um 'kioslave' para o ZeroConf
+Description[pt_BR]=Um IO-Slave para o ZeroConf
+Description[ro]=Un dispozitiv de I/E pentru ZeroConf
+Description[ru]=Kioslave для ZeroConf
+Description[sk]=kioslave pre ZeroConf
+Description[sl]=Kioslave za ZeroConf
+Description[sr]=kioslave за ZeroConf
+Description[sr@Latn]=kioslave za ZeroConf
+Description[sv]=En I/O-slav för Zeroconf
+Description[tr]=Zeroconf kioslave'i
+Description[uk]=Kioslave для ZeroConf
+Description[zh_CN]=ZeroConf 的 kioslave
+Description[zh_HK]=用於 ZeroConf 的 kioslave
+Description[zh_TW]=ZeroConf 的 kioslave
+maxInstances=4
+Class=:local
+