summaryrefslogtreecommitdiffstats
path: root/krdc/kservicelocator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'krdc/kservicelocator.cpp')
-rw-r--r--krdc/kservicelocator.cpp760
1 files changed, 760 insertions, 0 deletions
diff --git a/krdc/kservicelocator.cpp b/krdc/kservicelocator.cpp
new file mode 100644
index 00000000..b8382db1
--- /dev/null
+++ b/krdc/kservicelocator.cpp
@@ -0,0 +1,760 @@
+/*
+ * Interface to find SLP services.
+ * Copyright (C) 2002 Tim Jansen <tim@tjansen.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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 Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "kservicelocator.h"
+#include <kdebug.h>
+#include <qregexp.h>
+#include <qapplication.h>
+
+#ifdef HAVE_SLP
+#include <slp.h>
+#include <qevent.h>
+#include <qthread.h>
+#endif
+
+const QString KServiceLocator::DEFAULT_AUTHORITY = "";
+const QString KServiceLocator::ALL_AUTHORITIES = QString::null;
+
+class AsyncThread;
+
+class KServiceLocatorPrivate {
+public:
+ KServiceLocator *m_ksl;
+ bool m_opened;
+ volatile bool m_abort;
+ QString m_lang;
+ bool m_async;
+
+ bool ensureOpen();
+
+ KServiceLocatorPrivate(KServiceLocator *ksl,
+ const QString &lang,
+ bool async);
+ ~KServiceLocatorPrivate();
+
+#ifdef HAVE_SLP
+ SLPHandle m_handle;
+ AsyncThread *m_thread;
+ QString m_operationServiceUrl; // for findAttributes()/foundAttributes()
+
+ friend class FindSrvTypesThread;
+ friend class FindSrvsThread;
+ friend class FindAttrsThread;
+ friend class FindScopesThread;
+
+ friend SLPBoolean srvTypeCallback(SLPHandle hslp,
+ const char* srvtypes,
+ SLPError errcode,
+ void* cookie);
+ friend SLPBoolean srvTypeCallbackAsync(SLPHandle hslp,
+ const char* srvtypes,
+ SLPError errcode,
+ void* cookie);
+ friend SLPBoolean srvUrlCallback(SLPHandle hslp,
+ const char* srvurl,
+ unsigned short lifetime,
+ SLPError errcode,
+ void* cookie);
+ friend SLPBoolean srvUrlCallbackAsync(SLPHandle hslp,
+ const char* srvurl,
+ unsigned short lifetime,
+ SLPError errcode,
+ void* cookie);
+ friend SLPBoolean srvAttrCallback(SLPHandle hslp,
+ const char* attrlist,
+ SLPError errcode,
+ void* cookie);
+ friend SLPBoolean srvAttrCallbackAsync(SLPHandle hslp,
+ const char* attrlist,
+ SLPError errcode,
+ void* cookie);
+
+ SLPBoolean handleSrvTypeCallback(const char* srvtypes,
+ SLPError errcode);
+ SLPBoolean handleSrvTypeCallbackAsync(const char* srvtypes,
+ SLPError errcode);
+ SLPBoolean handleSrvUrlCallback(const char* srvUrl,
+ unsigned short lifetime,
+ SLPError errcode);
+ SLPBoolean handleSrvUrlCallbackAsync(const char* srvUrl,
+ unsigned short lifetime,
+ SLPError errcode);
+ SLPBoolean handleAttrCallback(const char* attrlist,
+ SLPError errcode);
+ SLPBoolean handleAttrCallbackAsync(const char* attrlist,
+ SLPError errcode);
+#endif
+};
+
+KServiceLocator::KServiceLocator(const QString &lang, bool async) :
+ QObject(0, "KServiceLocator") {
+
+ d = new KServiceLocatorPrivate(this, lang, async);
+}
+
+KServiceLocatorPrivate::KServiceLocatorPrivate(KServiceLocator *ksl,
+ const QString &lang,
+ bool async) :
+ m_ksl(ksl),
+ m_opened(false),
+ m_abort(false),
+ m_lang(lang),
+ m_async(async) {
+
+#ifdef HAVE_SLP
+ m_thread = 0;
+#endif
+}
+
+
+#ifdef HAVE_SLP /** The real SLP implementations ********************** */
+
+
+/* ****** *** ****** *** ****** */
+/* Signals for async events */
+/* ****** *** ****** *** ****** */
+
+const int MinLastSignalEventType = 45001;
+const int LastServiceTypeSignalEventType = 45001;
+const int LastServiceSignalEventType = 45002;
+const int LastAttributesSignalEventType = 45003;
+const int MaxLastSignalEventType = 45003;
+class LastSignalEvent : public QCustomEvent
+{
+private:
+ bool m_success;
+public:
+ LastSignalEvent(int type, bool s) :
+ QCustomEvent(type),
+ m_success(s)
+ {};
+ int success() const { return m_success; };
+};
+
+const int FoundServiceTypesEventType = 45012;
+class FoundServiceTypesEvent : public QCustomEvent
+{
+private:
+ QString m_srvtypes;
+public:
+ FoundServiceTypesEvent(const char *srvtypes) :
+ QCustomEvent(FoundServiceTypesEventType),
+ m_srvtypes(srvtypes)
+ {};
+ QString srvtypes() const { return m_srvtypes; };
+};
+
+const int FoundServiceEventType = 45013;
+class FoundServiceEvent : public QCustomEvent
+{
+private:
+ QString m_srvUrl;
+ unsigned short m_lifetime;
+public:
+ FoundServiceEvent(const char *srvUrl, unsigned short lifetime) :
+ QCustomEvent(FoundServiceEventType),
+ m_srvUrl(srvUrl),
+ m_lifetime(lifetime)
+ {};
+ QString srvUrl() const { return m_srvUrl; };
+ unsigned short lifetime() const { return m_lifetime; };
+};
+
+const int FoundAttributesEventType = 45014;
+class FoundAttributesEvent : public QCustomEvent
+{
+private:
+ QString m_attributes;
+public:
+ FoundAttributesEvent(const char *attributes) :
+ QCustomEvent(FoundAttributesEventType),
+ m_attributes(attributes)
+ {};
+ QString attributes() const { return m_attributes; };
+};
+
+const int FoundScopesEventType = 45015;
+class FoundScopesEvent : public QCustomEvent
+{
+private:
+ QString m_scopes;
+public:
+ FoundScopesEvent(const char *scopes) :
+ QCustomEvent(FoundScopesEventType),
+ m_scopes(scopes)
+ {};
+ QString scopes() const { return m_scopes; };
+};
+
+
+
+/* ****** *** ****** *** ****** */
+/* Callbacks */
+/* ****** *** ****** *** ****** */
+
+SLPBoolean srvTypeCallback(SLPHandle,
+ const char* srvtypes,
+ SLPError errcode,
+ void* cookie) {
+ KServiceLocatorPrivate *ksl = (KServiceLocatorPrivate*) cookie;
+ return ksl->handleSrvTypeCallback(srvtypes, errcode);
+}
+SLPBoolean srvTypeCallbackAsync(SLPHandle,
+ const char* srvtypes,
+ SLPError errcode,
+ void* cookie) {
+ KServiceLocatorPrivate *ksl = (KServiceLocatorPrivate*) cookie;
+ if ((errcode != SLP_OK) || ksl->m_abort) {
+ QApplication::postEvent(ksl->m_ksl, new LastSignalEvent(LastServiceTypeSignalEventType,
+ (errcode == SLP_OK) ||
+ (errcode == SLP_LAST_CALL) ||
+ ksl->m_abort));
+ return SLP_FALSE;
+ }
+ QApplication::postEvent(ksl->m_ksl, new FoundServiceTypesEvent(srvtypes));
+ return SLP_TRUE;
+}
+
+SLPBoolean srvUrlCallback(SLPHandle,
+ const char* srvurl,
+ unsigned short lifetime,
+ SLPError errcode,
+ void* cookie) {
+ KServiceLocatorPrivate *ksl = (KServiceLocatorPrivate*) cookie;
+ return ksl->handleSrvUrlCallback(srvurl, lifetime, errcode);
+}
+SLPBoolean srvUrlCallbackAsync(SLPHandle,
+ const char* srvurl,
+ unsigned short lifetime,
+ SLPError errcode,
+ void* cookie) {
+ KServiceLocatorPrivate *ksl = (KServiceLocatorPrivate*) cookie;
+ if ((errcode != SLP_OK) || ksl->m_abort) {
+ QApplication::postEvent(ksl->m_ksl, new LastSignalEvent(LastServiceSignalEventType,
+ (errcode == SLP_OK) ||
+ (errcode == SLP_LAST_CALL) ||
+ ksl->m_abort));
+ return SLP_FALSE;
+ }
+ QApplication::postEvent(ksl->m_ksl,
+ new FoundServiceEvent(srvurl, lifetime));
+ return SLP_TRUE;
+}
+
+SLPBoolean srvAttrCallback(SLPHandle,
+ const char* attrlist,
+ SLPError errcode,
+ void* cookie) {
+ KServiceLocatorPrivate *ksl = (KServiceLocatorPrivate*) cookie;
+ return ksl->handleAttrCallback(attrlist, errcode);
+}
+SLPBoolean srvAttrCallbackAsync(SLPHandle,
+ const char* attrlist,
+ SLPError errcode,
+ void* cookie) {
+ KServiceLocatorPrivate *ksl = (KServiceLocatorPrivate*) cookie;
+ if ((errcode != SLP_OK) || ksl->m_abort) {
+ QApplication::postEvent(ksl->m_ksl,
+ new LastSignalEvent(LastAttributesSignalEventType,
+ (errcode == SLP_OK) ||
+ (errcode == SLP_LAST_CALL) ||
+ ksl->m_abort));
+ return SLP_FALSE;
+ }
+ QApplication::postEvent(ksl->m_ksl,
+ new FoundAttributesEvent(attrlist));
+ return SLP_TRUE;
+}
+
+
+
+/* ****** *** ****** *** ****** */
+/* Threads for async events */
+/* ****** *** ****** *** ****** */
+
+class AsyncThread : public QThread {
+protected:
+ SLPHandle m_handle;
+ KServiceLocatorPrivate *m_parent;
+ AsyncThread(SLPHandle handle, KServiceLocatorPrivate *parent) :
+ m_handle(handle),
+ m_parent(parent) {
+ }
+};
+class FindSrvTypesThread : public AsyncThread {
+ QString m_namingAuthority, m_scopeList;
+public:
+ FindSrvTypesThread(SLPHandle handle,
+ KServiceLocatorPrivate *parent,
+ const char *namingAuthority,
+ const char *scopeList) :
+ AsyncThread(handle, parent),
+ m_namingAuthority(namingAuthority),
+ m_scopeList(scopeList){
+ }
+ virtual void run() {
+ SLPError e;
+ e = SLPFindSrvTypes(m_handle,
+ m_namingAuthority.latin1(),
+ m_scopeList.latin1(),
+ srvTypeCallbackAsync,
+ m_parent);
+ if (e != SLP_OK)
+ QApplication::postEvent(m_parent->m_ksl,
+ new LastSignalEvent(LastServiceTypeSignalEventType,
+ false));
+ }
+};
+class FindSrvsThread : public AsyncThread {
+ QString m_srvUrl, m_scopeList, m_filter;
+public:
+ FindSrvsThread(SLPHandle handle,
+ KServiceLocatorPrivate *parent,
+ const char *srvUrl,
+ const char *scopeList,
+ const char *filter) :
+ AsyncThread(handle, parent),
+ m_srvUrl(srvUrl),
+ m_scopeList(scopeList),
+ m_filter(filter) {
+ }
+ virtual void run() {
+ SLPError e;
+
+ e = SLPFindSrvs(m_handle,
+ m_srvUrl.latin1(),
+ m_scopeList.isNull() ? "" : m_scopeList.latin1(),
+ m_filter.isNull() ? "" : m_filter.latin1(),
+ srvUrlCallbackAsync,
+ m_parent);
+ if (e != SLP_OK)
+ QApplication::postEvent(m_parent->m_ksl,
+ new LastSignalEvent(LastServiceSignalEventType,
+ false));
+ }
+};
+class FindAttrsThread : public AsyncThread {
+ QString m_srvUrl, m_scopeList, m_attrIds;
+public:
+ FindAttrsThread(SLPHandle handle,
+ KServiceLocatorPrivate *parent,
+ const char *srvUrl,
+ const char *scopeList,
+ const char *attrIds) :
+ AsyncThread(handle, parent),
+ m_srvUrl(srvUrl),
+ m_scopeList(scopeList),
+ m_attrIds(attrIds) {
+ }
+ virtual void run() {
+ SLPError e;
+ e = SLPFindAttrs(m_handle,
+ m_srvUrl.latin1(),
+ m_scopeList.isNull() ? "" : m_scopeList.latin1(),
+ m_attrIds.isNull() ? "" : m_attrIds.latin1(),
+ srvAttrCallbackAsync,
+ m_parent);
+ if (e != SLP_OK)
+ QApplication::postEvent(m_parent->m_ksl,
+ new LastSignalEvent(LastAttributesSignalEventType,
+ false));
+ }
+};
+class FindScopesThread : public AsyncThread {
+public:
+ FindScopesThread(SLPHandle handle,
+ KServiceLocatorPrivate *parent) :
+ AsyncThread(handle, parent){
+ }
+ virtual void run() {
+ SLPError e;
+ char *_scopelist;
+
+ e = SLPFindScopes(m_handle, &_scopelist);
+ if (e != SLP_OK) {
+ QApplication::postEvent(m_parent->m_ksl,
+ new FoundScopesEvent(""));
+ return;
+ }
+
+ QString scopeList(_scopelist);
+ SLPFree(_scopelist);
+ QApplication::postEvent(m_parent->m_ksl,
+ new FoundScopesEvent(scopeList.latin1()));
+ }
+};
+
+KServiceLocatorPrivate::~KServiceLocatorPrivate() {
+ if (m_thread) {
+ m_abort = true;
+ m_thread->wait();
+ delete m_thread;
+ m_thread = 0; // important, because event handler will run
+ }
+ if (m_opened)
+ SLPClose(m_handle);
+}
+
+KServiceLocator::~KServiceLocator() {
+ delete d;
+}
+
+bool KServiceLocator::available() {
+ return d->ensureOpen();
+}
+
+void KServiceLocator::abortOperation() {
+ d->m_abort = true;
+}
+
+bool KServiceLocatorPrivate::ensureOpen() {
+ SLPError e;
+
+ if (m_opened)
+ return true;
+ e = SLPOpen(m_lang.latin1(), SLP_FALSE, &m_handle);
+ if (e != SLP_OK) {
+ kdError() << "KServiceLocator: error while opening:" << e <<endl;
+ return false;
+ }
+ m_opened = true;
+ return true;
+}
+
+bool KServiceLocator::findServiceTypes(const QString &namingAuthority,
+ const QString &scopeList) {
+ if (!d->ensureOpen())
+ return false;
+ if (d->m_thread)
+ return false;
+ d->m_abort = false;
+
+ if (d->m_async) {
+ d->m_thread = new FindSrvTypesThread(d->m_handle,
+ d,
+ namingAuthority.isNull() ? "*" : namingAuthority.latin1(),
+ scopeList.isNull() ? "" : scopeList.latin1());
+ d->m_thread->start();
+ return true;
+ }
+ else {
+ SLPError e;
+ e = SLPFindSrvTypes(d->m_handle,
+ namingAuthority.isNull() ? "*" : namingAuthority.latin1(),
+ scopeList.isNull() ? "" : scopeList.latin1(),
+ srvTypeCallback,
+ d);
+ return e == SLP_OK;
+ }
+}
+
+bool KServiceLocator::findServices(const QString &srvtype,
+ const QString &filter,
+ const QString &scopeList) {
+ if (!d->ensureOpen())
+ return false;
+ if (d->m_thread)
+ return false;
+ d->m_abort = false;
+
+ if (d->m_async) {
+ d->m_thread = new FindSrvsThread(d->m_handle,
+ d,
+ srvtype.latin1(),
+ scopeList.isNull() ? "" : scopeList.latin1(),
+ filter.isNull() ? "" : filter.latin1());
+ d->m_thread->start();
+ return true;
+ }
+ else {
+ SLPError e;
+ e = SLPFindSrvs(d->m_handle,
+ srvtype.latin1(),
+ scopeList.isNull() ? "" : scopeList.latin1(),
+ filter.isNull() ? "" : filter.latin1(),
+ srvUrlCallback,
+ d);
+ return e == SLP_OK;
+ }
+}
+
+bool KServiceLocator::findAttributes(const QString &serviceUrl,
+ const QString &attributeIds) {
+ if (!d->ensureOpen())
+ return false;
+ if (d->m_thread)
+ return false;
+ d->m_abort = false;
+
+ d->m_operationServiceUrl = serviceUrl;
+ if (d->m_async) {
+ d->m_thread = new FindAttrsThread(d->m_handle,
+ d,
+ serviceUrl.latin1(),
+ "",
+ attributeIds.isNull() ? "" : attributeIds.latin1());
+ d->m_thread->start();
+ return true;
+ }
+ else {
+ SLPError e;
+ e = SLPFindAttrs(d->m_handle,
+ serviceUrl.latin1(),
+ "",
+ attributeIds.isNull() ? "" : attributeIds.latin1(),
+ srvAttrCallback,
+ d);
+ return e == SLP_OK;
+ }
+}
+
+bool KServiceLocator::findScopes() {
+ if (!d->ensureOpen())
+ return false;
+ if (d->m_thread)
+ return false;
+ d->m_abort = false;
+
+ if (d->m_async) {
+ d->m_thread = new FindScopesThread(d->m_handle, d);
+ d->m_thread->start();
+ return true;
+ }
+ else {
+ SLPError e;
+ char *_scopelist;
+ QStringList scopeList;
+ e = SLPFindScopes(d->m_handle, &_scopelist);
+ if (e != SLP_OK)
+ return false;
+ scopeList = parseCommaList(_scopelist);
+ SLPFree(_scopelist);
+ emit foundScopes(scopeList);
+ return true;
+ }
+}
+
+SLPBoolean KServiceLocatorPrivate::handleSrvTypeCallback(const char* srvtypes,
+ SLPError errcode) {
+ if ((errcode != SLP_OK) || m_abort) {
+ m_ksl->emitLastServiceTypeSignal((errcode == SLP_OK) ||
+ (errcode == SLP_LAST_CALL) ||
+ m_abort);
+ return SLP_FALSE;
+ }
+ m_ksl->emitFoundServiceTypes(srvtypes);
+ return SLP_TRUE;
+}
+
+SLPBoolean KServiceLocatorPrivate::handleSrvUrlCallback(const char* srvurl,
+ unsigned short lifetime,
+ SLPError errcode) {
+ if ((errcode != SLP_OK) || m_abort) {
+ m_ksl->emitLastServiceSignal((errcode == SLP_OK) ||
+ (errcode == SLP_LAST_CALL) ||
+ m_abort);
+ return SLP_FALSE;
+ }
+ m_ksl->emitFoundService(srvurl, lifetime);
+ return SLP_TRUE;
+}
+
+SLPBoolean KServiceLocatorPrivate::handleAttrCallback(const char* attrlist,
+ SLPError errcode) {
+ if ((errcode != SLP_OK) || m_abort) {
+ m_ksl->emitLastAttributesSignal((errcode == SLP_OK) ||
+ (errcode == SLP_LAST_CALL) ||
+ m_abort);
+ return SLP_FALSE;
+ }
+ m_ksl->emitFoundAttributes(m_operationServiceUrl, attrlist);
+ return SLP_TRUE;
+}
+
+
+void KServiceLocator::customEvent(QCustomEvent *e) {
+ if ((e->type() >= MinLastSignalEventType) &&
+ (e->type() <= MaxLastSignalEventType)){
+ bool s = true;
+ if (d->m_thread) {
+ d->m_thread->wait();
+ delete d->m_thread;
+ d->m_thread = 0;
+ s = ((LastSignalEvent*)e)->success();
+ }
+ if (e->type() == LastServiceTypeSignalEventType)
+ emit lastServiceTypeSignal(s);
+ else if (e->type() == LastServiceSignalEventType)
+ emit lastServiceSignal(s);
+ else if (e->type() == LastAttributesSignalEventType)
+ emit lastAttributesSignal(s);
+ else
+ kdFatal() << "unmapped last signal type " << e->type()<< endl;
+ }
+ else if (e->type() == FoundAttributesEventType) {
+ emit foundAttributes(d->m_operationServiceUrl,
+ ((FoundAttributesEvent*)e)->attributes());
+ }
+ else if (e->type() == FoundServiceEventType) {
+ FoundServiceEvent *fse = (FoundServiceEvent*)e;
+ emit foundService(fse->srvUrl(), fse->lifetime());
+ }
+ else if (e->type() == FoundServiceTypesEventType) {
+ emit foundServiceTypes(((FoundServiceTypesEvent*)e)->srvtypes());
+ }
+ else if (e->type() == FoundScopesEventType) {
+ if (d->m_thread) {
+ d->m_thread->wait();
+ delete d->m_thread;
+ d->m_thread = 0;
+ emit foundScopes(KServiceLocator::parseCommaList(((FoundScopesEvent*)e)->scopes()));
+ }
+ }
+}
+
+QString KServiceLocator::decodeAttributeValue(const QString &value) {
+ char *n;
+ if (value.isNull())
+ return value;
+ if (SLPUnescape(value.latin1(), &n, SLP_TRUE) != SLP_OK)
+ return QString::null;
+ QString r(n);
+ SLPFree(n);
+ return r;
+}
+
+#else /** Empty dummy functions is SLP is not available ************************* */
+
+
+KServiceLocator::~KServiceLocator() {
+}
+bool KServiceLocator::available() {
+ return false;
+}
+void KServiceLocator::abortOperation() {
+}
+bool KServiceLocator::findServiceTypes(const QString &,const QString &) {
+ return false;
+}
+bool KServiceLocator::findServices(const QString &,const QString &,const QString &) {
+ return false;
+}
+bool KServiceLocator::findAttributes(const QString &,const QString &) {
+ return false;
+}
+bool KServiceLocator::findScopes() {
+ return false;
+}
+void KServiceLocator::customEvent(QCustomEvent *) {
+}
+QString KServiceLocator::decodeAttributeValue(const QString &value) {
+ return value;
+}
+
+#endif
+
+
+/*** Private emit-helpers ***/
+
+void KServiceLocator::emitFoundServiceTypes(QString serviceTypes) {
+ emit foundServiceTypes(serviceTypes);
+}
+void KServiceLocator::emitFoundService(QString serviceUrl,
+ int lifetime) {
+ emit foundService(serviceUrl, lifetime);
+}
+void KServiceLocator::emitFoundAttributes(QString serviceUrl,
+ QString attributes) {
+ emit foundAttributes(serviceUrl, attributes);
+}
+void KServiceLocator::emitFoundScopes(QStringList scopeList) {
+ emit foundScopes(scopeList);
+}
+void KServiceLocator::emitLastServiceTypeSignal(bool success) {
+ emit lastServiceTypeSignal(success);
+}
+void KServiceLocator::emitLastServiceSignal(bool success) {
+ emit lastServiceSignal(success);
+}
+void KServiceLocator::emitLastAttributesSignal(bool success) {
+ emit lastAttributesSignal(success);
+}
+
+
+
+/*** Static helpers ***/
+
+void KServiceLocator::parseAttributeList(const QString &attributes,
+ QMap<QString,QString> &attributeMap) {
+ QRegExp r("\\((.*)=(.*)\\)");
+ r.setMinimal(true);
+ int pos = 0;
+ while (pos >= 0) {
+ pos = r.search(attributes, pos);
+ if (pos != -1) {
+ attributeMap[r.cap(1)] = r.cap(2);
+ pos += r.matchedLength();
+ }
+ }
+}
+
+QStringList KServiceLocator::parseCommaList(const QString &list) {
+ return QStringList::split(QChar(','), list);
+}
+
+QString KServiceLocator::createCommaList(const QStringList &values) {
+ return values.join(",");
+}
+
+QString KServiceLocator::escapeFilter(const QString &str) {
+ QString f;
+ int s = str.length();
+ for (int i = 0; i < s; i++) {
+ char c = str[i];
+ switch(c) {
+ case '*':
+ f.append("\2a");
+ break;
+ case '(':
+ f.append("\28");
+ break;
+ case ')':
+ f.append("\29");
+ break;
+ case '\\':
+ f.append("\5c");
+ break;
+ case 0:
+ f.append("\2a");
+ break;
+ default:
+ f.append(c);
+ break;
+ }
+ }
+ return f;
+}
+
+#include "kservicelocator.moc"
+