mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-04-20 09:36:55 -04:00
Merge branch 'release/1.1.1'
# Conflicts: # main/ant-kit/pom.xml # main/commons-test/pom.xml # main/commons/pom.xml # main/filesystem-api/pom.xml # main/filesystem-charsets/pom.xml # main/filesystem-crypto-integration-tests/pom.xml # main/filesystem-crypto/pom.xml # main/filesystem-inmemory/pom.xml # main/filesystem-invariants-tests/pom.xml # main/filesystem-nameshortening/pom.xml # main/filesystem-nio/pom.xml # main/filesystem-stats/pom.xml # main/frontend-api/pom.xml # main/frontend-webdav/pom.xml # main/jacoco-report/pom.xml # main/pom.xml # main/uber-jar/pom.xml # main/ui/pom.xml
This commit is contained in:
@@ -39,7 +39,7 @@ addons:
|
||||
name: "cryptomator/cryptomator"
|
||||
notification_email: sebastian.stenzel@cryptomator.org
|
||||
build_command: "mvn -fmain/pom.xml clean test -DskipTests"
|
||||
branch_pattern: coverity_scan
|
||||
branch_pattern: release.*
|
||||
|
||||
deploy:
|
||||
provider: releases
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>main</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</parent>
|
||||
<artifactId>ant-kit</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<parent>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>main</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</parent>
|
||||
<artifactId>commons-test</artifactId>
|
||||
<name>Cryptomator common test dependencies</name>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<parent>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>main</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</parent>
|
||||
<artifactId>commons</artifactId>
|
||||
<name>Cryptomator common</name>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>main</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</parent>
|
||||
<artifactId>filesystem-api</artifactId>
|
||||
<name>Cryptomator filesystem: API</name>
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
<parent>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>main</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</parent>
|
||||
<artifactId>filesystem-charsets</artifactId>
|
||||
<name>Cryptomator filesystem: Filename charset compatibility layer</name>
|
||||
<name>Cryptomator filesystem: Charset compatibility layer</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<parent>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>main</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</parent>
|
||||
<artifactId>filesystem-crypto-integration-tests</artifactId>
|
||||
<name>Cryptomator filesystem: Encryption layer tests</name>
|
||||
|
||||
@@ -12,14 +12,14 @@
|
||||
<parent>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>main</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</parent>
|
||||
<artifactId>filesystem-crypto</artifactId>
|
||||
<name>Cryptomator filesystem: Encryption layer</name>
|
||||
|
||||
<properties>
|
||||
<bouncycastle.version>1.51</bouncycastle.version>
|
||||
<sivmode.version>1.0.2</sivmode.version>
|
||||
<sivmode.version>1.0.4</sivmode.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -11,28 +11,28 @@ package org.cryptomator.crypto.engine;
|
||||
public class UnsupportedVaultFormatException extends CryptoException {
|
||||
|
||||
private final Integer detectedVersion;
|
||||
private final Integer supportedVersion;
|
||||
private final Integer latestSupportedVersion;
|
||||
|
||||
public UnsupportedVaultFormatException(Integer detectedVersion, Integer supportedVersion) {
|
||||
super("Tried to open vault of version " + detectedVersion + ", but can only handle version " + supportedVersion);
|
||||
public UnsupportedVaultFormatException(Integer detectedVersion, Integer latestSupportedVersion) {
|
||||
super("Tried to open vault of version " + detectedVersion + ", latest supported version is " + latestSupportedVersion);
|
||||
this.detectedVersion = detectedVersion;
|
||||
this.supportedVersion = supportedVersion;
|
||||
this.latestSupportedVersion = latestSupportedVersion;
|
||||
}
|
||||
|
||||
public Integer getDetectedVersion() {
|
||||
return detectedVersion;
|
||||
}
|
||||
|
||||
public Integer getSupportedVersion() {
|
||||
return supportedVersion;
|
||||
public Integer getLatestSupportedVersion() {
|
||||
return latestSupportedVersion;
|
||||
}
|
||||
|
||||
public boolean isVaultOlderThanSoftware() {
|
||||
return detectedVersion == null || detectedVersion < supportedVersion;
|
||||
return detectedVersion == null || detectedVersion < latestSupportedVersion;
|
||||
}
|
||||
|
||||
public boolean isSoftwareOlderThanVault() {
|
||||
return detectedVersion > supportedVersion;
|
||||
return detectedVersion > latestSupportedVersion;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
package org.cryptomator.crypto.engine.impl;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
public final class Constants {
|
||||
|
||||
private Constants() {
|
||||
}
|
||||
|
||||
static final Integer CURRENT_VAULT_VERSION = 3;
|
||||
static final Collection<Integer> SUPPORTED_VAULT_VERSIONS = Collections.unmodifiableCollection(Arrays.asList(3, 4));
|
||||
static final Integer CURRENT_VAULT_VERSION = 4;
|
||||
|
||||
public static final int PAYLOAD_SIZE = 32 * 1024;
|
||||
public static final int NONCE_SIZE = 16;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
package org.cryptomator.crypto.engine.impl;
|
||||
|
||||
import static org.cryptomator.crypto.engine.impl.Constants.CURRENT_VAULT_VERSION;
|
||||
import static org.cryptomator.crypto.engine.impl.Constants.SUPPORTED_VAULT_VERSIONS;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
@@ -18,6 +19,7 @@ import java.security.SecureRandom;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
@@ -81,14 +83,15 @@ class CryptorImpl implements Cryptor {
|
||||
|
||||
@Override
|
||||
public void randomizeMasterkey() {
|
||||
final byte[] randomBytes = new byte[KEYLENGTH_IN_BYTES];
|
||||
try {
|
||||
randomSource.nextBytes(randomBytes);
|
||||
encryptionKey = new SecretKeySpec(randomBytes, ENCRYPTION_ALG);
|
||||
randomSource.nextBytes(randomBytes);
|
||||
macKey = new SecretKeySpec(randomBytes, MAC_ALG);
|
||||
} finally {
|
||||
Arrays.fill(randomBytes, (byte) 0x00);
|
||||
KeyGenerator encKeyGen = KeyGenerator.getInstance(ENCRYPTION_ALG);
|
||||
encKeyGen.init(KEYLENGTH_IN_BYTES * Byte.SIZE, randomSource);
|
||||
encryptionKey = encKeyGen.generateKey();
|
||||
KeyGenerator macKeyGen = KeyGenerator.getInstance(MAC_ALG);
|
||||
macKeyGen.init(KEYLENGTH_IN_BYTES * Byte.SIZE, randomSource);
|
||||
macKey = macKeyGen.generateKey();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new IllegalStateException("Hard-coded algorithm doesn't exist.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +110,7 @@ class CryptorImpl implements Cryptor {
|
||||
assert keyFile != null;
|
||||
|
||||
// check version
|
||||
if (!CURRENT_VAULT_VERSION.equals(keyFile.getVersion())) {
|
||||
if (!SUPPORTED_VAULT_VERSIONS.contains(keyFile.getVersion())) {
|
||||
throw new UnsupportedVaultFormatException(keyFile.getVersion(), CURRENT_VAULT_VERSION);
|
||||
}
|
||||
|
||||
@@ -116,12 +119,12 @@ class CryptorImpl implements Cryptor {
|
||||
final SecretKey kek = new SecretKeySpec(kekBytes, ENCRYPTION_ALG);
|
||||
this.macKey = AesKeyWrap.unwrap(kek, keyFile.getMacMasterKey(), MAC_ALG);
|
||||
// future use (as soon as we need to prevent downgrade attacks):
|
||||
// final Mac mac = new ThreadLocalMac(macKey, MAC_ALG).get();
|
||||
// final byte[] versionMac = mac.doFinal(ByteBuffer.allocate(Integer.BYTES).putInt(CURRENT_VAULT_VERSION).array());
|
||||
// if (!MessageDigest.isEqual(versionMac, keyFile.getVersionMac())) {
|
||||
// destroyQuietly(macKey);
|
||||
// throw new UnsupportedVaultFormatException(Integer.MAX_VALUE, CURRENT_VAULT_VERSION);
|
||||
// }
|
||||
// final Mac mac = new ThreadLocalMac(macKey, MAC_ALG).get();
|
||||
// final byte[] versionMac = mac.doFinal(ByteBuffer.allocate(Integer.BYTES).putInt(CURRENT_VAULT_VERSION).array());
|
||||
// if (!MessageDigest.isEqual(versionMac, keyFile.getVersionMac())) {
|
||||
// destroyQuietly(macKey);
|
||||
// throw new UnsupportedVaultFormatException(Integer.MAX_VALUE, CURRENT_VAULT_VERSION);
|
||||
// }
|
||||
this.encryptionKey = AesKeyWrap.unwrap(kek, keyFile.getEncryptionMasterKey(), ENCRYPTION_ALG);
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new InvalidPassphraseException();
|
||||
|
||||
@@ -11,12 +11,14 @@ package org.cryptomator.crypto.engine.impl;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.ShortBufferException;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
@@ -36,13 +38,13 @@ class FileHeaderPayload implements Destroyable {
|
||||
private final SecretKey contentKey;
|
||||
|
||||
public FileHeaderPayload(SecureRandom randomSource) {
|
||||
filesize = 0;
|
||||
final byte[] contentKey = new byte[CONTENT_KEY_LEN];
|
||||
this.filesize = 0;
|
||||
try {
|
||||
randomSource.nextBytes(contentKey);
|
||||
this.contentKey = new SecretKeySpec(contentKey, AES);
|
||||
} finally {
|
||||
Arrays.fill(contentKey, (byte) 0x00);
|
||||
KeyGenerator keyGen = KeyGenerator.getInstance(AES);
|
||||
keyGen.init(CONTENT_KEY_LEN * Byte.SIZE, randomSource);
|
||||
this.contentKey = keyGen.generateKey();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new IllegalStateException("Hard-coded algorithm doesn't exist.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,8 @@ import org.cryptomator.siv.SivMode;
|
||||
class FilenameCryptorImpl implements FilenameCryptor {
|
||||
|
||||
private static final BaseNCodec BASE32 = new Base32();
|
||||
private static final Pattern BASE32_PATTERN = Pattern.compile("([A-Z0-9]{8})*[A-Z0-9=]{8}");
|
||||
// https://tools.ietf.org/html/rfc4648#section-6
|
||||
private static final Pattern BASE32_PATTERN = Pattern.compile("([A-Z2-7]{8})*[A-Z2-7=]{8}");
|
||||
private static final ThreadLocal<MessageDigest> SHA1 = new ThreadLocalSha1();
|
||||
private static final ThreadLocal<SivMode> AES_SIV = new ThreadLocal<SivMode>() {
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package org.cryptomator.filesystem.crypto;
|
||||
|
||||
import static org.cryptomator.filesystem.crypto.Constants.DIR_SUFFIX;
|
||||
import static org.cryptomator.filesystem.crypto.Constants.DIR_PREFIX;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
@@ -32,7 +32,7 @@ final class ConflictResolver {
|
||||
}
|
||||
|
||||
public File resolveIfNecessary(File file) {
|
||||
Matcher m = encryptedNamePattern.matcher(StringUtils.removeEnd(file.name(), DIR_SUFFIX));
|
||||
Matcher m = encryptedNamePattern.matcher(StringUtils.removeStart(file.name(), DIR_PREFIX));
|
||||
if (m.matches()) {
|
||||
// full match, use file as is
|
||||
return file;
|
||||
@@ -47,11 +47,11 @@ final class ConflictResolver {
|
||||
|
||||
private File resolveConflict(File conflictingFile, MatchResult matchResult) {
|
||||
String ciphertext = matchResult.group();
|
||||
boolean isDirectory = conflictingFile.name().substring(matchResult.end()).startsWith(DIR_SUFFIX);
|
||||
boolean isDirectory = conflictingFile.name().startsWith(DIR_PREFIX);
|
||||
Optional<String> cleartext = nameDecryptor.apply(ciphertext);
|
||||
if (cleartext.isPresent()) {
|
||||
Folder folder = conflictingFile.parent().get();
|
||||
File canonicalFile = folder.file(isDirectory ? ciphertext + DIR_SUFFIX : ciphertext);
|
||||
File canonicalFile = folder.file(isDirectory ? DIR_PREFIX + ciphertext : ciphertext);
|
||||
if (canonicalFile.exists()) {
|
||||
// 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))) {
|
||||
@@ -66,7 +66,7 @@ final class ConflictResolver {
|
||||
conflictId = createConflictId();
|
||||
String alternativeCleartext = cleartext.get() + " (Conflict " + conflictId + ")";
|
||||
String alternativeCiphertext = nameEncryptor.apply(alternativeCleartext).get();
|
||||
alternativeFile = folder.file(isDirectory ? alternativeCiphertext + DIR_SUFFIX : alternativeCiphertext);
|
||||
alternativeFile = folder.file(isDirectory ? DIR_PREFIX + alternativeCiphertext : alternativeCiphertext);
|
||||
} while (alternativeFile.exists());
|
||||
LOG.info("Detected conflict {}:\n{}\n{}", conflictId, canonicalFile, conflictingFile);
|
||||
conflictingFile.moveTo(alternativeFile);
|
||||
|
||||
@@ -8,9 +8,9 @@ public final class Constants {
|
||||
static final String DATA_ROOT_DIR = "d";
|
||||
static final String ROOT_DIRECOTRY_ID = "";
|
||||
|
||||
static final String MASTERKEY_FILENAME = "masterkey.cryptomator";
|
||||
static final String MASTERKEY_BACKUP_FILENAME = "masterkey.cryptomator.bkup";
|
||||
public static final String MASTERKEY_FILENAME = "masterkey.cryptomator";
|
||||
public static final String MASTERKEY_BACKUP_FILENAME = "masterkey.cryptomator.bkup";
|
||||
|
||||
static final String DIR_SUFFIX = "_";
|
||||
static final String DIR_PREFIX = "0";
|
||||
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ package org.cryptomator.filesystem.crypto;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.cryptomator.filesystem.crypto.Constants.DIR_SUFFIX;
|
||||
import static org.cryptomator.filesystem.crypto.Constants.DIR_PREFIX;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.UncheckedIOException;
|
||||
@@ -54,9 +54,9 @@ class CryptoFolder extends CryptoNode implements Folder {
|
||||
@Override
|
||||
protected Optional<String> encryptedName() {
|
||||
if (parent().isPresent()) {
|
||||
return parent().get().encryptChildName(name()).map(s -> s + DIR_SUFFIX);
|
||||
return parent().get().encryptChildName(name()).map(s -> DIR_PREFIX + s);
|
||||
} else {
|
||||
return Optional.of(cryptor.getFilenameCryptor().encryptFilename(name()) + DIR_SUFFIX);
|
||||
return Optional.of(DIR_PREFIX + cryptor.getFilenameCryptor().encryptFilename(name()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,20 +121,20 @@ class CryptoFolder extends CryptoNode implements Folder {
|
||||
|
||||
@Override
|
||||
public Stream<CryptoFile> files() {
|
||||
return nonConflictingFiles().map(File::name).filter(endsWithDirSuffix().negate()).map(this::decryptChildName).filter(Optional::isPresent).map(Optional::get).map(this::file);
|
||||
return nonConflictingFiles().map(File::name).filter(startsWithDirPrefix().negate()).map(this::decryptChildName).filter(Optional::isPresent).map(Optional::get).map(this::file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<CryptoFolder> folders() {
|
||||
return nonConflictingFiles().map(File::name).filter(endsWithDirSuffix()).map(this::removeDirSuffix).map(this::decryptChildName).filter(Optional::isPresent).map(Optional::get).map(this::folder);
|
||||
return nonConflictingFiles().map(File::name).filter(startsWithDirPrefix()).map(this::removeDirPrefix).map(this::decryptChildName).filter(Optional::isPresent).map(Optional::get).map(this::folder);
|
||||
}
|
||||
|
||||
private Predicate<String> endsWithDirSuffix() {
|
||||
return (String encryptedFolderName) -> StringUtils.endsWith(encryptedFolderName, DIR_SUFFIX);
|
||||
private Predicate<String> startsWithDirPrefix() {
|
||||
return (String encryptedFolderName) -> StringUtils.startsWith(encryptedFolderName, DIR_PREFIX);
|
||||
}
|
||||
|
||||
private String removeDirSuffix(String encryptedFolderName) {
|
||||
return StringUtils.removeEnd(encryptedFolderName, DIR_SUFFIX);
|
||||
private String removeDirPrefix(String encryptedFolderName) {
|
||||
return StringUtils.removeStart(encryptedFolderName, DIR_PREFIX);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,20 +21,20 @@ public class CryptorImplTest {
|
||||
|
||||
@Test
|
||||
public void testMasterkeyDecryptionWithCorrectPassphrase() throws IOException {
|
||||
final String testMasterKey = "{\"version\":3,\"scryptSalt\":\"AAAAAAAAAAA=\",\"scryptCostParam\":2,\"scryptBlockSize\":8," //
|
||||
final String testMasterKey = "{\"version\":4,\"scryptSalt\":\"AAAAAAAAAAA=\",\"scryptCostParam\":2,\"scryptBlockSize\":8," //
|
||||
+ "\"primaryMasterKey\":\"mM+qoQ+o0qvPTiDAZYt+flaC3WbpNAx1sTXaUzxwpy0M9Ctj6Tih/Q==\"," //
|
||||
+ "\"hmacMasterKey\":\"mM+qoQ+o0qvPTiDAZYt+flaC3WbpNAx1sTXaUzxwpy0M9Ctj6Tih/Q==\"," //
|
||||
+ "\"versionMac\":\"iUmRRHITuyJsJbVNqGNw+82YQ4A3Rma7j/y1v0DCVLA=\"}";
|
||||
+ "\"versionMac\":\"Z9J8Uc5K1f7YKckLUFpXG39NHK1qUjzadw5nvOqvfok=\"}";
|
||||
final Cryptor cryptor = TestCryptorImplFactory.insecureCryptorImpl();
|
||||
cryptor.readKeysFromMasterkeyFile(testMasterKey.getBytes(), "asd");
|
||||
}
|
||||
|
||||
@Test(expected = InvalidPassphraseException.class)
|
||||
public void testMasterkeyDecryptionWithWrongPassphrase() throws IOException {
|
||||
final String testMasterKey = "{\"version\":3,\"scryptSalt\":\"AAAAAAAAAAA=\",\"scryptCostParam\":2,\"scryptBlockSize\":8," //
|
||||
final String testMasterKey = "{\"version\":4,\"scryptSalt\":\"AAAAAAAAAAA=\",\"scryptCostParam\":2,\"scryptBlockSize\":8," //
|
||||
+ "\"primaryMasterKey\":\"mM+qoQ+o0qvPTiDAZYt+flaC3WbpNAx1sTXaUzxwpy0M9Ctj6Tih/Q==\"," //
|
||||
+ "\"hmacMasterKey\":\"mM+qoQ+o0qvPTiDAZYt+flaC3WbpNAx1sTXaUzxwpy0M9Ctj6Tih/Q==\"," //
|
||||
+ "\"versionMac\":\"iUmRRHITuyJsJbVNqGNw+82YQ4A3Rma7j/y1v0DCVLA=\"}";
|
||||
+ "\"versionMac\":\"Z9J8Uc5K1f7YKckLUFpXG39NHK1qUjzadw5nvOqvfok=\"}";
|
||||
final Cryptor cryptor = TestCryptorImplFactory.insecureCryptorImpl();
|
||||
cryptor.readKeysFromMasterkeyFile(testMasterKey.getBytes(), "qwe");
|
||||
}
|
||||
@@ -44,7 +44,7 @@ public class CryptorImplTest {
|
||||
final String testMasterKey = "{\"version\":-1,\"scryptSalt\":\"AAAAAAAAAAA=\",\"scryptCostParam\":2,\"scryptBlockSize\":8," //
|
||||
+ "\"primaryMasterKey\":\"mM+qoQ+o0qvPTiDAZYt+flaC3WbpNAx1sTXaUzxwpy0M9Ctj6Tih/Q==\"," //
|
||||
+ "\"hmacMasterKey\":\"mM+qoQ+o0qvPTiDAZYt+flaC3WbpNAx1sTXaUzxwpy0M9Ctj6Tih/Q==\"," //
|
||||
+ "\"versionMac\":\"iUmRRHITuyJsJbVNqGNw+82YQ4A3Rma7j/y1v0DCVLA=\"}";
|
||||
+ "\"versionMac\":\"Z9J8Uc5K1f7YKckLUFpXG39NHK1qUjzadw5nvOqvfok=\"}";
|
||||
final Cryptor cryptor = TestCryptorImplFactory.insecureCryptorImpl();
|
||||
cryptor.readKeysFromMasterkeyFile(testMasterKey.getBytes(), "asd");
|
||||
}
|
||||
@@ -62,23 +62,24 @@ public class CryptorImplTest {
|
||||
@Ignore
|
||||
@Test(expected = UnsupportedVaultFormatException.class)
|
||||
public void testMasterkeyDecryptionWithWrongVersionMac() throws IOException {
|
||||
final String testMasterKey = "{\"version\":3,\"scryptSalt\":\"AAAAAAAAAAA=\",\"scryptCostParam\":2,\"scryptBlockSize\":8," //
|
||||
final String testMasterKey = "{\"version\":4,\"scryptSalt\":\"AAAAAAAAAAA=\",\"scryptCostParam\":2,\"scryptBlockSize\":8," //
|
||||
+ "\"primaryMasterKey\":\"mM+qoQ+o0qvPTiDAZYt+flaC3WbpNAx1sTXaUzxwpy0M9Ctj6Tih/Q==\"," //
|
||||
+ "\"hmacMasterKey\":\"mM+qoQ+o0qvPTiDAZYt+flaC3WbpNAx1sTXaUzxwpy0M9Ctj6Tih/Q==\"," //
|
||||
+ "\"versionMac\":\"iUmRRHITuyJsJbVNqGNw+82YQ4A3Rma7j/y1v0DCVLa=\"}";
|
||||
+ "\"versionMac\":\"z9J8Uc5K1f7YKckLUFpXG39NHK1qUjzadw5nvOqvfoK=\"}";
|
||||
final Cryptor cryptor = TestCryptorImplFactory.insecureCryptorImpl();
|
||||
cryptor.readKeysFromMasterkeyFile(testMasterKey.getBytes(), "asd");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMasterkeyEncryption() throws IOException {
|
||||
final String expectedMasterKey = "{\"version\":3,\"scryptSalt\":\"AAAAAAAAAAA=\",\"scryptCostParam\":16384,\"scryptBlockSize\":8," //
|
||||
final String expectedMasterKey = "{\"version\":4,\"scryptSalt\":\"AAAAAAAAAAA=\",\"scryptCostParam\":16384,\"scryptBlockSize\":8," //
|
||||
+ "\"primaryMasterKey\":\"BJPIq5pvhN24iDtPJLMFPLaVJWdGog9k4n0P03j4ru+ivbWY9OaRGQ==\"," //
|
||||
+ "\"hmacMasterKey\":\"BJPIq5pvhN24iDtPJLMFPLaVJWdGog9k4n0P03j4ru+ivbWY9OaRGQ==\"," //
|
||||
+ "\"versionMac\":\"iUmRRHITuyJsJbVNqGNw+82YQ4A3Rma7j/y1v0DCVLA=\"}";
|
||||
+ "\"versionMac\":\"Z9J8Uc5K1f7YKckLUFpXG39NHK1qUjzadw5nvOqvfok=\"}";
|
||||
final Cryptor cryptor = TestCryptorImplFactory.insecureCryptorImpl();
|
||||
cryptor.randomizeMasterkey();
|
||||
final byte[] masterkeyFile = cryptor.writeKeysToMasterkeyFile("asd");
|
||||
System.out.println(new String(masterkeyFile));
|
||||
Assert.assertArrayEquals(expectedMasterKey.getBytes(), masterkeyFile);
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ public class ConflictResolverTest {
|
||||
unrelatedFile = Mockito.mock(File.class);
|
||||
|
||||
String canonicalFileName = encode.apply("test name").get();
|
||||
String canonicalFolderName = canonicalFileName + Constants.DIR_SUFFIX;
|
||||
String canonicalFolderName = Constants.DIR_PREFIX + canonicalFileName;
|
||||
String conflictingFileName = canonicalFileName + " (version 2)";
|
||||
String conflictingFolderName = canonicalFolderName + " (version 2)";
|
||||
String unrelatedName = "notBa$e32!";
|
||||
@@ -70,6 +70,7 @@ public class ConflictResolverTest {
|
||||
Mockito.doReturn(Optional.of(folder)).when(unrelatedFile).parent();
|
||||
|
||||
Mockito.when(folder.file(Mockito.startsWith(canonicalFileName.substring(0, 8)))).thenReturn(resolved);
|
||||
Mockito.when(folder.file(Mockito.startsWith(canonicalFolderName.substring(0, 8)))).thenReturn(resolved);
|
||||
Mockito.when(folder.file(canonicalFileName)).thenReturn(canonicalFile);
|
||||
Mockito.when(folder.file(canonicalFolderName)).thenReturn(canonicalFolder);
|
||||
Mockito.when(folder.file(conflictingFileName)).thenReturn(conflictingFile);
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<parent>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>main</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</parent>
|
||||
<artifactId>filesystem-inmemory</artifactId>
|
||||
<name>Cryptomator filesystem: In-memory mock</name>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>main</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</parent>
|
||||
<artifactId>filesystem-invariants-tests</artifactId>
|
||||
<name>Cryptomator filesystem: Invariants tests</name>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<parent>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>main</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</parent>
|
||||
<artifactId>filesystem-nameshortening</artifactId>
|
||||
<name>Cryptomator filesystem: Name shortening layer</name>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>main</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</parent>
|
||||
<artifactId>filesystem-nio</artifactId>
|
||||
<name>Cryptomator filesystem: NIO-based physical layer</name>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<parent>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>main</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</parent>
|
||||
<artifactId>filesystem-stats</artifactId>
|
||||
<name>Cryptomator filesystem: Throughput statistics</name>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<parent>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>main</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</parent>
|
||||
<artifactId>frontend-api</artifactId>
|
||||
<name>Cryptomator frontend: API</name>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<parent>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>main</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</parent>
|
||||
<artifactId>frontend-webdav</artifactId>
|
||||
<name>Cryptomator frontend: WebDAV frontend</name>
|
||||
|
||||
@@ -32,7 +32,7 @@ public class WindowsCompatibilityServlet extends HttpServlet {
|
||||
protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
resp.addHeader("DAV", "1, 2");
|
||||
resp.addHeader("MS-Author-Via", "DAV");
|
||||
// resp.addHeader("Allow", "OPTIONS, GET, HEAD, POST, TRACE, PROPFIND, PROPPATCH, MKCOL, COPY, PUT, DELETE, MOVE, LOCK, UNLOCK");
|
||||
resp.addHeader("Allow", "OPTIONS, GET, HEAD");
|
||||
resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>main</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</parent>
|
||||
<artifactId>jacoco-report</artifactId>
|
||||
<name>Cryptomator Code Coverage Report</name>
|
||||
|
||||
21
main/pom.xml
21
main/pom.xml
@@ -7,7 +7,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>main</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>Cryptomator</name>
|
||||
|
||||
@@ -43,23 +43,6 @@
|
||||
<dagger.version>2.4</dagger.version>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>jitpack.io</id>
|
||||
<url>https://jitpack.io</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>jacoco-snapshots</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<!-- modules -->
|
||||
@@ -332,7 +315,7 @@
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
<version>0.7.7-SNAPSHOT</version>
|
||||
<version>0.7.7.201606060606</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>prepare-agent</id>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<parent>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>main</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</parent>
|
||||
<artifactId>uber-jar</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<parent>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>main</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</parent>
|
||||
<artifactId>ui</artifactId>
|
||||
<name>Cryptomator GUI</name>
|
||||
|
||||
@@ -26,6 +26,7 @@ import javax.inject.Singleton;
|
||||
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.ui.controls.DirectoryListCell;
|
||||
import org.cryptomator.ui.model.UpgradeStrategies;
|
||||
import org.cryptomator.ui.model.Vault;
|
||||
import org.cryptomator.ui.model.VaultFactory;
|
||||
import org.cryptomator.ui.settings.Localization;
|
||||
@@ -78,6 +79,7 @@ public class MainController extends LocalizedFXMLViewController {
|
||||
private final Provider<UnlockedController> unlockedControllerProvider;
|
||||
private final Lazy<ChangePasswordController> changePasswordController;
|
||||
private final Lazy<SettingsController> settingsController;
|
||||
private final Lazy<UpgradeStrategies> upgradeStrategies;
|
||||
private final ObjectProperty<AbstractFXMLViewController> activeController = new SimpleObjectProperty<>();
|
||||
private final ObservableList<Vault> vaults;
|
||||
private final ObjectProperty<Vault> selectedVault = new SimpleObjectProperty<>();
|
||||
@@ -90,7 +92,7 @@ public class MainController extends LocalizedFXMLViewController {
|
||||
@Inject
|
||||
public MainController(@Named("mainWindow") Stage mainWindow, Localization localization, Settings settings, VaultFactory vaultFactoy, Lazy<WelcomeController> welcomeController,
|
||||
Lazy<InitializeController> initializeController, Lazy<NotFoundController> notFoundController, Lazy<UpgradeController> upgradeController, Lazy<UnlockController> unlockController,
|
||||
Provider<UnlockedController> unlockedControllerProvider, Lazy<ChangePasswordController> changePasswordController, Lazy<SettingsController> settingsController) {
|
||||
Provider<UnlockedController> unlockedControllerProvider, Lazy<ChangePasswordController> changePasswordController, Lazy<SettingsController> settingsController, Lazy<UpgradeStrategies> upgradeStrategies) {
|
||||
super(localization);
|
||||
this.mainWindow = mainWindow;
|
||||
this.vaultFactoy = vaultFactoy;
|
||||
@@ -102,6 +104,7 @@ public class MainController extends LocalizedFXMLViewController {
|
||||
this.unlockedControllerProvider = unlockedControllerProvider;
|
||||
this.changePasswordController = changePasswordController;
|
||||
this.settingsController = settingsController;
|
||||
this.upgradeStrategies = upgradeStrategies;
|
||||
this.vaults = FXCollections.observableList(settings.getDirectories());
|
||||
this.vaults.addListener((Change<? extends Vault> c) -> {
|
||||
settings.save();
|
||||
@@ -202,7 +205,7 @@ public class MainController extends LocalizedFXMLViewController {
|
||||
@FXML
|
||||
private void didClickAddExistingVaults(ActionEvent event) {
|
||||
final FileChooser fileChooser = new FileChooser();
|
||||
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Cryptomator vault", "*" + Vault.VAULT_FILE_EXTENSION));
|
||||
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Cryptomator Masterkey", "*" + Vault.VAULT_FILE_EXTENSION));
|
||||
final List<File> files = fileChooser.showOpenMultipleDialog(mainWindow);
|
||||
if (files != null) {
|
||||
for (final File file : files) {
|
||||
@@ -288,7 +291,7 @@ public class MainController extends LocalizedFXMLViewController {
|
||||
this.showUnlockedView(newValue);
|
||||
} else if (!newValue.doesVaultDirectoryExist()) {
|
||||
this.showNotFoundView();
|
||||
} else if (newValue.isValidVaultDirectory() && newValue.needsUpgrade()) {
|
||||
} else if (newValue.isValidVaultDirectory() && upgradeStrategies.get().getUpgradeStrategy(newValue).isPresent()) {
|
||||
this.showUpgradeView();
|
||||
} else if (newValue.isValidVaultDirectory()) {
|
||||
this.showUnlockView();
|
||||
|
||||
@@ -7,8 +7,10 @@ import java.util.concurrent.ExecutorService;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.cryptomator.ui.model.UpgradeInstruction;
|
||||
import org.cryptomator.ui.model.UpgradeInstruction.UpgradeFailedException;
|
||||
import org.cryptomator.ui.controls.SecPasswordField;
|
||||
import org.cryptomator.ui.model.UpgradeStrategies;
|
||||
import org.cryptomator.ui.model.UpgradeStrategy;
|
||||
import org.cryptomator.ui.model.UpgradeStrategy.UpgradeFailedException;
|
||||
import org.cryptomator.ui.model.Vault;
|
||||
import org.cryptomator.ui.settings.Localization;
|
||||
import org.fxmisc.easybind.EasyBind;
|
||||
@@ -16,7 +18,6 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.binding.Binding;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.event.ActionEvent;
|
||||
@@ -30,19 +31,24 @@ public class UpgradeController extends LocalizedFXMLViewController {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(UpgradeController.class);
|
||||
|
||||
final ObjectProperty<Vault> vault = new SimpleObjectProperty<>();
|
||||
final ObjectProperty<Optional<UpgradeStrategy>> strategy = new SimpleObjectProperty<>();
|
||||
private final UpgradeStrategies strategies;
|
||||
private final ExecutorService exec;
|
||||
private final Binding<Optional<UpgradeInstruction>> upgradeInstruction = EasyBind.monadic(vault).map(Vault::availableUpgrade);
|
||||
private Optional<UpgradeListener> listener = Optional.empty();
|
||||
|
||||
@Inject
|
||||
public UpgradeController(Localization localization, ExecutorService exec) {
|
||||
public UpgradeController(Localization localization, UpgradeStrategies strategies, ExecutorService exec) {
|
||||
super(localization);
|
||||
this.strategies = strategies;
|
||||
this.exec = exec;
|
||||
}
|
||||
|
||||
@FXML
|
||||
private Label upgradeLabel;
|
||||
|
||||
@FXML
|
||||
private SecPasswordField passwordField;
|
||||
|
||||
@FXML
|
||||
private Button upgradeButton;
|
||||
|
||||
@@ -54,10 +60,12 @@ public class UpgradeController extends LocalizedFXMLViewController {
|
||||
|
||||
@Override
|
||||
protected void initialize() {
|
||||
upgradeLabel.textProperty().bind(EasyBind.monadic(upgradeInstruction).map(instruction -> {
|
||||
upgradeLabel.textProperty().bind(EasyBind.monadic(strategy).map(instruction -> {
|
||||
return instruction.map(this::upgradeNotification).orElse("");
|
||||
}).orElse(""));
|
||||
|
||||
upgradeButton.disableProperty().bind(passwordField.textProperty().isEmpty().or(passwordField.disabledProperty()));
|
||||
|
||||
EasyBind.subscribe(vault, this::vaultDidChange);
|
||||
}
|
||||
|
||||
@@ -68,14 +76,18 @@ public class UpgradeController extends LocalizedFXMLViewController {
|
||||
|
||||
private void vaultDidChange(Vault newVault) {
|
||||
errorLabel.setText(null);
|
||||
strategy.set(strategies.getUpgradeStrategy(newVault));
|
||||
// trigger "default" change to refresh key bindings:
|
||||
upgradeButton.setDefaultButton(false);
|
||||
upgradeButton.setDefaultButton(true);
|
||||
}
|
||||
|
||||
// ****************************************
|
||||
// Upgrade label
|
||||
// ****************************************
|
||||
|
||||
private String upgradeNotification(UpgradeInstruction instruction) {
|
||||
return instruction.getNotification(vault.get(), localization);
|
||||
private String upgradeNotification(UpgradeStrategy instruction) {
|
||||
return instruction.getNotification(vault.get());
|
||||
}
|
||||
|
||||
// ****************************************
|
||||
@@ -84,36 +96,45 @@ public class UpgradeController extends LocalizedFXMLViewController {
|
||||
|
||||
@FXML
|
||||
private void didClickUpgradeButton(ActionEvent event) {
|
||||
upgradeInstruction.getValue().ifPresent(this::upgrade);
|
||||
strategy.getValue().ifPresent(this::upgrade);
|
||||
}
|
||||
|
||||
private void upgrade(UpgradeInstruction instruction) {
|
||||
Vault v = vault.getValue();
|
||||
Objects.requireNonNull(v);
|
||||
private void upgrade(UpgradeStrategy instruction) {
|
||||
Vault v = Objects.requireNonNull(vault.getValue());
|
||||
passwordField.setDisable(true);
|
||||
progressIndicator.setVisible(true);
|
||||
upgradeButton.setDisable(true);
|
||||
exec.submit(() -> {
|
||||
if (!instruction.isApplicable(v)) {
|
||||
LOG.error("No upgrade needed for " + v.path().getValue());
|
||||
throw new IllegalStateException("No ugprade needed for " + v.path().getValue());
|
||||
}
|
||||
try {
|
||||
instruction.upgrade(v, localization);
|
||||
Platform.runLater(() -> {
|
||||
progressIndicator.setVisible(false);
|
||||
upgradeButton.setDisable(false);
|
||||
listener.ifPresent(UpgradeListener::didUpgrade);
|
||||
});
|
||||
instruction.upgrade(v, passwordField.getCharacters());
|
||||
Platform.runLater(this::showNextUpgrade);
|
||||
} catch (UpgradeFailedException e) {
|
||||
Platform.runLater(() -> {
|
||||
errorLabel.setText(e.getLocalizedMessage());
|
||||
});
|
||||
} finally {
|
||||
Platform.runLater(() -> {
|
||||
progressIndicator.setVisible(false);
|
||||
upgradeButton.setDisable(false);
|
||||
passwordField.setDisable(false);
|
||||
passwordField.swipe();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void showNextUpgrade() {
|
||||
errorLabel.setText(null);
|
||||
Optional<UpgradeStrategy> nextStrategy = strategies.getUpgradeStrategy(vault.getValue());
|
||||
if (nextStrategy.isPresent()) {
|
||||
strategy.set(nextStrategy);
|
||||
} else {
|
||||
listener.ifPresent(UpgradeListener::didUpgrade);
|
||||
}
|
||||
}
|
||||
|
||||
/* callback */
|
||||
|
||||
public void setListener(UpgradeListener listener) {
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
package org.cryptomator.ui.model;
|
||||
|
||||
import org.cryptomator.ui.settings.Localization;
|
||||
|
||||
public interface UpgradeInstruction {
|
||||
|
||||
static UpgradeInstruction[] AVAILABLE_INSTRUCTIONS = {new UpgradeVersion3DropBundleExtension()};
|
||||
|
||||
/**
|
||||
* @return Localized string to display to the user when an upgrade is needed.
|
||||
*/
|
||||
String getNotification(Vault vault, Localization localization);
|
||||
|
||||
/**
|
||||
* Upgrades a vault. Might take a moment, should be run in a background thread.
|
||||
*/
|
||||
void upgrade(Vault vault, Localization localization) throws UpgradeFailedException;
|
||||
|
||||
/**
|
||||
* Determines in O(1), if an upgrade can be applied to a vault.
|
||||
*
|
||||
* @return <code>true</code> if and only if the vault can be migrated to a newer version without the risk of data losses.
|
||||
*/
|
||||
boolean isApplicable(Vault vault);
|
||||
|
||||
/**
|
||||
* Thrown when data migration failed.
|
||||
*/
|
||||
public class UpgradeFailedException extends Exception {
|
||||
|
||||
UpgradeFailedException() {
|
||||
}
|
||||
|
||||
UpgradeFailedException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package org.cryptomator.ui.model;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
@Singleton
|
||||
public class UpgradeStrategies {
|
||||
|
||||
private final Collection<UpgradeStrategy> strategies;
|
||||
|
||||
@Inject
|
||||
public UpgradeStrategies(UpgradeVersion3DropBundleExtension upgrader1, UpgradeVersion3to4 upgrader2) {
|
||||
strategies = Collections.unmodifiableList(Arrays.asList(upgrader1, upgrader2));
|
||||
}
|
||||
|
||||
public Optional<UpgradeStrategy> getUpgradeStrategy(Vault vault) {
|
||||
return strategies.stream().filter(strategy -> {
|
||||
return strategy.isApplicable(vault);
|
||||
}).findFirst();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package org.cryptomator.ui.model;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
|
||||
import javax.inject.Provider;
|
||||
|
||||
import org.cryptomator.crypto.engine.Cryptor;
|
||||
import org.cryptomator.crypto.engine.InvalidPassphraseException;
|
||||
import org.cryptomator.crypto.engine.UnsupportedVaultFormatException;
|
||||
import org.cryptomator.filesystem.crypto.Constants;
|
||||
import org.cryptomator.ui.settings.Localization;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public abstract class UpgradeStrategy {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(UpgradeStrategy.class);
|
||||
|
||||
protected final Provider<Cryptor> cryptorProvider;
|
||||
protected final Localization localization;
|
||||
|
||||
UpgradeStrategy(Provider<Cryptor> cryptorProvider, Localization localization) {
|
||||
this.cryptorProvider = cryptorProvider;
|
||||
this.localization = localization;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Localized string to display to the user when an upgrade is needed.
|
||||
*/
|
||||
public abstract String getNotification(Vault vault);
|
||||
|
||||
/**
|
||||
* Upgrades a vault. Might take a moment, should be run in a background thread.
|
||||
*/
|
||||
public void upgrade(Vault vault, CharSequence passphrase) throws UpgradeFailedException {
|
||||
final Cryptor cryptor = cryptorProvider.get();
|
||||
try {
|
||||
final Path masterkeyFile = vault.path().getValue().resolve(Constants.MASTERKEY_FILENAME);
|
||||
final byte[] masterkeyFileContents = Files.readAllBytes(masterkeyFile);
|
||||
cryptor.readKeysFromMasterkeyFile(masterkeyFileContents, passphrase);
|
||||
// create backup, as soon as we know the password was correct:
|
||||
final Path masterkeyBackupFile = vault.path().getValue().resolve(Constants.MASTERKEY_BACKUP_FILENAME);
|
||||
Files.copy(masterkeyFile, masterkeyBackupFile, StandardCopyOption.REPLACE_EXISTING);
|
||||
// do stuff:
|
||||
upgrade(vault, cryptor);
|
||||
// write updated masterkey file:
|
||||
final byte[] upgradedMasterkeyFileContents = cryptor.writeKeysToMasterkeyFile(passphrase);
|
||||
final Path masterkeyFileAfterUpgrading = vault.path().getValue().resolve(Constants.MASTERKEY_FILENAME); // path may have changed
|
||||
Files.write(masterkeyFileAfterUpgrading, upgradedMasterkeyFileContents, StandardOpenOption.TRUNCATE_EXISTING);
|
||||
} catch (InvalidPassphraseException e) {
|
||||
throw new UpgradeFailedException(localization.getString("unlock.errorMessage.wrongPassword"));
|
||||
} catch (IOException | UnsupportedVaultFormatException e) {
|
||||
LOG.warn("Upgrade failed.", e);
|
||||
throw new UpgradeFailedException("Upgrade failed. Details in log message.");
|
||||
} finally {
|
||||
cryptor.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void upgrade(Vault vault, Cryptor cryptor) throws UpgradeFailedException;
|
||||
|
||||
/**
|
||||
* Determines in O(1), if an upgrade can be applied to a vault.
|
||||
*
|
||||
* @return <code>true</code> if and only if the vault can be migrated to a newer version without the risk of data losses.
|
||||
*/
|
||||
public abstract boolean isApplicable(Vault vault);
|
||||
|
||||
/**
|
||||
* Thrown when data migration failed.
|
||||
*/
|
||||
public static class UpgradeFailedException extends Exception {
|
||||
|
||||
UpgradeFailedException() {
|
||||
}
|
||||
|
||||
UpgradeFailedException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,22 +1,40 @@
|
||||
package org.cryptomator.ui.model;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.cryptomator.crypto.engine.Cryptor;
|
||||
import org.cryptomator.crypto.engine.InvalidPassphraseException;
|
||||
import org.cryptomator.crypto.engine.UnsupportedVaultFormatException;
|
||||
import org.cryptomator.filesystem.crypto.Constants;
|
||||
import org.cryptomator.ui.settings.Localization;
|
||||
import org.cryptomator.ui.settings.Settings;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javafx.application.Platform;
|
||||
|
||||
class UpgradeVersion3DropBundleExtension implements UpgradeInstruction {
|
||||
@Singleton
|
||||
class UpgradeVersion3DropBundleExtension extends UpgradeStrategy {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(UpgradeVersion3DropBundleExtension.class);
|
||||
private final Settings settings;
|
||||
|
||||
@Inject
|
||||
public UpgradeVersion3DropBundleExtension(Provider<Cryptor> cryptorProvider, Localization localization, Settings settings) {
|
||||
super(cryptorProvider, localization);
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNotification(Vault vault, Localization localization) {
|
||||
public String getNotification(Vault vault) {
|
||||
String fmt = localization.getString("upgrade.version3dropBundleExtension.msg");
|
||||
Path path = vault.path().getValue();
|
||||
String oldVaultName = path.getFileName().toString();
|
||||
@@ -25,7 +43,26 @@ class UpgradeVersion3DropBundleExtension implements UpgradeInstruction {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void upgrade(Vault vault, Localization localization) throws UpgradeFailedException {
|
||||
public void upgrade(Vault vault, CharSequence passphrase) throws UpgradeFailedException {
|
||||
final Cryptor cryptor = cryptorProvider.get();
|
||||
try {
|
||||
final Path masterkeyFile = vault.path().getValue().resolve(Constants.MASTERKEY_FILENAME);
|
||||
final byte[] masterkeyFileContents = Files.readAllBytes(masterkeyFile);
|
||||
cryptor.readKeysFromMasterkeyFile(masterkeyFileContents, passphrase);
|
||||
upgrade(vault, cryptor);
|
||||
// don't write new masterkey. this is a special case, as we were stupid and didn't increase the vault version with this upgrade...
|
||||
} catch (InvalidPassphraseException e) {
|
||||
throw new UpgradeFailedException(localization.getString("unlock.errorMessage.wrongPassword"));
|
||||
} catch (IOException | UnsupportedVaultFormatException e) {
|
||||
LOG.warn("Upgrade failed.", e);
|
||||
throw new UpgradeFailedException("Upgrade failed. Details in log message.");
|
||||
} finally {
|
||||
cryptor.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void upgrade(Vault vault, Cryptor cryptor) throws UpgradeFailedException {
|
||||
Path path = vault.path().getValue();
|
||||
String oldVaultName = path.getFileName().toString();
|
||||
String newVaultName = StringUtils.removeEnd(oldVaultName, Vault.VAULT_FILE_EXTENSION);
|
||||
@@ -39,6 +76,7 @@ class UpgradeVersion3DropBundleExtension implements UpgradeInstruction {
|
||||
Files.move(path, path.resolveSibling(newVaultName));
|
||||
Platform.runLater(() -> {
|
||||
vault.setPath(newPath);
|
||||
settings.save();
|
||||
});
|
||||
} catch (IOException e) {
|
||||
LOG.error("Vault migration failed", e);
|
||||
@@ -49,7 +87,24 @@ class UpgradeVersion3DropBundleExtension implements UpgradeInstruction {
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(Vault vault) {
|
||||
return vault.path().getValue().getFileName().toString().endsWith(Vault.VAULT_FILE_EXTENSION);
|
||||
Path vaultPath = vault.path().getValue();
|
||||
if (vaultPath.toString().endsWith(Vault.VAULT_FILE_EXTENSION)) {
|
||||
final Path masterkeyFile = vaultPath.resolve(Constants.MASTERKEY_FILENAME);
|
||||
try {
|
||||
if (Files.isRegularFile(masterkeyFile)) {
|
||||
final String keyContents = new String(Files.readAllBytes(masterkeyFile), StandardCharsets.UTF_8);
|
||||
return keyContents.contains("\"version\":3") || keyContents.contains("\"version\": 3");
|
||||
} else {
|
||||
LOG.warn("Not a file: {}", masterkeyFile);
|
||||
return false;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOG.warn("Could not determine, whether upgrade is applicable.", e);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
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;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.cryptomator.crypto.engine.Cryptor;
|
||||
import org.cryptomator.filesystem.crypto.Constants;
|
||||
import org.cryptomator.ui.settings.Localization;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Singleton
|
||||
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) {
|
||||
super(cryptorProvider, localization);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNotification(Vault vault) {
|
||||
return localization.getString("upgrade.version3to4.msg");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void upgrade(Vault vault, Cryptor cryptor) throws UpgradeFailedException {
|
||||
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
|
||||
public boolean isApplicable(Vault vault) {
|
||||
final Path masterkeyFile = vault.path().getValue().resolve(Constants.MASTERKEY_FILENAME);
|
||||
try {
|
||||
if (Files.isRegularFile(masterkeyFile)) {
|
||||
final String keyContents = new String(Files.readAllBytes(masterkeyFile), StandardCharsets.UTF_8);
|
||||
return keyContents.contains("\"version\":3") || keyContents.contains("\"version\": 3");
|
||||
} else {
|
||||
LOG.warn("Not a file: {}", masterkeyFile);
|
||||
return false;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOG.warn("Could not determine, whether upgrade is applicable.", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,7 +16,6 @@ import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.text.Normalizer;
|
||||
import java.text.Normalizer.Form;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
@@ -64,9 +63,9 @@ public class Vault implements CryptoFileSystemDelegate {
|
||||
public static final String VAULT_FILE_EXTENSION = ".cryptomator";
|
||||
|
||||
private final ObjectProperty<Path> path;
|
||||
private final DeferredCloser closer;
|
||||
private final ShorteningFileSystemFactory shorteningFileSystemFactory;
|
||||
private final CryptoFileSystemFactory cryptoFileSystemFactory;
|
||||
private final DeferredCloser closer;
|
||||
private final BooleanProperty unlocked = new SimpleBooleanProperty();
|
||||
private final ObservableList<String> namesOfResourcesWithInvalidMac = FXThreads.observableListOnMainThread(FXCollections.observableArrayList());
|
||||
private final Set<String> whitelistedResourcesWithInvalidMac = new HashSet<>();
|
||||
@@ -82,9 +81,9 @@ public class Vault implements CryptoFileSystemDelegate {
|
||||
*/
|
||||
Vault(Path vaultDirectoryPath, ShorteningFileSystemFactory shorteningFileSystemFactory, CryptoFileSystemFactory cryptoFileSystemFactory, DeferredCloser closer) {
|
||||
this.path = new SimpleObjectProperty<Path>(vaultDirectoryPath);
|
||||
this.closer = closer;
|
||||
this.shorteningFileSystemFactory = shorteningFileSystemFactory;
|
||||
this.cryptoFileSystemFactory = cryptoFileSystemFactory;
|
||||
this.closer = closer;
|
||||
|
||||
try {
|
||||
setMountName(name().getValue());
|
||||
@@ -167,16 +166,6 @@ public class Vault implements CryptoFileSystemDelegate {
|
||||
Optionals.ifPresent(filesystemFrontend.get(), Frontend::unmount);
|
||||
}
|
||||
|
||||
public boolean needsUpgrade() {
|
||||
return availableUpgrade().isPresent();
|
||||
}
|
||||
|
||||
public Optional<UpgradeInstruction> availableUpgrade() {
|
||||
return Arrays.stream(UpgradeInstruction.AVAILABLE_INSTRUCTIONS).filter(instruction -> {
|
||||
return instruction.isApplicable(this);
|
||||
}).findAny();
|
||||
}
|
||||
|
||||
// ******************************************************************************
|
||||
// Delegate methods
|
||||
// ********************************************************************************/
|
||||
|
||||
@@ -11,17 +11,38 @@
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.ProgressIndicator?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import org.cryptomator.ui.controls.SecPasswordField?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<?import javafx.scene.layout.ColumnConstraints?>
|
||||
<?import javafx.scene.layout.Pane?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
|
||||
<VBox prefWidth="400.0" prefHeight="400.0" spacing="24.0" alignment="CENTER" xmlns:fx="http://javafx.com/fxml" cacheShape="true" cache="true">
|
||||
<GridPane vgap="12.0" hgap="12.0" prefWidth="400.0" xmlns:fx="http://javafx.com/fxml" cacheShape="true" cache="true">
|
||||
<padding>
|
||||
<Insets top="24.0" right="12.0" bottom="24.0" left="12.0" />
|
||||
</padding>
|
||||
|
||||
<Label fx:id="upgradeLabel" textAlignment="CENTER" wrapText="true"/>
|
||||
<columnConstraints>
|
||||
<ColumnConstraints percentWidth="38.2" />
|
||||
<ColumnConstraints percentWidth="61.8" />
|
||||
</columnConstraints>
|
||||
|
||||
<Button fx:id="upgradeButton" text="%upgrade.button" prefWidth="150.0" onAction="#didClickUpgradeButton" cacheShape="true" cache="true" />
|
||||
<children>
|
||||
<Label fx:id="upgradeLabel" wrapText="true" GridPane.rowIndex="0" GridPane.columnIndex="0" GridPane.columnSpan="2" cacheShape="true" cache="true" />
|
||||
|
||||
<ProgressIndicator progress="-1" fx:id="progressIndicator" visible="false" cacheShape="true" cache="true" cacheHint="SPEED" />
|
||||
|
||||
<Label fx:id="errorLabel" textAlignment="CENTER" wrapText="true"/>
|
||||
</VBox>
|
||||
<Pane prefHeight="12.0" GridPane.rowIndex="1" GridPane.columnIndex="0" GridPane.columnSpan="2" cacheShape="true" cache="true">
|
||||
</Pane>
|
||||
|
||||
<Label text="%unlock.label.password" cacheShape="true" cache="true" GridPane.rowIndex="2" GridPane.columnIndex="0" />
|
||||
<SecPasswordField fx:id="passwordField" cacheShape="true" cache="true" GridPane.rowIndex="2" GridPane.columnIndex="1" />
|
||||
|
||||
<HBox alignment="CENTER_RIGHT" GridPane.hgrow="ALWAYS" GridPane.rowIndex="3" GridPane.columnIndex="0" GridPane.columnSpan="2" cacheShape="true" cache="true">
|
||||
<Button fx:id="upgradeButton" text="%upgrade.button" prefWidth="150.0" onAction="#didClickUpgradeButton" cacheShape="true" cache="true" />
|
||||
</HBox>
|
||||
|
||||
<ProgressIndicator progress="-1" fx:id="progressIndicator" visible="false" cacheShape="true" cache="true" cacheHint="SPEED" GridPane.rowIndex="4" GridPane.columnIndex="0" GridPane.columnSpan="2" />
|
||||
|
||||
<Label fx:id="errorLabel" wrapText="true" GridPane.rowIndex="5" GridPane.columnIndex="0" GridPane.columnSpan="2" cacheShape="true" cache="true" />
|
||||
</children>
|
||||
</GridPane>
|
||||
|
||||
@@ -1,15 +1,3 @@
|
||||
# Copyright (c) 2016 The Cryptomator Contributors
|
||||
# This file is licensed under the terms of the MIT license.
|
||||
# See the LICENSE.txt file for more info.
|
||||
#
|
||||
# Contributors:
|
||||
# Christian Schmickler
|
||||
# Joscha Feth
|
||||
# Markus Kreusch
|
||||
# Michael Schmetter
|
||||
# Sebastian Wiesendahl
|
||||
# Tim Marius Wunderlich
|
||||
|
||||
app.name = Cryptomator
|
||||
# main.fxml
|
||||
main.emptyListInstructions = Klicken Sie hier, um neue Tresore hinzuzufügen
|
||||
@@ -18,8 +6,8 @@ main.directoryList.contextMenu.changePassword = Passwort ändern
|
||||
main.addDirectory.contextMenu.new = Tresor erstellen
|
||||
main.addDirectory.contextMenu.open = Tresor öffnen
|
||||
# welcome.fxml
|
||||
welcome.checkForUpdates.label.currentlyChecking = Auf Updates prüfen...
|
||||
welcome.newVersionMessage = Version %s kann heruntergeladen werden. Aktuelle Version %s.
|
||||
welcome.checkForUpdates.label.currentlyChecking = Prüfe auf Updates...
|
||||
welcome.newVersionMessage = Version %1$s kann heruntergeladen werden. Momentane Version %2$s.
|
||||
# initialize.fxml
|
||||
initialize.label.password = Passwort
|
||||
initialize.label.retypePassword = Passwort bestätigen
|
||||
@@ -44,7 +32,6 @@ unlock.button.advancedOptions.hide = Weniger Optionen
|
||||
unlock.choicebox.winDriveLetter.auto = Automatisch ermitteln
|
||||
unlock.errorMessage.wrongPassword = Falsches Passwort
|
||||
unlock.errorMessage.mountingFailed = Verbindung fehlgeschlagen. Details in der Log-Datei.
|
||||
unlock.errorMessage.unsupportedKeyLengthInstallJCE = Entschlüsselung fehlgeschlagen. Bitte die Oracle JCE Unlimited Strength Policy installieren.
|
||||
unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Tresor nicht unterstützt. Der Tresor wurde mit einer älteren Version von Cryptomator erstellt.
|
||||
unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Tresor nicht unterstützt. Der Tresor wurde mit einer neueren Version von Cryptomator erstellt.
|
||||
unlock.messageLabel.startServerFailed = Starten des WebDAV-Servers fehlgeschlagen.
|
||||
@@ -56,9 +43,6 @@ changePassword.label.downloadsPageLink = Alle Cryptomator Versionen
|
||||
changePassword.button.change = Passwort ändern
|
||||
changePassword.errorMessage.wrongPassword = Falsches Passwort
|
||||
changePassword.errorMessage.decryptionFailed = Entschlüsselung fehlgeschlagen
|
||||
changePassword.errorMessage.unsupportedKeyLengthInstallJCE = Entschlüsselung fehlgeschlagen. Bitte die Oracle JCE Unlimited Strength Policy installieren.
|
||||
changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Tresor nicht unterstützt. Der Tresor wurde mit einer älteren Version von Cryptomator erstellt.
|
||||
changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = Tresor nicht unterstützt. Der Tresor wurde mit einer neueren Version von Cryptomator erstellt.
|
||||
changePassword.infoMessage.success = Passwort geändert
|
||||
# unlocked.fxml
|
||||
unlocked.button.lock = Tresor sperren
|
||||
@@ -92,4 +76,10 @@ initialize.messageLabel.passwordStrength.0 = Sehr schwach
|
||||
initialize.messageLabel.passwordStrength.1 = Schwach
|
||||
initialize.messageLabel.passwordStrength.2 = Mittel
|
||||
initialize.messageLabel.passwordStrength.3 = Stark
|
||||
initialize.messageLabel.passwordStrength.4 = Sehr stark
|
||||
initialize.messageLabel.passwordStrength.4 = Sehr stark
|
||||
initialize.label.doNotForget = WICHTIG\: Falls Sie Ihr Passwort vergessen, gibt es keine Möglichkeit Ihre Daten wiederherzustellen.
|
||||
main.directoryList.remove.confirmation.title = Tresor entfernen
|
||||
main.directoryList.remove.confirmation.header = Möchten Sie diesen Tresor wirklich entfernen?
|
||||
main.directoryList.remove.confirmation.content = Dieser Tresor wird nur aus der Liste entfernt. Um den Tresor unwiderruflich zu löschen, entfernen Sie bitte die Dateien aus Ihrem Dateisystem.
|
||||
upgrade.version3to4.msg = Dieser Tresor muss auf ein neueres Format aktualisiert werden.\nVerschlüsselte Ordnernamen werden dabei aktualisiert.\nStellen Sie bitte sicher, dass derzeit keine Synchronisation stattfindet.
|
||||
upgrade.version3to4.err.io = Migration aufgrund eines I/O-Fehlers fehlgeschlagen.\nWeitere Informationen in der Log-Datei.
|
||||
@@ -19,14 +19,14 @@ main.directoryList.remove.confirmation.content=The vault will only be removed fr
|
||||
|
||||
# welcome.fxml
|
||||
welcome.checkForUpdates.label.currentlyChecking=Checking for Updates...
|
||||
welcome.newVersionMessage=Version %s can be downloaded. This is %s.
|
||||
welcome.newVersionMessage=Version %1$s can be downloaded. This is %2$s.
|
||||
|
||||
# initialize.fxml
|
||||
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
|
||||
@@ -43,6 +43,9 @@ upgrade.button=Upgrade vault
|
||||
upgrade.version3dropBundleExtension.msg=This vault needs to be migrated to a newer format.\n"%1$s" will be renamed to "%2$s".\nPlease make sure synchronization has finished before proceeding.
|
||||
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
|
||||
unlock.label.mountName=Drive name
|
||||
@@ -54,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.
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
# Copyright (c) 2016 The Cryptomator Contributors
|
||||
# This file is licensed under the terms of the MIT license.
|
||||
# See the LICENSE.txt file for more info.
|
||||
#
|
||||
# Contributos:
|
||||
# Jay
|
||||
# Sebastian Wiesendahl
|
||||
|
||||
app.name = Cryptomator
|
||||
# main.fxml
|
||||
main.emptyListInstructions = Click aquí para añadir una caja fuerte
|
||||
@@ -16,13 +8,13 @@ main.addDirectory.contextMenu.new = Crear una nueva caja fuerte
|
||||
main.addDirectory.contextMenu.open = Abrir una caja fuerte existente
|
||||
# welcome.fxml
|
||||
welcome.checkForUpdates.label.currentlyChecking = Chequando por actualizaciónes...
|
||||
welcome.newVersionMessage = Se puede bajar version %s. Este es %s.
|
||||
welcome.newVersionMessage = Se puede bajar version %1$s. Este es %2$s.
|
||||
# initialize.fxml
|
||||
initialize.label.password = Contraseña
|
||||
initialize.label.retypePassword = Reintroduzca contraseña
|
||||
initialize.button.ok = Crear caja fuerte
|
||||
initialize.messageLabel.alreadyInitialized = Caja fuerte ya está inicializado
|
||||
initialize.messageLabel.initializationFailed = No se pudo inicializar la caja fuerte. Ver archivo de registro para detalles.
|
||||
initialize.messageLabel.initializationFailed = No se pudo inicializar la caja fuerte. Ver archivo de registro para detalles.
|
||||
# notfound.fxml
|
||||
notfound.label = No se pudo encontrar la caja fuerte. Se movió a otro lugar?
|
||||
# upgrade.fxml
|
||||
@@ -41,7 +33,6 @@ unlock.button.advancedOptions.hide = Menos opciones
|
||||
unlock.choicebox.winDriveLetter.auto = Asignar automáticamente
|
||||
unlock.errorMessage.wrongPassword = Contraseña incorrecta
|
||||
unlock.errorMessage.mountingFailed = Monteo ha fallado. Ver archivo del registro para detalles.
|
||||
unlock.errorMessage.unsupportedKeyLengthInstallJCE = Decifración ha fallado. Por favor instala archivos de la Oracle JCE Unlimited Strength Policy.
|
||||
unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Caja fuerte insupportado. Este caja se ha creado con una versión pasada de Cryptomator.
|
||||
unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Caja fuerte insupportado. Este caja se ha creado con una versión nueva de Cryptomator.
|
||||
unlock.messageLabel.startServerFailed = Iniciación del servidor de WebDAV ha fallado.
|
||||
@@ -54,13 +45,10 @@ changePassword.label.downloadsPageLink = Todas las versiones de Cryptomator
|
||||
changePassword.button.change = Cambiar contraseña
|
||||
changePassword.errorMessage.wrongPassword = Contraseña incorrecta
|
||||
changePassword.errorMessage.decryptionFailed = Decifración ha fallado
|
||||
changePassword.errorMessage.unsupportedKeyLengthInstallJCE = Decifración ha fallado. Por favor instala Oracle JCE Unlimited Strength Policy.
|
||||
changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Caja fuerte insupportado. Este caja se ha creado con una versión pasada de Cryptomator.
|
||||
changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = Caja fuerte insupportado. Este caja se ha creado con una versión nueva de Cryptomator.
|
||||
changePassword.infoMessage.success = Contraseña se ha cambiado
|
||||
# unlocked.fxml
|
||||
unlocked.button.lock = Encerrar caja fuerte
|
||||
unlocked.moreOptions.reveal = Revelar disco
|
||||
unlocked.moreOptions.reveal = Mostrar disco
|
||||
unlocked.moreOptions.copyUrl = Copiar URL de WebDAV
|
||||
unlocked.label.revealFailed = Comando ha fallado
|
||||
unlocked.label.unmountFailed = Expulsar el disco ha fallado
|
||||
@@ -83,5 +71,16 @@ settings.requiresRestartLabel = * Cryptomator se necesita reiniciar
|
||||
tray.menu.open = Abrir
|
||||
tray.menu.quit = Salir
|
||||
tray.infoMsg.title = Todavía en ejecución
|
||||
tray.infoMsg.msg = Cryptomator todavía esta en ejecución. Sale del icono del tray.
|
||||
tray.infoMsg.msg.osx = Cryptomator todavía esta en ejecución. Sale del icono de la barra del menú.
|
||||
tray.infoMsg.msg = Cryptomator todavía esta en ejecución. Para salir usa el icono del tray.
|
||||
tray.infoMsg.msg.osx = Cryptomator todavía esta en ejecución. Para salir usa el icono de la barra del menú.
|
||||
initialize.messageLabel.passwordStrength.0 = muy débil
|
||||
initialize.messageLabel.passwordStrength.1 = débil
|
||||
initialize.messageLabel.passwordStrength.2 = suficiente
|
||||
initialize.messageLabel.passwordStrength.3 = fuerte
|
||||
initialize.messageLabel.passwordStrength.4 = muy fuerte
|
||||
initialize.label.doNotForget = IMPORTANTE\: Si olivdes tú contraseña no hay ninguna manera de recuperar tus datos.
|
||||
main.directoryList.remove.confirmation.title = Borrar caja fuerte
|
||||
main.directoryList.remove.confirmation.header = ¿Quieres de verdad borrar este caja fuerte?
|
||||
main.directoryList.remove.confirmation.content = La caja fuerte solo se borra de la lista. Para eliminarla permanente por favor elimina los datos de tú sistema de archivos.
|
||||
upgrade.version3to4.msg = Este caja fuerte se debe migrar a un formato más reciente.\nLos nombres de las carpetas cifradas se actualizan.\nPor favor asegurarse de que la sincronización ha terminado antes de seguir.
|
||||
upgrade.version3to4.err.io = Migración ha fallado por causa de una excepción I/O. Para detalles revisa el archivo de registro.
|
||||
@@ -1,12 +1,3 @@
|
||||
# Copyright (c) 2016 The Cryptomator Contributors
|
||||
# This file is licensed under the terms of the MIT license.
|
||||
# See the LICENSE.txt file for more info.
|
||||
#
|
||||
# Contributors:
|
||||
# Jean-Noël Charon
|
||||
# Olivier Thomasson
|
||||
# vesparny
|
||||
|
||||
app.name = Cryptomator
|
||||
# main.fxml
|
||||
main.emptyListInstructions = Cliquez ici pour ajouter un coffre
|
||||
@@ -16,7 +7,7 @@ main.addDirectory.contextMenu.new = Créer un nouveau coffre
|
||||
main.addDirectory.contextMenu.open = Ouvrir un coffre existant
|
||||
# welcome.fxml
|
||||
welcome.checkForUpdates.label.currentlyChecking = Recherche de mise à jour...
|
||||
welcome.newVersionMessage = La version %s peut-être téléchargée. Il s'agit de %s.
|
||||
welcome.newVersionMessage = La version %1$s peut-être téléchargée. Il s'agit de %2$s.
|
||||
# initialize.fxml
|
||||
initialize.label.password = Mot de passe
|
||||
initialize.label.retypePassword = Confirmation
|
||||
@@ -41,7 +32,6 @@ unlock.button.advancedOptions.hide = Moins d'options
|
||||
unlock.choicebox.winDriveLetter.auto = Assigner automatiquement
|
||||
unlock.errorMessage.wrongPassword = Mot de passe incorrect
|
||||
unlock.errorMessage.mountingFailed = Echec du montage. Voir le fichier de log pour plus de détails.
|
||||
unlock.errorMessage.unsupportedKeyLengthInstallJCE = Echec du décryptage. Veuillez installer la Policy Oracle "JCE Unlimited Strength Policy".
|
||||
unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Coffre non supporté. Ce coffre a été créé avec une ancienne version de Cryptomator.
|
||||
unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Coffre non supporté. Ce coffre a été créé avec une version de Cryptomator plus récente.
|
||||
unlock.messageLabel.startServerFailed = Le serveur WebDAV n'a pas pu démarrer.
|
||||
@@ -52,25 +42,25 @@ changePassword.label.retypePassword = Vérification
|
||||
changePassword.label.downloadsPageLink = Toutes les versions de Cryptomator
|
||||
changePassword.button.change = Modification du mot de masse
|
||||
changePassword.errorMessage.wrongPassword = Mot de passe incorrect
|
||||
changePassword.errorMessage.decryptionFailed = Echec du décryptage
|
||||
changePassword.errorMessage.unsupportedKeyLengthInstallJCE = Echec du décryptage. Veuillez installer la Policy Oracle "JCE Unlimited Strength Policy".
|
||||
changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Coffre non supporté. Ce coffre a été créé avec une ancienne version de Cryptomator.
|
||||
changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = Coffre non supporté. Ce coffre a été créé avec une version de Cryptomator plus récente.
|
||||
changePassword.infoMessage.success = Password changed
|
||||
# En français, on dit déchiffrement lorsque la clé est connue
|
||||
changePassword.errorMessage.decryptionFailed = Echec du déchiffrement
|
||||
changePassword.infoMessage.success = Mot de passe modifié
|
||||
# unlocked.fxml
|
||||
unlocked.button.lock = Verrouiller le coffre
|
||||
unlocked.moreOptions.reveal = Voir le lecteur
|
||||
unlocked.moreOptions.copyUrl = Copier l'URL WebDAV
|
||||
unlocked.label.revealFailed = Echec de la commande
|
||||
unlocked.label.unmountFailed = Echec de l'éjection du lecteur
|
||||
unlocked.label.statsEncrypted = crypté
|
||||
unlocked.label.statsDecrypted = décryptage
|
||||
# Crypter n'existe pas en français.
|
||||
unlocked.label.statsEncrypted = chiffré
|
||||
# Décryptage signifie récupérer les données en clair tout en ne connaissant pas la clé
|
||||
unlocked.label.statsDecrypted = déchiffré
|
||||
unlocked.ioGraph.yAxis.label = Débit (MiB/s)
|
||||
# mac_warnings.fxml
|
||||
macWarnings.windowTitle = Attention - Fichier corrompu dans %s
|
||||
macWarnings.message = Cryptomator a détecté des corruptions de données dans les fichiers suivants\:
|
||||
macWarnings.moreInformationButton = En savoir plus
|
||||
macWarnings.whitelistButton = Décrypter tout de même
|
||||
macWarnings.whitelistButton = Déchiffrer tout de même
|
||||
# settings.fxml
|
||||
settings.version.label = Version %s
|
||||
settings.checkForUpdates.label = Vérif. des mises à jour
|
||||
@@ -84,3 +74,14 @@ tray.menu.quit = Quitter
|
||||
tray.infoMsg.title = Toujours en fonctionnement
|
||||
tray.infoMsg.msg = Cryptomator est toujours en fonctionnement. Utiliser l'icône de la barre des tâches pour quitter.
|
||||
tray.infoMsg.msg.osx = Cryptomator est toujours en fonctionnement. Utilisez la barre de menu pour quitter.
|
||||
initialize.messageLabel.passwordStrength.0 = Très faible
|
||||
initialize.messageLabel.passwordStrength.1 = Faible
|
||||
initialize.messageLabel.passwordStrength.2 = Raisonnable
|
||||
initialize.messageLabel.passwordStrength.3 = Fort
|
||||
initialize.messageLabel.passwordStrength.4 = Très fort\n
|
||||
initialize.label.doNotForget = ATTENTION \: Si vous oubliez votre mot de passe, il n'y aura aucun moyen de récupérer vos données.
|
||||
main.directoryList.remove.confirmation.title = Retirer un coffre
|
||||
main.directoryList.remove.confirmation.header = Voulez-vous vraiment retirer ce coffre ?
|
||||
main.directoryList.remove.confirmation.content = Le coffre sera simplement retiré de la liste. Pour le supprimer complètement, supprimez les fichiers depuis votre système de fichiers.
|
||||
upgrade.version3to4.msg = Ce coffre doit être converti dans un nouveau format. Les noms de dossiers chiffrés seront mis à jour.\nMerci de vous assurer que la procédure de synchronisation est terminée avant de continuer.
|
||||
upgrade.version3to4.err.io = La migration a échoué à cause d'une erreur d'entrée/sortie. Référez-vous au fichier log pour plus de détails.
|
||||
@@ -1,20 +1,13 @@
|
||||
# Copyright (c) 2016 The Cryptomator Contributors
|
||||
# This file is licensed under the terms of the MIT license.
|
||||
# See the LICENSE.txt file for more info.
|
||||
#
|
||||
# Contributors:
|
||||
# Roland Burda
|
||||
|
||||
app.name = Cryptomator
|
||||
# main.fxml
|
||||
main.emptyListInstructions = Kattints ide egy széf létrehozásához
|
||||
main.directoryList.contextMenu.remove = Eltávolítás listából
|
||||
main.directoryList.contextMenu.changePassword = Jelszó megváltoztatása
|
||||
main.addDirectory.contextMenu.new = Új széf létrehozása
|
||||
main.addDirectory.contextMenu.open = Létez\u0151 széf megnyitása
|
||||
main.addDirectory.contextMenu.open = Létező széf megnyitása
|
||||
# welcome.fxml
|
||||
welcome.checkForUpdates.label.currentlyChecking = Frissítések keresése...
|
||||
welcome.newVersionMessage = Új verzió érhet\u0151 el\: %s. Jelenlegi verzió\: %s.
|
||||
welcome.newVersionMessage = Új verzió érhető el\: %1$s. Jelenlegi verzió\: %2$s.
|
||||
# initialize.fxml
|
||||
initialize.label.password = Jelszó
|
||||
initialize.label.retypePassword = Jelszó ismét
|
||||
@@ -25,12 +18,12 @@ initialize.messageLabel.initializationFailed = Nem sikerült megnyitni a széfet
|
||||
notfound.label = Széf nem található. Lehetséges, hogy áthelyezésre került?
|
||||
# upgrade.fxml
|
||||
upgrade.button = Széf frissítése
|
||||
upgrade.version3dropBundleExtension.msg = A széf új verzióra történ\u0151 migrációja szükséges. "%1$s" a következ\u0151re lesz átnevezve\: "%2$s". Kérlek gy\u0151z\u0151dj meg a szinkronizáció befejeztér\u0151l, miel\u0151tt más m\u0171veletet végeznél.
|
||||
upgrade.version3dropBundleExtension.msg = A széf új verzióra történő migrációja szükséges. "%1$s" a következőre lesz átnevezve\: "%2$s". Kérlek győződj meg a szinkronizáció befejeztéről, mielőtt más műveletet végeznél.
|
||||
upgrade.version3dropBundleExtension.err.alreadyExists = Automatikus migráció meghíusúlt. "%s" már létezik.
|
||||
# unlock.fxml
|
||||
unlock.label.password = Jelszó
|
||||
unlock.label.mountName = Meghajtó neve
|
||||
unlock.label.winDriveLetter = Meghajtó bet\u0171jele
|
||||
unlock.label.winDriveLetter = Meghajtó betűjele
|
||||
unlock.label.downloadsPageLink = Összes Cryptomator verzió
|
||||
unlock.label.advancedHeading = Haladó beállítások
|
||||
unlock.button.unlock = Széf feloldása
|
||||
@@ -39,7 +32,6 @@ unlock.button.advancedOptions.hide = Alapbeállítások
|
||||
unlock.choicebox.winDriveLetter.auto = Automatikus hozzárendelés
|
||||
unlock.errorMessage.wrongPassword = Hibás jelszó
|
||||
unlock.errorMessage.mountingFailed = Meghajtó felcsatolása sikertelen. További információk a naplófájlban.
|
||||
unlock.errorMessage.unsupportedKeyLengthInstallJCE = A titkosítás feloldása sikertelen. Kérlek telepítsd a "Oracle JCE Unlimited Strength Policy Files"-t.
|
||||
unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Nem támogatott széf. Ez a széf a Cryptomator egy korábbi verziójával került létrehozásra.
|
||||
unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Nem támogatott széf. Ez a széf a Cryptomator egy újabb verziójával került létrehozásra.
|
||||
unlock.messageLabel.startServerFailed = WebDAV szerver indítása sikertelen.
|
||||
@@ -51,9 +43,6 @@ changePassword.label.downloadsPageLink = Összes Cryptomator verzió
|
||||
changePassword.button.change = Jelszó megváltoztatása
|
||||
changePassword.errorMessage.wrongPassword = Hibás jelszó
|
||||
changePassword.errorMessage.decryptionFailed = A titkosítás feloldása meghíusúlt
|
||||
changePassword.errorMessage.unsupportedKeyLengthInstallJCE = A titkosítás feloldása sikertelen. Kérlek telepítsd a "Oracle JCE Unlimited Strength Policy"-t.
|
||||
changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Nem támogatott széf. Ez a széf a Cryptomator egy korábbi verziójával került létrehozásra.
|
||||
changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = Nem támogatott széf. Ez a széf a Cryptomator egy újabb verziójával került létrehozásra.
|
||||
changePassword.infoMessage.success = Jelszó megváltoztatva
|
||||
# unlocked.fxml
|
||||
unlocked.button.lock = Széf lezárása
|
||||
@@ -65,8 +54,8 @@ unlocked.label.statsEncrypted = titkosított
|
||||
unlocked.label.statsDecrypted = titkosítás feloldva
|
||||
unlocked.ioGraph.yAxis.label = Teljesítmény (MiB/s)
|
||||
# mac_warnings.fxml
|
||||
macWarnings.windowTitle = Veszély - Korrupt fájl a következ\u0151ben\: %s
|
||||
macWarnings.message = Cryptomator potenciálisan rosszindulatú hibákat fedezett fel a következ\u0151 fájlokban\:
|
||||
macWarnings.windowTitle = Veszély - Korrupt fájl a következőben\: %s
|
||||
macWarnings.message = Cryptomator potenciálisan rosszindulatú hibákat fedezett fel a következő fájlokban\:
|
||||
macWarnings.moreInformationButton = Tudj meg többet
|
||||
macWarnings.whitelistButton = Kiválasztottak titkosításának feloldása mindenképp
|
||||
# settings.fxml
|
||||
@@ -79,6 +68,15 @@ settings.requiresRestartLabel = * Cryptomator újraindítása szükséges
|
||||
# tray icon
|
||||
tray.menu.open = Megnyit
|
||||
tray.menu.quit = Kilépés
|
||||
tray.infoMsg.title = M\u0171velet folyamatban
|
||||
tray.infoMsg.title = Művelet folyamatban
|
||||
tray.infoMsg.msg = Cryptomator még fut. A tálcán található ikon segítségével bezárhatod.
|
||||
tray.infoMsg.msg.osx = Cryptomator még fut. A menüsávban található ikon segítségével bezárhatod.
|
||||
initialize.messageLabel.passwordStrength.0 = Nagyon gyenge
|
||||
initialize.messageLabel.passwordStrength.1 = Gyenge
|
||||
initialize.messageLabel.passwordStrength.2 = Megfelelő
|
||||
initialize.messageLabel.passwordStrength.3 = Erős
|
||||
initialize.messageLabel.passwordStrength.4 = Nagyon erős
|
||||
initialize.label.doNotForget = FONTOS\: Ha elfelejted a jelszavadat, akkor nincs lehetőség az adataid visszaállítására.
|
||||
main.directoryList.remove.confirmation.title = Széf eltávolítása
|
||||
main.directoryList.remove.confirmation.header = Tényleg törölni akarod ezt a széfet?
|
||||
main.directoryList.remove.confirmation.content = A széf csak a listából lesz eltávolítva. Végleges törléshez kérlek töröld a merevlemezen tárolt fájlokat.
|
||||
@@ -1,10 +1,3 @@
|
||||
# Copyright (c) 2016 The Cryptomator Contributors
|
||||
# This file is licensed under the terms of the MIT license.
|
||||
# See the LICENSE.txt file for more info.
|
||||
#
|
||||
# Contributors:
|
||||
# vesparny
|
||||
|
||||
app.name = Cryptomator
|
||||
# main.fxml
|
||||
main.emptyListInstructions = Clicca qui per aggiungere un vault
|
||||
@@ -14,7 +7,7 @@ main.addDirectory.contextMenu.new = Crea un nuovo vault
|
||||
main.addDirectory.contextMenu.open = Apri un vault
|
||||
# welcome.fxml
|
||||
welcome.checkForUpdates.label.currentlyChecking = Verifica aggiornamenti...
|
||||
welcome.newVersionMessage = La versione %s può essere scaricata. Questa è %s
|
||||
welcome.newVersionMessage = La versione %1$s può essere scaricata. Questa è %2$s
|
||||
# initialize.fxml
|
||||
initialize.label.password = Password
|
||||
initialize.label.retypePassword = Conferma password
|
||||
@@ -39,7 +32,6 @@ unlock.button.advancedOptions.hide = Meno opzioni
|
||||
unlock.choicebox.winDriveLetter.auto = Assegna automaticamente
|
||||
unlock.errorMessage.wrongPassword = Password errata
|
||||
unlock.errorMessage.mountingFailed = Montaggio fallito. Controlla il file di log per dettagli.
|
||||
unlock.errorMessage.unsupportedKeyLengthInstallJCE = Decriptaggio fallito.
|
||||
unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Vault non supportato. Questo vault è stato creato con una versione di Cryptomator più vecchia.
|
||||
unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Vault non supportato. Questo vault è stato creato con una versione di Cryptomator più recente.
|
||||
unlock.messageLabel.startServerFailed = Avvio del server WebDAV fallito
|
||||
@@ -51,19 +43,16 @@ changePassword.label.downloadsPageLink = Tutte le versioni di Cryptomator
|
||||
changePassword.button.change = Cambia la password
|
||||
changePassword.errorMessage.wrongPassword = Password errata
|
||||
changePassword.errorMessage.decryptionFailed = Decriptaggio fallito
|
||||
changePassword.errorMessage.unsupportedKeyLengthInstallJCE = Decriptaggio fallito. Per favore installa Oracle JCE Unlimited Strength Policy
|
||||
changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Vault non supportato. Questo vault è stato creato con una versione di Cryptomator più recente.
|
||||
changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = Vault non supportato. Questo vault è stato creato con una versione di Cryptomator più vecchia.
|
||||
changePassword.infoMessage.success = Password cambiata
|
||||
# unlocked.fxml
|
||||
unlocked.button.lock = Blocca vault
|
||||
unlocked.button.lock = Blocca vault
|
||||
unlocked.moreOptions.reveal = Apri il disco
|
||||
unlocked.moreOptions.copyUrl = Copia url WebDAV
|
||||
unlocked.label.revealFailed = Comando fallito
|
||||
unlocked.label.unmountFailed = Espulsione disco fallita
|
||||
unlocked.label.statsEncrypted = criptato
|
||||
unlocked.label.statsDecrypted = decriptato
|
||||
unlocked.ioGraph.yAxis.label = Volume dati (MiB/s)
|
||||
unlocked.ioGraph.yAxis.label = Volume dati (MiB/s)
|
||||
# mac_warnings.fxml
|
||||
macWarnings.windowTitle = Pericolo - File corroto in %s
|
||||
macWarnings.message = Cryptomator ha individuato potenziali pericolose corruzioni nei seguenti file\:
|
||||
@@ -80,5 +69,14 @@ settings.requiresRestartLabel = * Cryptomator deve essere riavviato
|
||||
tray.menu.open = Apri
|
||||
tray.menu.quit = Chiudi
|
||||
tray.infoMsg.title = Ancora in esecuzione
|
||||
tray.infoMsg.msg = Cryptomator è ancora in esecuzione. Chiudilo utilizzando l'icona nel menù di stato.
|
||||
tray.infoMsg.msg = Cryptomator è ancora in esecuzione. Chiudilo utilizzando l'icona nel menù di stato.
|
||||
tray.infoMsg.msg.osx = Cryptomator è ancora in esecuzione. Chiudilo utilizzando l'icona nella barra del menù.
|
||||
initialize.messageLabel.passwordStrength.0 = Molto debole
|
||||
initialize.messageLabel.passwordStrength.1 = Debole
|
||||
initialize.messageLabel.passwordStrength.2 = Buona
|
||||
initialize.messageLabel.passwordStrength.3 = Sicura
|
||||
initialize.messageLabel.passwordStrength.4 = Molto sicura
|
||||
initialize.label.doNotForget = IMPORTANTE\: Se dimentichi la password, non c'è modo di recuperare i tuoi dati.
|
||||
main.directoryList.remove.confirmation.title = Rimuovi vault
|
||||
main.directoryList.remove.confirmation.header = Vuoi davvero rimuovere questo vault?
|
||||
main.directoryList.remove.confirmation.content = Il vault sarà rimosso solo dalla lista. Per eliminarlo definitivamente, elimina per favore i file dal tuo hard disk.
|
||||
@@ -1,10 +1,3 @@
|
||||
# Copyright (c) 2016 The Cryptomator Contributors
|
||||
# This file is licensed under the terms of the MIT license.
|
||||
# See the LICENSE.txt file for more info.
|
||||
#
|
||||
# Contributors:
|
||||
# ChangHwan Kim
|
||||
|
||||
app.name = Cryptomator
|
||||
# main.fxml
|
||||
main.emptyListInstructions = 여기를 클릭하여 보관함 추가하기
|
||||
@@ -13,8 +6,8 @@ main.directoryList.contextMenu.changePassword = 비밀번호 변경
|
||||
main.addDirectory.contextMenu.new = 새 보관함 만들기
|
||||
main.addDirectory.contextMenu.open = 기존 보관함 열기
|
||||
# welcome.fxml
|
||||
welcome.checkForUpdates.label.currentlyChecking = 업데이트 확인
|
||||
welcome.newVersionMessage = %s 버전이 새로 다운로드 가능합니다. 지금 버전은 %s 입니다.
|
||||
welcome.checkForUpdates.label.currentlyChecking = 업데이트 확인 중...
|
||||
welcome.newVersionMessage = %1$s 버전이 새로 다운로드 가능합니다. 지금 버전은 %2$s 입니다.
|
||||
# initialize.fxml
|
||||
initialize.label.password = 비밀번호
|
||||
initialize.label.retypePassword = 비밀번호 재입력
|
||||
@@ -39,9 +32,8 @@ unlock.button.advancedOptions.hide = 기본 옵션
|
||||
unlock.choicebox.winDriveLetter.auto = 자동으로 할당
|
||||
unlock.errorMessage.wrongPassword = 틀린 비밀번호
|
||||
unlock.errorMessage.mountingFailed = 마운트 실패. 자세한 사항은 로그 파일을 참조하세요.
|
||||
unlock.errorMessage.unsupportedKeyLengthInstallJCE = 복호화 실패. Oracle JCE Unlimited Strength Policy Files을 설치하세요.
|
||||
unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = 지원되지 않는 보관함. 이 보관함은 이전 버전의 Cryptomator에서 생성되었습니다.
|
||||
unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = 지원되지 않는 보관함. 이 보관함은 최신 버전의 Cryptomator에서 생성되었습니다.
|
||||
unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = 지원되지 않는 보관함. 이 보관함은 상위 버전의 Cryptomator에서 생성되었습니다.
|
||||
unlock.messageLabel.startServerFailed = WedDAV 서버 시작 실패
|
||||
# change_password.fxml
|
||||
changePassword.label.oldPassword = 이전 비밀번호
|
||||
@@ -51,9 +43,6 @@ changePassword.label.downloadsPageLink = 모든 Cryptomator 버전
|
||||
changePassword.button.change = 비밀번호 변경
|
||||
changePassword.errorMessage.wrongPassword = 틀린 비밀번호
|
||||
changePassword.errorMessage.decryptionFailed = 복호화 실패
|
||||
changePassword.errorMessage.unsupportedKeyLengthInstallJCE = 복호화 실패. Oracle JCE Unlimited Strength Policy Files을 설치하세요.
|
||||
changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = 지원되지 않는 보관함. 이 보관함은 이전 버전의 Cryptomator에서 생성되었습니다.
|
||||
changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = 지원되지 않는 보관함. 이 보관함은 최신 버전의 Cryptomator에서 생성되었습니다.
|
||||
changePassword.infoMessage.success = 비밀번호 변경
|
||||
# unlocked.fxml
|
||||
unlocked.button.lock = 보관함 잠그기
|
||||
@@ -68,7 +57,7 @@ unlocked.ioGraph.yAxis.label = 처리량 (MiB/s)
|
||||
macWarnings.windowTitle = 위험 - %s에 손상된 파일
|
||||
macWarnings.message = Cryptomator가 다음 파일들에서 잠재적인 손상 위험을 감지했습니다.
|
||||
macWarnings.moreInformationButton = 더 알아보기
|
||||
macWarnings.whitelistButton = 선택 항목 강제 복호화
|
||||
macWarnings.whitelistButton = 선택 항목 강제로 암호 풀기
|
||||
# settings.fxml
|
||||
settings.version.label = 버전 %s
|
||||
settings.checkForUpdates.label = 업데이트 확인
|
||||
@@ -82,8 +71,14 @@ tray.menu.quit = 종료
|
||||
tray.infoMsg.title = 계속 실행 중입니다.
|
||||
tray.infoMsg.msg = Cryptomator가 계속 실행 중입니다. 종료하실려면 트레이 아이콘에서 해주세요.
|
||||
tray.infoMsg.msg.osx = Cryptomator가 계속 실행중입니다. 종료하실려면 메뉴 바 아이콘에서 해주세요.
|
||||
initialize.messageLabel.passwordStrength.0 = 너무 약함
|
||||
initialize.messageLabel.passwordStrength.0 = 매우 약함
|
||||
initialize.messageLabel.passwordStrength.1 = 약함
|
||||
initialize.messageLabel.passwordStrength.2 = 괜찮음
|
||||
initialize.messageLabel.passwordStrength.3 = 강력함
|
||||
initialize.messageLabel.passwordStrength.4 = 매우 강력함
|
||||
initialize.label.doNotForget = 중요\: 만약 비밀번호를 잊으셨다면, 여러분의 데이터를 복구할 수 없습니다.
|
||||
main.directoryList.remove.confirmation.title = 보관함 삭제
|
||||
main.directoryList.remove.confirmation.header = 정말 이 보관함을 삭제하시겠습니까?
|
||||
main.directoryList.remove.confirmation.content = 보관함이 목록에서만 제거되었습니다. 데이터를 완전히 제거하시려면, 여러분의 파일시스템이서 제거해 주시기 바랍니다.
|
||||
upgrade.version3to4.msg = 이 보관함은 새로운 형식으로 바뀔 필요가 있습니다. 암호화된 폴더 이름이 업데이트 될 것입니다. 진행하기 전에 동기화가 완료되었는지 확인하기 바랍니다.
|
||||
upgrade.version3to4.err.io = 입출력 예외 문제로 마이그레이션이 실패하였습니다. 자세한 사항은 로그 파일을 확인하세요.
|
||||
84
main/ui/src/main/resources/localization/nl.txt
Normal file
84
main/ui/src/main/resources/localization/nl.txt
Normal file
@@ -0,0 +1,84 @@
|
||||
app.name = Cryptomator
|
||||
# main.fxml
|
||||
main.emptyListInstructions = Klik hier om een kluis toe te voegen
|
||||
main.directoryList.contextMenu.remove = Verwijder van lijst
|
||||
main.directoryList.contextMenu.changePassword = Verander wachtwoord
|
||||
main.addDirectory.contextMenu.new = Creeer nieuwe kluis
|
||||
main.addDirectory.contextMenu.open = Open bestaande kluis
|
||||
# welcome.fxml
|
||||
welcome.checkForUpdates.label.currentlyChecking = Controleren op Updates...
|
||||
welcome.newVersionMessage = Versie %1$s kan worden gedownload. Dit is %2$s.
|
||||
# initialize.fxml
|
||||
initialize.label.password = Wachtwoord
|
||||
initialize.label.retypePassword = Voer wachtwoord opnieuw in
|
||||
initialize.button.ok = Creëer kluis
|
||||
initialize.messageLabel.alreadyInitialized = Kluis reeds geïnitialiseerd
|
||||
initialize.messageLabel.initializationFailed = Kon kluis niet initialiseren. Zie logbestand voor details.
|
||||
# notfound.fxml
|
||||
notfound.label = Kluis kon niet gevonden worden. Is de kluis wellicht verplaatst?
|
||||
# upgrade.fxml
|
||||
upgrade.button = Upgrade kluis
|
||||
upgrade.version3dropBundleExtension.msg = Deze kluis dient te worden gemigreerd naar een nieuwer type.\n"%1$s" zal worden hernoemd naar "%2$s".\nZorg ervoor dat de synchronisatie voltooid is alvorens door te gaan.
|
||||
upgrade.version3dropBundleExtension.err.alreadyExists = Automatische migratie mislukt.\n"%s" bestaat al.
|
||||
# unlock.fxml
|
||||
unlock.label.password = Wachtwoord
|
||||
unlock.label.mountName = Schijfnaam
|
||||
unlock.label.winDriveLetter = Schijfletter
|
||||
unlock.label.downloadsPageLink = Alle Cryptomator versies
|
||||
unlock.label.advancedHeading = Geavanceerde opties
|
||||
unlock.button.unlock = Ontgrendel kluis
|
||||
unlock.button.advancedOptions.show = Meer opties
|
||||
unlock.button.advancedOptions.hide = Minder opties
|
||||
unlock.choicebox.winDriveLetter.auto = Automatisch toekennen
|
||||
unlock.errorMessage.wrongPassword = Verkeerd wachtwoord
|
||||
unlock.errorMessage.mountingFailed = Mounten mislukt. Zie logbestand voor details.
|
||||
unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Niet ondersteunde kluis. Deze kluis is gecreëerd met een oudere versie van Cryptomator.
|
||||
unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Niet ondersteunde kluis. Deze kluis is gecreëerd met een nieuwere versie van Cryptomator.
|
||||
unlock.messageLabel.startServerFailed = WebDAV server starten mislukt.
|
||||
# change_password.fxml
|
||||
changePassword.label.oldPassword = Huidig wachtwoord
|
||||
changePassword.label.newPassword = Nieuw wachtwoord
|
||||
changePassword.label.retypePassword = Herhaal wachtwoord
|
||||
changePassword.label.downloadsPageLink = Alle Cryptomator versies
|
||||
changePassword.button.change = Verander wachtwoord
|
||||
changePassword.errorMessage.wrongPassword = Alle Cryptomator versies
|
||||
changePassword.errorMessage.decryptionFailed = Decoderen mislukt
|
||||
changePassword.infoMessage.success = Wachtwoord verandert
|
||||
# unlocked.fxml
|
||||
unlocked.button.lock = Vergrendel kluis
|
||||
unlocked.moreOptions.reveal = Maak schijf zichtbaar
|
||||
unlocked.moreOptions.copyUrl = Kopieer WebDAV URL
|
||||
unlocked.label.revealFailed = Commando mislukt
|
||||
unlocked.label.unmountFailed = Uitwerpen schijf mislukt
|
||||
unlocked.label.statsEncrypted = versleuteld
|
||||
unlocked.label.statsDecrypted = gedecodeerd
|
||||
unlocked.ioGraph.yAxis.label = Doorvoer (MiB/s)
|
||||
# mac_warnings.fxml
|
||||
macWarnings.windowTitle = Pas op - Corrupt bestand in %s
|
||||
macWarnings.message = Cryptomator heeft mogelijk kwaadwillende corrupte items aangetroffen in de volgende bestanden\:
|
||||
macWarnings.moreInformationButton = Leer meer
|
||||
macWarnings.whitelistButton = Doorgaan met decoderen van selectie
|
||||
# settings.fxml
|
||||
settings.version.label = Versie %s
|
||||
settings.checkForUpdates.label = Controleer op updates
|
||||
settings.port.label = WebDAV Poort *
|
||||
settings.port.prompt = 0 \= Kies automatisch
|
||||
settings.useipv6.label = Gebruik IPv6 literal
|
||||
settings.requiresRestartLabel = * Cryptomator dient te worden herstart
|
||||
# tray icon
|
||||
tray.menu.open = Open
|
||||
tray.menu.quit = Afsluiten
|
||||
tray.infoMsg.title = Nog steeds actief
|
||||
tray.infoMsg.msg = Cryptomator is nog steeds actief. Sluit het af via het icon in het systeemvak.
|
||||
tray.infoMsg.msg.osx = Cryptomator is nog steeds actief. Sluit het af via het icon op de menubalk.
|
||||
initialize.messageLabel.passwordStrength.0 = Zeer zwak
|
||||
initialize.messageLabel.passwordStrength.1 = Zwak
|
||||
initialize.messageLabel.passwordStrength.2 = Redelijk
|
||||
initialize.messageLabel.passwordStrength.3 = Sterk
|
||||
initialize.messageLabel.passwordStrength.4 = Zeer sterk
|
||||
initialize.label.doNotForget = BELANGRIJK\: Indien je het wachtwoord vergeet, is er geen manier om je data te herstellen.
|
||||
main.directoryList.remove.confirmation.title = Verwijder Kluis
|
||||
main.directoryList.remove.confirmation.header = Weet je zeker dat je deze kluis wilt verwijderen?
|
||||
main.directoryList.remove.confirmation.content = De kluis zal alleen van de lijst worden verwijdert. Verwijder de bestanden van het bestandssysteem voor permanente verwijdering.
|
||||
upgrade.version3to4.msg = Deze kluis dient gemigreerd te worden naar een nieuwer type. \nVersleutelde mapnamen zullen worden geüpdatet. \nZorg ervoor dat de synchronisatie voltooid is alvorens door te gaan.
|
||||
upgrade.version3to4.err.io = Migratie mislukt door een I/O Exception. Zie logbestand voor details.
|
||||
@@ -1,55 +1,86 @@
|
||||
# Copyright (c) 2016 The Cryptomator Contributors
|
||||
# This file is licensed under the terms of the MIT license.
|
||||
# See the LICENSE.txt file for more info.
|
||||
#
|
||||
# Contributors:
|
||||
# Garik
|
||||
# Konstantine
|
||||
|
||||
app.name = Cryptomator
|
||||
# main.fxml
|
||||
main.emptyListInstructions = Нажмите здесь что добавить хранилище
|
||||
main.emptyListInstructions = Нажмите здесь, чтобы добавить хранилище
|
||||
main.directoryList.contextMenu.remove = Удалить из списка
|
||||
main.directoryList.contextMenu.changePassword = Сменить пароль
|
||||
main.addDirectory.contextMenu.new = Создать новое хранилище
|
||||
main.addDirectory.contextMenu.open = Открыть существующее хранилище
|
||||
main.addDirectory.contextMenu.open = Открыть имеющееся хранилище
|
||||
# welcome.fxml
|
||||
welcome.checkForUpdates.label.currentlyChecking = Проверка обновлений...
|
||||
welcome.newVersionMessage = Версия может быть скачена. Это.
|
||||
# Does the first %s mean the new version number, and the second %s - the current version user has?
|
||||
welcome.newVersionMessage = Доступна версия %1$s. У вас версия %2$s.
|
||||
# initialize.fxml
|
||||
initialize.label.password = Пароль
|
||||
initialize.label.retypePassword = Повторите пароль
|
||||
initialize.label.retypePassword = Введите пароль ещё раз
|
||||
initialize.button.ok = Создать хранилище
|
||||
initialize.messageLabel.alreadyInitialized = Хранилище уже инициализировано
|
||||
initialize.messageLabel.initializationFailed = Невозможно инициировать хранилище. Смотрите лог для деталей.
|
||||
initialize.messageLabel.initializationFailed = Невозможно инициализировать хранилище. См. подробности в файле-отчёте.
|
||||
# notfound.fxml
|
||||
notfound.label = Хранилище не найдено.Оно было удалено?
|
||||
notfound.label = Хранилище не найдено. Оно было перемещено?
|
||||
# upgrade.fxml
|
||||
upgrade.button = Обновить хранилище
|
||||
upgrade.version3dropBundleExtension.msg = Этому хранилищу нужно мигрировать в новый формат.\n"%1$s" will be renamed to "%2$s".\nPlease make sure synchronization has finished before proceeding.
|
||||
upgrade.version3dropBundleExtension.err.alreadyExists = Автоматическая миграция не удалась.\n"%" уже существует.
|
||||
upgrade.version3dropBundleExtension.msg = Это хранилище нужно преобразовать в новый формат.\n"%1$s" будет переименовано в "%2$s".\nПрежде чем продолжить, выполните синхронизацию.
|
||||
upgrade.version3dropBundleExtension.err.alreadyExists = Автоматическое преобразование не выполнено.\n"%s" уже существует.
|
||||
# unlock.fxml
|
||||
unlock.label.password = Пароль
|
||||
unlock.label.mountName = Имя носителя
|
||||
changePassword.errorMessage.wrongPassword = Неправильный пароль
|
||||
changePassword.errorMessage.decryptionFailed = Расшифровка провалилась
|
||||
changePassword.errorMessage.unsupportedKeyLengthInstallJCE = Расшифровка не удалась. Пожалуйста установите Oracle JCE Unlimited Strength Policy.
|
||||
changePassword.infoMessage.success = Пароль изменился
|
||||
unlock.label.mountName = Имя диска
|
||||
unlock.label.winDriveLetter = Буква диска
|
||||
unlock.label.downloadsPageLink = Все версии Cryptomator
|
||||
unlock.label.advancedHeading = Дополнительно
|
||||
unlock.button.unlock = Разблокировать хранилище
|
||||
unlock.button.advancedOptions.show = Ещё настройки
|
||||
unlock.button.advancedOptions.hide = Убрать настройки
|
||||
unlock.choicebox.winDriveLetter.auto = Автоназначение
|
||||
unlock.errorMessage.wrongPassword = Неверный пароль
|
||||
unlock.errorMessage.mountingFailed = Ошибка монтирования. См. подробности в файле-отчёте.
|
||||
unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Неподдерживаемое хранилище. Оно было создано в более старой версии Cryptomator.
|
||||
unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Неподдерживаемое хранилище. Оно было создано в более новой версии Cryptomator.
|
||||
unlock.messageLabel.startServerFailed = Ошибка запуска сервера WebDAV.
|
||||
# change_password.fxml
|
||||
changePassword.label.oldPassword = Старый пароль
|
||||
changePassword.label.newPassword = Новый пароль
|
||||
changePassword.label.retypePassword = Введите пароль ещё раз
|
||||
changePassword.label.downloadsPageLink = Все версии Cryptomator
|
||||
changePassword.button.change = Сменить пароль
|
||||
changePassword.errorMessage.wrongPassword = Неверный пароль
|
||||
changePassword.errorMessage.decryptionFailed = Ошибка дешифрования
|
||||
changePassword.infoMessage.success = Пароль изменён
|
||||
# unlocked.fxml
|
||||
unlocked.button.lock = Заблокировать хранилище
|
||||
unlocked.moreOptions.copyUrl = Скопировать WebDAV URL
|
||||
unlocked.label.revealFailed = Команда не удалась
|
||||
unlocked.label.unmountFailed = Извлечение диска не удалось
|
||||
# Does it mean "open" drive?
|
||||
unlocked.moreOptions.reveal = Открыть накопитель
|
||||
unlocked.moreOptions.copyUrl = Скопировать URL-адрес WebDAV
|
||||
unlocked.label.revealFailed = Ошибка команды
|
||||
unlocked.label.unmountFailed = Ошибка извлечения диска
|
||||
unlocked.label.statsEncrypted = зашифровано
|
||||
unlocked.label.statsDecrypted = расшифровано
|
||||
macWarnings.moreInformationButton = Изучить больше
|
||||
unlocked.ioGraph.yAxis.label = Пропускная способность (МиБ/с)
|
||||
# mac_warnings.fxml
|
||||
macWarnings.windowTitle = Внимание\! Повреждённый файл в %s
|
||||
macWarnings.message = Cryptomator обнаружил потенциально опасные повреждения в следующих файлах\:
|
||||
macWarnings.moreInformationButton = Подробнее
|
||||
macWarnings.whitelistButton = Дешифровать выбранные всё равно
|
||||
# settings.fxml
|
||||
settings.version.label = Версия %s
|
||||
settings.checkForUpdates.label = Проверка обновлений
|
||||
settings.requiresRestartLabel = * Cryptomator должен перезагрузится
|
||||
settings.port.label = Порт WebDAV *
|
||||
settings.port.prompt = 0 \= автовыбор
|
||||
settings.useipv6.label = Использование IPv
|
||||
settings.requiresRestartLabel = * Требуется перезагрузка Cryptomator
|
||||
# tray icon
|
||||
tray.menu.open = Открыть
|
||||
tray.menu.quit = Выйти
|
||||
tray.infoMsg.title = Всё ещё работает
|
||||
tray.infoMsg.msg = Cryptomator работает. Выйдите c помощью иконки в трее.
|
||||
tray.infoMsg.msg.osx = Cryptomator всё ещё работает.Выйдите с помощью иконки в меню баре.
|
||||
tray.menu.quit = Выход
|
||||
tray.infoMsg.title = Всё ещё выполняется
|
||||
tray.infoMsg.msg = Cryptomator всё ещё работает. Выйдите c помощью значка в области уведомлений.
|
||||
tray.infoMsg.msg.osx = Cryptomator всё ещё работает. Выйдите с помощью значка в строке меню.
|
||||
initialize.messageLabel.passwordStrength.0 = Очень слабый
|
||||
initialize.messageLabel.passwordStrength.1 = Слабый
|
||||
initialize.messageLabel.passwordStrength.2 = Приемлемый
|
||||
initialize.messageLabel.passwordStrength.3 = Сильный
|
||||
initialize.messageLabel.passwordStrength.4 = Очень сильный
|
||||
initialize.label.doNotForget = ВАЖНО\: Если вы забудете свой пароль, то восстановить данные будет невозможно.
|
||||
main.directoryList.remove.confirmation.title = Удаление хранилища
|
||||
main.directoryList.remove.confirmation.header = Вы действительно хотите удалить это хранилище?
|
||||
main.directoryList.remove.confirmation.content = Хранилище будет удалено только из списка. Чтобы стереть его окончательно, удалите файлы из файловой системы.
|
||||
upgrade.version3to4.msg = Это хранилище требуется преобразовать в новый формат. Зашифрованные имена папок будут обновлены. Прежде чем продолжить, выполните синхронизацию.
|
||||
upgrade.version3to4.err.io = Преобразование не выполнено из-за ошибки ввода-вывода. См. подробности в файле-отчёте.
|
||||
@@ -1,11 +1,6 @@
|
||||
# Copyright (c) 2016 The Cryptomator Contributors
|
||||
# This file is licensed under the terms of the MIT license.
|
||||
# Copyright (c) 2016 The Cryptomator Contributors
|
||||
# This file is licensed under the terms of the MIT license.
|
||||
# See the LICENSE.txt file for more info.
|
||||
#
|
||||
# Contributors:
|
||||
# Filip Havrlent
|
||||
# Tatiana Chovancová
|
||||
|
||||
app.name = Cryptomator
|
||||
# main.fxml
|
||||
main.emptyListInstructions = Pridať trezor
|
||||
@@ -15,7 +10,7 @@ main.addDirectory.contextMenu.new = Vytvoriť nový trezor
|
||||
main.addDirectory.contextMenu.open = Otvoriť existujúci trezor
|
||||
# welcome.fxml
|
||||
welcome.checkForUpdates.label.currentlyChecking = Kontrolujú sa aktualizácie...
|
||||
welcome.newVersionMessage = Verzia %s je pripravená na stiahnutie. Toto je verzia %s.
|
||||
welcome.newVersionMessage = Verzia %1$s je pripravená na stiahnutie. Toto je verzia %2$s.
|
||||
# initialize.fxml
|
||||
initialize.label.password = Heslo
|
||||
initialize.label.retypePassword = Zadajte heslo znova
|
||||
@@ -27,7 +22,7 @@ notfound.label = Trezor nemohol byť nenájdený. Bol presunutý?
|
||||
# upgrade.fxml
|
||||
upgrade.button = Upgradnúť trezor
|
||||
upgrade.version3dropBundleExtension.msg = Tento trezor musí byť premigrovaný na nový formát. "%1$s" bude premenovaný na "%2$s". Prosím, uistite sa že je dokončená synchronizácia skôr než budete pokračovať.
|
||||
upgrade.version3dropBundleExtension.err.alreadyExists = Automatická migrácia zlyhala. "%s" už existuje.
|
||||
upgrade.version3dropBundleExtension.err.alreadyExists = Automatická migrácia zlyhala. "%s" už existuje.
|
||||
# unlock.fxml
|
||||
unlock.label.password = Heslo
|
||||
unlock.label.mountName = Názov jednotky
|
||||
@@ -40,7 +35,6 @@ unlock.button.advancedOptions.hide = Menej nastavení
|
||||
unlock.choicebox.winDriveLetter.auto = Priradiť automaticky
|
||||
unlock.errorMessage.wrongPassword = Nesprávne heslo
|
||||
unlock.errorMessage.mountingFailed = Pripájanie zlyhalo. Viac informácii v logu.
|
||||
unlock.errorMessage.unsupportedKeyLengthInstallJCE = Dešifrovanie zlyhalo. Prosím nainštalujte Oracle JCE Unlimited Strength Policy Files.
|
||||
unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Nepodporovaný trezor. Tento trezor bol vytvorený staršou verziou Cryptromatoru.
|
||||
unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Nepodporovaný trezor. Bol vytvorený z novšou verziou Cryptomatoru.
|
||||
unlock.messageLabel.startServerFailed = Spustenie WebDAv servera zlyhalo.
|
||||
@@ -52,9 +46,6 @@ changePassword.label.downloadsPageLink = Všetky verzie Cryptomatoru.
|
||||
changePassword.button.change = Zmeniť heslo
|
||||
changePassword.errorMessage.wrongPassword = Nesprávne heslo
|
||||
changePassword.errorMessage.decryptionFailed = Dešifrovanie zlyhalo.
|
||||
changePassword.errorMessage.unsupportedKeyLengthInstallJCE = Dešifrovanie zlyhalo. Prosím nainštalujte Oracle JCE Unlimited Strength Policy.
|
||||
changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Nepodporovaný trezor. Bol vytvorený staršou verziou Cryptomatoru.
|
||||
changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = Nepodporovaný trezor. Bol vytvorený novšou verziou Cryptomatoru.
|
||||
changePassword.infoMessage.success = Heslo zmenené
|
||||
# unlocked.fxml
|
||||
unlocked.button.lock = Zamknúť trezor
|
||||
@@ -82,4 +73,4 @@ tray.menu.open = Otvoriť
|
||||
tray.menu.quit = Vypnúť
|
||||
tray.infoMsg.title = Stále beží
|
||||
tray.infoMsg.msg = Cryptomator je stále spustený. Vypnite ho pomocou ikony v systémovej lište.
|
||||
tray.infoMsg.msg.osx = Cryptomator je stále sputený. Ukončite ho pomocou ikony v menu.
|
||||
tray.infoMsg.msg.osx = Cryptomator je stále sputený. Ukončite ho pomocou ikony v menu.
|
||||
@@ -1,10 +1,3 @@
|
||||
# Copyright (c) 2016 The Cryptomator Contributors
|
||||
# This file is licensed under the terms of the MIT license.
|
||||
# See the LICENSE.txt file for more info.
|
||||
#
|
||||
# Contributors:
|
||||
# Cem KOÇ
|
||||
|
||||
app.name = Cryptomator
|
||||
# main.fxml
|
||||
main.emptyListInstructions = Kasa eklemek için tıkla
|
||||
@@ -14,7 +7,7 @@ main.addDirectory.contextMenu.new = Yeni bir kasa yarat
|
||||
main.addDirectory.contextMenu.open = Var olan kasayı aç
|
||||
# welcome.fxml
|
||||
welcome.checkForUpdates.label.currentlyChecking = Güncellemeler kontrol ediliyor...
|
||||
welcome.newVersionMessage = Sürüm %s indirilebilir. Şu anki sürüm\: %s
|
||||
welcome.newVersionMessage = Sürüm %1$s indirilebilir. Şu anki sürüm\: %2$s
|
||||
# initialize.fxml
|
||||
initialize.label.password = Şifre
|
||||
initialize.label.retypePassword = Şifre (tekrar)
|
||||
@@ -39,7 +32,6 @@ unlock.button.advancedOptions.hide = Daha az seçenek
|
||||
unlock.choicebox.winDriveLetter.auto = Otomatik ata
|
||||
unlock.errorMessage.wrongPassword = Yanlış şifre
|
||||
unlock.errorMessage.mountingFailed = Başlama başarısız. Detaylar için log dosyasına bakın
|
||||
unlock.errorMessage.unsupportedKeyLengthInstallJCE = Şifre çözme başarısız. Lütfen Oracle JCE Unlimited Strength Policy yükleyin.
|
||||
unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Desteklenmeyen kasa. Bu kasa daha eski bir Cryptomator sürümü ile oluşturulmuş.
|
||||
unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Desteklenmeyen kasa. Bu kasa daha yeni bir Cryptomator sürümü ile oluşturulmuş.
|
||||
unlock.messageLabel.startServerFailed = WebDAV sunucu başlatma başarısız.
|
||||
@@ -51,9 +43,6 @@ changePassword.label.downloadsPageLink = Tüm Cryptomator sürümleri
|
||||
changePassword.button.change = Şifreyi değiştir
|
||||
changePassword.errorMessage.wrongPassword = Yanlış şifre
|
||||
changePassword.errorMessage.decryptionFailed = Şifre çözme başarısız
|
||||
changePassword.errorMessage.unsupportedKeyLengthInstallJCE = Şifre çözme başarısız. Lütfen Oracle JCE Unlimited Strength Policy yükleyin.
|
||||
changePassword.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Desteklenmeyen kasa. Bu kasa daha eski bir Cryptomator sürümü ile oluşturulmuş.
|
||||
changePassword.errorMessage.unsupportedVersion.softwareOlderThanVault = Desteklenmeyen kasa. Bu kasa daha yeni bir Cryptomator sürümü ile oluşturulmuş.
|
||||
changePassword.infoMessage.success = Şifre değiştirildi.
|
||||
# unlocked.fxml
|
||||
unlocked.button.lock = Kasayı kilitle
|
||||
@@ -86,4 +75,10 @@ initialize.messageLabel.passwordStrength.0 = Çok zayıf
|
||||
initialize.messageLabel.passwordStrength.1 = Zayıf
|
||||
initialize.messageLabel.passwordStrength.2 = İyi
|
||||
initialize.messageLabel.passwordStrength.3 = Güçlü
|
||||
initialize.messageLabel.passwordStrength.4 = Çok güçlü
|
||||
initialize.messageLabel.passwordStrength.4 = Çok güçlü
|
||||
initialize.label.doNotForget = ÖNEMLİ\: Şifrenizi unutursanız, geri almanın bir yolu olmayacaktır.
|
||||
main.directoryList.remove.confirmation.title = Kasayı Sil
|
||||
main.directoryList.remove.confirmation.header = Kasayı silmek istediğinize emin misiniz ?
|
||||
main.directoryList.remove.confirmation.content = Kasa yalnızca listeden silinecek. Tamamen silmek için dosya sisteminizden dosyaları elle siliniz.
|
||||
upgrade.version3to4.msg = Bu kasanın yeni formata geçirilmesi gerekmekte. Şifreli klasör isimleri güncellenecek. Devam etmeden önce senkronizasyonun bittiğine emin olun.
|
||||
upgrade.version3to4.err.io = Format değiştirme işlemi I/O Hatası dolayısı ile başarısız oldu. Detaylar için log dosyasına bakın
|
||||
@@ -0,0 +1,93 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Sebastian Stenzel and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the accompanying LICENSE.txt.
|
||||
*
|
||||
* Contributors:
|
||||
* Sebastian Stenzel - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.ui;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.PropertyResourceBundle;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class LocalizationTest {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(LocalizationTest.class);
|
||||
private static final String RESOURCE_FOLDER_PATH = "/localization/";
|
||||
private static final String REF_FILE_NAME = "en.txt";
|
||||
private static final String[] LANG_FILE_NAMES = {"de.txt", "es.txt", "fr.txt", "hu.txt", "it.txt", "kr.txt", "nl.txt", "pt.txt", "ru.txt", "sk.txt", "tr.txt"};
|
||||
|
||||
/*
|
||||
* @see Formatter
|
||||
*/
|
||||
private static final String ARG_INDEX_REGEX = "(\\d+\\$)?"; // e.g. %1$s
|
||||
private static final String FLAG_REGEX = "[-#+ 0,\\(]*"; // e.g. %0,f
|
||||
private static final String WIDTH_AND_PRECISION_REGEX = "(\\d*(\\.\\d+)?)?"; // e.g. %4.2f
|
||||
private static final String GENERAL_CONVERSION_REGEX = "[bBhHsScCdoxXeEfgGaA%n]"; // e.g. %f
|
||||
private static final String TIME_CONVERSION_REGEX = "[tT][HIklMSLNpzZsQBbhAaCYyjmdeRTrDFc]"; // e.g. %1$tY-%1$tm-%1$td
|
||||
private static final String CONVERSION_REGEX = "(" + GENERAL_CONVERSION_REGEX + "|" + TIME_CONVERSION_REGEX + ")";
|
||||
private static final String PLACEHOLDER_REGEX = "%" + ARG_INDEX_REGEX + FLAG_REGEX + WIDTH_AND_PRECISION_REGEX + CONVERSION_REGEX;
|
||||
private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile(PLACEHOLDER_REGEX);
|
||||
|
||||
@Test
|
||||
public void testStringFormatIsValid() throws IOException {
|
||||
ResourceBundle ref = loadLanguage(RESOURCE_FOLDER_PATH + REF_FILE_NAME);
|
||||
boolean allGood = true;
|
||||
for (String langFileName : LANG_FILE_NAMES) {
|
||||
ResourceBundle lang = loadLanguage(RESOURCE_FOLDER_PATH + langFileName);
|
||||
allGood &= allStringFormatSpecifiersMatchReferenceLanguage(ref, lang, langFileName);
|
||||
}
|
||||
Assert.assertTrue(allGood);
|
||||
}
|
||||
|
||||
private boolean allStringFormatSpecifiersMatchReferenceLanguage(ResourceBundle ref, ResourceBundle lang, String langFileName) {
|
||||
boolean allGood = true;
|
||||
for (String key : Collections.list(ref.getKeys())) {
|
||||
if (!lang.containsKey(key)) {
|
||||
continue;
|
||||
}
|
||||
List<String> refPlaceholders = findPlaceholders(ref.getString(key));
|
||||
if (refPlaceholders.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
List<String> langPlaceholders = findPlaceholders(lang.getString(key));
|
||||
if (!langPlaceholders.containsAll(refPlaceholders) || !refPlaceholders.containsAll(langPlaceholders)) {
|
||||
LOG.warn("Placeholders don't match for term {}. Lang={}, Required={}, Found={}", key, langFileName, refPlaceholders, langPlaceholders);
|
||||
allGood = false;
|
||||
}
|
||||
}
|
||||
return allGood;
|
||||
}
|
||||
|
||||
private List<String> findPlaceholders(String str) {
|
||||
Matcher m = PLACEHOLDER_PATTERN.matcher(str);
|
||||
List<String> placeholders = new ArrayList<>();
|
||||
while (m.find()) {
|
||||
placeholders.add(m.group());
|
||||
}
|
||||
return placeholders;
|
||||
}
|
||||
|
||||
private ResourceBundle loadLanguage(String path) throws IOException {
|
||||
try (InputStream in = getClass().getResourceAsStream(path)) {
|
||||
Reader reader = new InputStreamReader(in, StandardCharsets.UTF_8);
|
||||
return new PropertyResourceBundle(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user