File indexing completed on 2024-05-05 16:07:04
0001 /* 0002 SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "davitemmodifyjob.h" 0008 #include "davjobbase_p.h" 0009 0010 #include "daverror.h" 0011 #include "davitemfetchjob.h" 0012 0013 #include <KIO/Job> 0014 0015 using namespace KDAV; 0016 namespace KDAV 0017 { 0018 class DavItemModifyJobPrivate : public DavJobBasePrivate 0019 { 0020 public: 0021 void davJobFinished(KJob *job); 0022 void itemRefreshed(KJob *job); 0023 void conflictingItemFetched(KJob *job); 0024 0025 DavItem mItem; 0026 DavItem mFreshItem; 0027 int mFreshResponseCode = 0; 0028 0029 Q_DECLARE_PUBLIC(DavItemModifyJob) 0030 }; 0031 } 0032 0033 DavItemModifyJob::DavItemModifyJob(const DavItem &item, QObject *parent) 0034 : DavJobBase(new DavItemModifyJobPrivate, parent) 0035 { 0036 Q_D(DavItemModifyJob); 0037 d->mItem = item; 0038 } 0039 0040 void DavItemModifyJob::start() 0041 { 0042 Q_D(DavItemModifyJob); 0043 QString headers = QStringLiteral("Content-Type: "); 0044 headers += d->mItem.contentType(); 0045 headers += QLatin1String("\r\n"); 0046 headers += QLatin1String("If-Match: ") + d->mItem.etag(); 0047 0048 KIO::StoredTransferJob *job = KIO::storedPut(d->mItem.data(), itemUrl(), -1, KIO::HideProgressInfo | KIO::DefaultFlags); 0049 job->addMetaData(QStringLiteral("PropagateHttpHeader"), QStringLiteral("true")); 0050 job->addMetaData(QStringLiteral("customHTTPHeader"), headers); 0051 job->addMetaData(QStringLiteral("cookies"), QStringLiteral("none")); 0052 job->addMetaData(QStringLiteral("no-auth-prompt"), QStringLiteral("true")); 0053 0054 connect(job, &KIO::StoredTransferJob::result, this, [d](KJob *job) { 0055 d->davJobFinished(job); 0056 }); 0057 } 0058 0059 DavItem DavItemModifyJob::item() const 0060 { 0061 Q_D(const DavItemModifyJob); 0062 return d->mItem; 0063 } 0064 0065 DavItem DavItemModifyJob::freshItem() const 0066 { 0067 Q_D(const DavItemModifyJob); 0068 return d->mFreshItem; 0069 } 0070 0071 int DavItemModifyJob::freshResponseCode() const 0072 { 0073 Q_D(const DavItemModifyJob); 0074 return d->mFreshResponseCode; 0075 } 0076 0077 QUrl DavItemModifyJob::itemUrl() const 0078 { 0079 Q_D(const DavItemModifyJob); 0080 return d->mItem.url().url(); 0081 } 0082 0083 void DavItemModifyJobPrivate::davJobFinished(KJob *job) 0084 { 0085 Q_Q(DavItemModifyJob); 0086 KIO::StoredTransferJob *storedJob = qobject_cast<KIO::StoredTransferJob *>(job); 0087 0088 if (storedJob->error()) { 0089 const int responseCode = storedJob->queryMetaData(QStringLiteral("responsecode")).isEmpty() // 0090 ? 0 0091 : storedJob->queryMetaData(QStringLiteral("responsecode")).toInt(); 0092 0093 setLatestResponseCode(responseCode); 0094 setError(ERR_ITEMMODIFY); 0095 setJobErrorText(storedJob->errorText()); 0096 setJobError(storedJob->error()); 0097 setErrorTextFromDavError(); 0098 0099 if (q->hasConflict()) { 0100 DavItemFetchJob *fetchJob = new DavItemFetchJob(mItem); 0101 QObject::connect(fetchJob, &DavItemFetchJob::result, q, [this](KJob *job) { 0102 conflictingItemFetched(job); 0103 }); 0104 fetchJob->start(); 0105 } else { 0106 emitResult(); 0107 } 0108 0109 return; 0110 } 0111 0112 // The 'Location:' HTTP header is used to indicate the new URL 0113 const QStringList allHeaders = storedJob->queryMetaData(QStringLiteral("HTTP-Headers")).split(QLatin1Char('\n')); 0114 QString location; 0115 for (const QString &header : allHeaders) { 0116 if (header.startsWith(QLatin1String("location:"), Qt::CaseInsensitive)) { 0117 location = header.section(QLatin1Char(' '), 1); 0118 } 0119 } 0120 0121 QUrl url; 0122 if (location.isEmpty()) { 0123 url = storedJob->url(); 0124 } else if (location.startsWith(QLatin1Char('/'))) { 0125 url = storedJob->url(); 0126 url.setPath(location, QUrl::TolerantMode); 0127 } else { 0128 url = QUrl::fromUserInput(location); 0129 } 0130 0131 url.setUserInfo(q->itemUrl().userInfo()); 0132 mItem.setUrl(DavUrl(url, mItem.url().protocol())); 0133 0134 DavItemFetchJob *fetchJob = new DavItemFetchJob(mItem); 0135 QObject::connect(fetchJob, &DavItemFetchJob::result, q, [this](KJob *job) { 0136 itemRefreshed(job); 0137 }); 0138 fetchJob->start(); 0139 } 0140 0141 void DavItemModifyJobPrivate::itemRefreshed(KJob *job) 0142 { 0143 if (!job->error()) { 0144 DavItemFetchJob *fetchJob = qobject_cast<DavItemFetchJob *>(job); 0145 mItem.setEtag(fetchJob->item().etag()); 0146 } else { 0147 mItem.setEtag(QString()); 0148 } 0149 emitResult(); 0150 } 0151 0152 void DavItemModifyJobPrivate::conflictingItemFetched(KJob *job) 0153 { 0154 DavItemFetchJob *fetchJob = qobject_cast<DavItemFetchJob *>(job); 0155 mFreshResponseCode = fetchJob->latestResponseCode(); 0156 0157 if (!job->error()) { 0158 mFreshItem = fetchJob->item(); 0159 } 0160 0161 emitResult(); 0162 } 0163 0164 #include "moc_davitemmodifyjob.cpp"