From c2dc3ad585b72f0414b1d9469444de099d0825fe Mon Sep 17 00:00:00 2001 From: Tim Allison Date: Fri, 21 Apr 2017 13:02:29 +0000 Subject: [PATCH] bug 61021 - extract abspath from xlsb git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1792198 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/xssf/binary/XSSFBParser.java | 2 +- .../poi/xssf/binary/XSSFBRecordType.java | 2 + .../poi/xssf/eventusermodel/XSSFBReader.java | 52 +++++++++++++++++++ .../xssf/eventusermodel/TestXSSFBReader.java | 7 +++ 4 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/ooxml/java/org/apache/poi/xssf/binary/XSSFBParser.java b/src/ooxml/java/org/apache/poi/xssf/binary/XSSFBParser.java index 4f4fc81ff..3c52ed78c 100644 --- a/src/ooxml/java/org/apache/poi/xssf/binary/XSSFBParser.java +++ b/src/ooxml/java/org/apache/poi/xssf/binary/XSSFBParser.java @@ -47,7 +47,7 @@ public abstract class XSSFBParser { * @param is inputStream * @param bitSet call {@link #handleRecord(int, byte[])} only on those records in this bitSet */ - XSSFBParser(InputStream is, BitSet bitSet) { + protected XSSFBParser(InputStream is, BitSet bitSet) { this.is = new LittleEndianInputStream(is); records = bitSet; } 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 354650430..aa417a46d 100644 --- a/src/ooxml/java/org/apache/poi/xssf/binary/XSSFBRecordType.java +++ b/src/ooxml/java/org/apache/poi/xssf/binary/XSSFBRecordType.java @@ -74,6 +74,8 @@ public enum XSSFBRecordType { BrtBundleSh(156), //defines worksheet in wb part + BrtAbsPath15(2071), //Excel 2013 path where the file was stored in wbpart + //TODO -- implement these as needed //BrtFileVersion(128), //file version //BrtWbProp(153), //Workbook prop contains 1904/1900-date based bit 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 825422936..0606ecec4 100644 --- a/src/ooxml/java/org/apache/poi/xssf/eventusermodel/XSSFBReader.java +++ b/src/ooxml/java/org/apache/poi/xssf/eventusermodel/XSSFBReader.java @@ -19,6 +19,7 @@ package org.apache.poi.xssf.eventusermodel; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.BitSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -31,6 +32,7 @@ import org.apache.poi.openxml4j.opc.PackagePartName; 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.IOUtils; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; @@ -62,6 +64,26 @@ public class XSSFBReader extends XSSFReader { super(pkg); } + /** + * In Excel 2013, the absolute path where the file was last saved may be stored in + * the {@link XSSFBRecordType#BrtAbsPath15} record. The equivalent in ooxml is + * <x15ac:absPath>. + * + * @return absolute path or null if it could not be found. + * @throws IOException when there's a problem with the workbook part's stream + */ + public String getAbsPathMetadata() throws IOException { + InputStream is = null; + try { + is = workbookPart.getInputStream(); + PathExtractor p = new PathExtractor(workbookPart.getInputStream()); + p.parse(); + return p.getPath(); + } finally { + IOUtils.closeQuietly(is); + } + } + /** * Returns an Iterator which will let you get at all the * different Sheets in turn. @@ -137,6 +159,36 @@ public class XSSFBReader extends XSSFReader { } + + private static class PathExtractor extends XSSFBParser { + private static BitSet RECORDS = new BitSet(); + static { + RECORDS.set(XSSFBRecordType.BrtAbsPath15.getId()); + } + private String path = null; + public PathExtractor(InputStream is) { + super(is, RECORDS); + } + + @Override + public void handleRecord(int recordType, byte[] data) throws XSSFBParseException { + if (recordType != XSSFBRecordType.BrtAbsPath15.getId()) { + return; + } + StringBuilder sb = new StringBuilder(); + XSSFBUtils.readXLWideString(data, 0, sb); + path = sb.toString(); + } + + /** + * + * @return the path if found, otherwise null + */ + String getPath() { + return path; + } + } + private static class SheetRefLoader extends XSSFBParser { List sheets = new LinkedList(); diff --git a/src/ooxml/testcases/org/apache/poi/xssf/eventusermodel/TestXSSFBReader.java b/src/ooxml/testcases/org/apache/poi/xssf/eventusermodel/TestXSSFBReader.java index 6ea533276..4c12af470 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/eventusermodel/TestXSSFBReader.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/eventusermodel/TestXSSFBReader.java @@ -118,6 +118,13 @@ public class TestXSSFBReader { } + @Test + public void testAbsPath() throws Exception { + OPCPackage pkg = OPCPackage.open(_ssTests.openResourceAsStream("testVarious.xlsb")); + XSSFBReader r = new XSSFBReader(pkg); + assertEquals("C:\\Users\\tallison\\Desktop\\working\\xlsb\\", r.getAbsPathMetadata()); + } + private List getSheets(String testFileName) throws Exception { OPCPackage pkg = OPCPackage.open(_ssTests.openResourceAsStream(testFileName)); List sheetTexts = new ArrayList();