Skip to content

Commit 0b82f54

Browse files
Merge branch 'release/1.7.0'
2 parents 483693e + ba27a5d commit 0b82f54

File tree

96 files changed

+2921
-2402
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

96 files changed

+2921
-2402
lines changed

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ jdk:
55
env:
66
global:
77
- secure: "LT4nMSKCu4qL+jQ80BdBIOqFO3GCyAPoxNkskS0q0wvscDpEx2bvFZa9KF6/dQxubhWnfACqWxxPKfF3VadfZoKn1z01TaZ/rKHkA5GedZweFO0wBIvi/gDIcAxVX0oPOkIruugYY3iDOzOqTUuBM686cW1XWs0LEV7qPTb6KM02/IeckQs+P9SSiarqSKROlQ8dABGdyxJTXheHHphFu4mDiQsi1vtub6OoQclKLLuK2MJvFiyDeZDYYXAnjFNC/pcBUBjr5b886zPB6HLLGgvQKRLvzQudedz08ZlJdnt3k6u7HvLINbs00U60fnD/+4krQQN4EEx0Natv4L1SxFjYO4wFK2FTCKoBMkVfjINqiWzmb/yhoG33Sw9VGiYdcV45QbH32CX1oiATohV+79gfIID6p3UOL1SZuELR2XzRq70K4Kw2BXig99a0+LjYCv4ynnzetqyWVZIdhBQ1Srf/4GxUwF21Urn9TJCNr2F5BcbqGrMUMvXNjTI0WqQCTMqM+Ha9Rbe27GG7ZMtMUHd83YWP0GDiSIg2S0T0lNL2e9iQGXsGBiX3Bz+E3HEWhnE4l6XKYVgn3NXrlDjwc2B6GTGeImZXkrbFFJwQihUSujj5H6l/+5a7NxbyA1MvzNwjeTaHzdNdYovTq6ywydVtF/Kt5h7oA2KmUoajaFs=" # CODACY_PROJECT_TOKEN
8-
- secure: "E5T75tGRnA6kplWe1/gxnvHzzZn5Z1/Wb58Th67Nm0MHmGK8PnR0tukcQbfNPsGMp3P3lb+wmTFfNeiuWXfan88F5CrktBJYJgsNQxWMnNk1fcT+QNyHlm7Xngpm/ntHGJCDGF/yFuJLvwzlD6SDSTAU709MxB60aoKVDtylGkkLhVWpNMtSNwgjRu2pzGjR8VxOWckt4zQw4mSXQfVZqHsQAPWGTGKktN08/ff71FyoO2uKffnzhLny9wjsUx7ora2/EyKDqFpkqMvOEN2njcMc6QF5M041VzoYw/gsURowImRHP385xqqg4kl45Fb7unHVv2rz1rRwSbWlJawGBRrzkLR+B1+sE2Jij0o30Wifijwh3HRtHIR7k0T7f893xN7B6du4VhKhKrYMVUn9xVILEWElkwHb50BnBP/3zTfrm38/nlW+KtY+vBSrvqbfAfaoKsJZQuNcJ8ezcvdMXVHuOWixozJpHROFvLRzMJJCB07mSNdGTgX8jI34se+299/M0sLpT5N8PQ8WJjs5h+YkK6FLL7KqEOR6QWHkgYamZirQF2dqYw1Rdw37x5Lad6Py938lBn5P5c+Gx00D43MwoN31tiTWdp/NlUyFbEPst225Fj1/VpLDnZiek+QcgAf6PzpejeKyS018EEiO10CYgb2J38nivQ6RuvU9kII=" # BINTRAY_API_KEY
8+
- secure: "atP4OKMKBLaixI1BiypWRxdQ1DJKpUcxQStwJpXteaZuXdkTMx31ts9WGhwwWJCjDaPJJRmWqhxTNKxJLThWFWLmBso1gHm8KDoHWBGM5jS1ua8Ly7s72HCpa7z+ABZ1/2LsoUXfQGLGDIPs1EdL/2E8OlaPSFUDFwgyquEIEm0hcKOO9q9MxjXwj8EO8OsfGt3PjiWEsh+JRaK5+hRPPVbG7TXidG84C/2cndzNSnin57LUSNkKDPoysRrQipGZQSLm12MpBagcota2HDdiuDXLHJLauNllCsr/NLnurGhwqeV3zVjPlN6z5TbZhbWvni+a8jVO9tMR3zCPs2MR++rJqXoQ4Gviy9yHQFc/RnVtCIRfCHhmh3XyhEM/Z5c1zEjhyZD1eGzr625/1F/RJLJEi0jb0kihKBpEKRgGw/ppt9BkdWQ4xJsMI8H9IQ5ZfzvRhLMXhbLDwqfyfyr3fX8pWg8T9lajEcDwnWMrYerAIF67lyQBjl3c3cGcGn909FTPGjum2PFSY7MuFfmbzzi41Y9ekssiRun4XrgNu563VtIywwuy/35N4ub1+oXS0I2PCG5XBY5uvxZbL8niqmoKiFFeyIhkMdGcbvIqA7PLapPqY5NxkY4+gRSP/eOMzMCnJv/No1ZaDV/8PW4/Q5IRxehVIIX/sXPiOvDSR58=" # BINTRAY_API_KEY
99
install:
1010
- curl -o $HOME/.m2/settings.xml https://gist.githubusercontent.com/cryptobot/cf5fbd909c4782aaeeeb7c7f4a1a43da/raw/e60ee486e34ee0c79f89f947abe2c83b4290c6bb/settings.xml
1111
- mvn source:help javadoc:help dependency:go-offline -Pdependency-check,coverage,release
@@ -38,4 +38,4 @@ deploy:
3838
repo: cryptomator/cryptofs
3939
tags: true
4040
after_deploy:
41-
- "echo '{\"close\": \"1\"}' | curl -v -X POST -u cryptobot:${BINTRAY_API_KEY} https://api.bintray.com/maven_central_sync/cryptomator/maven/cryptofs/versions/${TRAVIS_TAG}"
41+
- "echo '{\"close\": \"1\"}' | curl -X POST -u cryptobot:${BINTRAY_API_KEY} https://api.bintray.com/maven_central_sync/cryptomator/maven/cryptofs/versions/${TRAVIS_TAG}"

