Skip to content

Commit

Permalink
Merge branch 'release/2.6.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
infeo committed Jan 4, 2023
2 parents ae19036 + 665ef9f commit 1fe8036
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 6 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.cryptomator</groupId>
<artifactId>cryptofs</artifactId>
<version>2.5.3</version>
<version>2.6.0</version>
<name>Cryptomator Crypto Filesystem</name>
<description>This library provides the Java filesystem provider used by Cryptomator.</description>
<url>https://github.com/cryptomator/cryptofs</url>
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/org/cryptomator/cryptofs/CryptoFileSystem.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.cryptomator.cryptofs;

import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
Expand Down Expand Up @@ -29,6 +30,17 @@ public abstract class CryptoFileSystem extends FileSystem {
*/
public abstract Path getPathToVault();

/**
* Provides the {@link Path} to the (data) ciphertext from a given cleartext path.
*
* @param cleartextPath absolute path to the cleartext file or folder belonging to this {@link CryptoFileSystem}. Internally the path must be an instance of {@link CryptoPath}
* @return the {@link Path} to ciphertext file or folder containing teh actual encrypted data
* @throws java.nio.file.ProviderMismatchException if the cleartext path does not belong to this CryptoFileSystem
* @throws java.nio.file.NoSuchFileException if for the cleartext path no ciphertext resource exists
* @throws IOException if an I/O error occurs looking for the ciphertext resource
*/
public abstract Path getCiphertextPath(Path cleartextPath) throws IOException;

/**
* Provides file system performance statistics.
*
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/org/cryptomator/cryptofs/CryptoFileSystemImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,20 @@ public Path getPathToVault() {
return pathToVault;
}

@Override
public Path getCiphertextPath(Path cleartextPath) throws IOException {
var p = CryptoPath.castAndAssertAbsolute(cleartextPath);
var nodeType = cryptoPathMapper.getCiphertextFileType(p);
var cipherFile = cryptoPathMapper.getCiphertextFilePath(p);
if( nodeType == CiphertextFileType.DIRECTORY) {
return cryptoPathMapper.getCiphertextDir(p).path;
} else if( nodeType == CiphertextFileType.SYMLINK) {
return cipherFile.getSymlinkFilePath();
} else {
return cipherFile.getFilePath();
}
}

@Override
public CryptoFileSystemStats getStats() {
return stats;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.nio.file.ProviderMismatchException;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.BasicFileAttributeView;
Expand Down Expand Up @@ -119,11 +120,11 @@ public void setup() {

when(fileSystemProperties.maxCleartextNameLength()).thenReturn(32768);

inTest = new CryptoFileSystemImpl(provider, cryptoFileSystems, pathToVault, cryptor,
fileStore, stats, cryptoPathMapper, cryptoPathFactory,
pathMatcherFactory, directoryStreamFactory, dirIdProvider, dirIdBackup,
fileAttributeProvider, fileAttributeByNameProvider, fileAttributeViewProvider,
openCryptoFiles, symlinks, finallyUtil, ciphertextDirDeleter, readonlyFlag,
inTest = new CryptoFileSystemImpl(provider, cryptoFileSystems, pathToVault, cryptor, //
fileStore, stats, cryptoPathMapper, cryptoPathFactory, //
pathMatcherFactory, directoryStreamFactory, dirIdProvider, dirIdBackup, //
fileAttributeProvider, fileAttributeByNameProvider, fileAttributeViewProvider, //
openCryptoFiles, symlinks, finallyUtil, ciphertextDirDeleter, readonlyFlag, //
fileSystemProperties);
}

Expand Down Expand Up @@ -188,6 +189,89 @@ public void testGetFileStoresReturnsFileStore() {
Assertions.assertSame(fileStore, inTest.getFileStore());
}

@Nested
public class PathToDataCiphertext {

@Test
@DisplayName("Getting data ciphertext path of directory returns ciphertext content dir")
public void testCleartextDirectory() throws IOException {
Path ciphertext = Mockito.mock(Path.class, "/d/AB/CD...XYZ/");
Path cleartext = inTest.getPath("/");
try (var cryptoPathMock = Mockito.mockStatic(CryptoPath.class)) {
cryptoPathMock.when(() -> CryptoPath.castAndAssertAbsolute(any())).thenReturn(cleartext);
when(cryptoPathMapper.getCiphertextFileType(any())).thenReturn(CiphertextFileType.DIRECTORY);
when(cryptoPathMapper.getCiphertextDir(any())).thenReturn(new CiphertextDirectory("foo", ciphertext));

Path result = inTest.getCiphertextPath(cleartext);
Assertions.assertEquals(ciphertext, result);
}
}

@Test
@DisplayName("Getting data ciphertext path of file returns ciphertext file")
public void testCleartextFile() throws IOException {
Path ciphertext = Mockito.mock(Path.class, "/d/AB/CD..XYZ/foo.c9r");
Path cleartext = inTest.getPath("/foo.bar");
try (var cryptoPathMock = Mockito.mockStatic(CryptoPath.class)) {
CiphertextFilePath p = Mockito.mock(CiphertextFilePath.class);
cryptoPathMock.when(() -> CryptoPath.castAndAssertAbsolute(any())).thenReturn(cleartext);
when(cryptoPathMapper.getCiphertextFileType(any())).thenReturn(CiphertextFileType.FILE);
when(cryptoPathMapper.getCiphertextFilePath(any())).thenReturn(p);
when(p.getFilePath()).thenReturn(ciphertext);

Path result = inTest.getCiphertextPath(cleartext);
Assertions.assertEquals(ciphertext, result);
}
}

@Test
@DisplayName("Getting data ciphertext path of symlink returns ciphertext symlink.c9r")
public void testCleartextSymlink() throws IOException {
Path ciphertext = Mockito.mock(Path.class, "/d/AB/CD..XYZ/foo.c9s/symlink.c9r");
Path cleartext = inTest.getPath("/foo.bar");
try (var cryptoPathMock = Mockito.mockStatic(CryptoPath.class)) {
CiphertextFilePath p = Mockito.mock(CiphertextFilePath.class);
cryptoPathMock.when(() -> CryptoPath.castAndAssertAbsolute(any())).thenReturn(cleartext);
when(cryptoPathMapper.getCiphertextFileType(any())).thenReturn(CiphertextFileType.SYMLINK);
when(cryptoPathMapper.getCiphertextFilePath(any())).thenReturn(p);
when(p.getSymlinkFilePath()).thenReturn(ciphertext);

Path result = inTest.getCiphertextPath(cleartext);
Assertions.assertEquals(ciphertext, result);
}
}

@Test
@DisplayName("Path not pointing into the vault throws exception")
public void testForeignPathThrows() throws IOException {
Path cleartext = Mockito.mock(Path.class, "/some.file");
Assertions.assertThrows(ProviderMismatchException.class, () -> inTest.getCiphertextPath(cleartext));
}

@Test
@DisplayName("Not existing resource throws NoSuchFileException")
public void testNoSuchFile() throws IOException {
Path cleartext = inTest.getPath("/i-do-not-exist");
try (var cryptoPathMock = Mockito.mockStatic(CryptoPath.class)) {
cryptoPathMock.when(() -> CryptoPath.castAndAssertAbsolute(any())).thenReturn(cleartext);
when(cryptoPathMapper.getCiphertextFileType(any())).thenThrow(new NoSuchFileException("no such file"));

Assertions.assertThrows(NoSuchFileException.class, () -> inTest.getCiphertextPath(cleartext));
}
}

@Test
@DisplayName("Relative cleartext path throws exception")
public void testRelativePathException() throws IOException {
Path cleartext = inTest.getPath("relative/path");
try (var cryptoPathMock = Mockito.mockStatic(CryptoPath.class)) {
cryptoPathMock.when(() -> CryptoPath.castAndAssertAbsolute(any())).thenThrow(new IllegalArgumentException());

Assertions.assertThrows(IllegalArgumentException.class, () -> inTest.getCiphertextPath(cleartext));
}
}
}

@Nested
public class CloseAndIsOpen {

Expand Down

0 comments on commit 1fe8036

Please sign in to comment.