Forráskód Böngészése

minor I/O improvements

Sebastian Stenzel 10 éve
szülő
commit
9433c22d7f

+ 4 - 4
main/core/src/main/java/org/cryptomator/webdav/jackrabbit/resources/EncryptedDir.java

@@ -11,6 +11,7 @@ package org.cryptomator.webdav.jackrabbit.resources;
 import java.io.IOException;
 import java.nio.channels.SeekableByteChannel;
 import java.nio.file.DirectoryStream;
+import java.nio.file.FileAlreadyExistsException;
 import java.nio.file.FileVisitResult;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -78,17 +79,16 @@ public class EncryptedDir extends AbstractEncryptedNode {
 
 	private void addMemberFile(DavResource resource, InputContext inputContext) throws DavException {
 		final Path childPath = ResourcePathUtils.getPhysicalPath(resource);
-		SeekableByteChannel channel = null;
-		try {
-			channel = Files.newByteChannel(childPath, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
+		try (final SeekableByteChannel channel = Files.newByteChannel(childPath, StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW)) {
 			cryptor.encryptFile(inputContext.getInputStream(), channel);
 		} catch (SecurityException e) {
 			throw new DavException(DavServletResponse.SC_FORBIDDEN, e);
+		} catch (FileAlreadyExistsException e) {
+			throw new DavException(DavServletResponse.SC_CONFLICT, e);
 		} catch (IOException e) {
 			LOG.error("Failed to create file.", e);
 			throw new IORuntimeException(e);
 		} finally {
-			IOUtils.closeQuietly(channel);
 			IOUtils.closeQuietly(inputContext.getInputStream());
 		}
 	}

+ 7 - 11
main/core/src/main/java/org/cryptomator/webdav/jackrabbit/resources/EncryptedFile.java

@@ -16,7 +16,6 @@ import java.nio.file.Path;
 import java.nio.file.StandardOpenOption;
 import java.nio.file.attribute.BasicFileAttributes;
 
-import org.apache.commons.io.IOUtils;
 import org.apache.jackrabbit.webdav.DavException;
 import org.apache.jackrabbit.webdav.DavResource;
 import org.apache.jackrabbit.webdav.DavResourceFactory;
@@ -70,9 +69,7 @@ public class EncryptedFile extends AbstractEncryptedNode {
 		if (Files.exists(path)) {
 			outputContext.setModificationTime(Files.getLastModifiedTime(path).toMillis());
 			outputContext.setProperty(HttpHeader.ACCEPT_RANGES.asString(), HttpHeaderValue.BYTES.asString());
-			SeekableByteChannel channel = null;
-			try {
-				channel = Files.newByteChannel(path, StandardOpenOption.READ);
+			try (final SeekableByteChannel channel = Files.newByteChannel(path, StandardOpenOption.READ)) {
 				outputContext.setContentLength(cryptor.decryptedContentLength(channel));
 				if (outputContext.hasStream()) {
 					cryptor.decryptedFile(channel, outputContext.getOutputStream());
@@ -81,8 +78,6 @@ public class EncryptedFile extends AbstractEncryptedNode {
 				LOG.warn("Unexpected end of stream (possibly client hung up).");
 			} catch (DecryptFailedException e) {
 				throw new IOException("Error decrypting file " + path.toString(), e);
-			} finally {
-				IOUtils.closeQuietly(channel);
 			}
 		}
 	}
@@ -91,12 +86,15 @@ public class EncryptedFile extends AbstractEncryptedNode {
 	protected void determineProperties() {
 		final Path path = ResourcePathUtils.getPhysicalPath(this);
 		if (Files.exists(path)) {
-			SeekableByteChannel channel = null;
-			try {
-				channel = Files.newByteChannel(path, StandardOpenOption.READ);
+			try (final SeekableByteChannel channel = Files.newByteChannel(path, StandardOpenOption.READ)) {
 				final Long contentLength = cryptor.decryptedContentLength(channel);
 				properties.add(new DefaultDavProperty<Long>(DavPropertyName.GETCONTENTLENGTH, contentLength));
+			} catch (IOException e) {
+				LOG.error("Error reading filesize " + path.toString(), e);
+				throw new IORuntimeException(e);
+			}
 
+			try {
 				final BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
 				properties.add(new DefaultDavProperty<String>(DavPropertyName.CREATIONDATE, FileTimeUtils.toRfc1123String(attrs.creationTime())));
 				properties.add(new DefaultDavProperty<String>(DavPropertyName.GETLASTMODIFIED, FileTimeUtils.toRfc1123String(attrs.lastModifiedTime())));
@@ -104,8 +102,6 @@ public class EncryptedFile extends AbstractEncryptedNode {
 			} catch (IOException e) {
 				LOG.error("Error determining metadata " + path.toString(), e);
 				throw new IORuntimeException(e);
-			} finally {
-				IOUtils.closeQuietly(channel);
 			}
 		}
 	}

+ 1 - 6
main/core/src/main/java/org/cryptomator/webdav/jackrabbit/resources/EncryptedFilePart.java

@@ -9,7 +9,6 @@ import java.nio.file.StandardOpenOption;
 import java.util.HashSet;
 import java.util.Set;
 
-import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.MutablePair;
@@ -113,9 +112,7 @@ public class EncryptedFilePart extends EncryptedFile {
 		final Path path = ResourcePathUtils.getPhysicalPath(this);
 		if (Files.exists(path)) {
 			outputContext.setModificationTime(Files.getLastModifiedTime(path).toMillis());
-			SeekableByteChannel channel = null;
-			try {
-				channel = Files.newByteChannel(path, StandardOpenOption.READ);
+			try (final SeekableByteChannel channel = Files.newByteChannel(path, StandardOpenOption.READ)) {
 				final Long fileSize = cryptor.decryptedContentLength(channel);
 				final Pair<Long, Long> range = getUnionRange(fileSize);
 				final Long rangeLength = range.getRight() - range.getLeft() + 1;
@@ -130,8 +127,6 @@ public class EncryptedFilePart extends EncryptedFile {
 				}
 			} catch (DecryptFailedException e) {
 				throw new IOException("Error decrypting file " + path.toString(), e);
-			} finally {
-				IOUtils.closeQuietly(channel);
 			}
 		}
 	}

+ 13 - 2
main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/Aes256Cryptor.java

@@ -504,9 +504,20 @@ public class Aes256Cryptor extends AbstractCryptor implements AesCryptographicCo
 		final ByteBuffer macBuffer = ByteBuffer.allocate(mac.getMacLength());
 		encryptedFile.write(macBuffer);
 
-		// init filesize buffer and skip 16 bytes
+		// write initial file size = 0 into the next 16 bytes
 		final ByteBuffer encryptedFileSizeBuffer = ByteBuffer.allocate(AES_BLOCK_LENGTH);
-		encryptedFile.write(encryptedFileSizeBuffer);
+		try {
+			final ByteBuffer fileSizeBuffer = ByteBuffer.allocate(Long.BYTES);
+			fileSizeBuffer.putLong(0l);
+			final Cipher sizeCipher = aesEcbCipher(primaryMasterKey, Cipher.ENCRYPT_MODE);
+			final byte[] encryptedFileSize = sizeCipher.doFinal(fileSizeBuffer.array());
+			encryptedFileSizeBuffer.position(0);
+			encryptedFileSizeBuffer.put(encryptedFileSize);
+			encryptedFileSizeBuffer.position(0);
+			encryptedFile.write(encryptedFileSizeBuffer);
+		} catch (IllegalBlockSizeException | BadPaddingException e) {
+			throw new IllegalStateException("Block size must be valid, as padding is requested. BadPaddingException not possible in encrypt mode.", e);
+		}
 
 		// write content:
 		final OutputStream out = new SeekableByteChannelOutputStream(encryptedFile);