Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,7 @@ public void finish(boolean onException) {
isOutputStreamEncrypt = doOutputStreamEncrypt07();
} catch (Throwable t) {
throwable = t;
writeExcel = false;
}
}
if (!isOutputStreamEncrypt) {
Expand Down Expand Up @@ -574,6 +575,13 @@ public void finish(boolean onException) {
doFileEncrypt07();
} catch (Throwable t) {
throwable = t;
// The workbook was written to the file before encryption, so the file still holds the unprotected
// workbook and must not be left behind.
File file = writeWorkbookHolder.getFile();
if (file.exists() && !file.delete()) {
throwable =
new ExcelGenerateException("Can not delete unencrypted file: " + file.getAbsolutePath(), t);
}
}
}
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@

package org.apache.fesod.sheet.readwrite;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.nio.file.Files;
import java.util.List;
import org.apache.fesod.sheet.FesodSheet;
import org.apache.fesod.sheet.exception.ExcelGenerateException;
import org.apache.fesod.sheet.read.builder.ExcelReaderBuilder;
import org.apache.fesod.sheet.support.ExcelTypeEnum;
import org.apache.fesod.sheet.testkit.Tags;
Expand All @@ -38,9 +40,13 @@
import org.apache.fesod.sheet.testkit.listeners.CollectingReadListener;
import org.apache.fesod.sheet.testkit.models.SimpleData;
import org.apache.fesod.sheet.testkit.params.ExcelFormatSource;
import org.apache.fesod.sheet.util.FileUtils;
import org.apache.fesod.sheet.write.builder.ExcelWriterBuilder;
import org.apache.fesod.sheet.write.handler.WorkbookWriteHandler;
import org.apache.fesod.sheet.write.handler.context.WorkbookWriteHandlerContext;
import org.apache.poi.EncryptedDocumentException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
Expand Down Expand Up @@ -138,4 +144,53 @@ void xlsPasswordWrite_isActuallyEncrypted() throws Exception {
.doReadSync();
Assertions.assertEquals(10, dataList.size());
}

/**
* Verifies that when encrypting an XLSX stream write fails, nothing is written to the stream rather than
* the unencrypted workbook.
*/
@Test
void xlsxStreamPasswordWrite_encryptionFails_writesNothing() throws Exception {
// A temp directory under a regular file cannot be created, so the encryption step fails
File regularFile = createTempFile("enc-blocker", ExcelFormat.XLSX);
String originalPrefix = FileUtils.getTempFilePrefix();
FileUtils.setTempFilePrefix(regularFile.getAbsolutePath() + File.separator + "sub" + File.separator);
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
Assertions.assertThrows(ExcelGenerateException.class, () -> FesodSheet.write(out, SimpleData.class)
.excelType(ExcelTypeEnum.XLSX)
.password(PASSWORD)
.sheet()
.doWrite(TestDataBuilder.simpleData(10)));
Assertions.assertEquals(0, out.size());
} finally {
FileUtils.setTempFilePrefix(originalPrefix);
}
}

/**
* Verifies that when encrypting an XLSX file write fails, the unencrypted file is not left behind.
*/
@Test
void xlsxFilePasswordWrite_encryptionFails_leavesNoFile() throws Exception {
File file = createTempFile("enc-readonly", ExcelFormat.XLSX);
// Root ignores file permissions, so the failure forced below cannot happen
Assumptions.assumeTrue(file.setReadOnly() && !file.canWrite(), "file permissions are not enforced");
Assertions.assertTrue(file.setWritable(true));
// Once the write stream is open, making the file read-only makes the encrypt-in-place step fail
WorkbookWriteHandler makeReadOnly = new WorkbookWriteHandler() {
@Override
public void afterWorkbookDispose(WorkbookWriteHandlerContext context) {
Assertions.assertTrue(file.setReadOnly());
}
};

Assertions.assertThrows(ExcelGenerateException.class, () -> FesodSheet.write(file, SimpleData.class)
.excelType(ExcelTypeEnum.XLSX)
.password(PASSWORD)
.registerWriteHandler(makeReadOnly)
.sheet()
.doWrite(TestDataBuilder.simpleData(10)));
Assertions.assertFalse(file.exists());
}
}
Loading