File indexing completed on 2024-11-17 04:44:01

0001 /*
0002     Copyright (c) 2010 Grégory Oestreicher <greg@kamago.net>
0003     Based on DavItemsListJob which is copyright (c) 2010 Tobias Koenig <tokoe@kde.org>
0004 
0005     This program is free software; you can redistribute it and/or modify
0006     it under the terms of the GNU General Public License as published by
0007     the Free Software Foundation; either version 2 of the License, or
0008     (at your option) any later version.
0009 
0010     This program is distributed in the hope that it will be useful,
0011     but WITHOUT ANY WARRANTY; without even the implied warranty of
0012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0013     GNU General Public License for more details.
0014 
0015     You should have received a copy of the GNU General Public License
0016     along with this program; if not, write to the Free Software
0017     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
0018 */
0019 
0020 #include "davitemsfetchjob.h"
0021 
0022 #include "davmanager.h"
0023 #include "davmultigetprotocol.h"
0024 #include "utils.h"
0025 #include "daverror.h"
0026 #include "davjob.h"
0027 
0028 using namespace KDAV2;
0029 
0030 DavItemsFetchJob::DavItemsFetchJob(const DavUrl &collectionUrl, const QStringList &urls, QObject *parent)
0031     : DavJobBase(parent), mCollectionUrl(collectionUrl), mUrls(urls)
0032 {
0033 }
0034 
0035 void DavItemsFetchJob::start()
0036 {
0037     const DavMultigetProtocol *protocol =
0038         dynamic_cast<const DavMultigetProtocol *>(DavManager::self()->davProtocol(mCollectionUrl.protocol()));
0039     if (!protocol) {
0040         setError(ERR_NO_MULTIGET);
0041         setErrorTextFromDavError();
0042         emitResult();
0043         return;
0044     }
0045 
0046     if (mUrls.isEmpty()) {
0047         setError(ERR_PROBLEM_WITH_REQUEST);
0048         setErrorText("DavItemsFetchJob without urls.");
0049         emitResult();
0050         return;
0051     }
0052 
0053     const QDomDocument report = protocol->itemsReportQuery(mUrls)->buildQuery();
0054     DavJob *job = DavManager::self()->createReportJob(mCollectionUrl.url(), report, QStringLiteral("0"));
0055     connect(job, &DavJob::result, this, &DavItemsFetchJob::davJobFinished);
0056 }
0057 
0058 DavItem::List DavItemsFetchJob::items() const
0059 {
0060     DavItem::List values;
0061     values.reserve(mItems.size());
0062     Q_FOREACH (const auto &value, mItems) {
0063         values << value;
0064     }
0065     return values;
0066 }
0067 
0068 DavItem DavItemsFetchJob::item(const QString &url) const
0069 {
0070     return mItems.value(url);
0071 }
0072 
0073 void DavItemsFetchJob::davJobFinished(KJob *job)
0074 {
0075     auto davJob = static_cast<DavJob *>(job);
0076     if (davJob->error()) {
0077         setErrorFromJob(davJob);
0078         emitResult();
0079         return;
0080     }
0081 
0082     const DavMultigetProtocol *protocol =
0083         static_cast<const DavMultigetProtocol *>(DavManager::self()->davProtocol(mCollectionUrl.protocol()));
0084 
0085     const QDomDocument document = davJob->response();
0086     const QDomElement documentElement = document.documentElement();
0087 
0088     QDomElement responseElement = Utils::firstChildElementNS(documentElement, QStringLiteral("DAV:"), QStringLiteral("response"));
0089 
0090     while (!responseElement.isNull()) {
0091         QDomElement propstatElement = Utils::firstChildElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("propstat"));
0092 
0093         if (propstatElement.isNull()) {
0094             responseElement = Utils::nextSiblingElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("response"));
0095             continue;
0096         }
0097 
0098         // Check for errors
0099         const QDomElement statusElement = Utils::firstChildElementNS(propstatElement, QStringLiteral("DAV:"), QStringLiteral("status"));
0100         if (!statusElement.text().contains(QLatin1String("200"))) {
0101             responseElement = Utils::nextSiblingElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("response"));
0102             continue;
0103         }
0104 
0105         const QDomElement propElement = Utils::firstChildElementNS(propstatElement, QStringLiteral("DAV:"), QStringLiteral("prop"));
0106 
0107         DavItem item;
0108 
0109         // extract path
0110         const QDomElement hrefElement = Utils::firstChildElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("href"));
0111         const QString href = hrefElement.text();
0112 
0113         QUrl url = davJob->url();
0114         if (href.startsWith(QLatin1Char('/'))) {
0115             // href is only a path, use request url to complete
0116             url.setPath(href, QUrl::TolerantMode);
0117         } else {
0118             // href is a complete url
0119             url = QUrl::fromUserInput(href);
0120         }
0121 
0122         auto _url = url;
0123         _url.setUserInfo(mCollectionUrl.url().userInfo());
0124         item.setUrl(DavUrl(_url, mCollectionUrl.protocol()));
0125 
0126         // extract etag
0127         const QDomElement getetagElement = Utils::firstChildElementNS(propElement, QStringLiteral("DAV:"), QStringLiteral("getetag"));
0128         item.setEtag(getetagElement.text());
0129 
0130         // extract content
0131         const QDomElement dataElement = Utils::firstChildElementNS(propElement,
0132                                         protocol->responseNamespace(),
0133                                         protocol->dataTagName());
0134 
0135         if (dataElement.isNull()) {
0136             responseElement = Utils::nextSiblingElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("response"));
0137             continue;
0138         }
0139 
0140         const QByteArray data = dataElement.firstChild().toText().data().toUtf8();
0141         if (data.isEmpty()) {
0142             responseElement = Utils::nextSiblingElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("response"));
0143             continue;
0144         }
0145 
0146         item.setData(data);
0147 
0148         mItems.insert(item.url().toDisplayString(), item);
0149         responseElement = Utils::nextSiblingElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("response"));
0150     }
0151 
0152     emitResult();
0153 }