From 4a1a5fa0764d2dbed076cfeb17e9aee6a4b856b7 Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Fri, 3 Mar 2017 11:20:53 +0100 Subject: [PATCH] AbstractNetworkJob: Improve redirect handling #5555 * For requests: - reuse the original QNetworkRequest, so headers and attributes are the same as in the original request - determine the original http method from the reply and the request attributes - keep the original request body around such that it can be sent again in case the request is redirected * Simplify the interface that is used for creating new requests in AbstractNetworkJob. --- src/gui/notificationconfirmjob.cpp | 4 +- src/gui/ocsjob.cpp | 4 +- src/gui/owncloudsetupwizard.cpp | 7 +- src/gui/thumbnailjob.cpp | 3 +- src/libsync/abstractnetworkjob.cpp | 101 ++++++++++++++++---------- src/libsync/abstractnetworkjob.h | 47 +++++++++--- src/libsync/account.cpp | 55 +++----------- src/libsync/account.h | 12 +-- src/libsync/networkjobs.cpp | 40 ++++------ src/libsync/propagatedownload.cpp | 5 +- src/libsync/propagateremotedelete.cpp | 7 +- src/libsync/propagateremotemove.cpp | 7 +- src/libsync/propagateupload.cpp | 15 ++-- src/libsync/propagateupload.h | 12 ++- test/syncenginetestutils.h | 6 +- 15 files changed, 166 insertions(+), 159 deletions(-) diff --git a/src/gui/notificationconfirmjob.cpp b/src/gui/notificationconfirmjob.cpp index b3051827ebf..479c4238db5 100644 --- a/src/gui/notificationconfirmjob.cpp +++ b/src/gui/notificationconfirmjob.cpp @@ -54,9 +54,7 @@ void NotificationConfirmJob::start() req.setRawHeader("Ocs-APIREQUEST", "true"); req.setRawHeader("Content-Type", "application/x-www-form-urlencoded"); - QIODevice *iodevice = 0; - setReply(davRequest(_verb, _link, req, iodevice)); - setupConnections(reply()); + sendRequest(_verb, _link, req); AbstractNetworkJob::start(); } diff --git a/src/gui/ocsjob.cpp b/src/gui/ocsjob.cpp index 8c4ca983f9c..b6f9f4ece04 100644 --- a/src/gui/ocsjob.cpp +++ b/src/gui/ocsjob.cpp @@ -93,9 +93,7 @@ void OcsJob::start() queryItems.append(qMakePair(QByteArray("format"), QByteArray("json"))); url.setEncodedQueryItems(queryItems); - setReply(davRequest(_verb, url, req, buffer)); - setupConnections(reply()); - buffer->setParent(reply()); + sendRequest(_verb, url, req, buffer); AbstractNetworkJob::start(); } diff --git a/src/gui/owncloudsetupwizard.cpp b/src/gui/owncloudsetupwizard.cpp index 53e360e4140..22ac50b0ec2 100644 --- a/src/gui/owncloudsetupwizard.cpp +++ b/src/gui/owncloudsetupwizard.cpp @@ -594,9 +594,7 @@ DetermineAuthTypeJob::DetermineAuthTypeJob(AccountPtr account, QObject *parent) void DetermineAuthTypeJob::start() { - QNetworkReply *reply = getRequest(account()->davPath()); - setReply(reply); - setupConnections(reply); + sendRequest("GET", account()->davUrl()); AbstractNetworkJob::start(); } @@ -613,8 +611,7 @@ bool DetermineAuthTypeJob::finished() // do a new run _redirects++; resetTimeout(); - setReply(getRequest(redirection)); - setupConnections(reply()); + sendRequest("GET", redirection); return false; // don't discard } else { #ifndef NO_SHIBBOLETH diff --git a/src/gui/thumbnailjob.cpp b/src/gui/thumbnailjob.cpp index d3e92cb42c3..5ffe6c2918e 100644 --- a/src/gui/thumbnailjob.cpp +++ b/src/gui/thumbnailjob.cpp @@ -27,8 +27,7 @@ ThumbnailJob::ThumbnailJob(const QString &path, AccountPtr account, QObject* par void ThumbnailJob::start() { - setReply(getRequest(path())); - setupConnections(reply()); + sendRequest("GET", makeAccountUrl(path())); AbstractNetworkJob::start(); } diff --git a/src/libsync/abstractnetworkjob.cpp b/src/libsync/abstractnetworkjob.cpp index eb865456be0..fcd2928372c 100644 --- a/src/libsync/abstractnetworkjob.cpp +++ b/src/libsync/abstractnetworkjob.cpp @@ -122,40 +122,49 @@ QNetworkReply* AbstractNetworkJob::addTimer(QNetworkReply *reply) return reply; } -QNetworkReply* AbstractNetworkJob::davRequest(const QByteArray &verb, const QString &relPath, - QNetworkRequest req, QIODevice *data) +QNetworkReply *AbstractNetworkJob::sendRequest(const QByteArray &verb, const QUrl &url, + QNetworkRequest req, QIODevice *requestBody) { - return addTimer(_account->davRequest(verb, relPath, req, data)); -} - -QNetworkReply *AbstractNetworkJob::davRequest(const QByteArray &verb, const QUrl &url, QNetworkRequest req, QIODevice *data) -{ - return addTimer(_account->davRequest(verb, url, req, data)); -} - -QNetworkReply* AbstractNetworkJob::getRequest(const QString &relPath) -{ - return addTimer(_account->getRequest(relPath)); -} - -QNetworkReply *AbstractNetworkJob::getRequest(const QUrl &url) -{ - return addTimer(_account->getRequest(url)); + auto reply = _account->sendRequest(verb, url, req, requestBody); + _requestBody = requestBody; + if (_requestBody) { + _requestBody->setParent(reply); + } + addTimer(reply); + setReply(reply); + setupConnections(reply); + return reply; } -QNetworkReply *AbstractNetworkJob::headRequest(const QString &relPath) +QUrl AbstractNetworkJob::makeAccountUrl(const QString& relativePath) const { - return addTimer(_account->headRequest(relPath)); + return Utility::concatUrlPath(_account->url(), relativePath); } -QNetworkReply *AbstractNetworkJob::headRequest(const QUrl &url) +QUrl AbstractNetworkJob::makeDavUrl(const QString& relativePath) const { - return addTimer(_account->headRequest(url)); + return Utility::concatUrlPath(_account->davUrl(), relativePath); } -QNetworkReply *AbstractNetworkJob::deleteRequest(const QUrl &url) +QByteArray AbstractNetworkJob::requestVerb(QNetworkReply* reply) { - return addTimer(_account->deleteRequest(url)); + switch (reply->operation()) { + case QNetworkAccessManager::HeadOperation: + return "HEAD"; + case QNetworkAccessManager::GetOperation: + return "GET"; + case QNetworkAccessManager::PutOperation: + return "PUT"; + case QNetworkAccessManager::PostOperation: + return "POST"; + case QNetworkAccessManager::DeleteOperation: + return "DELETE"; + case QNetworkAccessManager::CustomOperation: + return reply->request().attribute(QNetworkRequest::CustomVerbAttribute).toByteArray(); + case QNetworkAccessManager::UnknownOperation: + break; + } + return QByteArray(); } void AbstractNetworkJob::slotFinished() @@ -178,24 +187,36 @@ void AbstractNetworkJob::slotFinished() // get the Date timestamp from reply _responseTimestamp = _reply->rawHeader("Date"); - if (_followRedirects) { - // ### the qWarnings here should be exported via displayErrors() so they + QUrl requestedUrl = reply()->request().url(); + QUrl redirectUrl = reply()->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); + if (_followRedirects && !redirectUrl.isEmpty()) { + _redirectCount++; + + // ### some of the qWarnings here should be exported via displayErrors() so they // ### can be presented to the user if the job executor has a GUI - QUrl requestedUrl = reply()->request().url(); - QUrl redirectUrl = reply()->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); - if (!redirectUrl.isEmpty()) { - _redirectCount++; - if (requestedUrl.scheme() == QLatin1String("https") && - redirectUrl.scheme() == QLatin1String("http")) { - qWarning() << this << "HTTPS->HTTP downgrade detected!"; - } else if (requestedUrl == redirectUrl || _redirectCount >= maxRedirects()) { - qWarning() << this << "Redirect loop detected!"; - } else { - resetTimeout(); - setReply(getRequest(redirectUrl)); - setupConnections(reply()); - return; + QByteArray verb = requestVerb(reply()); + if (requestedUrl.scheme() == QLatin1String("https") && + redirectUrl.scheme() == QLatin1String("http")) { + qWarning() << this << "HTTPS->HTTP downgrade detected!"; + } else if (requestedUrl == redirectUrl || _redirectCount >= maxRedirects()) { + qWarning() << this << "Redirect loop detected!"; + } else if (_requestBody && _requestBody->isSequential()) { + qWarning() << this << "cannot redirect request with sequential body"; + } else if (verb.isEmpty()) { + qWarning() << this << "cannot redirect request: could not detect original verb"; + } else { + // Create the redirected request and send it + qDebug() << "Redirecting" << verb << requestedUrl << redirectUrl; + resetTimeout(); + if (_requestBody) { + _requestBody->seek(0); } + sendRequest( + verb, + redirectUrl, + reply()->request(), + _requestBody); + return; } } diff --git a/src/libsync/abstractnetworkjob.h b/src/libsync/abstractnetworkjob.h index 272ee604f47..a2ec226bbd4 100644 --- a/src/libsync/abstractnetworkjob.h +++ b/src/libsync/abstractnetworkjob.h @@ -78,17 +78,29 @@ public slots: void networkActivity(); protected: void setupConnections(QNetworkReply *reply); - QNetworkReply* davRequest(const QByteArray& verb, const QString &relPath, - QNetworkRequest req = QNetworkRequest(), - QIODevice *data = 0); - QNetworkReply* davRequest(const QByteArray& verb, const QUrl &url, - QNetworkRequest req = QNetworkRequest(), - QIODevice *data = 0); - QNetworkReply* getRequest(const QString &relPath); - QNetworkReply* getRequest(const QUrl &url); - QNetworkReply* headRequest(const QString &relPath); - QNetworkReply* headRequest(const QUrl &url); - QNetworkReply* deleteRequest(const QUrl &url); + + /** Initiate a network request, returning a QNetworkReply. + * + * Calls setReply() and setupConnections() on it. + * + * Takes ownership of the requestBody (to allow redirects). + */ + QNetworkReply* sendRequest(const QByteArray& verb, const QUrl &url, + QNetworkRequest req = QNetworkRequest(), + QIODevice *requestBody = 0); + + // sendRequest does not take a relative path instead of an url, + // but the old API allowed that. We have this undefined overload + // to help catch usage errors + QNetworkReply* sendRequest(const QByteArray& verb, const QString &relativePath, + QNetworkRequest req = QNetworkRequest(), + QIODevice *requestBody = 0); + + /// Creates a url for the account from a relative path + QUrl makeAccountUrl(const QString& relativePath) const; + + /// Like makeAccountUrl() but uses the account's dav base path + QUrl makeDavUrl(const QString& relativePath) const; int maxRedirects() const { return 10; } virtual bool finished() = 0; @@ -99,12 +111,19 @@ public slots: // GET requests that don't set up any HTTP body or other flags. bool _followRedirects; + /** Helper to construct the HTTP verb used in the request + * + * Returns an empty QByteArray for UnknownOperation. + */ + static QByteArray requestVerb(QNetworkReply* reply); + private slots: void slotFinished(); virtual void slotTimeout(); protected: AccountPtr _account; + private: QNetworkReply* addTimer(QNetworkReply *reply); bool _ignoreCredentialFailure; @@ -112,6 +131,12 @@ private slots: QString _path; QTimer _timer; int _redirectCount; + + // Set by the xyzRequest() functions and needed to be able to redirect + // requests, should it be required. + // + // Reparented to the currently running QNetworkReply. + QPointer _requestBody; }; /** diff --git a/src/libsync/account.cpp b/src/libsync/account.cpp index 8dc93aea554..2918d2a3920 100644 --- a/src/libsync/account.cpp +++ b/src/libsync/account.cpp @@ -202,54 +202,23 @@ QNetworkAccessManager *Account::networkAccessManager() return _am.data(); } -QNetworkReply *Account::headRequest(const QString &relPath) -{ - return headRequest(Utility::concatUrlPath(url(), relPath)); -} - -QNetworkReply *Account::headRequest(const QUrl &url) -{ - QNetworkRequest request(url); -#if QT_VERSION > QT_VERSION_CHECK(4, 8, 4) - request.setSslConfiguration(this->getOrCreateSslConfig()); -#endif - return _am->head(request); -} - -QNetworkReply *Account::getRequest(const QString &relPath) -{ - return getRequest(Utility::concatUrlPath(url(), relPath)); -} - -QNetworkReply *Account::getRequest(const QUrl &url) -{ - QNetworkRequest request(url); -#if QT_VERSION > QT_VERSION_CHECK(4, 8, 4) - request.setSslConfiguration(this->getOrCreateSslConfig()); -#endif - return _am->get(request); -} - -QNetworkReply *Account::deleteRequest( const QUrl &url) -{ - QNetworkRequest request(url); -#if QT_VERSION > QT_VERSION_CHECK(4, 8, 4) - request.setSslConfiguration(this->getOrCreateSslConfig()); -#endif - return _am->deleteResource(request); -} - -QNetworkReply *Account::davRequest(const QByteArray &verb, const QString &relPath, QNetworkRequest req, QIODevice *data) -{ - return davRequest(verb, Utility::concatUrlPath(davUrl(), relPath), req, data); -} - -QNetworkReply *Account::davRequest(const QByteArray &verb, const QUrl &url, QNetworkRequest req, QIODevice *data) +QNetworkReply *Account::sendRequest(const QByteArray &verb, const QUrl &url, QNetworkRequest req, QIODevice *data) { req.setUrl(url); #if QT_VERSION > QT_VERSION_CHECK(4, 8, 4) req.setSslConfiguration(this->getOrCreateSslConfig()); #endif + if (verb == "HEAD" && !data) { + return _am->head(req); + } else if (verb == "GET" && !data) { + return _am->get(req); + } else if (verb == "POST") { + return _am->post(req, data); + } else if (verb == "PUT") { + return _am->put(req, data); + } else if (verb == "DELETE" && !data) { + return _am->deleteResource(req); + } return _am->sendCustomRequest(req, verb, data); } diff --git a/src/libsync/account.h b/src/libsync/account.h index 823bfa6d610..5e5ab494439 100644 --- a/src/libsync/account.h +++ b/src/libsync/account.h @@ -106,14 +106,10 @@ class OWNCLOUDSYNC_EXPORT Account : public QObject { // For creating various network requests - QNetworkReply* headRequest(const QString &relPath); - QNetworkReply* headRequest(const QUrl &url); - QNetworkReply* getRequest(const QString &relPath); - QNetworkReply* getRequest(const QUrl &url); - QNetworkReply* deleteRequest( const QUrl &url); - QNetworkReply* davRequest(const QByteArray &verb, const QString &relPath, QNetworkRequest req, QIODevice *data = 0); - QNetworkReply* davRequest(const QByteArray &verb, const QUrl &url, QNetworkRequest req, QIODevice *data = 0); - + QNetworkReply* sendRequest(const QByteArray &verb, + const QUrl &url, + QNetworkRequest req = QNetworkRequest(), + QIODevice *data = 0); /** The ssl configuration during the first connection */ QSslConfiguration getOrCreateSslConfig(); diff --git a/src/libsync/networkjobs.cpp b/src/libsync/networkjobs.cpp index 4cc5801ae7c..b12c65a8e16 100644 --- a/src/libsync/networkjobs.cpp +++ b/src/libsync/networkjobs.cpp @@ -67,9 +67,7 @@ void RequestEtagJob::start() buf->setData(xml); buf->open(QIODevice::ReadOnly); // assumes ownership - setReply(davRequest("PROPFIND", path(), req, buf)); - buf->setParent(reply()); - setupConnections(reply()); + sendRequest("PROPFIND", makeDavUrl(path()), req, buf); if( reply()->error() != QNetworkReply::NoError ) { qDebug() << "getting etag: request network error: " << reply()->errorString(); @@ -122,10 +120,11 @@ void MkColJob::start() } // assumes ownership - QNetworkReply *reply = _url.isValid() ? davRequest("MKCOL", _url, req) - : davRequest("MKCOL", path(), req); - setReply(reply); - setupConnections(reply); + if (_url.isValid()) { + sendRequest("MKCOL", _url, req); + } else { + sendRequest("MKCOL", makeDavUrl(path()), req); + } AbstractNetworkJob::start(); } @@ -322,11 +321,11 @@ void LsColJob::start() QBuffer *buf = new QBuffer(this); buf->setData(xml); buf->open(QIODevice::ReadOnly); - QNetworkReply *reply = _url.isValid() ? davRequest("PROPFIND", _url, req, buf) - : davRequest("PROPFIND", path(), req, buf); - buf->setParent(reply); - setReply(reply); - setupConnections(reply); + if (_url.isValid()) { + sendRequest("PROPFIND", _url, req, buf); + } else { + sendRequest("PROPFIND", makeDavUrl(path()), req, buf); + } AbstractNetworkJob::start(); } @@ -380,8 +379,7 @@ CheckServerJob::CheckServerJob(AccountPtr account, QObject *parent) void CheckServerJob::start() { - setReply(getRequest(path())); - setupConnections(reply()); + sendRequest("GET", makeAccountUrl(path())); connect(reply(), SIGNAL(metaDataChanged()), this, SLOT(metaDataChangedSlot())); connect(reply(), SIGNAL(encrypted()), this, SLOT(encryptedSlot())); AbstractNetworkJob::start(); @@ -529,9 +527,7 @@ void PropfindJob::start() QBuffer *buf = new QBuffer(this); buf->setData(xml); buf->open(QIODevice::ReadOnly); - setReply(davRequest("PROPFIND", path(), req, buf)); - buf->setParent(reply()); - setupConnections(reply()); + sendRequest("PROPFIND", makeDavUrl(path()), req, buf); AbstractNetworkJob::start(); } @@ -632,9 +628,7 @@ void ProppatchJob::start() QBuffer *buf = new QBuffer(this); buf->setData(xml); buf->open(QIODevice::ReadOnly); - setReply(davRequest("PROPPATCH", path(), req, buf)); - buf->setParent(reply()); - setupConnections(reply()); + sendRequest("PROPPATCH", makeDavUrl(path()), req, buf); AbstractNetworkJob::start(); } @@ -671,8 +665,7 @@ EntityExistsJob::EntityExistsJob(AccountPtr account, const QString &path, QObjec void EntityExistsJob::start() { - setReply(headRequest(path())); - setupConnections(reply()); + sendRequest("HEAD", makeAccountUrl(path())); AbstractNetworkJob::start(); } @@ -700,8 +693,7 @@ void JsonApiJob::start() QList > params = _additionalParams; params << qMakePair(QString::fromLatin1("format"), QString::fromLatin1("json")); url.setQueryItems(params); - setReply(davRequest("GET", url, req)); - setupConnections(reply()); + sendRequest("GET", url, req); AbstractNetworkJob::start(); } diff --git a/src/libsync/propagatedownload.cpp b/src/libsync/propagatedownload.cpp index 030826c0b02..51a3ab319ea 100644 --- a/src/libsync/propagatedownload.cpp +++ b/src/libsync/propagatedownload.cpp @@ -100,12 +100,11 @@ void GETFileJob::start() { } if (_directDownloadUrl.isEmpty()) { - setReply(davRequest("GET", path(), req)); + sendRequest("GET", makeDavUrl(path()), req); } else { // Use direct URL - setReply(davRequest("GET", _directDownloadUrl, req)); + sendRequest("GET", _directDownloadUrl, req); } - setupConnections(reply()); reply()->setReadBufferSize(16 * 1024); // keep low so we can easier limit the bandwidth qDebug() << Q_FUNC_INFO << _bandwidthManager << _bandwidthChoked << _bandwidthLimited; diff --git a/src/libsync/propagateremotedelete.cpp b/src/libsync/propagateremotedelete.cpp index ff9d863eb10..a85d73c2813 100644 --- a/src/libsync/propagateremotedelete.cpp +++ b/src/libsync/propagateremotedelete.cpp @@ -30,8 +30,11 @@ DeleteJob::DeleteJob(AccountPtr account, const QUrl& url, QObject* parent) void DeleteJob::start() { QNetworkRequest req; - setReply(_url.isValid() ? davRequest("DELETE", _url, req) : davRequest("DELETE", path(), req)); - setupConnections(reply()); + if (_url.isValid()) { + sendRequest("DELETE", _url, req); + } else { + sendRequest("DELETE", makeDavUrl(path()), req); + } if( reply()->error() != QNetworkReply::NoError ) { qWarning() << Q_FUNC_INFO << " Network error: " << reply()->errorString(); diff --git a/src/libsync/propagateremotemove.cpp b/src/libsync/propagateremotemove.cpp index 11370d573c8..5a59f91244c 100644 --- a/src/libsync/propagateremotemove.cpp +++ b/src/libsync/propagateremotemove.cpp @@ -43,8 +43,11 @@ void MoveJob::start() for(auto it = _extraHeaders.constBegin(); it != _extraHeaders.constEnd(); ++it) { req.setRawHeader(it.key(), it.value()); } - setReply(_url.isValid() ? davRequest("MOVE", _url, req) : davRequest("MOVE", path(), req)); - setupConnections(reply()); + if (_url.isValid()) { + sendRequest("MOVE", _url, req); + } else { + sendRequest("MOVE", makeDavUrl(path()), req); + } if( reply()->error() != QNetworkReply::NoError ) { qWarning() << Q_FUNC_INFO << " Network error: " << reply()->errorString(); diff --git a/src/libsync/propagateupload.cpp b/src/libsync/propagateupload.cpp index 2f8c544fb7d..0ad02c09ac2 100644 --- a/src/libsync/propagateupload.cpp +++ b/src/libsync/propagateupload.cpp @@ -73,9 +73,11 @@ void PUTFileJob::start() { req.setRawHeader(it.key(), it.value()); } - setReply(_url.isValid() ? davRequest("PUT", _url, req, _device.data()) - : davRequest("PUT", path(), req, _device.data())); - setupConnections(reply()); + if (_url.isValid()) { + sendRequest("PUT", _url, req, _device); + } else { + sendRequest("PUT", makeDavUrl(path()), req, _device); + } if( reply()->error() != QNetworkReply::NoError ) { qWarning() << Q_FUNC_INFO << " Network error: " << reply()->errorString(); @@ -89,10 +91,10 @@ void PUTFileJob::start() { // (workaround disabled on windows and mac because the binaries we ship have patched qt) #if QT_VERSION < QT_VERSION_CHECK(4, 8, 7) if (QLatin1String(qVersion()) < QLatin1String("4.8.7")) - connect(_device.data(), SIGNAL(wasReset()), this, SLOT(slotSoftAbort())); + connect(_device, SIGNAL(wasReset()), this, SLOT(slotSoftAbort())); #elif QT_VERSION > QT_VERSION_CHECK(5, 0, 0) && QT_VERSION < QT_VERSION_CHECK(5, 4, 2) && !defined Q_OS_WIN && !defined Q_OS_MAC if (QLatin1String(qVersion()) < QLatin1String("5.4.2")) - connect(_device.data(), SIGNAL(wasReset()), this, SLOT(slotSoftAbort())); + connect(_device, SIGNAL(wasReset()), this, SLOT(slotSoftAbort())); #endif AbstractNetworkJob::start(); @@ -119,8 +121,7 @@ void PollJob::start() QUrl accountUrl = account()->url(); QUrl finalUrl = QUrl::fromUserInput(accountUrl.scheme() + QLatin1String("://") + accountUrl.authority() + (path().startsWith('/') ? QLatin1String("") : QLatin1String("/")) + path()); - setReply(getRequest(finalUrl)); - setupConnections(reply()); + sendRequest("GET", finalUrl); connect(reply(), SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(resetTimeout())); AbstractNetworkJob::start(); } diff --git a/src/libsync/propagateupload.h b/src/libsync/propagateupload.h index 31e9067d640..3a7224a7019 100644 --- a/src/libsync/propagateupload.h +++ b/src/libsync/propagateupload.h @@ -86,7 +86,7 @@ class PUTFileJob : public AbstractNetworkJob { Q_OBJECT private: - QScopedPointer _device; + QIODevice* _device; QMap _headers; QString _errorString; QUrl _url; @@ -95,11 +95,17 @@ class PUTFileJob : public AbstractNetworkJob { // Takes ownership of the device explicit PUTFileJob(AccountPtr account, const QString& path, QIODevice *device, const QMap &headers, int chunk, QObject* parent = 0) - : AbstractNetworkJob(account, path, parent), _device(device), _headers(headers), _chunk(chunk) {} + : AbstractNetworkJob(account, path, parent), _device(device), _headers(headers), _chunk(chunk) + { + _device->setParent(this); + } explicit PUTFileJob(AccountPtr account, const QUrl& url, QIODevice *device, const QMap &headers, int chunk, QObject* parent = 0) : AbstractNetworkJob(account, QString(), parent), _device(device), _headers(headers) - , _url(url), _chunk(chunk) {} + , _url(url), _chunk(chunk) + { + _device->setParent(this); + } ~PUTFileJob(); int _chunk; diff --git a/test/syncenginetestutils.h b/test/syncenginetestutils.h index 937bf35fda4..64b06328402 100644 --- a/test/syncenginetestutils.h +++ b/test/syncenginetestutils.h @@ -730,13 +730,13 @@ class FakeQNAM : public QNetworkAccessManager if (verb == QLatin1String("PROPFIND")) // Ignore outgoingData always returning somethign good enough, works for now. return new FakePropfindReply{info, op, request, this}; - else if (verb == QLatin1String("GET")) + else if (verb == QLatin1String("GET") || op == QNetworkAccessManager::GetOperation) return new FakeGetReply{info, op, request, this}; - else if (verb == QLatin1String("PUT")) + else if (verb == QLatin1String("PUT") || op == QNetworkAccessManager::PutOperation) return new FakePutReply{info, op, request, outgoingData->readAll(), this}; else if (verb == QLatin1String("MKCOL")) return new FakeMkcolReply{info, op, request, this}; - else if (verb == QLatin1String("DELETE")) + else if (verb == QLatin1String("DELETE") || op == QNetworkAccessManager::DeleteOperation) return new FakeDeleteReply{info, op, request, this}; else if (verb == QLatin1String("MOVE") && !isUpload) return new FakeMoveReply{info, op, request, this};