1/*
2 SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "davitemcreatejob.h"
8#include "davjobbase_p.h"
9
10#include "daverror.h"
11#include "davitemfetchjob.h"
12
13#include <KIO/DavJob>
14#include <KIO/StoredTransferJob>
15
16using namespace KDAV;
17
18namespace KDAV
19{
20class DavItemCreateJobPrivate : public DavJobBasePrivate
21{
22public:
23 void davJobFinished(KJob *job);
24 void itemRefreshed(KJob *job);
25
26 DavItem mItem;
27 int mRedirectCount = 0;
28
29 Q_DECLARE_PUBLIC(DavItemCreateJob)
30};
31}
32
33DavItemCreateJob::DavItemCreateJob(const DavItem &item, QObject *parent)
34 : DavJobBase(new DavItemCreateJobPrivate, parent)
35{
36 Q_D(DavItemCreateJob);
37 d->mItem = item;
38}
39
40void DavItemCreateJob::start()
41{
42 Q_D(DavItemCreateJob);
43 QString headers = QStringLiteral("Content-Type: ");
44 headers += d->mItem.contentType();
45 headers += QLatin1String("\r\n");
46 headers += QLatin1String("If-None-Match: *");
47
48 KIO::StoredTransferJob *job = KIO::storedPut(arr: d->mItem.data(), url: itemUrl(), permissions: -1, flags: KIO::HideProgressInfo | KIO::DefaultFlags);
49 job->addMetaData(QStringLiteral("PropagateHttpHeader"), QStringLiteral("true"));
50 job->addMetaData(QStringLiteral("customHTTPHeader"), value: headers);
51 job->addMetaData(QStringLiteral("cookies"), QStringLiteral("none"));
52 job->addMetaData(QStringLiteral("no-auth-prompt"), QStringLiteral("true"));
53 job->setRedirectionHandlingEnabled(false);
54
55 connect(sender: job, signal: &KIO::StoredTransferJob::result, context: this, slot: [d](KJob *job) {
56 d->davJobFinished(job);
57 });
58}
59
60DavItem DavItemCreateJob::item() const
61{
62 Q_D(const DavItemCreateJob);
63 return d->mItem;
64}
65
66QUrl DavItemCreateJob::itemUrl() const
67{
68 Q_D(const DavItemCreateJob);
69 return d->mItem.url().url();
70}
71
72void DavItemCreateJobPrivate::davJobFinished(KJob *job)
73{
74 Q_Q(DavItemCreateJob);
75 KIO::StoredTransferJob *storedJob = qobject_cast<KIO::StoredTransferJob *>(object: job);
76 const QString responseCodeStr = storedJob->queryMetaData(QStringLiteral("responsecode"));
77 const int responseCode = responseCodeStr.isEmpty() ? 0 : responseCodeStr.toInt();
78 if (storedJob->error()) {
79 setLatestResponseCode(responseCode);
80 setError(ERR_ITEMCREATE);
81 setJobErrorText(storedJob->errorText());
82 setJobError(storedJob->error());
83 setErrorTextFromDavError();
84
85 emitResult();
86 return;
87 }
88
89 // The 'Location:' HTTP header is used to indicate the new URL
90 const QStringList allHeaders = storedJob->queryMetaData(QStringLiteral("HTTP-Headers")).split(sep: QLatin1Char('\n'));
91 QString location;
92 for (const QString &header : allHeaders) {
93 if (header.startsWith(s: QLatin1String("location:"), cs: Qt::CaseInsensitive)) {
94 location = header.section(asep: QLatin1Char(' '), astart: 1);
95 }
96 }
97
98 QUrl url;
99 if (location.isEmpty()) {
100 url = storedJob->url();
101 } else if (location.startsWith(c: QLatin1Char('/'))) {
102 url = storedJob->url();
103 url.setPath(path: location, mode: QUrl::TolerantMode);
104 } else {
105 url = QUrl::fromUserInput(userInput: location);
106 }
107
108 if (responseCode == 301 || responseCode == 302 || responseCode == 307 || responseCode == 308) {
109 if (mRedirectCount > 4) {
110 setLatestResponseCode(responseCode);
111 setError(DavItemCreateJob::UserDefinedError + responseCode);
112 emitResult();
113 } else {
114 QUrl _itemUrl(url);
115 _itemUrl.setUserInfo(userInfo: q->itemUrl().userInfo());
116 mItem.setUrl(DavUrl(_itemUrl, mItem.url().protocol()));
117
118 ++mRedirectCount;
119 q->start();
120 }
121
122 return;
123 }
124
125 url.setUserInfo(userInfo: q->itemUrl().userInfo());
126 mItem.setUrl(DavUrl(url, mItem.url().protocol()));
127
128 DavItemFetchJob *fetchJob = new DavItemFetchJob(mItem);
129 QObject::connect(sender: fetchJob, signal: &DavItemFetchJob::result, context: q, slot: [this](KJob *job) {
130 itemRefreshed(job);
131 });
132 fetchJob->start();
133}
134
135void DavItemCreateJobPrivate::itemRefreshed(KJob *job)
136{
137 if (!job->error()) {
138 DavItemFetchJob *fetchJob = qobject_cast<DavItemFetchJob *>(object: job);
139 mItem.setEtag(fetchJob->item().etag());
140 }
141 emitResult();
142}
143
144#include "moc_davitemcreatejob.cpp"
145

source code of kdav/src/common/davitemcreatejob.cpp