KDAV

davcollectionmodifyjob.cpp
1/*
2 SPDX-FileCopyrightText: 2010 Grégory Oestreicher <greg@kamago.net>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "davcollectionmodifyjob.h"
8#include "davjobbase_p.h"
9#include "davmanager_p.h"
10
11#include "daverror.h"
12#include "utils_p.h"
13
14#include <KIO/DavJob>
15#include <KIO/Job>
16
17using namespace KDAV;
18
19namespace KDAV
20{
21class DavCollectionModifyJobPrivate : public DavJobBasePrivate
22{
23public:
24 void davJobFinished(KJob *job);
25
26 DavUrl mUrl;
27 QDomDocument mQuery;
28
29 QList<QDomElement> mSetProperties;
30 QList<QDomElement> mRemoveProperties;
31};
32}
33
35 : DavJobBase(new DavCollectionModifyJobPrivate, parent)
36{
38 d->mUrl = url;
39}
40
41void DavCollectionModifyJob::setProperty(const QString &prop, const QString &value, const QString &ns)
42{
44 QDomElement propElement;
45
46 if (ns.isEmpty()) {
47 propElement = d->mQuery.createElement(prop);
48 } else {
49 propElement = d->mQuery.createElementNS(ns, prop);
50 }
51
52 const QDomText textElement = d->mQuery.createTextNode(value);
53 propElement.appendChild(textElement);
54
55 d->mSetProperties << propElement;
56}
57
59{
61 QDomElement propElement;
62
63 if (ns.isEmpty()) {
64 propElement = d->mQuery.createElement(prop);
65 } else {
66 propElement = d->mQuery.createElementNS(ns, prop);
67 }
68
69 d->mRemoveProperties << propElement;
70}
71
73{
75 if (d->mSetProperties.isEmpty() && d->mRemoveProperties.isEmpty()) {
76 setError(ERR_COLLECTIONMODIFY_NO_PROPERITES);
77 d->setErrorTextFromDavError();
78 emitResult();
79 return;
80 }
81
82 QDomDocument mQuery;
83 QDomElement propertyUpdateElement = mQuery.createElementNS(QStringLiteral("DAV:"), QStringLiteral("propertyupdate"));
84 mQuery.appendChild(propertyUpdateElement);
85
86 if (!d->mSetProperties.isEmpty()) {
87 QDomElement setElement = mQuery.createElementNS(QStringLiteral("DAV:"), QStringLiteral("set"));
88 propertyUpdateElement.appendChild(setElement);
89
90 QDomElement propElement = mQuery.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop"));
91 setElement.appendChild(propElement);
92
93 for (const QDomElement &element : std::as_const(d->mSetProperties)) {
94 propElement.appendChild(element);
95 }
96 }
97
98 if (!d->mRemoveProperties.isEmpty()) {
99 QDomElement removeElement = mQuery.createElementNS(QStringLiteral("DAV:"), QStringLiteral("remove"));
100 propertyUpdateElement.appendChild(removeElement);
101
102 QDomElement propElement = mQuery.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop"));
103 removeElement.appendChild(propElement);
104
105 for (const QDomElement &element : std::as_const(d->mSetProperties)) {
106 propElement.appendChild(element);
107 }
108 }
109
110 KIO::DavJob *job = DavManager::self()->createPropPatchJob(d->mUrl.url(), mQuery.toString());
111 job->addMetaData(QStringLiteral("PropagateHttpHeader"), QStringLiteral("true"));
112 connect(job, &KIO::DavJob::result, this, [d](KJob *job) {
113 d->davJobFinished(job);
114 });
115}
116
117void DavCollectionModifyJobPrivate::davJobFinished(KJob *job)
118{
119 KIO::DavJob *davJob = qobject_cast<KIO::DavJob *>(job);
120 const QString responseCodeStr = davJob->queryMetaData(QStringLiteral("responsecode"));
121 const int responseCode = responseCodeStr.isEmpty() ? 0 : responseCodeStr.toInt();
122
123 // KIO::DavJob does not set error() even if the HTTP status code is a 4xx or a 5xx
124 if (davJob->error() || (responseCode >= 400 && responseCode < 600)) {
125 setLatestResponseCode(responseCode);
126 setError(ERR_COLLECTIONMODIFY);
127 setJobErrorText(davJob->errorText());
128 setJobError(davJob->error());
129 setErrorTextFromDavError();
130 emitResult();
131 return;
132 }
133
134 QDomDocument response;
135 response.setContent(davJob->responseData(), QDomDocument::ParseOption::UseNamespaceProcessing);
136 QDomElement responseElement = Utils::firstChildElementNS(response.documentElement(), QStringLiteral("DAV:"), QStringLiteral("response"));
137
138 bool hasError = false;
139
140 // parse all propstats answers to get the eventual errors
141 const QDomNodeList propstats = responseElement.elementsByTagNameNS(QStringLiteral("DAV:"), QStringLiteral("propstat"));
142 for (int i = 0; i < propstats.length(); ++i) {
143 const QDomElement propstatElement = propstats.item(i).toElement();
144 const QDomElement statusElement = Utils::firstChildElementNS(propstatElement, QStringLiteral("DAV:"), QStringLiteral("status"));
145
146 const QString statusText = statusElement.text();
147 if (statusText.contains(QLatin1String("200"))) {
148 continue;
149 } else {
150 // Generic error
151 hasError = true;
152 break;
153 }
154 }
155
156 if (hasError) {
157 setError(ERR_COLLECTIONMODIFY_RESPONSE);
158
159 // Trying to get more information about the error
160 const QDomElement responseDescriptionElement =
161 Utils::firstChildElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("responsedescription"));
162 if (!responseDescriptionElement.isNull()) {
163 setJobErrorText(responseDescriptionElement.text());
164 }
165 setErrorTextFromDavError();
166 }
167
168 emitResult();
169}
170
171#include "moc_davcollectionmodifyjob.cpp"
A job that modifies a DAV collection.
void start() override
Starts the job.
DavCollectionModifyJob(const DavUrl &url, QObject *parent=nullptr)
Creates a new DAV collection modify job.
void setProperty(const QString &property, const QString &value, const QString &ns=QString())
Sets the property that shall be modified by the job.
void removeProperty(const QString &property, const QString &ns)
Sets the property that shall be removed by the job.
base class for the jobs used by the resource.
Definition davjobbase.h:27
A helper class to combine URL and protocol of a DAV URL.
Definition davurl.h:27
QByteArray responseData() const
void addMetaData(const QMap< QString, QString > &values)
QString queryMetaData(const QString &key)
void emitResult()
int error() const
void result(KJob *job)
void setError(int errorCode)
QString errorText() const
The KDAV namespace.
QDomElement createElementNS(const QString &nsURI, const QString &qName)
QDomElement documentElement() const const
ParseResult setContent(QAnyStringView text, ParseOptions options)
QString toString(int indent) const const
QDomNodeList elementsByTagNameNS(const QString &nsURI, const QString &localName) const const
QString text() const const
QDomNode appendChild(const QDomNode &newChild)
bool isNull() const const
QDomElement toElement() const const
QDomNode item(int index) const const
int length() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
int toInt(bool *ok, int base) const const
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Nov 22 2024 12:05:53 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.