Chunked upload: Fix percent encoding in If header #7176
authorChristian Kamm <mail@ckamm.de>
Tue, 7 May 2019 06:08:24 +0000 (08:08 +0200)
committerKevin Ottens <kevin.ottens@nextcloud.com>
Tue, 15 Dec 2020 09:58:50 +0000 (10:58 +0100)
test/syncenginetestutils.h
test/testchunkingng.cpp

index a57ea502873902e5f3c47b7a8618d9aa9fe67e02..c34d7b93c56671b7b2969e0da277b14aac4fc18b 100644 (file)
@@ -354,7 +354,7 @@ public:
         auto writeFileResponse = [&](const FileInfo &fileInfo) {
             xml.writeStartElement(davUri, QStringLiteral("response"));
 
-            xml.writeTextElement(davUri, QStringLiteral("href"), prefix + fileInfo.path());
+            xml.writeTextElement(davUri, QStringLiteral("href"), prefix + QUrl::toPercentEncoding(fileInfo.path(), "/"));
             xml.writeStartElement(davUri, QStringLiteral("propstat"));
             xml.writeStartElement(davUri, QStringLiteral("prop"));
 
@@ -681,9 +681,14 @@ public:
 
         FileInfo *fileInfo = remoteRootFileInfo.find(fileName);
         if (fileInfo) {
-            Q_ASSERT(request.hasRawHeader("If")); // The client should put this header
-            if (request.rawHeader("If") != QByteArray("<" + request.rawHeader("Destination") +
-                                                "> ([\"" + fileInfo->etag.toLatin1() + "\"])")) {
+            // The client should put this header
+            Q_ASSERT(request.hasRawHeader("If"));
+
+            // And it should condition on the destination file
+            auto start = QByteArray("<" + request.rawHeader("Destination") + ">");
+            Q_ASSERT(request.rawHeader("If").startsWith(start));
+
+            if (request.rawHeader("If") != start + " ([\"" + fileInfo->etag.toLatin1() + "\"])") {
                 return nullptr;
             }
             fileInfo->size = size;
index 535ed56b51e7142089bac11e773ef5dcafd8cc29..94bc66620cec693d87f96cf2f4c9d04b7ba1d240 100644 (file)
@@ -575,6 +575,22 @@ private slots:
         QVERIFY(fakeFolder.syncOnce());
         QCOMPARE(nGET, 0);
     }
+
+    void testPercentEncoding() {
+        FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
+        fakeFolder.syncEngine().account()->setCapabilities({ { "dav", QVariantMap{ {"chunking", "1.0"} } } });
+        const int size = 5 * 1000 * 1000;
+        setChunkSize(fakeFolder.syncEngine(), 1 * 1000 * 1000);
+
+        fakeFolder.localModifier().insert("A/file % \u20ac", size);
+        QVERIFY(fakeFolder.syncOnce());
+        QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+
+        // Only the second upload contains an "If" header
+        fakeFolder.localModifier().appendByte("A/file % \u20ac");
+        QVERIFY(fakeFolder.syncOnce());
+        QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+    }
 };
 
 QTEST_GUILESS_MAIN(TestChunkingNG)