diff --git a/src/common/davcollectionsmultifetchjob.cpp b/src/common/davcollectionsmultifetchjob.cpp index a6be662..a63ac2b 100644 --- a/src/common/davcollectionsmultifetchjob.cpp +++ b/src/common/davcollectionsmultifetchjob.cpp @@ -1,65 +1,78 @@ /* Copyright (c) 2010 Tobias Koenig 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "davcollectionsmultifetchjob.h" #include "davcollectionsfetchjob.h" using namespace KDAV; +namespace KDAV { +class DavCollectionsMultiFetchJobPrivate +{ +public: + DavUrl::List mUrls; + DavCollection::List mCollections; + int mSubJobCount = -1; +}; +} + DavCollectionsMultiFetchJob::DavCollectionsMultiFetchJob(const DavUrl::List &urls, QObject *parent) : KJob(parent) - , mUrls(urls) - , mSubJobCount(urls.size()) + , d(new DavCollectionsMultiFetchJobPrivate) { + d->mUrls = urls; + d->mSubJobCount = urls.size(); } +DavCollectionsMultiFetchJob::~DavCollectionsMultiFetchJob() = default; + void DavCollectionsMultiFetchJob::start() { - if (mUrls.isEmpty()) { + if (d->mUrls.isEmpty()) { emitResult(); } - for (const DavUrl &url : qAsConst(mUrls)) { + for (const DavUrl &url : qAsConst(d->mUrls)) { DavCollectionsFetchJob *job = new DavCollectionsFetchJob(url, this); connect(job, &DavCollectionsFetchJob::result, this, &DavCollectionsMultiFetchJob::davJobFinished); connect(job, &DavCollectionsFetchJob::collectionDiscovered, this, &DavCollectionsMultiFetchJob::collectionDiscovered); job->start(); } } DavCollection::List DavCollectionsMultiFetchJob::collections() const { - return mCollections; + return d->mCollections; } void DavCollectionsMultiFetchJob::davJobFinished(KJob *job) { DavCollectionsFetchJob *fetchJob = qobject_cast(job); if (job->error()) { setError(job->error()); setErrorText(job->errorText()); } else { - mCollections << fetchJob->collections(); + d->mCollections << fetchJob->collections(); } - if (--mSubJobCount == 0) { + if (--d->mSubJobCount == 0) { emitResult(); } } diff --git a/src/common/davcollectionsmultifetchjob.h b/src/common/davcollectionsmultifetchjob.h index f80cafd..e435c99 100644 --- a/src/common/davcollectionsmultifetchjob.h +++ b/src/common/davcollectionsmultifetchjob.h @@ -1,79 +1,83 @@ /* Copyright (c) 2010 Tobias Koenig 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDAV_DAVCOLLECTIONSMULTIFETCHJOB_H #define KDAV_DAVCOLLECTIONSMULTIFETCHJOB_H #include "kpimkdav_export.h" #include "davcollection.h" #include "davurl.h" #include +#include + namespace KDAV { +class DavCollectionsMultiFetchJobPrivate; + /** * @short A job that fetches all DAV collection. * * This job is used to fetch all DAV collection that are available * under a certain list of DAV urls. * * @note This class just combines multiple calls of DavCollectionsFetchJob * into one job. */ class KPIMKDAV_EXPORT DavCollectionsMultiFetchJob : public KJob { Q_OBJECT public: /** * Creates a new dav collections multi fetch job. * * @param urls The list of DAV urls whose sub collections shall be fetched. * @param parent The parent object. */ explicit DavCollectionsMultiFetchJob(const DavUrl::List &urls, QObject *parent = nullptr); + ~DavCollectionsMultiFetchJob(); /** * Starts the job. */ void start() override; /** * Returns the list of fetched DAV collections. */ Q_REQUIRED_RESULT DavCollection::List collections() const; Q_SIGNALS: /** * This signal is emitted every time a new collection has been discovered. * * @param collectionUrl The URL of the discovered collection * @param configuredUrl The URL given to the job */ void collectionDiscovered(int protocol, const QString &collectionUrl, const QString &configuredUrl); private: void davJobFinished(KJob *); - DavUrl::List mUrls; - DavCollection::List mCollections; - int mSubJobCount = -1; + + const std::unique_ptr d; }; } #endif diff --git a/src/common/davmanager.cpp b/src/common/davmanager.cpp index 11cc145..5eaf661 100644 --- a/src/common/davmanager.cpp +++ b/src/common/davmanager.cpp @@ -1,124 +1,113 @@ /* Copyright (c) 2010 Tobias Koenig 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "davmanager.h" #include "protocols/caldavprotocol.h" #include "protocols/carddavprotocol.h" #include "protocols/groupdavprotocol.h" #include #include "libkdav_debug.h" #include #include using namespace KDAV; -DavManager *DavManager::mSelf = nullptr; - -DavManager::DavManager() +namespace KDAV { +class DavManagerPrivate { +public: + std::unique_ptr mProtocols[PROTOCOL_COUNT]; +}; } -DavManager::~DavManager() +DavManager::DavManager() : + d(new DavManagerPrivate) { - QMapIterator it(mProtocols); - while (it.hasNext()) { - it.next(); - delete it.value(); - } } +DavManager::~DavManager() = default; + DavManager *DavManager::self() { - if (!mSelf) { - mSelf = new DavManager(); - } - - return mSelf; + static DavManager sSelf; + return &sSelf; } KIO::DavJob *DavManager::createPropFindJob(const QUrl &url, const QDomDocument &document, const QString &depth) const { KIO::DavJob *job = KIO::davPropFind(url, document, depth, KIO::HideProgressInfo | KIO::DefaultFlags); // workaround needed, Depth: header doesn't seem to be correctly added const QString header = QLatin1String("Content-Type: text/xml\r\nDepth: ") + depth; job->addMetaData(QStringLiteral("customHTTPHeader"), header); job->addMetaData(QStringLiteral("cookies"), QStringLiteral("none")); job->addMetaData(QStringLiteral("no-auth-prompt"), QStringLiteral("true")); job->setProperty("extraDavDepth", QVariant::fromValue(depth)); return job; } KIO::DavJob *DavManager::createReportJob(const QUrl &url, const QDomDocument &document, const QString &depth) const { KIO::DavJob *job = KIO::davReport(url, document.toString(), depth, KIO::HideProgressInfo | KIO::DefaultFlags); // workaround needed, Depth: header doesn't seem to be correctly added const QString header = QLatin1String("Content-Type: text/xml\r\nDepth: ") + depth; job->addMetaData(QStringLiteral("customHTTPHeader"), header); job->addMetaData(QStringLiteral("cookies"), QStringLiteral("none")); job->addMetaData(QStringLiteral("no-auth-prompt"), QStringLiteral("true")); job->setProperty("extraDavDepth", QVariant::fromValue(depth)); return job; } KIO::DavJob *DavManager::createPropPatchJob(const QUrl &url, const QDomDocument &document) const { KIO::DavJob *job = KIO::davPropPatch(url, document, KIO::HideProgressInfo | KIO::DefaultFlags); const QString header = QStringLiteral("Content-Type: text/xml"); job->addMetaData(QStringLiteral("customHTTPHeader"), header); job->addMetaData(QStringLiteral("cookies"), QStringLiteral("none")); job->addMetaData(QStringLiteral("no-auth-prompt"), QStringLiteral("true")); return job; } const DavProtocolBase *DavManager::davProtocol(Protocol protocol) { - if (createProtocol(protocol)) { - return mProtocols[ protocol ]; - } else { - return nullptr; + if (!d->mProtocols[protocol]) { + switch (protocol) { + case KDAV::CalDav: + d->mProtocols[KDAV::CalDav].reset(new CaldavProtocol()); + break; + case KDAV::CardDav: + d->mProtocols[KDAV::CardDav].reset(new CarddavProtocol()); + break; + case KDAV::GroupDav: + d->mProtocols[KDAV::GroupDav].reset(new GroupdavProtocol()); + break; + default: + qCCritical(KDAV_LOG) << "Unknown protocol: " << static_cast(protocol); + return nullptr; + } } -} -bool DavManager::createProtocol(Protocol protocol) -{ - if (mProtocols.contains(protocol)) { - return true; - } - - switch (protocol) { - case KDAV::CalDav: - mProtocols.insert(KDAV::CalDav, new CaldavProtocol()); - return true; - case KDAV::CardDav: - mProtocols.insert(KDAV::CardDav, new CarddavProtocol()); - return true; - case KDAV::GroupDav: - mProtocols.insert(KDAV::GroupDav, new GroupdavProtocol()); - return true; - } - qCCritical(KDAV_LOG) << "Unknown protocol: " << static_cast(protocol); - return false; + return d->mProtocols[protocol].get(); } diff --git a/src/common/davmanager.h b/src/common/davmanager.h index f2386ea..8928408 100644 --- a/src/common/davmanager.h +++ b/src/common/davmanager.h @@ -1,109 +1,105 @@ /* Copyright (c) 2010 Tobias Koenig 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDAV_DAVMANAGER_H #define KDAV_DAVMANAGER_H #include "kpimkdav_export.h" #include "enums.h" #include #include +#include + namespace KIO { class DavJob; } class QUrl; class QDomDocument; /** CalDav/CardDav protocol implementation. */ namespace KDAV { class DavProtocolBase; +class DavManagerPrivate; /** * @short A factory class for handling DAV jobs. * * This class provides factory methods to create preconfigured * low-level DAV jobs and has access to the global DAV protocol dialect * objects which abstract the access to the various DAV protocol dialects. */ class KPIMKDAV_EXPORT DavManager { public: /** * Destroys the DAV manager. */ ~DavManager(); /** * Returns the global instance of the DAV manager. */ static DavManager *self(); /** * Returns a preconfigured DAV PROPFIND job. * * @param url The target url of the job. * @param document The query XML document. * @param depth The Depth: value to send in the HTTP request */ KIO::DavJob *createPropFindJob(const QUrl &url, const QDomDocument &document, const QString &depth = QStringLiteral("1")) const; /** * Returns a preconfigured DAV REPORT job. * * @param url The target url of the job. * @param document The query XML document. * @param depth The Depth: value to send in the HTTP request */ KIO::DavJob *createReportJob(const QUrl &url, const QDomDocument &document, const QString &depth = QStringLiteral("1")) const; /** * Returns a preconfigured DAV PROPPATCH job. * * @param url The target url of the job. * @param document The query XML document. */ KIO::DavJob *createPropPatchJob(const QUrl &url, const QDomDocument &document) const; /** * Returns the DAV protocol dialect object for the given DAV @p protocol. */ const DavProtocolBase *davProtocol(Protocol protocol); private: /** * Creates a new DAV manager. */ DavManager(); - /** - * Creates a new protocol. - */ - bool createProtocol(Protocol protocol); - - typedef QMap protocolsMap; - protocolsMap mProtocols; - static DavManager *mSelf; + const std::unique_ptr d; }; } #endif diff --git a/src/common/davprincipalsearchjob.cpp b/src/common/davprincipalsearchjob.cpp index a860a1b..6bb5dd9 100644 --- a/src/common/davprincipalsearchjob.cpp +++ b/src/common/davprincipalsearchjob.cpp @@ -1,376 +1,397 @@ /* Copyright (c) 2011 Grégory Oestreicher 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "davprincipalsearchjob.h" +#include "davjobbase_p.h" #include "davmanager.h" #include "utils.h" #include "daverror.h" #include #include #include using namespace KDAV; +namespace KDAV { +class DavPrincipalSearchJobPrivate : public DavJobBasePrivate +{ +public: + DavUrl mUrl; + DavPrincipalSearchJob::FilterType mType; + QString mFilter; + int mPrincipalPropertySearchSubJobCount = 0; + bool mPrincipalPropertySearchSubJobSuccessful = false; + QList< QPair > mFetchProperties; + QVector mResults; +}; +} + DavPrincipalSearchJob::DavPrincipalSearchJob(const DavUrl &url, DavPrincipalSearchJob::FilterType type, const QString &filter, QObject *parent) - : DavJobBase(parent) - , mUrl(url) - , mType(type) - , mFilter(filter) - , mPrincipalPropertySearchSubJobCount(0) - , mPrincipalPropertySearchSubJobSuccessful(false) + : DavJobBase(new DavPrincipalSearchJobPrivate, parent) { + Q_D(DavPrincipalSearchJob); + d->mUrl = url; + d->mType = type; + d->mFilter = filter; } void DavPrincipalSearchJob::fetchProperty(const QString &name, const QString &ns) { + Q_D(DavPrincipalSearchJob); QString propNamespace = ns; if (propNamespace.isEmpty()) { propNamespace = QStringLiteral("DAV:"); } - mFetchProperties << QPair(propNamespace, name); + d->mFetchProperties << QPair(propNamespace, name); } DavUrl DavPrincipalSearchJob::davUrl() const { - return mUrl; + Q_D(const DavPrincipalSearchJob); + return d->mUrl; } void DavPrincipalSearchJob::start() { + Q_D(DavPrincipalSearchJob); /* * The first step is to try to locate the URL that contains the principals. * This is done with a PROPFIND request and a XML like this: * * * * * * */ QDomDocument query; QDomElement propfind = query.createElementNS(QStringLiteral("DAV:"), QStringLiteral("propfind")); query.appendChild(propfind); QDomElement prop = query.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop")); propfind.appendChild(prop); QDomElement principalCollectionSet = query.createElementNS(QStringLiteral("DAV:"), QStringLiteral("principal-collection-set")); prop.appendChild(principalCollectionSet); - KIO::DavJob *job = DavManager::self()->createPropFindJob(mUrl.url(), query); + KIO::DavJob *job = DavManager::self()->createPropFindJob(d->mUrl.url(), query); job->addMetaData(QStringLiteral("PropagateHttpHeader"), QStringLiteral("true")); connect(job, &KIO::DavJob::result, this, &DavPrincipalSearchJob::principalCollectionSetSearchFinished); job->start(); } void DavPrincipalSearchJob::principalCollectionSetSearchFinished(KJob *job) { + Q_D(DavPrincipalSearchJob); KIO::DavJob *davJob = qobject_cast(job); const QString responseCodeStr = davJob->queryMetaData(QStringLiteral("responsecode")); const int responseCode = responseCodeStr.isEmpty() ? 0 : responseCodeStr.toInt(); // KIO::DavJob does not set error() even if the HTTP status code is a 4xx or a 5xx if (davJob->error() || (responseCode >= 400 && responseCode < 600)) { setLatestResponseCode(responseCode); setError(ERR_PROBLEM_WITH_REQUEST); setJobErrorText(davJob->errorText()); setJobError(davJob->error()); setErrorTextFromDavError(); emitResult(); return; } if (job->error()) { setError(job->error()); setErrorText(job->errorText()); emitResult(); return; } /* * Extract information from a document like the following: * * * * * http://www.example.com/papers/ * * * * http://www.example.com/acl/users/ * http://www.example.com/acl/groups/ * * * HTTP/1.1 200 OK * * * */ QDomDocument document = davJob->response(); QDomElement documentElement = document.documentElement(); QDomElement responseElement = Utils::firstChildElementNS(documentElement, QStringLiteral("DAV:"), QStringLiteral("response")); if (responseElement.isNull()) { emitResult(); return; } // check for the valid propstat, without giving up on first error QDomElement propstatElement; { const QDomNodeList propstats = responseElement.elementsByTagNameNS(QStringLiteral("DAV:"), QStringLiteral("propstat")); for (int i = 0; i < propstats.length(); ++i) { const QDomElement propstatCandidate = propstats.item(i).toElement(); const QDomElement statusElement = Utils::firstChildElementNS(propstatCandidate, QStringLiteral("DAV:"), QStringLiteral("status")); if (statusElement.text().contains(QLatin1String("200"))) { propstatElement = propstatCandidate; } } } if (propstatElement.isNull()) { emitResult(); return; } QDomElement propElement = Utils::firstChildElementNS(propstatElement, QStringLiteral("DAV:"), QStringLiteral("prop")); if (propElement.isNull()) { emitResult(); return; } QDomElement principalCollectionSetElement = Utils::firstChildElementNS(propElement, QStringLiteral("DAV:"), QStringLiteral("principal-collection-set")); if (principalCollectionSetElement.isNull()) { emitResult(); return; } QDomNodeList hrefNodes = principalCollectionSetElement.elementsByTagNameNS(QStringLiteral("DAV:"), QStringLiteral("href")); for (int i = 0; i < hrefNodes.size(); ++i) { QDomElement hrefElement = hrefNodes.at(i).toElement(); QString href = hrefElement.text(); - QUrl url = mUrl.url(); + QUrl url = d->mUrl.url(); if (href.startsWith(QLatin1Char('/'))) { // href is only a path, use request url to complete url.setPath(href, QUrl::TolerantMode); } else { // href is a complete url QUrl tmpUrl(href); tmpUrl.setUserName(url.userName()); tmpUrl.setPassword(url.password()); url = tmpUrl; } QDomDocument principalPropertySearchQuery; buildReportQuery(principalPropertySearchQuery); KIO::DavJob *reportJob = DavManager::self()->createReportJob(url, principalPropertySearchQuery); reportJob->addMetaData(QStringLiteral("PropagateHttpHeader"), QStringLiteral("true")); connect(reportJob, &KIO::DavJob::result, this, &DavPrincipalSearchJob::principalPropertySearchFinished); - ++mPrincipalPropertySearchSubJobCount; + ++d->mPrincipalPropertySearchSubJobCount; reportJob->start(); } } void DavPrincipalSearchJob::principalPropertySearchFinished(KJob *job) { - --mPrincipalPropertySearchSubJobCount; + Q_D(DavPrincipalSearchJob); + --d->mPrincipalPropertySearchSubJobCount; - if (job->error() && !mPrincipalPropertySearchSubJobSuccessful) { + if (job->error() && !d->mPrincipalPropertySearchSubJobSuccessful) { setError(job->error()); setErrorText(job->errorText()); - if (mPrincipalPropertySearchSubJobCount == 0) { + if (d->mPrincipalPropertySearchSubJobCount == 0) { emitResult(); } return; } KIO::DavJob *davJob = qobject_cast(job); const int responseCode = davJob->queryMetaData(QStringLiteral("responsecode")).toInt(); - if (responseCode > 499 && responseCode < 600 && !mPrincipalPropertySearchSubJobSuccessful) { + if (responseCode > 499 && responseCode < 600 && !d->mPrincipalPropertySearchSubJobSuccessful) { // Server-side error, unrecoverable setLatestResponseCode(responseCode); setError(ERR_SERVER_UNRECOVERABLE); setJobErrorText(davJob->errorText()); setJobError(davJob->error()); setErrorTextFromDavError(); - if (mPrincipalPropertySearchSubJobCount == 0) { + if (d->mPrincipalPropertySearchSubJobCount == 0) { emitResult(); } return; - } else if (responseCode > 399 && responseCode < 500 && !mPrincipalPropertySearchSubJobSuccessful) { + } else if (responseCode > 399 && responseCode < 500 && !d->mPrincipalPropertySearchSubJobSuccessful) { setLatestResponseCode(responseCode); setError(ERR_PROBLEM_WITH_REQUEST); setJobErrorText(davJob->errorText()); setJobError(davJob->error()); setErrorTextFromDavError(); - if (mPrincipalPropertySearchSubJobCount == 0) { + if (d->mPrincipalPropertySearchSubJobCount == 0) { emitResult(); } return; } - if (!mPrincipalPropertySearchSubJobSuccessful) { + if (!d->mPrincipalPropertySearchSubJobSuccessful) { setError(0); // nope, everything went fine - mPrincipalPropertySearchSubJobSuccessful = true; + d->mPrincipalPropertySearchSubJobSuccessful = true; } /* * Extract infos from a document like the following: * * * * http://www.example.com/users/jdoe * * * John Doe * * HTTP/1.1 200 OK * * */ const QDomDocument document = davJob->response(); const QDomElement documentElement = document.documentElement(); QDomElement responseElement = Utils::firstChildElementNS(documentElement, QStringLiteral("DAV:"), QStringLiteral("response")); if (responseElement.isNull()) { - if (mPrincipalPropertySearchSubJobCount == 0) { + if (d->mPrincipalPropertySearchSubJobCount == 0) { emitResult(); } return; } // check for the valid propstat, without giving up on first error QDomElement propstatElement; { const QDomNodeList propstats = responseElement.elementsByTagNameNS(QStringLiteral("DAV:"), QStringLiteral("propstat")); const int propStatsEnd(propstats.length()); for (int i = 0; i < propStatsEnd; ++i) { const QDomElement propstatCandidate = propstats.item(i).toElement(); const QDomElement statusElement = Utils::firstChildElementNS(propstatCandidate, QStringLiteral("DAV:"), QStringLiteral("status")); if (statusElement.text().contains(QLatin1String("200"))) { propstatElement = propstatCandidate; } } } if (propstatElement.isNull()) { - if (mPrincipalPropertySearchSubJobCount == 0) { + if (d->mPrincipalPropertySearchSubJobCount == 0) { emitResult(); } return; } QDomElement propElement = Utils::firstChildElementNS(propstatElement, QStringLiteral("DAV:"), QStringLiteral("prop")); if (propElement.isNull()) { - if (mPrincipalPropertySearchSubJobCount == 0) { + if (d->mPrincipalPropertySearchSubJobCount == 0) { emitResult(); } return; } // All requested properties are now under propElement, so let's find them typedef QPair PropertyPair; - for (const PropertyPair &fetchProperty : qAsConst(mFetchProperties)) { + for (const PropertyPair &fetchProperty : qAsConst(d->mFetchProperties)) { QDomNodeList fetchNodes = propElement.elementsByTagNameNS(fetchProperty.first, fetchProperty.second); for (int i = 0; i < fetchNodes.size(); ++i) { QDomElement fetchElement = fetchNodes.at(i).toElement(); Result result; result.propertyNamespace = fetchProperty.first; result.property = fetchProperty.second; result.value = fetchElement.text(); - mResults << result; + d->mResults << result; } } - if (mPrincipalPropertySearchSubJobCount == 0) { + if (d->mPrincipalPropertySearchSubJobCount == 0) { emitResult(); } } QVector< DavPrincipalSearchJob::Result > DavPrincipalSearchJob::results() const { - return mResults; + Q_D(const DavPrincipalSearchJob); + return d->mResults; } void DavPrincipalSearchJob::buildReportQuery(QDomDocument &query) { + Q_D(DavPrincipalSearchJob); /* * Build a document like the following, where XXX will * be replaced by the properties the user want to fetch: * * * * * * * * FILTER * * * XXX * * */ QDomElement principalPropertySearch = query.createElementNS(QStringLiteral("DAV:"), QStringLiteral("principal-property-search")); query.appendChild(principalPropertySearch); QDomElement propertySearch = query.createElementNS(QStringLiteral("DAV:"), QStringLiteral("property-search")); principalPropertySearch.appendChild(propertySearch); QDomElement prop = query.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop")); propertySearch.appendChild(prop); - if (mType == DisplayName) { + if (d->mType == DisplayName) { QDomElement displayName = query.createElementNS(QStringLiteral("DAV:"), QStringLiteral("displayname")); prop.appendChild(displayName); - } else if (mType == EmailAddress) { + } else if (d->mType == EmailAddress) { QDomElement calendarUserAddressSet = query.createElementNS(QStringLiteral("urn:ietf:params:xml:ns:caldav"), QStringLiteral("calendar-user-address-set")); prop.appendChild(calendarUserAddressSet); //QDomElement hrefElement = query.createElementNS( "DAV:", "href" ); //prop.appendChild( hrefElement ); } QDomElement match = query.createElementNS(QStringLiteral("DAV:"), QStringLiteral("match")); propertySearch.appendChild(match); - QDomText propFilter = query.createTextNode(mFilter); + QDomText propFilter = query.createTextNode(d->mFilter); match.appendChild(propFilter); prop = query.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop")); principalPropertySearch.appendChild(prop); typedef QPair PropertyPair; - for (const PropertyPair &fetchProperty : qAsConst(mFetchProperties)) { + for (const PropertyPair &fetchProperty : qAsConst(d->mFetchProperties)) { QDomElement elem = query.createElementNS(fetchProperty.first, fetchProperty.second); prop.appendChild(elem); } } diff --git a/src/common/davprincipalsearchjob.h b/src/common/davprincipalsearchjob.h index 2688fc2..1914475 100644 --- a/src/common/davprincipalsearchjob.h +++ b/src/common/davprincipalsearchjob.h @@ -1,118 +1,113 @@ /* Copyright (c) 2011 Grégory Oestreicher 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDAV_DAVPRINCIPALSEARCHJOB_H #define KDAV_DAVPRINCIPALSEARCHJOB_H #include "kpimkdav_export.h" #include "davjobbase.h" #include "davurl.h" #include #include #include #include class QDomDocument; namespace KDAV { +class DavPrincipalSearchJobPrivate; + /** * @short A job that search a DAV principal on a server * * This job is used to search a principal on a server * that implement the dav-property-search REPORT (RFC3744). * * The properties to fetch are set with @ref fetchProperty(). */ class KPIMKDAV_EXPORT DavPrincipalSearchJob : public DavJobBase { Q_OBJECT public: /** * Types of search that are supported by this job. * DisplayName will match on the DAV displayname property. * EmailAddress will match on the CalDav calendar-user-address-set property. */ enum FilterType { DisplayName, EmailAddress }; /** * Simple struct to hold the search job results */ struct Result { QString propertyNamespace; QString property; QString value; }; /** * Creates a new dav principal search job * * @param url The URL to use in the REPORT query. * @param type The type that the filter will match. * @param filter The filter that will be used to match the displayname attribute. * @param parent The parent object. */ explicit DavPrincipalSearchJob(const DavUrl &url, FilterType type, const QString &filter, QObject *parent = nullptr); /** * Add a new property to fetch from the server. * * @param name The name of the property. * @param ns The namespace of this property, defaults to 'DAV:'. */ void fetchProperty(const QString &name, const QString &ns = QString()); /** * Starts the job */ void start() override; /** * Return the DavUrl used by this job */ Q_REQUIRED_RESULT DavUrl davUrl() const; /** * Get the job results. */ Q_REQUIRED_RESULT QVector results() const; private: void principalCollectionSetSearchFinished(KJob *job); void principalPropertySearchFinished(KJob *job); void buildReportQuery(QDomDocument &query); -private: - DavUrl mUrl; - FilterType mType; - QString mFilter; - int mPrincipalPropertySearchSubJobCount; - bool mPrincipalPropertySearchSubJobSuccessful; - QList< QPair > mFetchProperties; - QVector mResults; + Q_DECLARE_PRIVATE(DavPrincipalSearchJob) }; } Q_DECLARE_TYPEINFO(KDAV::DavPrincipalSearchJob::Result, Q_MOVABLE_TYPE); #endif diff --git a/src/common/enums.h b/src/common/enums.h index 514dc37..e50cb1b 100644 --- a/src/common/enums.h +++ b/src/common/enums.h @@ -1,55 +1,56 @@ /* Copyright (c) 2010 Tobias Koenig 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDAV_ENUMS_H #define KDAV_ENUMS_H #include namespace KDAV { /** * Describes the DAV protocol dialect. */ enum Protocol { CalDav = 0, ///< The CalDav protocol as defined in https://devguide.calconnect.org/CalDAV CardDav, ///< The CardDav protocol as defined in https://devguide.calconnect.org/CardDAV - GroupDav ///< The GroupDav protocol as defined in http://www.groupdav.org + GroupDav, ///< The GroupDav protocol as defined in http://www.groupdav.org + PROTOCOL_COUNT }; /** * Describes the DAV privileges on a resource (see RFC3744) */ enum Privilege { None = 0x0, Read = 0x1, Write = 0x2, WriteProperties = 0x4, WriteContent = 0x8, Unlock = 0x10, ReadAcl = 0x20, ReadCurrentUserPrivilegeSet = 0x40, WriteAcl = 0x80, Bind = 0x100, Unbind = 0x200, All = 0x400 }; Q_DECLARE_FLAGS(Privileges, Privilege) Q_DECLARE_OPERATORS_FOR_FLAGS(Privileges) } #endif