Libkdav2

davitemslistjob.cpp
1 /*
2  Copyright (c) 2010 Tobias Koenig <[email protected]>
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18 
19 #include "davitemslistjob.h"
20 
21 #include "daverror.h"
22 #include "davmanager.h"
23 #include "davprotocolbase.h"
24 #include "davurl.h"
25 #include "utils.h"
26 #include "davjob.h"
27 
28 #include <QtCore/QBuffer>
29 #include <QtCore/QDebug>
30 
31 using namespace KDAV2;
32 
33 class DavItemsListJobPrivate {
34 public:
35  DavItemsListJobPrivate(const DavUrl &url);
36 
37  DavUrl mUrl;
38  QStringList mMimeTypes;
39  QString mRangeStart;
40  QString mRangeEnd;
41  DavItem::List mItems;
42  QSet<QString> mSeenUrls; // to prevent events duplication with some servers
43  uint mSubJobCount;
44 };
45 
46 DavItemsListJobPrivate::DavItemsListJobPrivate(const DavUrl &url)
47  : mUrl(url)
48  , mSubJobCount(0)
49 {
50 }
51 
52 
54  : DavJobBase(parent)
55  , d(std::unique_ptr<DavItemsListJobPrivate>(new DavItemsListJobPrivate(url)))
56 {
57 }
58 
59 DavItemsListJob::~DavItemsListJob()
60 {
61 }
62 
64 {
65  d->mMimeTypes = types;
66 }
67 
69 {
70  d->mRangeStart = start;
71  d->mRangeEnd = end;
72 }
73 
75 {
76  const DavProtocolBase *protocol = DavManager::self()->davProtocol(d->mUrl.protocol());
77  Q_ASSERT(protocol);
79 
80  while (it.hasNext()) {
81  XMLQueryBuilder::Ptr builder = it.next();
82  if (!d->mRangeStart.isEmpty()) {
83  builder->setParameter(QStringLiteral("start"), d->mRangeStart);
84  }
85  if (!d->mRangeEnd.isEmpty()) {
86  builder->setParameter(QStringLiteral("end"), d->mRangeEnd);
87  }
88 
89  const QDomDocument props = builder->buildQuery();
90  const QString mimeType = builder->mimeType();
91 
92  if (d->mMimeTypes.isEmpty() || d->mMimeTypes.contains(mimeType)) {
93  ++d->mSubJobCount;
94  const auto url = d->mUrl.url();
95  auto job = protocol->useReport() ?
96  DavManager::self()->createReportJob(url, props) :
97  DavManager::self()->createPropFindJob(url, props);
98  job->setProperty("itemsMimeType", mimeType);
99  connect(job, &DavJob::result, this, &DavItemsListJob::davJobFinished);
100  }
101  }
102 
103  if (d->mSubJobCount == 0) {
104  setError(ERR_ITEMLIST_NOMIMETYPE);
105  setErrorTextFromDavError();
106  emitResult();
107  }
108 }
109 
111 {
112  return d->mItems;
113 }
114 
115 void DavItemsListJob::davJobFinished(KJob *job)
116 {
117  auto davJob = static_cast<DavJob*>(job);
118  if (davJob->error()) {
119  setErrorFromJob(davJob);
120  } else {
121  /*
122  * Extract data from a document like the following:
123  *
124  * <multistatus xmlns="DAV:">
125  * <response xmlns="DAV:">
126  * <href xmlns="DAV:">/caldav.php/test1.user/home/KOrganizer-166749289.780.ics</href>
127  * <propstat xmlns="DAV:">
128  * <prop xmlns="DAV:">
129  * <getetag xmlns="DAV:">"b4bbea0278f4f63854c4167a7656024a"</getetag>
130  * </prop>
131  * <status xmlns="DAV:">HTTP/1.1 200 OK</status>
132  * </propstat>
133  * </response>
134  * <response xmlns="DAV:">
135  * <href xmlns="DAV:">/caldav.php/test1.user/home/KOrganizer-399416366.464.ics</href>
136  * <propstat xmlns="DAV:">
137  * <prop xmlns="DAV:">
138  * <getetag xmlns="DAV:">"52eb129018398a7da4f435b2bc4c6cd5"</getetag>
139  * </prop>
140  * <status xmlns="DAV:">HTTP/1.1 200 OK</status>
141  * </propstat>
142  * </response>
143  * </multistatus>
144  */
145 
146  const QString itemsMimeType = job->property("itemsMimeType").toString();
147  const QDomDocument document = davJob->response();
148  const QDomElement documentElement = document.documentElement();
149 
150  QDomElement responseElement = Utils::firstChildElementNS(documentElement, QStringLiteral("DAV:"), QStringLiteral("response"));
151  while (!responseElement.isNull()) {
152 
153  QDomElement propstatElement;
154 
155  // check for the valid propstat, without giving up on first error
156  {
157  const QDomNodeList propstats = responseElement.elementsByTagNameNS(QStringLiteral("DAV:"), QStringLiteral("propstat"));
158  for (int i = 0; i < propstats.length(); ++i) {
159  const QDomElement propstatCandidate = propstats.item(i).toElement();
160  const QDomElement statusElement = Utils::firstChildElementNS(propstatCandidate, QStringLiteral("DAV:"), QStringLiteral("status"));
161  if (statusElement.text().contains(QStringLiteral("200"))) {
162  propstatElement = propstatCandidate;
163  }
164  }
165  }
166 
167  if (propstatElement.isNull()) {
168  responseElement = Utils::nextSiblingElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("response"));
169  continue;
170  }
171 
172  const QDomElement propElement = Utils::firstChildElementNS(propstatElement, QStringLiteral("DAV:"), QStringLiteral("prop"));
173 
174  // check whether it is a dav collection ...
175  const QDomElement resourcetypeElement = Utils::firstChildElementNS(propElement, QStringLiteral("DAV:"), QStringLiteral("resourcetype"));
176  if (!responseElement.isNull()) {
177  const QDomElement collectionElement = Utils::firstChildElementNS(resourcetypeElement, QStringLiteral("DAV:"), QStringLiteral("collection"));
178  if (!collectionElement.isNull()) {
179  responseElement = Utils::nextSiblingElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("response"));
180  continue;
181  }
182  }
183 
184  // ... if not it is an item
185  DavItem item;
186  item.setContentType(itemsMimeType);
187 
188  // extract path
189  const QDomElement hrefElement = Utils::firstChildElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("href"));
190  const QString href = hrefElement.text();
191 
192  QUrl url = davJob->url();
193  url.setUserInfo(QString());
194  if (href.startsWith(QLatin1Char('/'))) {
195  // href is only a path, use request url to complete
196  url.setPath(href, QUrl::TolerantMode);
197  } else {
198  // href is a complete url
199  url = QUrl::fromUserInput(href);
200  }
201 
202  QString itemUrl = url.toDisplayString();
203  if (d->mSeenUrls.contains(itemUrl)) {
204  responseElement = Utils::nextSiblingElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("response"));
205  continue;
206  }
207 
208  d->mSeenUrls << itemUrl;
209  auto _url = url;
210  _url.setUserInfo(d->mUrl.url().userInfo());
211  item.setUrl(DavUrl(_url, d->mUrl.protocol()));
212 
213  // extract etag
214  const QDomElement getetagElement = Utils::firstChildElementNS(propElement, QStringLiteral("DAV:"), QStringLiteral("getetag"));
215 
216  item.setEtag(getetagElement.text());
217 
218  d->mItems << item;
219 
220  responseElement = Utils::nextSiblingElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("response"));
221  }
222  }
223 
224  if (--d->mSubJobCount == 0) {
225  emitResult();
226  }
227 }
228 
QString url(QUrl::FormattingOptions options) const const
DavJob * createPropFindJob(const QUrl &url, const QDomDocument &document, const QString &depth=QStringLiteral("1"))
Returns a preconfigured DAV PROPFIND job.
Definition: davmanager.cpp:66
QDomNode item(int index) const const
QString toDisplayString(QUrl::FormattingOptions options) const const
QDomNodeList elementsByTagNameNS(const QString &nsURI, const QString &localName) const const
void emitResult()
virtual bool useReport() const =0
Returns whether the dav protocol dialect supports the REPORT command to query all resources of a coll...
static DavManager * self()
Returns the global instance of the DAV manager.
Definition: davmanager.cpp:52
base class for the jobs used by the resource.
Definition: davjobbase.h:37
void setEtag(const QString &etag)
Sets the etag of the item.
Definition: davitem.cpp:109
void setError(int errorCode)
TolerantMode
QDomElement documentElement() const const
void start() override
Starts the job.
QUrl fromUserInput(const QString &userInput)
A helper class to combine url and protocol of a DAV url.
Definition: davurl.h:35
void setContentType(const QString &type)
Sets the content type of the item.
Definition: davitem.cpp:89
QDomElement toElement() const const
void setPath(const QString &path, QUrl::ParsingMode mode)
QVariant property(const char *name) const const
QString text() const const
void setUrl(const DavUrl &url)
Sets the url that identifies the item.
Definition: davitem.cpp:79
const DavProtocolBase * davProtocol(Protocol protocol)
Returns the DAV protocol dialect object for the given DAV protocol.
Definition: davmanager.cpp:140
DavJob * createReportJob(const QUrl &url, const QDomDocument &document, const QString &depth=QStringLiteral("1"))
Returns a preconfigured DAV REPORT job.
Definition: davmanager.cpp:73
void setContentMimeTypes(const QStringList &types)
Limits the mime types of the items requested.
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
DavItem::List items() const
Returns the list of items seen including identifier url and etag information.
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
A helper class to store information about DAV resources.
Definition: davitem.h:51
QDomElement KPIMKDAV2_EXPORT firstChildElementNS(const QDomElement &parent, const QString &namespaceUri, const QString &tagName)
Returns the first child element of parent that has the given tagName and is part of the namespaceUri...
Definition: utils.cpp:37
bool isNull() const const
DavItemsListJob(const DavUrl &url, QObject *parent=nullptr)
Creates a new dav items list job.
QDomElement KPIMKDAV2_EXPORT nextSiblingElementNS(const QDomElement &element, const QString &namespaceUri, const QString &tagName)
Returns the next sibling element of element that has the given tagName and is part of the namespaceUr...
Definition: utils.cpp:51
virtual QVector< XMLQueryBuilder::Ptr > itemsQueries() const =0
Returns a list of XML documents that represent DAV queries to list all available DAV resources inside...
int length() const const
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const const
void setUserInfo(const QString &userInfo, QUrl::ParsingMode mode)
QString toString() const const
Base class for various DAV groupware dialects.
void setTimeRange(const QString &start, const QString &end)
Sets the start and end time to list items for.
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Sat Sep 19 2020 23:18:34 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.