File indexing completed on 2024-05-26 05:17:00
0001 /* 0002 Copyright (c) 2014 Gregory Oestreicher <greg@kamago.net> 0003 0004 This program is free software; you can redistribute it and/or modify 0005 it under the terms of the GNU General Public License as published by 0006 the Free Software Foundation; either version 2 of the License, or 0007 (at your option) any later version. 0008 0009 This program is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0012 GNU General Public License for more details. 0013 0014 You should have received a copy of the GNU General Public License 0015 along with this program; if not, write to the Free Software 0016 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 0017 */ 0018 0019 #include "davjob.h" 0020 0021 #include "davmanager.h" 0022 #include "libkdav2_debug.h" 0023 0024 #include <QTextStream> 0025 0026 using namespace KDAV2; 0027 0028 class DavJobPrivate { 0029 public: 0030 QByteArray data; 0031 QDomDocument doc; 0032 QUrl url; 0033 0034 QString location; 0035 QString etag; 0036 QString contentType; 0037 QNetworkReply::NetworkError responseCode = QNetworkReply::NoError; 0038 int httpStatusCode = 0; 0039 }; 0040 0041 DavJob::DavJob(QNetworkReply *reply, QUrl url, QObject *parent) 0042 : KJob(parent), 0043 d(new DavJobPrivate) 0044 { 0045 d->url = url; 0046 connectToReply(reply); 0047 } 0048 0049 DavJob::~DavJob() 0050 { 0051 } 0052 0053 void DavJob::connectToReply(QNetworkReply *reply) 0054 { 0055 QObject::connect(reply, &QNetworkReply::readyRead, this, [=] () { 0056 d->data.append(reply->readAll()); 0057 }); 0058 QObject::connect(reply, static_cast<void(QNetworkReply::*)(QNetworkReply::NetworkError)>(&QNetworkReply::error), this, [=] (QNetworkReply::NetworkError error) { 0059 qCWarning(KDAV2_LOG) << "Network error:" << error << "Message:" << reply->errorString() << "HTTP Status code:" << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() << "\nAvailable data:" << reply->readAll(); 0060 }); 0061 QObject::connect(reply, &QNetworkReply::metaDataChanged, this, [=] () { 0062 qCDebug(KDAV2_LOG) << "Metadata changed: " << reply->rawHeaderPairs(); 0063 d->location = reply->rawHeader("Location"); 0064 d->etag = reply->rawHeader("ETag"); 0065 //"text/x-vcard; charset=utf-8" -> "text/x-vcard" 0066 d->contentType = reply->rawHeader("Content-Type").split(';').first(); 0067 }); 0068 QObject::connect(reply, &QNetworkReply::finished, this, [=] () { 0069 //This is a workaround for QNetworkAccessManager::setRedirectPolicy(QNetworkRequest::UserVerifiedRedirectPolicy), 0070 //which does not seem to work with multiple redirects. 0071 const auto possibleRedirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); 0072 if(!possibleRedirectUrl.isEmpty()) { 0073 qCDebug(KDAV2_LOG) << "Redirecting to " << possibleRedirectUrl; 0074 auto request = reply->request(); 0075 request.setUrl(possibleRedirectUrl); 0076 reply->disconnect(this); 0077 0078 //Set in QWebdav 0079 const auto requestData = reply->property("requestData").toByteArray(); 0080 d->data.clear(); 0081 0082 auto redirectReply = [&] { 0083 if (reply->property("isPut").toBool()) { 0084 return DavManager::networkAccessManager()->put(request, requestData); 0085 } 0086 return DavManager::networkAccessManager()->sendCustomRequest(request, request.attribute(QNetworkRequest::CustomVerbAttribute).toByteArray(), requestData); 0087 }(); 0088 redirectReply->setProperty("requestData", requestData); 0089 connectToReply(redirectReply); 0090 return; 0091 } 0092 0093 //Could have changed due to redirects 0094 d->url = reply->url(); 0095 0096 d->doc.setContent(d->data, true); 0097 0098 if (KDAV2_LOG().isDebugEnabled()) { 0099 QTextStream stream(stdout, QIODevice::WriteOnly); 0100 d->doc.save(stream, 2); 0101 } 0102 0103 d->responseCode = reply->error(); 0104 d->httpStatusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); 0105 if (d->responseCode) { 0106 setError(KJob::UserDefinedError); 0107 setErrorText(reply->errorString()); 0108 } else if (d->httpStatusCode >= 400) { 0109 qWarning() << "No error set even though we clearly have an http error?" << d->responseCode << d->httpStatusCode; 0110 Q_ASSERT(false); 0111 setError(KJob::UserDefinedError); 0112 setErrorText(reply->errorString()); 0113 } 0114 emitResult(); 0115 }); 0116 0117 } 0118 0119 void DavJob::start() 0120 { 0121 } 0122 0123 QDomDocument DavJob::response() const 0124 { 0125 return d->doc; 0126 } 0127 0128 QByteArray DavJob::data() const 0129 { 0130 return d->data; 0131 } 0132 0133 QUrl DavJob::url() const 0134 { 0135 return d->url; 0136 } 0137 0138 QString DavJob::getLocationHeader() const 0139 { 0140 return d->location; 0141 } 0142 0143 QString DavJob::getETagHeader() const 0144 { 0145 return d->etag; 0146 } 0147 0148 QString DavJob::getContentTypeHeader() const 0149 { 0150 return d->contentType; 0151 } 0152 0153 QNetworkReply::NetworkError DavJob::responseCode() const 0154 { 0155 return d->responseCode; 0156 } 0157 0158 int DavJob::httpStatusCode() const 0159 { 0160 return d->httpStatusCode; 0161 }