Explorar o código

migration from vault version 3 to 4

Sebastian Stenzel %!s(int64=8) %!d(string=hai) anos
pai
achega
45ca7e9e47

+ 1 - 1
main/filesystem-crypto/pom.xml

@@ -19,7 +19,7 @@
 	
 	<properties>
 		<bouncycastle.version>1.51</bouncycastle.version>
-		<sivmode.version>1.0.2</sivmode.version>
+		<sivmode.version>1.0.4</sivmode.version>
 	</properties>
 
 	<dependencies>

+ 0 - 7
main/pom.xml

@@ -43,13 +43,6 @@
 		<dagger.version>2.4</dagger.version>
 	</properties>
 
-	<repositories>
-		<repository>
-			<id>jitpack.io</id>
-			<url>https://jitpack.io</url>
-		</repository>
-	</repositories>
-
 	<dependencyManagement>
 		<dependencies>
 			<!-- modules -->

+ 62 - 1
main/ui/src/main/java/org/cryptomator/ui/model/UpgradeVersion3to4.java

@@ -2,8 +2,13 @@ package org.cryptomator.ui.model;
 
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
+import java.nio.file.FileVisitResult;
+import java.nio.file.FileVisitor;
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import javax.inject.Inject;
 import javax.inject.Provider;
@@ -19,6 +24,8 @@ import org.slf4j.LoggerFactory;
 class UpgradeVersion3to4 extends UpgradeStrategy {
 
 	private static final Logger LOG = LoggerFactory.getLogger(UpgradeVersion3to4.class);
+	private static final Pattern BASE32_FOLLOWED_BY_UNDERSCORE_PATTERN = Pattern.compile("^(([A-Z2-7]{8})*[A-Z2-7=]{8})_");
+	private static final int FILE_MIN_SIZE = 88; // vault version 3 files have a header of 88 bytes (assuming no chunks at all)
 
 	@Inject
 	public UpgradeVersion3to4(Provider<Cryptor> cryptorProvider, Localization localization) {
@@ -32,7 +39,61 @@ class UpgradeVersion3to4 extends UpgradeStrategy {
 
 	@Override
 	protected void upgrade(Vault vault, Cryptor cryptor) throws UpgradeFailedException {
-		throw new UpgradeFailedException("not yet implemented");
+		Path dataDir = vault.path().get().resolve("d");
+		if (!Files.isDirectory(dataDir)) {
+			return; // empty vault. no migration needed.
+		}
+		try {
+			Files.walkFileTree(dataDir, new FileVisitor<Path>() {
+
+				@Override
+				public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
+					return FileVisitResult.CONTINUE;
+				}
+
+				@Override
+				public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+					migrate(file, attrs);
+					return FileVisitResult.CONTINUE;
+				}
+
+				@Override
+				public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
+					throw exc;
+				}
+
+				@Override
+				public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
+					return FileVisitResult.CONTINUE;
+				}
+
+			});
+		} catch (IOException e) {
+			LOG.error("Migration failed.", e);
+			throw new UpgradeFailedException(localization.getString("upgrade.version3to4.err.io"));
+		}
+		LOG.info("Migration finished.");
+	}
+
+	private void migrate(Path file, BasicFileAttributes attrs) throws IOException {
+		String name = file.getFileName().toString();
+		long size = attrs.size();
+		Matcher m = BASE32_FOLLOWED_BY_UNDERSCORE_PATTERN.matcher(name);
+		if (m.find(0) && size < FILE_MIN_SIZE) {
+			String base32 = m.group(1);
+			String suffix = name.substring(m.end());
+			String renamed = "0" + base32 + (suffix.isEmpty() ? "" : " " + suffix);
+			renameWithoutOverwriting(file, renamed);
+		}
+	}
+
+	private void renameWithoutOverwriting(Path path, String newName) throws IOException {
+		Path newPath = path.resolveSibling(newName);
+		for (int i = 2; Files.exists(newPath); i++) {
+			newPath = path.resolveSibling(newName + " " + i);
+		}
+		Files.move(path, newPath);
+		LOG.info("Renaming {} to {}", path, newPath.getFileName());
 	}
 
 	@Override

+ 3 - 3
main/ui/src/main/resources/localization/en.txt

@@ -26,7 +26,7 @@ initialize.label.password=Password
 initialize.label.retypePassword=Retype password
 initialize.button.ok=Create vault
 initialize.messageLabel.alreadyInitialized=Vault already initialized
-initialize.messageLabel.initializationFailed=Could not initialize vault. See logfile for details.
+initialize.messageLabel.initializationFailed=Could not initialize vault. See log file for details.
 initialize.messageLabel.passwordStrength.0=Very weak
 initialize.messageLabel.passwordStrength.1=Weak
 initialize.messageLabel.passwordStrength.2=Fair
@@ -44,7 +44,7 @@ upgrade.version3dropBundleExtension.msg=This vault needs to be migrated to a new
 upgrade.version3dropBundleExtension.err.alreadyExists=Automatic migration failed.\n"%s" already exists.
 
 upgrade.version3to4.msg=This vault needs to be migrated to a newer format.\nEncrypted folder names will be updated.\nPlease make sure synchronization has finished before proceeding.
-
+upgrade.version3to4.err.io=Migration failed due to an I/O Exception. See log file for details.
 
 # unlock.fxml
 unlock.label.password=Password
@@ -57,7 +57,7 @@ unlock.button.advancedOptions.show=More options
 unlock.button.advancedOptions.hide=Less options
 unlock.choicebox.winDriveLetter.auto=Assign automatically
 unlock.errorMessage.wrongPassword=Wrong password
-unlock.errorMessage.mountingFailed=Mounting failed. See logfile for details.
+unlock.errorMessage.mountingFailed=Mounting failed. See log file for details.
 unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware=Unsupported vault. This vault has been created with an older version of Cryptomator.
 unlock.errorMessage.unsupportedVersion.softwareOlderThanVault=Unsupported vault. This vault has been created with a newer version of Cryptomator.
 unlock.messageLabel.startServerFailed=Starting WebDAV server failed.