File indexing completed on 2024-04-21 03:53:52

0001 /*
0002     SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "davitemcreatejob.h"
0008 #include "davjobbase_p.h"
0009 
0010 #include "daverror.h"
0011 #include "davitemfetchjob.h"
0012 
0013 #include <KIO/DavJob>
0014 #include <KIO/StoredTransferJob>
0015 
0016 using namespace KDAV;
0017 
0018 namespace KDAV
0019 {
0020 class DavItemCreateJobPrivate : public DavJobBasePrivate
0021 {
0022 public:
0023     void davJobFinished(KJob *job);
0024     void itemRefreshed(KJob *job);
0025 
0026     DavItem mItem;
0027     int mRedirectCount = 0;
0028 
0029     Q_DECLARE_PUBLIC(DavItemCreateJob)
0030 };
0031 }
0032 
0033 DavItemCreateJob::DavItemCreateJob(const DavItem &item, QObject *parent)
0034     : DavJobBase(new DavItemCreateJobPrivate, parent)
0035 {
0036     Q_D(DavItemCreateJob);
0037     d->mItem = item;
0038 }
0039 
0040 void DavItemCreateJob::start()
0041 {
0042     Q_D(DavItemCreateJob);
0043     QString headers = QStringLiteral("Content-Type: ");
0044     headers += d->mItem.contentType();
0045     headers += QLatin1String("\r\n");
0046     headers += QLatin1String("If-None-Match: *");
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     job->setRedirectionHandlingEnabled(false);
0054 
0055     connect(job, &KIO::StoredTransferJob::result, this, [d](KJob *job) {
0056         d->davJobFinished(job);
0057     });
0058 }
0059 
0060 DavItem DavItemCreateJob::item() const
0061 {
0062     Q_D(const DavItemCreateJob);
0063     return d->mItem;
0064 }
0065 
0066 QUrl DavItemCreateJob::itemUrl() const
0067 {
0068     Q_D(const DavItemCreateJob);
0069     return d->mItem.url().url();
0070 }
0071 
0072 void DavItemCreateJobPrivate::davJobFinished(KJob *job)
0073 {
0074     Q_Q(DavItemCreateJob);
0075     KIO::StoredTransferJob *storedJob = qobject_cast<KIO::StoredTransferJob *>(job);
0076     const QString responseCodeStr = storedJob->queryMetaData(QStringLiteral("responsecode"));
0077     const int responseCode = responseCodeStr.isEmpty() ? 0 : responseCodeStr.toInt();
0078     if (storedJob->error()) {
0079         setLatestResponseCode(responseCode);
0080         setError(ERR_ITEMCREATE);
0081         setJobErrorText(storedJob->errorText());
0082         setJobError(storedJob->error());
0083         setErrorTextFromDavError();
0084 
0085         emitResult();
0086         return;
0087     }
0088 
0089     // The 'Location:' HTTP header is used to indicate the new URL
0090     const QStringList allHeaders = storedJob->queryMetaData(QStringLiteral("HTTP-Headers")).split(QLatin1Char('\n'));
0091     QString location;
0092     for (const QString &header : allHeaders) {
0093         if (header.startsWith(QLatin1String("location:"), Qt::CaseInsensitive)) {
0094             location = header.section(QLatin1Char(' '), 1);
0095         }
0096     }
0097 
0098     QUrl url;
0099     if (location.isEmpty()) {
0100         url = storedJob->url();
0101     } else if (location.startsWith(QLatin1Char('/'))) {
0102         url = storedJob->url();
0103         url.setPath(location, QUrl::TolerantMode);
0104     } else {
0105         url = QUrl::fromUserInput(location);
0106     }
0107 
0108     if (responseCode == 301 || responseCode == 302 || responseCode == 307 || responseCode == 308) {
0109         if (mRedirectCount > 4) {
0110             setLatestResponseCode(responseCode);
0111             setError(DavItemCreateJob::UserDefinedError + responseCode);
0112             emitResult();
0113         } else {
0114             QUrl _itemUrl(url);
0115             _itemUrl.setUserInfo(q->itemUrl().userInfo());
0116             mItem.setUrl(DavUrl(_itemUrl, mItem.url().protocol()));
0117 
0118             ++mRedirectCount;
0119             q->start();
0120         }
0121 
0122         return;
0123     }
0124 
0125     url.setUserInfo(q->itemUrl().userInfo());
0126     mItem.setUrl(DavUrl(url, mItem.url().protocol()));
0127 
0128     DavItemFetchJob *fetchJob = new DavItemFetchJob(mItem);
0129     QObject::connect(fetchJob, &DavItemFetchJob::result, q, [this](KJob *job) {
0130         itemRefreshed(job);
0131     });
0132     fetchJob->start();
0133 }
0134 
0135 void DavItemCreateJobPrivate::itemRefreshed(KJob *job)
0136 {
0137     if (!job->error()) {
0138         DavItemFetchJob *fetchJob = qobject_cast<DavItemFetchJob *>(job);
0139         mItem.setEtag(fetchJob->item().etag());
0140     }
0141     emitResult();
0142 }
0143 
0144 #include "moc_davitemcreatejob.cpp"