pom.xml

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<modelVersion>4.0.0</modelVersion>
33
<groupId>org.cryptomator</groupId>
44
<artifactId>cryptofs</artifactId>
5-
<version>1.6.2</version>
5+
<version>1.7.0</version>
66
<name>Cryptomator Crypto Filesystem</name>
77
<description>This library provides the Java filesystem provider used by Cryptomator.</description>
88
<url>https://github.com/cryptomator/cryptofs</url>
@@ -15,7 +15,7 @@
1515

1616
<properties>
1717
<cryptolib.version>1.2.1</cryptolib.version>
18-
<dagger.version>2.19</dagger.version>
18+
<dagger.version>2.20</dagger.version>
1919
<guava.version>27.0-jre</guava.version>
2020
<slf4j.version>1.7.25</slf4j.version>
2121
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -86,12 +86,6 @@
8686
<artifactId>dagger</artifactId>
8787
<version>${dagger.version}</version>
8888
</dependency>
89-
<dependency>
90-
<groupId>com.google.dagger</groupId>
91-
<artifactId>dagger-compiler</artifactId>
92-
<version>${dagger.version}</version>
93-
<scope>provided</scope>
94-
</dependency>
9589

9690
<!-- Test -->
9791
<dependency>
@@ -139,10 +133,15 @@
139133
<artifactId>maven-compiler-plugin</artifactId>
140134
<version>3.8.0</version>
141135
<configuration>
142-
<source>1.8</source>
143-
<target>1.8</target>
144136
<release>8</release>
145137
<showWarnings>true</showWarnings>
138+
<annotationProcessorPaths>
139+
<path>
140+
<groupId>com.google.dagger</groupId>
141+
<artifactId>dagger-compiler</artifactId>
142+
<version>${dagger.version}</version>
143+
</path>
144+
</annotationProcessorPaths>
146145
</configuration>
147146
</plugin>
148147
</plugins>
@@ -156,10 +155,13 @@
156155
<plugin>
157156
<groupId>org.owasp</groupId>
158157
<artifactId>dependency-check-maven</artifactId>
159-
<version>3.3.4</version>
158+
<version>4.0.2</version>
160159
<configuration>
161160
<cveValidForHours>24</cveValidForHours>
162161
<failBuildOnCVSS>0</failBuildOnCVSS>
162+
<skipTestScope>true</skipTestScope>
163+
<detail>true</detail>
164+
<suppressionFile>suppression.xml</suppressionFile>
163165
</configuration>
164166
<executions>
165167
<execution>
@@ -180,14 +182,20 @@
180182
<plugin>
181183
<groupId>org.jacoco</groupId>
182184
<artifactId>jacoco-maven-plugin</artifactId>
183-
<version>0.8.2</version>
185+
<version>0.8.3</version>
184186
<executions>
185187
<execution>
186188
<id>prepare-agent</id>
187189
<goals>
188190
<goal>prepare-agent</goal>
189191
</goals>
190192
</execution>
193+
<execution>
194+
<id>report</id>
195+
<goals>
196+
<goal>report</goal>
197+
</goals>
198+
</execution>
191199
</executions>
192200
</plugin>
193201
</plugins>

