Add readme file to vault storage directory

This commit is contained in:
Sebastian Stenzel
2019-08-29 22:20:27 +02:00
parent e55b1f8ff9
commit 4a02bf529d
4 changed files with 127 additions and 1 deletions

View File

@@ -30,9 +30,13 @@ import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.WritableByteChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.ResourceBundle;
@AddVaultWizardScoped
@@ -50,6 +54,7 @@ public class CreateNewVaultPasswordController implements FxController {
private final VaultFactory vaultFactory;
private final ResourceBundle resourceBundle;
private final PasswordStrengthUtil strengthRater;
private final ReadmeGenerator readmeGenerator;
private final IntegerProperty passwordStrength;
public Button finishButton;
@@ -63,7 +68,7 @@ public class CreateNewVaultPasswordController implements FxController {
public CheckBox finalConfirmationCheckbox;
@Inject
CreateNewVaultPasswordController(@AddVaultWizard Stage window, @FxmlScene(FxmlFile.ADDVAULT_NEW_LOCATION) Lazy<Scene> chooseLocationScene, @FxmlScene(FxmlFile.ADDVAULT_SUCCESS) Lazy<Scene> successScene, StringProperty vaultName, ObjectProperty<Path> vaultPath, ObservableList<Vault> vaults, @AddVaultWizard ObjectProperty<Vault> vault, VaultFactory vaultFactory, ResourceBundle resourceBundle, PasswordStrengthUtil strengthRater) {
CreateNewVaultPasswordController(@AddVaultWizard Stage window, @FxmlScene(FxmlFile.ADDVAULT_NEW_LOCATION) Lazy<Scene> chooseLocationScene, @FxmlScene(FxmlFile.ADDVAULT_SUCCESS) Lazy<Scene> successScene, StringProperty vaultName, ObjectProperty<Path> vaultPath, ObservableList<Vault> vaults, @AddVaultWizard ObjectProperty<Vault> vault, VaultFactory vaultFactory, ResourceBundle resourceBundle, PasswordStrengthUtil strengthRater, ReadmeGenerator readmeGenerator) {
this.window = window;
this.chooseLocationScene = chooseLocationScene;
this.successScene = successScene;
@@ -74,6 +79,7 @@ public class CreateNewVaultPasswordController implements FxController {
this.vaultFactory = vaultFactory;
this.resourceBundle = resourceBundle;
this.strengthRater = strengthRater;
this.readmeGenerator = readmeGenerator;
this.passwordStrength = new SimpleIntegerProperty(-1);
}
@@ -120,6 +126,13 @@ public class CreateNewVaultPasswordController implements FxController {
try {
newVault.create(passwordField.getCharacters());
LOG.info("Created new vault at path {}", vaultPath.get());
String readmeFileName = resourceBundle.getString("addvault.new.readme.storageLocation.fileName");
Path readmeFile = vaultPath.get().resolve(readmeFileName);
try (WritableByteChannel ch = Files.newByteChannel(readmeFile, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE)) {
ByteBuffer buf = StandardCharsets.US_ASCII.encode(readmeGenerator.createVaultStorageLocationReadmeRtf());
ch.write(buf);
}
LOG.info("Created readme file {}", readmeFile);
vault.set(newVault);
vaults.add(newVault);
window.setScene(successScene.get());

View File

@@ -0,0 +1,62 @@
package org.cryptomator.ui.addvaultwizard;
import javax.inject.Inject;
import java.util.List;
import java.util.ResourceBundle;
@AddVaultWizardScoped
public class ReadmeGenerator {
// specs: https://web.archive.org/web/20190708132914/http://www.kleinlercher.at/tools/Windows_Protocols/Word2007RTFSpec9.pdf
private static final String RTF_HEADER = "{\\rtf1\\fbidis\\ansi\\uc0\\fs32\n";
private static final String RTF_FOOTER = "}";
private static final String HELP_URL = "{\\field{\\*\\fldinst HYPERLINK \"http://www.google.com/\"}{\\fldrslt google.com}}";
private final ResourceBundle resourceBundle;
@Inject
public ReadmeGenerator(ResourceBundle resourceBundle){
this.resourceBundle = resourceBundle;
}
public String createVaultStorageLocationReadmeRtf() {
return createDocument(List.of( //
resourceBundle.getString("addvault.new.readme.storageLocation.1"), //
resourceBundle.getString("addvault.new.readme.storageLocation.2"), //
resourceBundle.getString("addvault.new.readme.storageLocation.3"), //
String.format(resourceBundle.getString("addvault.new.readme.storageLocation.4"), HELP_URL) //
));
}
// visible for testing
String createDocument(Iterable<String> paragraphs) {
StringBuilder sb = new StringBuilder(RTF_HEADER);
for (String p : paragraphs) {
sb.append("\\par {\\sa80 ");
appendEscaped(sb, p);
sb.append("}\n");
}
sb.append(RTF_FOOTER);
return sb.toString();
}
// visible for testing
String escapeNonAsciiChars(CharSequence input) {
StringBuilder sb = new StringBuilder();
appendEscaped(sb, input);
return sb.toString();
}
private void appendEscaped(StringBuilder sb, CharSequence input) {
input.chars().forEachOrdered(c -> {
if (c < 128) {
sb.append((char) c);
} else if (c < 0xFFFF) {
sb.append("\\u").append(c);
}
});
}
}

View File

@@ -38,6 +38,11 @@ addvaultwizard.new.reenterPassword=Confirm the password
addvaultwizard.new.passwordsMatch=Passwords match!
addvaultwizard.new.passwordsDoNotMatch=Passwords do not match
addvaultwizard.new.finalConfirmation=I understand that I will not be able to recover my data if I forget my password
addvault.new.readme.storageLocation.fileName=WHAT IS THIS DIRECTORY.rtf
addvault.new.readme.storageLocation.1=\\fs40\\qc ⚠️ VAULT FILES ⚠️
addvault.new.readme.storageLocation.2=This is your vault's storage location. {\\b DO NOT} alter any files within this directory.
addvault.new.readme.storageLocation.3=If you want to encrypt files using Cryptomator, unlock the vault and use the provided drive.
addvault.new.readme.storageLocation.4=If you need help, try %s.
## Existing
addvaultwizard.existing.instruction=Choose the "masterkey.cryptomator" file of your existing vault.
addvaultwizard.existing.chooseBtn=Choose…

View File

@@ -0,0 +1,46 @@
package org.cryptomator.ui.addvaultwizard;
import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import java.util.List;
public class ReadMeGeneratorTest {
@ParameterizedTest
@CsvSource({ //
"test,test", //
"t\u00E4st,t\\u228st", //
"t\uD83D\uDE09st,t\\u55357\\u56841st", //
})
public void testEscapeNonAsciiChars(String input, String expectedResult) {
ReadmeGenerator readmeGenerator = new ReadmeGenerator(null);
String actualResult = readmeGenerator.escapeNonAsciiChars(input);
Assertions.assertEquals(expectedResult, actualResult);
}
@Test
public void testCreateDocument() {
ReadmeGenerator readmeGenerator = new ReadmeGenerator(null);
Iterable<String> paragraphs = List.of( //
"Dear User,", //
"\\b please don't touch the \"d\" directory.", //
"Thank you for your cooperation \uD83D\uDE09" //
);
String result = readmeGenerator.createDocument(paragraphs);
MatcherAssert.assertThat(result, CoreMatchers.startsWith("{\\rtf1\\fbidis\\ansi\\uc0\\fs32"));
MatcherAssert.assertThat(result, CoreMatchers.containsString("\\par {\\sa80 Dear User,}"));
MatcherAssert.assertThat(result, CoreMatchers.containsString("\\par {\\sa80 \\b please don't touch the \"d\" directory.}"));
MatcherAssert.assertThat(result, CoreMatchers.containsString("\\par {\\sa80 Thank you for your cooperation \\u55357\\u56841}"));
MatcherAssert.assertThat(result, CoreMatchers.endsWith("}"));
}
}