Libkdav2

davjob.cpp
1 /*
2  Copyright (c) 2014 Gregory Oestreicher <[email protected]>
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18 
19 #include "davjob.h"
20 
21 #include "davmanager.h"
22 #include "libkdav2_debug.h"
23 
24 #include <QTextStream>
25 
26 using namespace KDAV2;
27 
28 class DavJobPrivate {
29 public:
30  QByteArray data;
31  QDomDocument doc;
32  QUrl url;
33 
35  QString etag;
36  QString contentType;
38  int httpStatusCode = 0;
39 };
40 
41 DavJob::DavJob(QNetworkReply *reply, QUrl url, QObject *parent)
42  : KJob(parent),
43  d(new DavJobPrivate)
44 {
45  d->url = url;
46  connectToReply(reply);
47 }
48 
49 DavJob::~DavJob()
50 {
51 }
52 
53 void DavJob::connectToReply(QNetworkReply *reply)
54 {
55  QObject::connect(reply, &QNetworkReply::readyRead, this, [=] () {
56  d->data.append(reply->readAll());
57  });
59  qCWarning(KDAV2_LOG) << "Network error:" << error << "Message:" << reply->errorString() << "HTTP Status code:" << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() << "\nAvailable data:" << reply->readAll();
60  });
61  QObject::connect(reply, &QNetworkReply::metaDataChanged, this, [=] () {
62  qCDebug(KDAV2_LOG) << "Metadata changed: " << reply->rawHeaderPairs();
63  d->location = reply->rawHeader("Location");
64  d->etag = reply->rawHeader("ETag");
65  //"text/x-vcard; charset=utf-8" -> "text/x-vcard"
66  d->contentType = reply->rawHeader("Content-Type").split(';').first();
67  });
68  QObject::connect(reply, &QNetworkReply::finished, this, [=] () {
69  //This is a workaround for QNetworkAccessManager::setRedirectPolicy(QNetworkRequest::UserVerifiedRedirectPolicy),
70  //which does not seem to work with multiple redirects.
71  const auto possibleRedirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
72  if(!possibleRedirectUrl.isEmpty()) {
73  qCDebug(KDAV2_LOG) << "Redirecting to " << possibleRedirectUrl;
74  auto request = reply->request();
75  request.setUrl(possibleRedirectUrl);
76  reply->disconnect(this);
77 
78  //Set in QWebdav
79  const auto requestData = reply->property("requestData").toByteArray();
80  d->data.clear();
81 
82  auto redirectReply = [&] {
83  if (reply->property("isPut").toBool()) {
84  return DavManager::networkAccessManager()->put(request, requestData);
85  }
86  return DavManager::networkAccessManager()->sendCustomRequest(request, request.attribute(QNetworkRequest::CustomVerbAttribute).toByteArray(), requestData);
87  }();
88  redirectReply->setProperty("requestData", requestData);
89  connectToReply(redirectReply);
90  return;
91  }
92 
93  //Could have changed due to redirects
94  d->url = reply->url();
95 
96  d->doc.setContent(d->data, true);
97 
98  if (KDAV2_LOG().isDebugEnabled()) {
99  QTextStream stream(stdout, QIODevice::WriteOnly);
100  d->doc.save(stream, 2);
101  }
102 
103  d->responseCode = reply->error();
104  d->httpStatusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
105  if (d->responseCode) {
106  setError(KJob::UserDefinedError);
107  setErrorText(reply->errorString());
108  } else if (d->httpStatusCode >= 400) {
109  qWarning() << "No error set even though we clearly have an http error?" << d->responseCode << d->httpStatusCode;
110  Q_ASSERT(false);
111  setError(KJob::UserDefinedError);
112  setErrorText(reply->errorString());
113  }
114  emitResult();
115  });
116 
117 }
118 
119 void DavJob::start()
120 {
121 }
122 
123 QDomDocument DavJob::response() const
124 {
125  return d->doc;
126 }
127 
128 QByteArray DavJob::data() const
129 {
130  return d->data;
131 }
132 
133 QUrl DavJob::url() const
134 {
135  return d->url;
136 }
137 
138 QString DavJob::getLocationHeader() const
139 {
140  return d->location;
141 }
142 
143 QString DavJob::getETagHeader() const
144 {
145  return d->etag;
146 }
147 
148 QString DavJob::getContentTypeHeader() const
149 {
150  return d->contentType;
151 }
152 
153 QNetworkReply::NetworkError DavJob::responseCode() const
154 {
155  return d->responseCode;
156 }
157 
158 int DavJob::httpStatusCode() const
159 {
160  return d->httpStatusCode;
161 }
QNetworkReply * sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QIODevice *data)
QNetworkReply * put(const QNetworkRequest &request, QIODevice *data)
QUrl toUrl() const const
const QList< QNetworkReply::RawHeaderPair > & rawHeaderPairs() const const
QByteArray toByteArray() const const
void emitResult()
QList< QByteArray > split(char sep) const const
void setUrl(const QUrl &url)
static QNetworkAccessManager * networkAccessManager()
Provides access to the internally used network access manager.
Definition: davmanager.cpp:173
QString errorString() const const
void setError(int errorCode)
QVariant location(const QVariant &res)
QNetworkRequest request() const const
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
void setErrorText(const QString &errorText)
QVariant property(const char *name) const const
int toInt(bool *ok) const const
QByteArray readAll()
QByteArray rawHeader(const QByteArray &headerName) const const
T & first()
void metaDataChanged()
QVariant attribute(QNetworkRequest::Attribute code) const const
QUrl url() const const
bool toBool() const const
QNetworkReply::NetworkError error() const const
bool setProperty(const char *name, const QVariant &value)
void readyRead()
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
int error() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Thu Jan 27 2022 23:10:33 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.