From 206ca69e804ce76a03ca1689ffe05f51ce760a4c Mon Sep 17 00:00:00 2001 From: Tim Allison Date: Mon, 20 Mar 2017 18:50:25 +0000 Subject: [PATCH] 60879 -- figure out if we can support old beta xlsb or throw exception. For now, let's hope there's only one diff and/or the other bounds checking etc will throw exception if there are other problems. git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1787832 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/stress/XSSFBFileHandler.java | 7 +-- .../poi/xssf/binary/XSSFBRecordType.java | 4 ++ .../poi/xssf/eventusermodel/XSSFBReader.java | 50 +++++++++++++++++-- .../TestXSSFBEventBasedExcelExtractor.java | 9 ++++ 4 files changed, 62 insertions(+), 8 deletions(-) diff --git a/src/integrationtest/org/apache/poi/stress/XSSFBFileHandler.java b/src/integrationtest/org/apache/poi/stress/XSSFBFileHandler.java index 52691de9a0..02c5193d40 100644 --- a/src/integrationtest/org/apache/poi/stress/XSSFBFileHandler.java +++ b/src/integrationtest/org/apache/poi/stress/XSSFBFileHandler.java @@ -32,11 +32,8 @@ import org.apache.poi.xssf.usermodel.XSSFWorkbook; public class XSSFBFileHandler extends AbstractFileHandler { static { - //this is a "Beta" xlsb version and is not openable with Excel 2016 - //TODO: see if we can support this easily enough - AbstractFileHandler.EXPECTED_EXTRACTOR_FAILURES.add( - "spreadsheet/Simple.xlsb" - ); + //add expected failures here: +// AbstractFileHandler.EXPECTED_EXTRACTOR_FAILURES.add("spreadsheet/Simple.xlsb"); } @Override diff --git a/src/ooxml/java/org/apache/poi/xssf/binary/XSSFBRecordType.java b/src/ooxml/java/org/apache/poi/xssf/binary/XSSFBRecordType.java index 436dee986f..3546504306 100644 --- a/src/ooxml/java/org/apache/poi/xssf/binary/XSSFBRecordType.java +++ b/src/ooxml/java/org/apache/poi/xssf/binary/XSSFBRecordType.java @@ -73,6 +73,10 @@ public enum XSSFBRecordType { BrtEndSst(160), //stored strings end sst BrtBundleSh(156), //defines worksheet in wb part + + //TODO -- implement these as needed + //BrtFileVersion(128), //file version + //BrtWbProp(153), //Workbook prop contains 1904/1900-date based bit Unimplemented(-1); private static final Map TYPE_MAP = diff --git a/src/ooxml/java/org/apache/poi/xssf/eventusermodel/XSSFBReader.java b/src/ooxml/java/org/apache/poi/xssf/eventusermodel/XSSFBReader.java index cd8a208455..825422936e 100644 --- a/src/ooxml/java/org/apache/poi/xssf/eventusermodel/XSSFBReader.java +++ b/src/ooxml/java/org/apache/poi/xssf/eventusermodel/XSSFBReader.java @@ -32,6 +32,8 @@ import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; import org.apache.poi.openxml4j.opc.PackagingURIHelper; import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; import org.apache.poi.xssf.binary.XSSFBCommentsTable; import org.apache.poi.xssf.binary.XSSFBParseException; import org.apache.poi.xssf.binary.XSSFBParser; @@ -48,6 +50,9 @@ import org.apache.poi.xssf.usermodel.XSSFRelation; * @since 3.16-beta3 */ public class XSSFBReader extends XSSFReader { + + private final static POILogger log = POILogFactory.getLogger(XSSFBReader.class); + /** * Creates a new XSSFReader, for the given package * @@ -147,6 +152,23 @@ public class XSSFBReader extends XSSFReader { } private void addWorksheet(byte[] data) { + //try to parse the BrtBundleSh + //if there's an exception, catch it and + //try to figure out if this is one of the old beta-created xlsb files + //or if this is a general exception + try { + tryToAddWorksheet(data); + } catch (XSSFBParseException e) { + if (tryOldFormat(data)) { + log.log(POILogger.WARN, "This file was written with a beta version of Excel. "+ + "POI will try to parse the file as a regular xlsb."); + } else { + throw e; + } + } + } + + private void tryToAddWorksheet(byte[] data) throws XSSFBParseException { int offset = 0; //this is the sheet state #2.5.142 long hsShtat = LittleEndian.getUInt(data, offset); offset += LittleEndian.INT_SIZE; @@ -158,15 +180,37 @@ public class XSSFBReader extends XSSFReader { } StringBuilder sb = new StringBuilder(); offset += XSSFBUtils.readXLWideString(data, offset, sb); - String relId = sb.toString(); - sb.setLength(0); - XSSFBUtils.readXLWideString(data, offset, sb); + String relId = sb.toString(); sb.setLength(0); + offset += XSSFBUtils.readXLWideString(data, offset, sb); String name = sb.toString(); if (relId != null && relId.trim().length() > 0) { sheets.add(new XSSFSheetRef(relId, name)); } } + private boolean tryOldFormat(byte[] data) throws XSSFBParseException { + //undocumented what is contained in these 8 bytes. + //for the non-beta xlsb files, this would be 4, not 8. + int offset = 8; + long iTabID = LittleEndian.getUInt(data, offset); offset += LittleEndian.INT_SIZE; + if (iTabID < 1 || iTabID > 0x0000FFFFL) { + throw new XSSFBParseException("table id out of range: "+iTabID); + } + StringBuilder sb = new StringBuilder(); + offset += XSSFBUtils.readXLWideString(data, offset, sb); + String relId = sb.toString(); + sb.setLength(0); + offset += XSSFBUtils.readXLWideString(data, offset, sb); + String name = sb.toString(); + if (relId != null && relId.trim().length() > 0) { + sheets.add(new XSSFSheetRef(relId, name)); + } + if (offset == data.length) { + return true; + } + return false; + } + List getSheets() { return sheets; } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/extractor/TestXSSFBEventBasedExcelExtractor.java b/src/ooxml/testcases/org/apache/poi/xssf/extractor/TestXSSFBEventBasedExcelExtractor.java index a49a108217..56d17ee27d 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/extractor/TestXSSFBEventBasedExcelExtractor.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/extractor/TestXSSFBEventBasedExcelExtractor.java @@ -99,4 +99,13 @@ public class TestXSSFBEventBasedExcelExtractor { } } + @Test + public void testBeta() throws Exception { + XSSFEventBasedExcelExtractor extractor = getExtractor("Simple.xlsb"); + extractor.setIncludeCellComments(true); + String text = extractor.getText(); + assertContains(text, + "This is an example spreadsheet created with Microsoft Excel 2007 Beta 2."); + } + }