diff --git a/src/common/davcollectionfetchjob.cpp b/src/common/davcollectionfetchjob.cpp --- a/src/common/davcollectionfetchjob.cpp +++ b/src/common/davcollectionfetchjob.cpp @@ -83,8 +83,6 @@ const QDomDocument document = storedJob->response(); - //qWarning() << document.toString(); - const QDomElement documentElement = document.documentElement(); QDomElement responseElement = Utils::firstChildElementNS( documentElement, QStringLiteral("DAV:"), QStringLiteral("response")); diff --git a/src/common/davcollectionsfetchjob.h b/src/common/davcollectionsfetchjob.h --- a/src/common/davcollectionsfetchjob.h +++ b/src/common/davcollectionsfetchjob.h @@ -76,9 +76,11 @@ private Q_SLOTS: void principalFetchFinished(KJob *); void collectionsFetchFinished(KJob *); + void individualCollectionRefreshed(KJob *); private: void doCollectionsFetch(const QUrl &url); + void refreshIndividualCollection(const DavCollection &); void subjobFinished(); DavUrl mUrl; diff --git a/src/common/davcollectionsfetchjob.cpp b/src/common/davcollectionsfetchjob.cpp --- a/src/common/davcollectionsfetchjob.cpp +++ b/src/common/davcollectionsfetchjob.cpp @@ -20,6 +20,7 @@ #include "davmanager.h" #include "davprincipalhomesetsfetchjob.h" +#include "davcollectionfetchjob.h" #include "davprotocolbase.h" #include "utils.h" #include "daverror.h" @@ -142,6 +143,8 @@ _jobUrl.setUserInfo(QString()); const QString jobUrl = _jobUrl.toDisplayString(); + qCDebug(KDAV2_LOG).noquote() << davJob->response().toString(); + // Validate that we got a valid PROPFIND response QDomElement rootElement = davJob->response().documentElement(); if (rootElement.localName().compare(QStringLiteral("multistatus"), Qt::CaseInsensitive) != 0) { @@ -245,6 +248,18 @@ continue; } + bool protocolSupportsCTags = DavManager::self()->davProtocol(mUrl.protocol())->supportsCTags(); + if (protocolSupportsCTags && collection.CTag() == "") { + qCDebug(KDAV2_LOG) << "No CTag found for" + << collection.url().url().toDisplayString() + << "from the home set, trying from the direct URL"; + refreshIndividualCollection(collection); + + responseElement = Utils::nextSiblingElementNS( + responseElement, QStringLiteral("DAV:"), QStringLiteral("response")); + continue; + } + mCollections << collection; Q_EMIT collectionDiscovered(mUrl.protocol(), url.toDisplayString(), jobUrl); @@ -257,6 +272,47 @@ subjobFinished(); } +// This is a workaroud for Google who doesn't support providing the CTag +// directly from the home set. We refresh the collections individually from +// their own URLs, but only if we haven't found a CTag with the home set +// request. +void DavCollectionsFetchJob::refreshIndividualCollection(const DavCollection &collection) +{ + ++mSubJobCount; + auto individualFetchJob = new DavCollectionFetchJob(collection, this); + connect(individualFetchJob, &DavCollectionFetchJob::result, this, &DavCollectionsFetchJob::individualCollectionRefreshed); + individualFetchJob->start(); +} + +void DavCollectionsFetchJob::individualCollectionRefreshed(KJob *job) +{ + const auto *davJob = qobject_cast(job); + + if (davJob->error()) { + if (davJob->latestResponseCode()) { + // If we have a HTTP response code then this may mean that + // the URL was not a principal URL. Retry as if it were a calendar URL. + qCDebug(KDAV2_LOG) << "Individual fetch failed, retrying: " << job->errorText(); + doCollectionsFetch(mUrl.url()); + } else { + setDavError(davJob->davError()); + setErrorTextFromDavError(); + emitResult(); + } + return; + } + + qCDebug(KDAV2_LOG) << "Collection" + << davJob->collection().url().url().toDisplayString() << "refreshed"; + + if (davJob->collection().CTag() == "") { + qWarning() << "Collection with an empty CTag"; + } + + mCollections << davJob->collection(); + subjobFinished(); +} + void DavCollectionsFetchJob::subjobFinished() { if (--mSubJobCount == 0) { diff --git a/src/common/davprotocolbase.h b/src/common/davprotocolbase.h --- a/src/common/davprotocolbase.h +++ b/src/common/davprotocolbase.h @@ -79,6 +79,13 @@ */ virtual bool supportsPrincipals() const = 0; + /** + * Return whether the dav protocol dialect supports CTags. + * + * If true, it must fetch them in the collectionsQuery(). + */ + virtual bool supportsCTags() const = 0; + /** * Returns whether the dav protocol dialect supports the REPORT * command to query all resources of a collection. diff --git a/src/protocols/caldavprotocol.h b/src/protocols/caldavprotocol.h --- a/src/protocols/caldavprotocol.h +++ b/src/protocols/caldavprotocol.h @@ -26,6 +26,7 @@ public: CaldavProtocol(); bool supportsPrincipals() const Q_DECL_OVERRIDE; + bool supportsCTags() const Q_DECL_OVERRIDE; bool useReport() const Q_DECL_OVERRIDE; bool useMultiget() const Q_DECL_OVERRIDE; QString principalHomeSet() const Q_DECL_OVERRIDE; diff --git a/src/protocols/caldavprotocol.cpp b/src/protocols/caldavprotocol.cpp --- a/src/protocols/caldavprotocol.cpp +++ b/src/protocols/caldavprotocol.cpp @@ -298,6 +298,11 @@ return true; } +bool CaldavProtocol::supportsCTags() const +{ + return true; +} + bool CaldavProtocol::useReport() const { return true; diff --git a/src/protocols/carddavprotocol.h b/src/protocols/carddavprotocol.h --- a/src/protocols/carddavprotocol.h +++ b/src/protocols/carddavprotocol.h @@ -26,6 +26,7 @@ public: CarddavProtocol(); bool supportsPrincipals() const Q_DECL_OVERRIDE; + bool supportsCTags() const Q_DECL_OVERRIDE; bool useReport() const Q_DECL_OVERRIDE; bool useMultiget() const Q_DECL_OVERRIDE; QString principalHomeSet() const Q_DECL_OVERRIDE; diff --git a/src/protocols/carddavprotocol.cpp b/src/protocols/carddavprotocol.cpp --- a/src/protocols/carddavprotocol.cpp +++ b/src/protocols/carddavprotocol.cpp @@ -126,6 +126,11 @@ return true; } +bool CarddavProtocol::supportsCTags() const +{ + return true; +} + bool CarddavProtocol::useReport() const { return false; diff --git a/src/protocols/groupdavprotocol.h b/src/protocols/groupdavprotocol.h --- a/src/protocols/groupdavprotocol.h +++ b/src/protocols/groupdavprotocol.h @@ -26,6 +26,7 @@ public: GroupdavProtocol(); bool supportsPrincipals() const Q_DECL_OVERRIDE; + bool supportsCTags() const Q_DECL_OVERRIDE; bool useReport() const Q_DECL_OVERRIDE; bool useMultiget() const Q_DECL_OVERRIDE; KDAV2::XMLQueryBuilder::Ptr collectionsQuery() const Q_DECL_OVERRIDE; diff --git a/src/protocols/groupdavprotocol.cpp b/src/protocols/groupdavprotocol.cpp --- a/src/protocols/groupdavprotocol.cpp +++ b/src/protocols/groupdavprotocol.cpp @@ -85,6 +85,11 @@ return false; } +bool GroupdavProtocol::supportsCTags() const +{ + return false; +} + bool GroupdavProtocol::useReport() const { return false;