diff --git a/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/Aes256Cryptor.java b/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/Aes256Cryptor.java index 3178e4f14..b33a344bc 100644 --- a/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/Aes256Cryptor.java +++ b/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/Aes256Cryptor.java @@ -621,7 +621,7 @@ public class Aes256Cryptor implements Cryptor, AesCryptographicConfiguration, Fi return new Filter() { @Override public boolean accept(Path entry) throws IOException { - return ENCRYPTED_FILE_GLOB_MATCHER.matches(entry); + return ENCRYPTED_FILE_MATCHER.matches(entry); } }; } diff --git a/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/FileNamingConventions.java b/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/FileNamingConventions.java index 9a6f4b771..ca6da8eea 100644 --- a/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/FileNamingConventions.java +++ b/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/FileNamingConventions.java @@ -8,11 +8,13 @@ ******************************************************************************/ package org.cryptomator.crypto.aes256; -import java.nio.file.FileSystems; +import java.nio.file.Path; import java.nio.file.PathMatcher; +import java.util.regex.Pattern; import org.apache.commons.codec.binary.Base32; import org.apache.commons.codec.binary.BaseNCodec; +import org.apache.commons.lang3.StringUtils; interface FileNamingConventions { @@ -22,10 +24,11 @@ interface FileNamingConventions { BaseNCodec ENCRYPTED_FILENAME_CODEC = new Base32(); /** - * Maximum length possible on file systems with a filename or even path length limit of 255 chars.
- * Also we would need a few chars for our file extension, so lets use {@value #ENCRYPTED_FILENAME_LENGTH_LIMIT}. + * Maximum path length on some file systems or cloud storage providers is restricted.
+ * Parent folder path uses up to 58 chars (sha256 -> 32 bytes base32 encoded to 56 bytes + two slashes). That in mind we don't want the total path to be longer than 255 chars.
+ * 128 chars would be enought for up to 80 plaintext chars. Also we need up to 8 chars for our file extension. So lets use {@value #ENCRYPTED_FILENAME_LENGTH_LIMIT}. */ - int ENCRYPTED_FILENAME_LENGTH_LIMIT = 128; + int ENCRYPTED_FILENAME_LENGTH_LIMIT = 136; /** * For plaintext file names <= {@value #ENCRYPTED_FILENAME_LENGTH_LIMIT} chars. @@ -43,8 +46,27 @@ interface FileNamingConventions { int LONG_NAME_PREFIX_LENGTH = 8; /** - * Matches both, {@value #BASIC_FILE_EXT} and {@value #LONG_NAME_FILE_EXT} files. + * Matches valid encrypted filenames (both normal and long filenames - see {@link #ENCRYPTED_FILENAME_LENGTH_LIMIT}). */ - PathMatcher ENCRYPTED_FILE_GLOB_MATCHER = FileSystems.getDefault().getPathMatcher("glob:**/*{" + BASIC_FILE_EXT + "," + LONG_NAME_FILE_EXT + "}"); + PathMatcher ENCRYPTED_FILE_MATCHER = new PathMatcher() { + + private final Pattern BASIC_NAME_PATTERN = Pattern.compile("^[a-z2-7]+=*$", Pattern.CASE_INSENSITIVE); + private final Pattern LONG_NAME_PATTERN = Pattern.compile("^[a-z2-7]{8}[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", Pattern.CASE_INSENSITIVE); + + @Override + public boolean matches(Path path) { + final String filename = path.getFileName().toString(); + if (StringUtils.endsWithIgnoreCase(filename, LONG_NAME_FILE_EXT)) { + final String basename = StringUtils.removeEndIgnoreCase(filename, LONG_NAME_FILE_EXT); + return LONG_NAME_PATTERN.matcher(basename).matches(); + } else if (StringUtils.endsWithIgnoreCase(filename, BASIC_FILE_EXT)) { + final String basename = StringUtils.removeEndIgnoreCase(filename, BASIC_FILE_EXT); + return BASIC_NAME_PATTERN.matcher(basename).matches(); + } else { + return false; + } + } + + }; }