src/main/java/org/cryptomator/cryptofs/AbstractCryptoFileAttributeView.java

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,45 +9,51 @@
99
package org.cryptomator.cryptofs;
1010

1111
import java.io.IOException;
12+
import java.nio.file.LinkOption;
1213
import java.nio.file.Path;
13-
import java.nio.file.attribute.BasicFileAttributeView;
14-
import java.nio.file.attribute.BasicFileAttributes;
15-
import java.nio.file.attribute.FileTime;
14+
import java.nio.file.attribute.FileAttributeView;
1615
import java.util.Optional;
1716

18-
abstract class AbstractCryptoFileAttributeView<S extends BasicFileAttributes, T extends BasicFileAttributeView> implements BasicFileAttributeView {
19-
20-
protected final Path ciphertextPath;
21-
protected final CryptoFileAttributeProvider fileAttributeProvider;
22-
protected final T delegate;
23-
private final Class<S> attributesType;
24-
private final ReadonlyFlag readonlyFlag;
25-
private final Optional<OpenCryptoFile> openCryptoFile;
26-
27-
public AbstractCryptoFileAttributeView(Path ciphertextPath, CryptoFileAttributeProvider fileAttributeProvider, ReadonlyFlag readonlyFlag, Class<S> attributesType, Class<T> delegateType, Optional<OpenCryptoFile> openCryptoFile)
28-
throws UnsupportedFileAttributeViewException {
29-
this.ciphertextPath = ciphertextPath;
30-
this.fileAttributeProvider = fileAttributeProvider;
31-
this.readonlyFlag = readonlyFlag;
32-
this.attributesType = attributesType;
33-
this.openCryptoFile = openCryptoFile;
34-
this.delegate = ciphertextPath.getFileSystem().provider().getFileAttributeView(ciphertextPath, delegateType);
35-
if (delegate == null) {
36-
throw new UnsupportedFileAttributeViewException();
37-
}
17+
abstract class AbstractCryptoFileAttributeView implements FileAttributeView {
18+
19+
protected final CryptoPath cleartextPath;
20+
private final CryptoPathMapper pathMapper;
21+
protected final LinkOption[] linkOptions;
22+
private final Symlinks symlinks;
23+
private final OpenCryptoFiles openCryptoFiles;
24+
25+
public AbstractCryptoFileAttributeView(CryptoPath cleartextPath, CryptoPathMapper pathMapper, LinkOption[] linkOptions, Symlinks symlinks, OpenCryptoFiles openCryptoFiles) {
26+
this.cleartextPath = cleartextPath;
27+
this.pathMapper = pathMapper;
28+
this.linkOptions = linkOptions;
29+
this.symlinks = symlinks;
30+
this.openCryptoFiles = openCryptoFiles;
31+
}
32+
33+
protected <T extends FileAttributeView> T getCiphertextAttributeView(Class<T> delegateType) throws IOException {
34+
Path ciphertextPath = getCiphertextPath(cleartextPath);
35+
return ciphertextPath.getFileSystem().provider().getFileAttributeView(ciphertextPath, delegateType);
3836
}
3937

40-
@Override
41-
public final S readAttributes() throws IOException {
42-
return fileAttributeProvider.readAttributes(ciphertextPath, attributesType);
38+
protected Optional<OpenCryptoFile> getOpenCryptoFile() throws IOException {
39+
Path ciphertextPath = getCiphertextPath(cleartextPath);
40+
return openCryptoFiles.get(ciphertextPath);
4341
}
4442

45-
@Override
46-
public void setTimes(FileTime lastModifiedTime, FileTime lastAccessTime, FileTime createTime) throws IOException {
47-
readonlyFlag.assertWritable();
48-
delegate.setTimes(lastModifiedTime, lastAccessTime, createTime);
49-
if(lastModifiedTime != null){
50-
openCryptoFile.ifPresent(file -> file.setLastModifiedTime(lastModifiedTime));
43+
private Path getCiphertextPath(CryptoPath path) throws IOException {
44+
CryptoPathMapper.CiphertextFileType type = pathMapper.getCiphertextFileType(path);
45+
switch (type) {
46+
case SYMLINK:
47+
if (ArrayUtils.contains(linkOptions, LinkOption.NOFOLLOW_LINKS)) {
48+
return pathMapper.getCiphertextFilePath(path, type);
49+
} else {
50+
CryptoPath resolved = symlinks.resolveRecursively(path);
51+
return getCiphertextPath(resolved);
52+
}
53+
case DIRECTORY:
54+
return pathMapper.getCiphertextDirPath(path);
55+
default:
56+
return pathMapper.getCiphertextFilePath(path, type);
5157
}
5258
}
5359

src/main/java/org/cryptomator/cryptofs/ArrayUtils.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.util.Arrays;
44
import java.util.Objects;
5+
import java.util.stream.Stream;
56

67
/**
78
* Functions used from commons-lang
@@ -12,4 +13,16 @@ public static boolean contains(Object[] array, Object objectToFind) {
1213
return Arrays.stream(Objects.requireNonNull(array)).anyMatch(Objects.requireNonNull(objectToFind)::equals);
1314
}
1415

16+
public static <S, T extends S> Stream<T> filterByType(S[] array, Class<T> type) {
17+
return Arrays.stream(array).filter(type::isInstance).map(type::cast);
18+
}
19+
20+
public static <T> Stream<T> without(T[] array, T obj) {
21+
return Arrays.stream(array).filter(x -> !obj.equals(x));
22+
}
23+
24+
public static <T> Stream<T> with(T[] array, T obj) {
25+
return Stream.concat(Arrays.stream(array), Stream.of(obj));
26+
}
27+
1528
}

src/main/java/org/cryptomator/cryptofs/ChunkCache.java

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,52 @@
11
package org.cryptomator.cryptofs;
22

3-
import java.io.IOException;
4-
import java.util.concurrent.ExecutionException;
5-
6-
import javax.inject.Inject;
7-
8-
import org.cryptomator.cryptolib.api.AuthenticationFailedException;
9-
103
import com.google.common.cache.CacheBuilder;
114
import com.google.common.cache.CacheLoader;
125
import com.google.common.cache.LoadingCache;
6+
import com.google.common.cache.RemovalNotification;
137
import com.google.common.util.concurrent.UncheckedExecutionException;
8+
import org.cryptomator.cryptolib.api.AuthenticationFailedException;
9+
10+
import javax.inject.Inject;
11+
import java.io.IOException;
12+
import java.io.UncheckedIOException;
13+
import java.util.concurrent.ExecutionException;
1414

1515
@PerOpenFile
1616
class ChunkCache {
1717

1818
public static final int MAX_CACHED_CLEARTEXT_CHUNKS = 5;
1919

20+
private final ChunkLoader chunkLoader;
21+
private final ChunkSaver chunkSaver;
2022
private final CryptoFileSystemStats stats;
2123
private final LoadingCache<Long, ChunkData> chunks;
2224

2325
@Inject
2426
public ChunkCache(ChunkLoader chunkLoader, ChunkSaver chunkSaver, CryptoFileSystemStats stats) {
27+
this.chunkLoader = chunkLoader;
28+
this.chunkSaver = chunkSaver;
2529
this.stats = stats;
2630
this.chunks = CacheBuilder.newBuilder() //
2731
.maximumSize(MAX_CACHED_CLEARTEXT_CHUNKS) //
28-
.removalListener(removal -> chunkSaver.save((Long) removal.getKey(), (ChunkData) removal.getValue())) //
29-
.build(new CacheLoader<Long, ChunkData>() {
30-
@Override
31-
public ChunkData load(Long key) throws IOException {
32-
return chunkLoader.load(key);
33-
}
34-
});
32+
.removalListener(this::removeChunk) //
33+
.build(CacheLoader.from(this::loadChunk));
34+
}
35+
36+
private ChunkData loadChunk(Long chunkIndex) {
37+
try {
38+
return chunkLoader.load(chunkIndex);
39+
} catch (IOException e) {
40+
throw new UncheckedIOException(e);
41+
}
42+
}
43+
44+
private void removeChunk(RemovalNotification<Long, ChunkData> removal) {
45+
try {
46+
chunkSaver.save(removal.getKey(), removal.getValue());
47+
} catch (IOException e) {
48+
throw new UncheckedIOException(e);
49+
}
3550
}
3651

3752
public ChunkData get(long chunkIndex) throws IOException {
@@ -42,11 +57,15 @@ public ChunkData get(long chunkIndex) throws IOException {
4257
assert e.getCause() != null; // no exception in ChunkLoader -> no executionException during chunk loading ;-)
4358
throw (IOException) e.getCause();
4459
} catch (UncheckedExecutionException e) {
45-
if (e.getCause() instanceof AuthenticationFailedException) {
60+
if (e.getCause() instanceof UncheckedIOException) {
61+
UncheckedIOException uioe = (UncheckedIOException) e.getCause();
62+
throw uioe.getCause();
63+
} else if (e.getCause() instanceof AuthenticationFailedException) {
4664
// TODO provide means to pass an AuthenticationFailedException handler using an OpenOption
4765
throw new IOException(e.getCause());
66+
} else {
67+
throw e;
4868
}
49-
throw e;
5069
}
5170
}
5271

src/main/java/org/cryptomator/cryptofs/ChunkLoader.java

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,25 @@
11
package org.cryptomator.cryptofs;
22

3+
import org.cryptomator.cryptolib.api.Cryptor;
4+
5+
import javax.inject.Inject;
36
import java.io.IOException;
47
import java.nio.ByteBuffer;
58
import java.nio.channels.FileChannel;
69

7-
import javax.inject.Inject;
8-
9-
import org.cryptomator.cryptolib.api.Cryptor;
10-
import org.cryptomator.cryptolib.api.FileHeader;
11-
1210
@PerOpenFile
1311
class ChunkLoader {
1412

1513
private final Cryptor cryptor;
1614
private final FileChannel channel;
17-
private final FileHeader header;
15+
private final FileHeaderLoader headerLoader;
1816
private final CryptoFileSystemStats stats;
1917

2018
@Inject
21-
public ChunkLoader(Cryptor cryptor, FileChannel channel, FileHeader header, CryptoFileSystemStats stats) {
19+
public ChunkLoader(Cryptor cryptor, FileChannel channel, FileHeaderLoader headerLoader, CryptoFileSystemStats stats) {
2220
this.cryptor = cryptor;
2321
this.channel = channel;
24-
this.header = header;
22+
this.headerLoader = headerLoader;
2523
this.stats = stats;
2624
}
2725

@@ -37,7 +35,7 @@ public ChunkData load(Long chunkIndex) throws IOException {
3735
return ChunkData.emptyWithSize(payloadSize);
3836
} else {
3937
ciphertextBuf.flip();
40-
ByteBuffer cleartextBuf = cryptor.fileContentCryptor().decryptChunk(ciphertextBuf, chunkIndex, header, true);
38+
ByteBuffer cleartextBuf = cryptor.fileContentCryptor().decryptChunk(ciphertextBuf, chunkIndex, headerLoader.get(), true);
4139
stats.addBytesDecrypted(cleartextBuf.remaining());
4240
ByteBuffer cleartextBufWhichCanHoldFullChunk;
4341
if (cleartextBuf.capacity() < payloadSize) {

src/main/java/org/cryptomator/cryptofs/ChunkSaver.java

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,39 @@
11
package org.cryptomator.cryptofs;
22

3+
import org.cryptomator.cryptolib.api.Cryptor;
4+
5+
import javax.inject.Inject;
36
import java.io.IOException;
47
import java.nio.ByteBuffer;
58
import java.nio.channels.FileChannel;
69
import java.util.concurrent.atomic.AtomicLong;
710

8-
import javax.inject.Inject;
9-
10-
import org.cryptomator.cryptolib.api.Cryptor;
11-
import org.cryptomator.cryptolib.api.FileHeader;
12-
1311
@PerOpenFile
1412
class ChunkSaver {
1513

1614
private final Cryptor cryptor;
1715
private final FileChannel channel;
18-
private final FileHeader header;
16+
private final FileHeaderLoader headerLoader;
1917
private final ExceptionsDuringWrite exceptionsDuringWrite;
2018
private final AtomicLong size;
2119
private final CryptoFileSystemStats stats;
2220

2321
@Inject
24-
public ChunkSaver(Cryptor cryptor, FileChannel channel, FileHeader header, ExceptionsDuringWrite exceptionsDuringWrite, @OpenFileSize AtomicLong size, CryptoFileSystemStats stats) {
22+
public ChunkSaver(Cryptor cryptor, FileChannel channel, FileHeaderLoader headerLoader, ExceptionsDuringWrite exceptionsDuringWrite, @OpenFileSize AtomicLong size, CryptoFileSystemStats stats) {
2523
this.cryptor = cryptor;
2624
this.channel = channel;
27-
this.header = header;
25+
this.headerLoader = headerLoader;
2826
this.exceptionsDuringWrite = exceptionsDuringWrite;
2927
this.size = size;
3028
this.stats = stats;
3129
}
3230

33-
public void save(long chunkIndex, ChunkData chunkData) {
31+
public void save(long chunkIndex, ChunkData chunkData) throws IOException {
3432
if (chunkLiesInFile(chunkIndex) && chunkData.wasWritten()) {
3533
long ciphertextPos = chunkIndex * cryptor.fileContentCryptor().ciphertextChunkSize() + cryptor.fileHeaderCryptor().headerSize();
3634
ByteBuffer cleartextBuf = chunkData.asReadOnlyBuffer();
3735
stats.addBytesEncrypted(cleartextBuf.remaining());
38-
ByteBuffer ciphertextBuf = cryptor.fileContentCryptor().encryptChunk(cleartextBuf, chunkIndex, header);
36+
ByteBuffer ciphertextBuf = cryptor.fileContentCryptor().encryptChunk(cleartextBuf, chunkIndex, headerLoader.get());
3937
try {
4038
channel.write(ciphertextBuf, ciphertextPos);
4139
} catch (IOException e) {

0 commit comments

Comments
 (0)