Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions src/main/java/org/cryptomator/cryptofs/CryptoPathMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import com.google.common.io.BaseEncoding;
import org.cryptomator.cryptofs.common.CiphertextFileType;
import org.cryptomator.cryptofs.common.Constants;
import org.cryptomator.cryptofs.event.BrokenFileNodeEvent;
import org.cryptomator.cryptofs.event.FilesystemEvent;
import org.cryptomator.cryptolib.api.Cryptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -27,6 +29,7 @@
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Optional;
import java.util.function.Consumer;

import static org.cryptomator.cryptofs.common.Constants.DATA_DIR_NAME;

Expand All @@ -41,18 +44,20 @@ public class CryptoPathMapper {
private final DirectoryIdProvider dirIdProvider;
private final LongFileNameProvider longFileNameProvider;
private final VaultConfig vaultConfig;
private final Consumer<FilesystemEvent> eventConsumer;
private final LoadingCache<DirIdAndName, String> ciphertextNames;
private final CiphertextDirCache ciphertextDirCache;

private final CiphertextDirectory rootDirectory;

@Inject
CryptoPathMapper(@PathToVault Path pathToVault, Cryptor cryptor, DirectoryIdProvider dirIdProvider, LongFileNameProvider longFileNameProvider, VaultConfig vaultConfig) {
CryptoPathMapper(@PathToVault Path pathToVault, Cryptor cryptor, DirectoryIdProvider dirIdProvider, LongFileNameProvider longFileNameProvider, VaultConfig vaultConfig, Consumer<FilesystemEvent> eventConsumer) {
this.dataRoot = pathToVault.resolve(DATA_DIR_NAME);
this.cryptor = cryptor;
this.dirIdProvider = dirIdProvider;
this.longFileNameProvider = longFileNameProvider;
this.vaultConfig = vaultConfig;
this.eventConsumer = eventConsumer;
this.ciphertextNames = Caffeine.newBuilder().maximumSize(MAX_CACHED_CIPHERTEXT_NAMES).build(this::getCiphertextFileName);
this.ciphertextDirCache = new CiphertextDirCache();
this.rootDirectory = resolveDirectory(Constants.ROOT_DIR_ID);
Expand Down Expand Up @@ -98,6 +103,7 @@ public CiphertextFileType getCiphertextFileType(CryptoPath cleartextPath) throws
} else if (ciphertextPath.isShortened() && Files.exists(ciphertextPath.getFilePath(), LinkOption.NOFOLLOW_LINKS)) {
return CiphertextFileType.FILE;
} else {
eventConsumer.accept(new BrokenFileNodeEvent(cleartextPath, ciphertextPath.getRawPath()));
LOG.warn("Did not find valid content inside of {}", ciphertextPath.getRawPath());
throw new NoSuchFileException(cleartextPath.toString(), null, "Could not determine type of file " + ciphertextPath.getRawPath());
}
Expand All @@ -111,7 +117,7 @@ public CiphertextFileType getCiphertextFileType(CryptoPath cleartextPath) throws
public CiphertextFilePath getCiphertextFilePath(CryptoPath cleartextPath) throws IOException {
CryptoPath parentPath = cleartextPath.getParent();
if (parentPath == null) {
throw new IllegalArgumentException("Invalid file path (must have a parent): " + cleartextPath);
throw new IllegalArgumentException("Invalid file path (must have a parent): " + cleartextPath); //TODO: cleartext path in Logs!
}
CiphertextDirectory parent = getCiphertextDir(parentPath);
String cleartextName = cleartextPath.getFileName().toString();
Expand Down
11 changes: 9 additions & 2 deletions src/main/java/org/cryptomator/cryptofs/DirectoryIdLoader.java
Original file line number Diff line number Diff line change
@@ -1,26 +1,31 @@
package org.cryptomator.cryptofs;

import com.github.benmanes.caffeine.cache.CacheLoader;
import org.cryptomator.cryptofs.event.BrokenDirFileEvent;
import org.cryptomator.cryptofs.event.FilesystemEvent;

import javax.inject.Inject;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.UUID;
import java.util.function.Consumer;

@CryptoFileSystemScoped
class DirectoryIdLoader implements CacheLoader<Path, String> {

private static final int MAX_DIR_ID_LENGTH = 1000;

private final Consumer<FilesystemEvent> eventConsumer;

@Inject
public DirectoryIdLoader() {
public DirectoryIdLoader(Consumer<FilesystemEvent> eventConsumer) {
this.eventConsumer = eventConsumer;
}

@Override
Expand All @@ -29,8 +34,10 @@ public String load(Path dirFilePath) throws IOException {
InputStream in = Channels.newInputStream(ch)) {
long size = ch.size();
if (size == 0) {
eventConsumer.accept(new BrokenDirFileEvent(dirFilePath));
throw new IOException("Invalid, empty directory file: " + dirFilePath);
} else if (size > MAX_DIR_ID_LENGTH) {
eventConsumer.accept(new BrokenDirFileEvent(dirFilePath));
throw new IOException("Unexpectedly large directory file: " + dirFilePath);
} else {
assert size <= MAX_DIR_ID_LENGTH; // thus int
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.cryptomator.cryptofs.event;

import java.nio.file.Path;

/**
* Emitted, if a dir.c9r file is empty or exceeds 1000 Bytes.
*
* @param ciphertextPath path to the broken dir.c9r file
*/
public record BrokenDirFileEvent(Path ciphertextPath) implements FilesystemEvent {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.cryptomator.cryptofs.event;

import java.nio.file.Path;

/**
* Emitted, if a path within the cryptographic filesystem is accessed, but the directory representing it is missing identification files.
*
* @param cleartextPath path within the cryptographic filesystem
* @param ciphertextPath path of the incomplete, encrypted directory
*
* @see org.cryptomator.cryptofs.health.type.UnknownType
*/
public record BrokenFileNodeEvent(Path cleartextPath, Path ciphertextPath) implements FilesystemEvent {

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package org.cryptomator.cryptofs.event;

import org.cryptomator.cryptolib.api.AuthenticationFailedException;

import java.nio.file.Path;

/**
Expand All @@ -10,6 +8,5 @@
* @param ciphertextPath path to the encrypted resource
* @param e thrown exception
*/
public record DecryptionFailedEvent(Path ciphertextPath, AuthenticationFailedException e) implements FilesystemEvent {

public record DecryptionFailedEvent(Path ciphertextPath, Exception e) implements FilesystemEvent {
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@
*
* @apiNote Events might have occured a long time ago in a galaxy far, far away... therefore, any feedback method is non-blocking and might fail due to changes in the filesystem.
*/
public sealed interface FilesystemEvent permits ConflictResolutionFailedEvent, ConflictResolvedEvent, DecryptionFailedEvent {
public sealed interface FilesystemEvent permits BrokenDirFileEvent, BrokenFileNodeEvent, ConflictResolutionFailedEvent, ConflictResolvedEvent, DecryptionFailedEvent {

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import org.cryptomator.cryptofs.event.DecryptionFailedEvent;
import org.cryptomator.cryptofs.event.FilesystemEvent;
import org.cryptomator.cryptolib.api.AuthenticationFailedException;
import org.cryptomator.cryptolib.api.CryptoException;
import org.cryptomator.cryptolib.api.Cryptor;
import org.cryptomator.cryptolib.api.FileHeader;
Expand Down Expand Up @@ -81,9 +80,7 @@ FileHeader loadExisting(FileChannel ch) throws IOException {
isPersisted.set(true);
return existingHeader;
} catch (IllegalArgumentException | CryptoException e) {
if (e instanceof AuthenticationFailedException afe) {
eventConsumer.accept(new DecryptionFailedEvent(path.get(), afe));
}
eventConsumer.accept(new DecryptionFailedEvent(path.get(), e));
throw new IOException("Unable to decrypt header of file " + path.get(), e);
}
}
Expand Down
Loading