RequestEtagJob: Consistently parse etags #7271

Previously RequestEtagJob did return the etag verbatim (including extra
quotes) while the db had the parsed form. That caused the etag
comparison during discovery move detection to always fail. The test
didn't catch it because the etags there didn't have quotes.

Now:
- RequestEtagJob will parse the etag, leading to a consistent format
- Tests have etags with quotes, detecting the problem
This commit is contained in:
Christian Kamm 2019-06-21 15:29:42 +02:00 committed by Kevin Ottens
parent 69fa1e4775
commit 0e9f030b0f
No known key found for this signature in database
GPG key ID: 074BBBCB8DECC9E2
4 changed files with 31 additions and 21 deletions

View file

@ -56,6 +56,25 @@ Q_LOGGING_CATEGORY(lcJsonApiJob, "nextcloud.sync.networkjob.jsonapi", QtInfoMsg)
Q_LOGGING_CATEGORY(lcDetermineAuthTypeJob, "nextcloud.sync.networkjob.determineauthtype", QtInfoMsg)
const int notModifiedStatusCode = 304;
QByteArray parseEtag(const char *header)
{
if (!header)
return QByteArray();
QByteArray arr = header;
// Weak E-Tags can appear when gzip compression is on, see #3946
if (arr.startsWith("W/"))
arr = arr.mid(2);
// https://github.com/owncloud/client/issues/1195
arr.replace("-gzip", "");
if (arr.length() >= 2 && arr.startsWith('"') && arr.endsWith('"')) {
arr = arr.mid(1, arr.length() - 2);
}
return arr;
}
RequestEtagJob::RequestEtagJob(AccountPtr account, const QString &path, QObject *parent)
: AbstractNetworkJob(account, path, parent)
{
@ -100,7 +119,13 @@ bool RequestEtagJob::finished()
if (type == QXmlStreamReader::StartElement && reader.namespaceUri() == QLatin1String("DAV:")) {
QString name = reader.name().toString();
if (name == QLatin1String("getetag")) {
etag += reader.readElementText();
auto etagText = reader.readElementText();
auto parsedTag = parseEtag(etagText.toUtf8());
if (!parsedTag.isEmpty()) {
etag += QString::fromUtf8(parsedTag);
} else {
etag += etagText;
}
}
}
}

View file

@ -29,6 +29,9 @@ class QJsonObject;
namespace OCC {
/** Strips quotes and gzip annotations */
QByteArray parseEtag(const char *header);
struct HttpError
{
int code; // HTTP error code

View file

@ -17,30 +17,12 @@
#include "owncloudpropagator.h"
#include "syncfileitem.h"
#include "networkjobs.h"
#include <QLoggingCategory>
#include <QNetworkReply>
namespace OCC {
inline QByteArray parseEtag(const char *header)
{
if (!header)
return QByteArray();
QByteArray arr = header;
// Weak E-Tags can appear when gzip compression is on, see #3946
if (arr.startsWith("W/"))
arr = arr.mid(2);
// https://github.com/owncloud/client/issues/1195
arr.replace("-gzip", "");
if (arr.length() >= 2 && arr.startsWith('"') && arr.endsWith('"')) {
arr = arr.mid(1, arr.length() - 2);
}
return arr;
}
inline QByteArray getEtagFromReply(QNetworkReply *reply)
{
QByteArray ocEtag = parseEtag(reply->rawHeader("OC-ETag"));

View file

@ -369,7 +369,7 @@ public:
auto stringDate = QLocale::c().toString(gmtDate, "ddd, dd MMM yyyy HH:mm:ss 'GMT'");
xml.writeTextElement(davUri, QStringLiteral("getlastmodified"), stringDate);
xml.writeTextElement(davUri, QStringLiteral("getcontentlength"), QString::number(fileInfo.size));
xml.writeTextElement(davUri, QStringLiteral("getetag"), fileInfo.etag);
xml.writeTextElement(davUri, QStringLiteral("getetag"), QStringLiteral("\"%1\"").arg(fileInfo.etag));
xml.writeTextElement(ocUri, QStringLiteral("permissions"), !fileInfo.permissions.isNull()
? QString(fileInfo.permissions.toString())
: fileInfo.isShared ? QStringLiteral("SRDNVCKW") : QStringLiteral("RDNVCKW"));