mirror of
https://github.com/apache/poi.git
synced 2026-02-27 12:30:08 +08:00
Compare commits
4 Commits
c7976440c3
...
ac4e3c199e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac4e3c199e | ||
|
|
a1f6f2786f | ||
|
|
b923655b43 | ||
|
|
6b72a2dff3 |
@ -47,7 +47,7 @@ public class HSSFEventFactory {
|
||||
/**
|
||||
* Processes a file into essentially record events.
|
||||
*
|
||||
* @param req an Instance of HSSFRequest which has your registered listeners
|
||||
* @param req an instance of HSSFRequest which has your registered listeners
|
||||
* @param fs a POIFS filesystem containing your workbook
|
||||
*
|
||||
* @throws IOException if the workbook contained errors
|
||||
@ -59,12 +59,42 @@ public class HSSFEventFactory {
|
||||
/**
|
||||
* Processes a file into essentially record events.
|
||||
*
|
||||
* @param req an Instance of HSSFRequest which has your registered listeners
|
||||
* @param req an instance of HSSFRequest which has your registered listeners
|
||||
* @param fs a POIFS filesystem containing your workbook
|
||||
* @param password in char array format (can be null)
|
||||
*
|
||||
* @throws IOException if the workbook contained errors
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public void processWorkbookEvents(HSSFRequest req, POIFSFileSystem fs,
|
||||
final char[] password) throws IOException {
|
||||
processWorkbookEvents(req, fs.getRoot(), password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a file into essentially record events.
|
||||
*
|
||||
* @param req an instance of HSSFRequest which has your registered listeners
|
||||
* @param dir a DirectoryNode containing your workbook
|
||||
*
|
||||
* @throws IOException if the workbook contained errors
|
||||
*/
|
||||
public void processWorkbookEvents(HSSFRequest req, DirectoryNode dir) throws IOException {
|
||||
processWorkbookEvents(req, dir, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a file into essentially record events.
|
||||
*
|
||||
* @param req an instance of HSSFRequest which has your registered listeners
|
||||
* @param dir a DirectoryNode containing your workbook
|
||||
* @param password in char array format (can be null)
|
||||
*
|
||||
* @throws IOException if the workbook contained errors
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public void processWorkbookEvents(HSSFRequest req, DirectoryNode dir,
|
||||
final char[] password) throws IOException {
|
||||
// some old documents have "WORKBOOK" or "BOOK"
|
||||
String name = null;
|
||||
if (dir.hasEntry(WORKBOOK)) {
|
||||
@ -79,17 +109,16 @@ public class HSSFEventFactory {
|
||||
}
|
||||
|
||||
try (InputStream in = dir.createDocumentInputStream(name)) {
|
||||
processEvents(req, in);
|
||||
processEvents(req, in, password);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a file into essentially record events.
|
||||
*
|
||||
* @param req an Instance of HSSFRequest which has your registered listeners
|
||||
* @param req an instance of HSSFRequest which has your registered listeners
|
||||
* @param fs a POIFS filesystem containing your workbook
|
||||
* @return numeric user-specified result code.
|
||||
*
|
||||
* @throws HSSFUserException if the processing should be aborted
|
||||
* @throws IOException if the workbook contained errors
|
||||
*/
|
||||
@ -101,7 +130,24 @@ public class HSSFEventFactory {
|
||||
/**
|
||||
* Processes a file into essentially record events.
|
||||
*
|
||||
* @param req an Instance of HSSFRequest which has your registered listeners
|
||||
* @param req an instance of HSSFRequest which has your registered listeners
|
||||
* @param fs a POIFS filesystem containing your workbook
|
||||
* @param password in char array format (can be null)
|
||||
* @return numeric user-specified result code.
|
||||
* @throws HSSFUserException if the processing should be aborted
|
||||
* @throws IOException if the workbook contained errors
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public short abortableProcessWorkbookEvents(HSSFRequest req, POIFSFileSystem fs,
|
||||
final char[] password)
|
||||
throws IOException, HSSFUserException {
|
||||
return abortableProcessWorkbookEvents(req, fs.getRoot(), password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a file into essentially record events.
|
||||
*
|
||||
* @param req an instance of HSSFRequest which has your registered listeners
|
||||
* @param dir a DirectoryNode containing your workbook
|
||||
* @return numeric user-specified result code.
|
||||
*
|
||||
@ -115,6 +161,26 @@ public class HSSFEventFactory {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a file into essentially record events.
|
||||
*
|
||||
* @param req an instance of HSSFRequest which has your registered listeners
|
||||
* @param dir a DirectoryNode containing your workbook
|
||||
* @param password in char array format (can be null)
|
||||
* @return numeric user-specified result code.
|
||||
*
|
||||
* @throws HSSFUserException if the processing should be aborted
|
||||
* @throws IOException if the workbook contained errors
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public short abortableProcessWorkbookEvents(HSSFRequest req, DirectoryNode dir,
|
||||
final char[] password)
|
||||
throws IOException, HSSFUserException {
|
||||
try (InputStream in = dir.createDocumentInputStream("Workbook")) {
|
||||
return abortableProcessEvents(req, in, password);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a DocumentInputStream into essentially Record events.
|
||||
*
|
||||
@ -123,23 +189,43 @@ public class HSSFEventFactory {
|
||||
* user code or <code>HSSFUserException</code> will be passed back.
|
||||
*
|
||||
* @see org.apache.poi.poifs.filesystem.POIFSFileSystem#createDocumentInputStream(String)
|
||||
* @param req an Instance of HSSFRequest which has your registered listeners
|
||||
* @param req an instance of HSSFRequest which has your registered listeners
|
||||
* @param in a DocumentInputStream obtained from POIFS's POIFSFileSystem object
|
||||
*/
|
||||
public void processEvents(HSSFRequest req, InputStream in) {
|
||||
try {
|
||||
genericProcessEvents(req, in);
|
||||
genericProcessEvents(req, in, null);
|
||||
} catch (HSSFUserException hue) {
|
||||
/*If an HSSFUserException user exception is thrown, ignore it.*/
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a DocumentInputStream into essentially Record events.
|
||||
*
|
||||
* If an <code>AbortableHSSFListener</code> causes a halt to processing during this call
|
||||
* the method will return just as with <code>abortableProcessEvents</code>, but no
|
||||
* user code or <code>HSSFUserException</code> will be passed back.
|
||||
*
|
||||
* @see org.apache.poi.poifs.filesystem.POIFSFileSystem#createDocumentInputStream(String)
|
||||
* @param req an instance of HSSFRequest which has your registered listeners
|
||||
* @param in a DocumentInputStream obtained from POIFS's POIFSFileSystem object
|
||||
* @param password in char array format (can be null)
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public void processEvents(HSSFRequest req, InputStream in, final char[] password) {
|
||||
try {
|
||||
genericProcessEvents(req, in, password);
|
||||
} catch (HSSFUserException hue) {
|
||||
/*If an HSSFUserException user exception is thrown, ignore it.*/
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a DocumentInputStream into essentially Record events.
|
||||
*
|
||||
* @see org.apache.poi.poifs.filesystem.POIFSFileSystem#createDocumentInputStream(String)
|
||||
* @param req an Instance of HSSFRequest which has your registered listeners
|
||||
* @param req an instance of HSSFRequest which has your registered listeners
|
||||
* @param in a DocumentInputStream obtained from POIFS's POIFSFileSystem object
|
||||
* @return numeric user-specified result code.
|
||||
*
|
||||
@ -147,23 +233,41 @@ public class HSSFEventFactory {
|
||||
*/
|
||||
public short abortableProcessEvents(HSSFRequest req, InputStream in)
|
||||
throws HSSFUserException {
|
||||
return genericProcessEvents(req, in);
|
||||
return genericProcessEvents(req, in, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a DocumentInputStream into essentially Record events.
|
||||
*
|
||||
* @see org.apache.poi.poifs.filesystem.POIFSFileSystem#createDocumentInputStream(String)
|
||||
* @param req an Instance of HSSFRequest which has your registered listeners
|
||||
* @param req an instance of HSSFRequest which has your registered listeners
|
||||
* @param in a DocumentInputStream obtained from POIFS's POIFSFileSystem object
|
||||
* @param password in char array format (can be null)
|
||||
* @return numeric user-specified result code.
|
||||
*
|
||||
* @throws HSSFUserException if the processing should be aborted
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public short abortableProcessEvents(HSSFRequest req, InputStream in, final char[] password)
|
||||
throws HSSFUserException {
|
||||
return genericProcessEvents(req, in, password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a DocumentInputStream into essentially Record events.
|
||||
*
|
||||
* @see org.apache.poi.poifs.filesystem.POIFSFileSystem#createDocumentInputStream(String)
|
||||
* @param req an instance of HSSFRequest which has your registered listeners
|
||||
* @param in a DocumentInputStream obtained from POIFS's POIFSFileSystem object
|
||||
* @return numeric user-specified result code.
|
||||
*/
|
||||
private short genericProcessEvents(HSSFRequest req, InputStream in)
|
||||
private short genericProcessEvents(HSSFRequest req, InputStream in, final char[] password)
|
||||
throws HSSFUserException {
|
||||
short userCode = 0;
|
||||
|
||||
// Create a new RecordStream and use that
|
||||
RecordFactoryInputStream recordStream = new RecordFactoryInputStream(in, false);
|
||||
RecordFactoryInputStream recordStream = new RecordFactoryInputStream(
|
||||
in, false, password);
|
||||
|
||||
// Process each record as they come in
|
||||
while(true) {
|
||||
|
||||
@ -119,10 +119,8 @@ public final class RecordFactoryInputStream {
|
||||
return createDecryptingStream(original, pwdString);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public RecordInputStream createDecryptingStream(InputStream original, String password) {
|
||||
// keep this private because with new API methods, we want to encourage use of char array for passwords
|
||||
private RecordInputStream createDecryptingStream(InputStream original, String password) {
|
||||
if (password == null) {
|
||||
password = Biff8EncryptionKey.getCurrentUserPassword();
|
||||
if (password == null) {
|
||||
|
||||
@ -259,7 +259,7 @@ public final class DocumentInputStream extends InputStream implements LittleEndi
|
||||
return _current_offset == _document_size;
|
||||
}
|
||||
|
||||
private void checkAvaliable(int requestedSize) {
|
||||
private void checkAvailable(int requestedSize) {
|
||||
if (_closed) {
|
||||
throw new IllegalStateException("cannot perform requested operation on a closed stream");
|
||||
}
|
||||
@ -280,7 +280,7 @@ public final class DocumentInputStream extends InputStream implements LittleEndi
|
||||
throw new IllegalArgumentException("Can't read negative number of bytes, but had: " + len);
|
||||
}
|
||||
|
||||
checkAvaliable(len);
|
||||
checkAvailable(len);
|
||||
|
||||
int read = 0;
|
||||
while(read < len) {
|
||||
@ -314,7 +314,7 @@ public final class DocumentInputStream extends InputStream implements LittleEndi
|
||||
|
||||
@Override
|
||||
public long readLong() {
|
||||
checkAvaliable(LONG_SIZE);
|
||||
checkAvailable(LONG_SIZE);
|
||||
byte[] data = new byte[LONG_SIZE];
|
||||
readFully(data, 0, LONG_SIZE);
|
||||
return LittleEndian.getLong(data, 0);
|
||||
@ -322,7 +322,7 @@ public final class DocumentInputStream extends InputStream implements LittleEndi
|
||||
|
||||
@Override
|
||||
public short readShort() {
|
||||
checkAvaliable(SHORT_SIZE);
|
||||
checkAvailable(SHORT_SIZE);
|
||||
byte[] data = new byte[SHORT_SIZE];
|
||||
readFully(data, 0, SHORT_SIZE);
|
||||
return LittleEndian.getShort(data);
|
||||
@ -330,7 +330,7 @@ public final class DocumentInputStream extends InputStream implements LittleEndi
|
||||
|
||||
@Override
|
||||
public int readInt() {
|
||||
checkAvaliable(INT_SIZE);
|
||||
checkAvailable(INT_SIZE);
|
||||
byte[] data = new byte[INT_SIZE];
|
||||
readFully(data, 0, INT_SIZE);
|
||||
return LittleEndian.getInt(data);
|
||||
@ -343,7 +343,7 @@ public final class DocumentInputStream extends InputStream implements LittleEndi
|
||||
|
||||
@Override
|
||||
public int readUShort() {
|
||||
checkAvaliable(SHORT_SIZE);
|
||||
checkAvailable(SHORT_SIZE);
|
||||
byte[] data = new byte[SHORT_SIZE];
|
||||
readFully(data, 0, SHORT_SIZE);
|
||||
return LittleEndian.getUShort(data);
|
||||
@ -351,7 +351,7 @@ public final class DocumentInputStream extends InputStream implements LittleEndi
|
||||
|
||||
@Override
|
||||
public int readUByte() {
|
||||
checkAvaliable(1);
|
||||
checkAvailable(1);
|
||||
byte[] data = new byte[1];
|
||||
readFully(data, 0, 1);
|
||||
if (data[0] >= 0)
|
||||
|
||||
@ -17,12 +17,6 @@
|
||||
|
||||
package org.apache.poi.hssf.eventusermodel;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
@ -43,14 +37,15 @@ import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* Testing for {@link HSSFEventFactory}
|
||||
*/
|
||||
final class TestHSSFEventFactory {
|
||||
private final List<org.apache.poi.hssf.record.Record> records = new ArrayList<>();
|
||||
|
||||
private void openSample(String sampleFileName) throws IOException {
|
||||
records.clear();
|
||||
private List<org.apache.poi.hssf.record.Record> openSample(String sampleFileName) throws IOException {
|
||||
final List<org.apache.poi.hssf.record.Record> records = new ArrayList<>();
|
||||
HSSFRequest req = new HSSFRequest();
|
||||
req.addListenerForAllRecords(records::add);
|
||||
try (InputStream is = HSSFTestDataSamples.openSampleFileStream(sampleFileName);
|
||||
@ -58,12 +53,26 @@ final class TestHSSFEventFactory {
|
||||
HSSFEventFactory factory = new HSSFEventFactory();
|
||||
factory.processWorkbookEvents(req, fs);
|
||||
}
|
||||
return records;
|
||||
}
|
||||
|
||||
private List<org.apache.poi.hssf.record.Record> openSample(
|
||||
String sampleFileName, String password) throws IOException {
|
||||
final List<org.apache.poi.hssf.record.Record> records = new ArrayList<>();
|
||||
HSSFRequest req = new HSSFRequest();
|
||||
req.addListenerForAllRecords(records::add);
|
||||
try (InputStream is = HSSFTestDataSamples.openSampleFileStream(sampleFileName);
|
||||
POIFSFileSystem fs = new POIFSFileSystem(is)) {
|
||||
HSSFEventFactory factory = new HSSFEventFactory();
|
||||
factory.processWorkbookEvents(req, fs, password.toCharArray());
|
||||
}
|
||||
return records;
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithMissingRecords() throws Exception {
|
||||
|
||||
openSample("SimpleWithSkip.xls");
|
||||
final List<org.apache.poi.hssf.record.Record> records = openSample("SimpleWithSkip.xls");
|
||||
|
||||
int numRec = records.size();
|
||||
|
||||
@ -82,6 +91,7 @@ final class TestHSSFEventFactory {
|
||||
// Some files have crazy ordering of their continue records
|
||||
// Check that we don't break on them (bug #42844)
|
||||
|
||||
final List<org.apache.poi.hssf.record.Record> records =
|
||||
openSample("ContinueRecordProblem.xls");
|
||||
|
||||
int numRec = records.size();
|
||||
@ -106,14 +116,14 @@ final class TestHSSFEventFactory {
|
||||
@Test
|
||||
@SuppressWarnings("java:S2699")
|
||||
void testUnknownContinueRecords() throws Exception {
|
||||
openSample("42844.xls");
|
||||
assertNotNull(openSample("42844.xls"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("java:S2699")
|
||||
void testWithDifferentWorkbookName() throws Exception {
|
||||
openSample("BOOK_in_capitals.xls");
|
||||
openSample("WORKBOOK_in_capitals.xls");
|
||||
assertNotNull(openSample("BOOK_in_capitals.xls"));
|
||||
assertNotNull(openSample("WORKBOOK_in_capitals.xls"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -125,9 +135,49 @@ final class TestHSSFEventFactory {
|
||||
|
||||
@Test
|
||||
void testWithPasswordProtectedWorkbooks() throws Exception {
|
||||
final List<org.apache.poi.hssf.record.Record> records =
|
||||
openSample("xor-encryption-abc.xls", "abc");
|
||||
|
||||
// Check we got the sheet and the contents
|
||||
assertTrue(records.size() > 50);
|
||||
|
||||
// Has one sheet, with values 1,2,3 in column A rows 1-3
|
||||
boolean hasSheet = false, hasA1 = false, hasA2 = false, hasA3 = false;
|
||||
for (org.apache.poi.hssf.record.Record r : records) {
|
||||
if (r instanceof BoundSheetRecord) {
|
||||
BoundSheetRecord bsr = (BoundSheetRecord) r;
|
||||
assertEquals("Sheet1", bsr.getSheetname());
|
||||
hasSheet = true;
|
||||
}
|
||||
if (r instanceof NumberRecord) {
|
||||
NumberRecord nr = (NumberRecord) r;
|
||||
if (nr.getColumn() == 0 && nr.getRow() == 0) {
|
||||
assertEquals(1, (int) nr.getValue());
|
||||
hasA1 = true;
|
||||
}
|
||||
if (nr.getColumn() == 0 && nr.getRow() == 1) {
|
||||
assertEquals(2, (int) nr.getValue());
|
||||
hasA2 = true;
|
||||
}
|
||||
if (nr.getColumn() == 0 && nr.getRow() == 2) {
|
||||
assertEquals(3, (int) nr.getValue());
|
||||
hasA3 = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assertTrue(hasSheet, "Sheet record not found");
|
||||
assertTrue(hasA1, "Numeric record for A1 not found");
|
||||
assertTrue(hasA2, "Numeric record for A2 not found");
|
||||
assertTrue(hasA3, "Numeric record for A3 not found");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithPasswordProtectedWorkbooksBiff8EncryptionKey() throws Exception {
|
||||
// With the password, is properly processed
|
||||
Biff8EncryptionKey.setCurrentUserPassword("abc");
|
||||
try {
|
||||
final List<org.apache.poi.hssf.record.Record> records =
|
||||
openSample("xor-encryption-abc.xls");
|
||||
|
||||
// Check we got the sheet and the contents
|
||||
|
||||
@ -73,6 +73,18 @@ class TestXorEncryption {
|
||||
|
||||
@Test
|
||||
void testUserFile() throws IOException {
|
||||
File f = getSampleFile("xor-encryption-abc.xls");
|
||||
try (POIFSFileSystem fs = new POIFSFileSystem(f, true);
|
||||
HSSFWorkbook hwb = new HSSFWorkbook(fs.getRoot(), true, "abc".toCharArray())) {
|
||||
HSSFSheet sh = hwb.getSheetAt(0);
|
||||
assertEquals(1.0, sh.getRow(0).getCell(0).getNumericCellValue(), 0.0);
|
||||
assertEquals(2.0, sh.getRow(1).getCell(0).getNumericCellValue(), 0.0);
|
||||
assertEquals(3.0, sh.getRow(2).getCell(0).getNumericCellValue(), 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUserFileBiff8EncryptionKey() throws IOException {
|
||||
File f = getSampleFile("xor-encryption-abc.xls");
|
||||
Biff8EncryptionKey.setCurrentUserPassword("abc");
|
||||
try (POIFSFileSystem fs = new POIFSFileSystem(f, true);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user