File indexing completed on 2024-05-05 16:07:03
0001 /* 0002 SPDX-FileCopyrightText: 2010 Grégory Oestreicher <greg@kamago.net> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "davcollectionmodifyjob.h" 0008 #include "davjobbase_p.h" 0009 #include "davmanager_p.h" 0010 0011 #include "daverror.h" 0012 #include "utils_p.h" 0013 0014 #include <KIO/DavJob> 0015 #include <KIO/Job> 0016 0017 using namespace KDAV; 0018 0019 namespace KDAV 0020 { 0021 class DavCollectionModifyJobPrivate : public DavJobBasePrivate 0022 { 0023 public: 0024 void davJobFinished(KJob *job); 0025 0026 DavUrl mUrl; 0027 QDomDocument mQuery; 0028 0029 QVector<QDomElement> mSetProperties; 0030 QVector<QDomElement> mRemoveProperties; 0031 }; 0032 } 0033 0034 DavCollectionModifyJob::DavCollectionModifyJob(const DavUrl &url, QObject *parent) 0035 : DavJobBase(new DavCollectionModifyJobPrivate, parent) 0036 { 0037 Q_D(DavCollectionModifyJob); 0038 d->mUrl = url; 0039 } 0040 0041 void DavCollectionModifyJob::setProperty(const QString &prop, const QString &value, const QString &ns) 0042 { 0043 Q_D(DavCollectionModifyJob); 0044 QDomElement propElement; 0045 0046 if (ns.isEmpty()) { 0047 propElement = d->mQuery.createElement(prop); 0048 } else { 0049 propElement = d->mQuery.createElementNS(ns, prop); 0050 } 0051 0052 const QDomText textElement = d->mQuery.createTextNode(value); 0053 propElement.appendChild(textElement); 0054 0055 d->mSetProperties << propElement; 0056 } 0057 0058 void DavCollectionModifyJob::removeProperty(const QString &prop, const QString &ns) 0059 { 0060 Q_D(DavCollectionModifyJob); 0061 QDomElement propElement; 0062 0063 if (ns.isEmpty()) { 0064 propElement = d->mQuery.createElement(prop); 0065 } else { 0066 propElement = d->mQuery.createElementNS(ns, prop); 0067 } 0068 0069 d->mRemoveProperties << propElement; 0070 } 0071 0072 void DavCollectionModifyJob::start() 0073 { 0074 Q_D(DavCollectionModifyJob); 0075 if (d->mSetProperties.isEmpty() && d->mRemoveProperties.isEmpty()) { 0076 setError(ERR_COLLECTIONMODIFY_NO_PROPERITES); 0077 d->setErrorTextFromDavError(); 0078 emitResult(); 0079 return; 0080 } 0081 0082 QDomDocument mQuery; 0083 QDomElement propertyUpdateElement = mQuery.createElementNS(QStringLiteral("DAV:"), QStringLiteral("propertyupdate")); 0084 mQuery.appendChild(propertyUpdateElement); 0085 0086 if (!d->mSetProperties.isEmpty()) { 0087 QDomElement setElement = mQuery.createElementNS(QStringLiteral("DAV:"), QStringLiteral("set")); 0088 propertyUpdateElement.appendChild(setElement); 0089 0090 QDomElement propElement = mQuery.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop")); 0091 setElement.appendChild(propElement); 0092 0093 for (const QDomElement &element : std::as_const(d->mSetProperties)) { 0094 propElement.appendChild(element); 0095 } 0096 } 0097 0098 if (!d->mRemoveProperties.isEmpty()) { 0099 QDomElement removeElement = mQuery.createElementNS(QStringLiteral("DAV:"), QStringLiteral("remove")); 0100 propertyUpdateElement.appendChild(removeElement); 0101 0102 QDomElement propElement = mQuery.createElementNS(QStringLiteral("DAV:"), QStringLiteral("prop")); 0103 removeElement.appendChild(propElement); 0104 0105 for (const QDomElement &element : std::as_const(d->mSetProperties)) { 0106 propElement.appendChild(element); 0107 } 0108 } 0109 0110 KIO::DavJob *job = DavManager::self()->createPropPatchJob(d->mUrl.url(), mQuery.toString()); 0111 job->addMetaData(QStringLiteral("PropagateHttpHeader"), QStringLiteral("true")); 0112 connect(job, &KIO::DavJob::result, this, [d](KJob *job) { 0113 d->davJobFinished(job); 0114 }); 0115 } 0116 0117 void DavCollectionModifyJobPrivate::davJobFinished(KJob *job) 0118 { 0119 KIO::DavJob *davJob = qobject_cast<KIO::DavJob *>(job); 0120 const QString responseCodeStr = davJob->queryMetaData(QStringLiteral("responsecode")); 0121 const int responseCode = responseCodeStr.isEmpty() ? 0 : responseCodeStr.toInt(); 0122 0123 // KIO::DavJob does not set error() even if the HTTP status code is a 4xx or a 5xx 0124 if (davJob->error() || (responseCode >= 400 && responseCode < 600)) { 0125 setLatestResponseCode(responseCode); 0126 setError(ERR_COLLECTIONMODIFY); 0127 setJobErrorText(davJob->errorText()); 0128 setJobError(davJob->error()); 0129 setErrorTextFromDavError(); 0130 emitResult(); 0131 return; 0132 } 0133 0134 QDomDocument response; 0135 response.setContent(davJob->responseData(), true); 0136 QDomElement responseElement = Utils::firstChildElementNS(response.documentElement(), QStringLiteral("DAV:"), QStringLiteral("response")); 0137 0138 bool hasError = false; 0139 0140 // parse all propstats answers to get the eventual errors 0141 const QDomNodeList propstats = responseElement.elementsByTagNameNS(QStringLiteral("DAV:"), QStringLiteral("propstat")); 0142 for (int i = 0; i < propstats.length(); ++i) { 0143 const QDomElement propstatElement = propstats.item(i).toElement(); 0144 const QDomElement statusElement = Utils::firstChildElementNS(propstatElement, QStringLiteral("DAV:"), QStringLiteral("status")); 0145 0146 const QString statusText = statusElement.text(); 0147 if (statusText.contains(QLatin1String("200"))) { 0148 continue; 0149 } else { 0150 // Generic error 0151 hasError = true; 0152 break; 0153 } 0154 } 0155 0156 if (hasError) { 0157 setError(ERR_COLLECTIONMODIFY_RESPONSE); 0158 0159 // Trying to get more information about the error 0160 const QDomElement responseDescriptionElement = 0161 Utils::firstChildElementNS(responseElement, QStringLiteral("DAV:"), QStringLiteral("responsedescription")); 0162 if (!responseDescriptionElement.isNull()) { 0163 setJobErrorText(responseDescriptionElement.text()); 0164 } 0165 setErrorTextFromDavError(); 0166 } 0167 0168 emitResult(); 0169 } 0170 0171 #include "moc_davcollectionmodifyjob.cpp"