diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index be005a1d7..69291355a 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,6 +34,7 @@ + 51832 - handle XLS files where the WRITEPROTECT record preceeds the FILEPASS one, rather than following as normal 51809 - correct GTE handling in COUNTIF Add HWPF API to update range text and delete bookmarks HWPF Bookmarks tables are correctly updated on text updates diff --git a/src/java/org/apache/poi/hssf/record/RecordFactoryInputStream.java b/src/java/org/apache/poi/hssf/record/RecordFactoryInputStream.java index 479169a5c..344ad07ef 100644 --- a/src/java/org/apache/poi/hssf/record/RecordFactoryInputStream.java +++ b/src/java/org/apache/poi/hssf/record/RecordFactoryInputStream.java @@ -57,11 +57,26 @@ public final class RecordFactoryInputStream { FilePassRecord fpr = null; if (rec instanceof BOFRecord) { _hasBOFRecord = true; + + // Fetch the next record, and see if it indicates whether + // the document is encrypted or not if (rs.hasNextRecord()) { rs.nextRecord(); rec = RecordFactory.createSingleRecord(rs); recSize += rec.getRecordSize(); outputRecs.add(rec); + + // Encrypted is normally BOF then FILEPASS + // May sometimes be BOF, WRITEPROTECT, FILEPASS + if (rec instanceof WriteProtectRecord && rs.hasNextRecord()) { + rs.nextRecord(); + rec = RecordFactory.createSingleRecord(rs); + recSize += rec.getRecordSize(); + outputRecs.add(rec); + } + + // If it's a FILEPASS, track it specifically but + // don't include it in the main stream if (rec instanceof FilePassRecord) { fpr = (FilePassRecord) rec; outputRecs.remove(outputRecs.size()-1); diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java b/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java index e64cd7240..12171ccb0 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java @@ -18,6 +18,8 @@ package org.apache.poi.hssf.usermodel; import junit.framework.AssertionFailedError; + +import org.apache.poi.EncryptedDocumentException; import org.apache.poi.hssf.HSSFITestDataProvider; import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.OldExcelFormatException; @@ -2179,4 +2181,16 @@ if(1==2) { writeOutAndReadBack(wb); } + /** + * Normally encrypted files have BOF then FILEPASS, but + * some may squeeze a WRITEPROTECT in the middle + */ + public void test51832() { + try { + openSample("51832.xls"); + fail("Encrypted file"); + } catch(EncryptedDocumentException e) { + // Good + } + } } diff --git a/test-data/spreadsheet/51832.xls b/test-data/spreadsheet/51832.xls new file mode 100644 index 000000000..8b38bffe8 Binary files /dev/null and b/test-data/spreadsheet/51832.xls differ