From 1ac87dd32f16584592a089260e43e3ece4625bf7 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Fri, 8 Jul 2016 15:52:00 +0200 Subject: [PATCH 1/3] fixed NPE [ci skip] --- .../main/java/org/cryptomator/ui/model/UpgradeStrategies.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/main/ui/src/main/java/org/cryptomator/ui/model/UpgradeStrategies.java b/main/ui/src/main/java/org/cryptomator/ui/model/UpgradeStrategies.java index 8a8ec3444..ba4407c39 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/model/UpgradeStrategies.java +++ b/main/ui/src/main/java/org/cryptomator/ui/model/UpgradeStrategies.java @@ -19,6 +19,9 @@ public class UpgradeStrategies { } public Optional getUpgradeStrategy(Vault vault) { + if (vault == null) { + return Optional.empty(); + } return strategies.stream().filter(strategy -> { return strategy.isApplicable(vault); }).findFirst(); From bc815405d26bae8be4fc2da4815a6784338c28e3 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Sat, 9 Jul 2016 11:28:36 +0200 Subject: [PATCH 2/3] merged from hotfix/1.1.2 [ci skip] --- .../filesystem/crypto/ConflictResolver.java | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/ConflictResolver.java b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/ConflictResolver.java index 19dceb326..6b8a1f428 100644 --- a/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/ConflictResolver.java +++ b/main/filesystem-crypto/src/main/java/org/cryptomator/filesystem/crypto/ConflictResolver.java @@ -2,6 +2,7 @@ package org.cryptomator.filesystem.crypto; import static org.cryptomator.filesystem.crypto.Constants.DIR_PREFIX; +import java.nio.ByteBuffer; import java.util.Optional; import java.util.UUID; import java.util.function.Function; @@ -12,7 +13,7 @@ import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; import org.cryptomator.filesystem.File; import org.cryptomator.filesystem.Folder; -import org.cryptomator.io.FileContents; +import org.cryptomator.filesystem.ReadableFile; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -20,6 +21,7 @@ final class ConflictResolver { private static final Logger LOG = LoggerFactory.getLogger(ConflictResolver.class); private static final int UUID_FIRST_GROUP_STRLEN = 8; + private static final int MAX_DIR_FILE_SIZE = 87; // "normal" file header has 88 bytes private final Pattern encryptedNamePattern; private final Function> nameDecryptor; @@ -52,13 +54,11 @@ final class ConflictResolver { if (cleartext.isPresent()) { Folder folder = conflictingFile.parent().get(); File canonicalFile = folder.file(isDirectory ? DIR_PREFIX + ciphertext : ciphertext); - if (canonicalFile.exists()) { + if (isDirectory && canonicalFile.exists() && isSameFileBasedOnSample(canonicalFile, conflictingFile, MAX_DIR_FILE_SIZE)) { // there must not be two directories pointing to the same directory id. In this case no human interaction is needed to resolve this conflict: - if (isDirectory && FileContents.UTF_8.readContents(canonicalFile).equals(FileContents.UTF_8.readContents(conflictingFile))) { - conflictingFile.delete(); - return canonicalFile; - } - + conflictingFile.delete(); + return canonicalFile; + } else { // conventional conflict detected! look for an alternative name: File alternativeFile; String conflictId; @@ -71,9 +71,6 @@ final class ConflictResolver { LOG.info("Detected conflict {}:\n{}\n{}", conflictId, canonicalFile, conflictingFile); conflictingFile.moveTo(alternativeFile); return alternativeFile; - } else { - conflictingFile.moveTo(canonicalFile); - return canonicalFile; } } else { // not decryptable; false positive @@ -81,6 +78,22 @@ final class ConflictResolver { } } + private boolean isSameFileBasedOnSample(File file1, File file2, int sampleSize) { + try (ReadableFile r1 = file1.openReadable(); ReadableFile r2 = file2.openReadable()) { + if (r1.size() != r2.size()) { + return false; + } else { + ByteBuffer beginOfFile1 = ByteBuffer.allocate(sampleSize); + ByteBuffer beginOfFile2 = ByteBuffer.allocate(sampleSize); + r1.read(beginOfFile1); + r2.read(beginOfFile2); + beginOfFile1.flip(); + beginOfFile2.flip(); + return beginOfFile1.equals(beginOfFile2); + } + } + } + private String createConflictId() { return UUID.randomUUID().toString().substring(0, UUID_FIRST_GROUP_STRLEN); } From 0fdcdc816a11f303b7016311da435a0662e70838 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Sat, 9 Jul 2016 11:44:53 +0200 Subject: [PATCH 3/3] fixed unit test --- .../crypto/ConflictResolverTest.java | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/main/filesystem-crypto/src/test/java/org/cryptomator/filesystem/crypto/ConflictResolverTest.java b/main/filesystem-crypto/src/test/java/org/cryptomator/filesystem/crypto/ConflictResolverTest.java index bd1cf3b51..0e7d7f75a 100644 --- a/main/filesystem-crypto/src/test/java/org/cryptomator/filesystem/crypto/ConflictResolverTest.java +++ b/main/filesystem-crypto/src/test/java/org/cryptomator/filesystem/crypto/ConflictResolverTest.java @@ -80,29 +80,29 @@ public class ConflictResolverTest { @Test public void testCanonicalName() { - File resolved = conflictResolver.resolveIfNecessary(canonicalFile); - Assert.assertSame(canonicalFile, resolved); + File result = conflictResolver.resolveIfNecessary(canonicalFile); + Assert.assertSame(canonicalFile, result); } @Test public void testUnrelatedName() { - File resolved = conflictResolver.resolveIfNecessary(unrelatedFile); - Assert.assertSame(unrelatedFile, resolved); + File result = conflictResolver.resolveIfNecessary(unrelatedFile); + Assert.assertSame(unrelatedFile, result); } @Test public void testConflictingFile() { - File resolved = conflictResolver.resolveIfNecessary(conflictingFile); + File result = conflictResolver.resolveIfNecessary(conflictingFile); Mockito.verify(conflictingFile).moveTo(resolved); - Assert.assertSame(resolved, resolved); + Assert.assertSame(resolved, result); } @Test public void testConflictingFileIfCanonicalDoesntExist() { Mockito.when(canonicalFile.exists()).thenReturn(false); - File resolved = conflictResolver.resolveIfNecessary(conflictingFile); - Mockito.verify(conflictingFile).moveTo(canonicalFile); - Assert.assertSame(canonicalFile, resolved); + File result = conflictResolver.resolveIfNecessary(conflictingFile); + Mockito.verify(conflictingFile).moveTo(resolved); + Assert.assertSame(resolved, result); } @Test @@ -122,9 +122,11 @@ public class ConflictResolverTest { @Test public void testConflictingFolderWithSameId() { ReadableFile directoryId1 = Mockito.mock(ReadableFile.class); + ReadableFile directoryId2 = Mockito.mock(ReadableFile.class); Mockito.when(canonicalFolder.openReadable()).thenReturn(directoryId1); - Mockito.when(conflictingFolder.openReadable()).thenReturn(directoryId1); + Mockito.when(conflictingFolder.openReadable()).thenReturn(directoryId2); Mockito.when(directoryId1.read(Mockito.any())).thenAnswer(new FillBufferAnswer("id1")); + Mockito.when(directoryId2.read(Mockito.any())).thenAnswer(new FillBufferAnswer("id1")); File result = conflictResolver.resolveIfNecessary(conflictingFolder); Mockito.verify(conflictingFolder).delete();