KDAV

davitemmodifyjob.cpp
1/*
2 SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "davitemmodifyjob.h"
8#include "davjobbase_p.h"
9
10#include "daverror.h"
11#include "davitemfetchjob.h"
12
13#include <KIO/StoredTransferJob>
14
15using namespace KDAV;
16namespace KDAV
17{
18class DavItemModifyJobPrivate : public DavJobBasePrivate
19{
20public:
21 void davJobFinished(KJob *job);
22 void itemRefreshed(KJob *job);
23 void conflictingItemFetched(KJob *job);
24
25 DavItem mItem;
26 DavItem mFreshItem;
27 int mFreshResponseCode = 0;
28
29 Q_DECLARE_PUBLIC(DavItemModifyJob)
30};
31}
32
34 : DavJobBase(new DavItemModifyJobPrivate, parent)
35{
37 d->mItem = item;
38}
39
41{
43 QString headers = QStringLiteral("Content-Type: ");
44 headers += d->mItem.contentType();
45 headers += QLatin1String("\r\n");
46 headers += QLatin1String("If-Match: ") + d->mItem.etag();
47
48 KIO::StoredTransferJob *job = KIO::storedPut(d->mItem.data(), itemUrl(), -1, KIO::HideProgressInfo | KIO::DefaultFlags);
49 job->addMetaData(QStringLiteral("PropagateHttpHeader"), QStringLiteral("true"));
50 job->addMetaData(QStringLiteral("customHTTPHeader"), headers);
51 job->addMetaData(QStringLiteral("cookies"), QStringLiteral("none"));
52 job->addMetaData(QStringLiteral("no-auth-prompt"), QStringLiteral("true"));
53
54 connect(job, &KIO::StoredTransferJob::result, this, [d](KJob *job) {
55 d->davJobFinished(job);
56 });
57}
58
60{
61 Q_D(const DavItemModifyJob);
62 return d->mItem;
63}
64
66{
67 Q_D(const DavItemModifyJob);
68 return d->mFreshItem;
69}
70
72{
73 Q_D(const DavItemModifyJob);
74 return d->mFreshResponseCode;
75}
76
77QUrl DavItemModifyJob::itemUrl() const
78{
79 Q_D(const DavItemModifyJob);
80 return d->mItem.url().url();
81}
82
83void DavItemModifyJobPrivate::davJobFinished(KJob *job)
84{
86 KIO::StoredTransferJob *storedJob = qobject_cast<KIO::StoredTransferJob *>(job);
87
88 if (storedJob->error()) {
89 const int responseCode = storedJob->queryMetaData(QStringLiteral("responsecode")).isEmpty() //
90 ? 0
91 : storedJob->queryMetaData(QStringLiteral("responsecode")).toInt();
92
93 setLatestResponseCode(responseCode);
94 setError(ERR_ITEMMODIFY);
95 setJobErrorText(storedJob->errorText());
96 setJobError(storedJob->error());
97 setErrorTextFromDavError();
98
99 if (q->hasConflict()) {
100 DavItemFetchJob *fetchJob = new DavItemFetchJob(mItem);
101 QObject::connect(fetchJob, &DavItemFetchJob::result, q, [this](KJob *job) {
102 conflictingItemFetched(job);
103 });
104 fetchJob->start();
105 } else {
106 emitResult();
107 }
108
109 return;
110 }
111
112 // The 'Location:' HTTP header is used to indicate the new URL
113 const QStringList allHeaders = storedJob->queryMetaData(QStringLiteral("HTTP-Headers")).split(QLatin1Char('\n'));
115 for (const QString &header : allHeaders) {
116 if (header.startsWith(QLatin1String("location:"), Qt::CaseInsensitive)) {
117 location = header.section(QLatin1Char(' '), 1);
118 }
119 }
120
121 QUrl url;
122 if (location.isEmpty()) {
123 url = storedJob->url();
124 } else if (location.startsWith(QLatin1Char('/'))) {
125 url = storedJob->url();
126 url.setPath(location, QUrl::TolerantMode);
127 } else {
128 url = QUrl::fromUserInput(location);
129 }
130
131 url.setUserInfo(q->itemUrl().userInfo());
132 mItem.setUrl(DavUrl(url, mItem.url().protocol()));
133
134 DavItemFetchJob *fetchJob = new DavItemFetchJob(mItem);
135 QObject::connect(fetchJob, &DavItemFetchJob::result, q, [this](KJob *job) {
136 itemRefreshed(job);
137 });
138 fetchJob->start();
139}
140
141void DavItemModifyJobPrivate::itemRefreshed(KJob *job)
142{
143 if (!job->error()) {
144 DavItemFetchJob *fetchJob = qobject_cast<DavItemFetchJob *>(job);
145 mItem.setEtag(fetchJob->item().etag());
146 } else {
147 mItem.setEtag(QString());
148 }
149 emitResult();
150}
151
152void DavItemModifyJobPrivate::conflictingItemFetched(KJob *job)
153{
154 DavItemFetchJob *fetchJob = qobject_cast<DavItemFetchJob *>(job);
155 mFreshResponseCode = fetchJob->latestResponseCode();
156
157 if (!job->error()) {
158 mFreshItem = fetchJob->item();
159 }
160
161 emitResult();
162}
163
164#include "moc_davitemmodifyjob.cpp"
A job that fetches a DAV item from the DAV server.
DavItem item() const
Returns the fetched item including current ETag information.
void start() override
Starts the job.
A job that modifies a DAV item on the DAV server.
DavItem item() const
Returns the modified item including the updated ETag information.
DavItemModifyJob(const DavItem &item, QObject *parent=nullptr)
Creates a new DAV item modify job.
void start() override
Starts the job.
int freshResponseCode() const
Returns the response code we got when fetching the fresh item.
DavItem freshItem() const
Returns the item that triggered the conflict, if any.
A helper class to store information about DAV resources.
Definition davitem.h:39
DavUrl url() const
Returns the URL that identifies the item.
Definition davitem.cpp:47
void setEtag(const QString &etag)
Sets the etag of the item.
Definition davitem.cpp:72
void setUrl(const DavUrl &url)
Sets the url that identifies the item.
Definition davitem.cpp:42
QString etag() const
Returns the ETag of the item.
Definition davitem.cpp:77
base class for the jobs used by the resource.
Definition davjobbase.h:27
int latestResponseCode() const
Get the latest response code.
A helper class to combine URL and protocol of a DAV URL.
Definition davurl.h:27
Protocol protocol() const
Returns the DAV protocol dialect that is used to retrieve the DAV object.
Definition davurl.cpp:55
void addMetaData(const QMap< QString, QString > &values)
QString queryMetaData(const QString &key)
const QUrl & url() const
int error() const
void result(KJob *job)
QString errorText() const
The KDAV namespace.
KIOCORE_EXPORT StoredTransferJob * storedPut(const QByteArray &arr, const QUrl &url, int permissions, JobFlags flags=DefaultFlags)
DefaultFlags
HideProgressInfo
QVariant location(const QVariant &res)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool isEmpty() const const
QStringList split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
int toInt(bool *ok, int base) const const
CaseInsensitive
TolerantMode
QUrl fromUserInput(const QString &userInput, const QString &workingDirectory, UserInputResolutionOptions options)
void setPath(const QString &path, ParsingMode mode)
void setUserInfo(const QString &userInfo, ParsingMode mode)
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:16:34 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.