RequestEtagJob: Consistently parse etags #7271
authorChristian Kamm <mail@ckamm.de>
Fri, 21 Jun 2019 13:29:42 +0000 (15:29 +0200)
committerKevin Ottens <kevin.ottens@nextcloud.com>
Tue, 15 Dec 2020 09:58:52 +0000 (10:58 +0100)
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

src/libsync/networkjobs.cpp
src/libsync/networkjobs.h
src/libsync/owncloudpropagator_p.h
test/syncenginetestutils.h

index fc953c3cb24967a0f5839508dd52545a6f7e4e8f..155139baa9f73858250e223d408959c168fa0ac1 100644 (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;
+                    }
                 }
             }
         }
index a29365c3acfb00e9946747346280c7d9d381ab29..1aeaddcf7273d5daa944b1ddd6dc4f453c0dcdbe 100644 (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
index 042ec545ee503bb4908e62ce9c6a8d42baf884cc..6b4ad374809c678a74b97ee0cbf77557d99ee5b7 100644 (file)
 
 #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"));
index f559e16353dc0e5f342ab3cdc7d63b83d8f599c7..8f349adc872d113e28eab31dbcce9e2806771743 100644 (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"));