Add methods to check to see if a given InputStream has a OOXML file header, or a OLE2 file header, so that a future factory method could figure out which class to instantiate for a given InputStraeam
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@612438 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
32a7c6ac86
commit
18a4647b24
@ -31,4 +31,7 @@ public interface POIFSConstants
|
|||||||
public static final int END_OF_CHAIN = -2;
|
public static final int END_OF_CHAIN = -2;
|
||||||
public static final int PROPERTY_SIZE = 0x0080;
|
public static final int PROPERTY_SIZE = 0x0080;
|
||||||
public static final int UNUSED_BLOCK = -1;
|
public static final int UNUSED_BLOCK = -1;
|
||||||
|
|
||||||
|
public static final byte[] OOXML_FILE_HEADER =
|
||||||
|
new byte[] { 0x50, 0x4b, 0x03, 0x04 };
|
||||||
} // end public interface POIFSConstants;
|
} // end public interface POIFSConstants;
|
||||||
|
@ -34,6 +34,7 @@ import org.apache.poi.poifs.storage.BlockAllocationTableReader;
|
|||||||
import org.apache.poi.poifs.storage.BlockAllocationTableWriter;
|
import org.apache.poi.poifs.storage.BlockAllocationTableWriter;
|
||||||
import org.apache.poi.poifs.storage.BlockList;
|
import org.apache.poi.poifs.storage.BlockList;
|
||||||
import org.apache.poi.poifs.storage.BlockWritable;
|
import org.apache.poi.poifs.storage.BlockWritable;
|
||||||
|
import org.apache.poi.poifs.storage.HeaderBlockConstants;
|
||||||
import org.apache.poi.poifs.storage.HeaderBlockReader;
|
import org.apache.poi.poifs.storage.HeaderBlockReader;
|
||||||
import org.apache.poi.poifs.storage.HeaderBlockWriter;
|
import org.apache.poi.poifs.storage.HeaderBlockWriter;
|
||||||
import org.apache.poi.poifs.storage.RawDataBlock;
|
import org.apache.poi.poifs.storage.RawDataBlock;
|
||||||
@ -41,6 +42,9 @@ import org.apache.poi.poifs.storage.RawDataBlockList;
|
|||||||
import org.apache.poi.poifs.storage.SmallBlockTableReader;
|
import org.apache.poi.poifs.storage.SmallBlockTableReader;
|
||||||
import org.apache.poi.poifs.storage.SmallBlockTableWriter;
|
import org.apache.poi.poifs.storage.SmallBlockTableWriter;
|
||||||
import org.apache.poi.poifs.storage.SmallDocumentBlock;
|
import org.apache.poi.poifs.storage.SmallDocumentBlock;
|
||||||
|
import org.apache.poi.util.IOUtils;
|
||||||
|
import org.apache.poi.util.LongField;
|
||||||
|
import org.apache.xmlbeans.impl.common.IOUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the main class of the POIFS system; it manages the entire
|
* This is the main class of the POIFS system; it manages the entire
|
||||||
@ -107,6 +111,35 @@ public class POIFSFileSystem
|
|||||||
.getChildren(), null);
|
.getChildren(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks that the supplied InputStream (which MUST
|
||||||
|
* support mark and reset, or be a PushbackInputStream)
|
||||||
|
* has a POIFS (OLE2) header at the start of it.
|
||||||
|
* If your InputStream does not support mark / reset,
|
||||||
|
* then wrap it in a PushBackInputStream, then be
|
||||||
|
* sure to always use that, and not the original!
|
||||||
|
* @param inp An InputStream which supports either mark/reset, or is a PushbackInputStream
|
||||||
|
*/
|
||||||
|
public static boolean hasPOIFSHeader(InputStream inp) throws IOException {
|
||||||
|
// We want to peek at the first 8 bytes
|
||||||
|
inp.mark(8);
|
||||||
|
|
||||||
|
byte[] header = new byte[8];
|
||||||
|
IOUtils.readFully(inp, header);
|
||||||
|
LongField signature = new LongField(HeaderBlockConstants._signature_offset, header);
|
||||||
|
|
||||||
|
// Wind back those 8 bytes
|
||||||
|
if(inp instanceof PushbackInputStream) {
|
||||||
|
PushbackInputStream pin = (PushbackInputStream)inp;
|
||||||
|
pin.unread(header);
|
||||||
|
} else {
|
||||||
|
inp.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Did it match the signature?
|
||||||
|
return (signature.get() == HeaderBlockConstants._signature);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new document to be added to the root directory
|
* Create a new document to be added to the root directory
|
||||||
*
|
*
|
||||||
|
@ -91,8 +91,11 @@ public class HeaderBlockReader
|
|||||||
if (signature.get() != _signature)
|
if (signature.get() != _signature)
|
||||||
{
|
{
|
||||||
// Is it one of the usual suspects?
|
// Is it one of the usual suspects?
|
||||||
if(_data[0] == 0x50 && _data[1] == 0x4b && _data[2] == 0x03 &&
|
byte[] OOXML_FILE_HEADER = POIFSConstants.OOXML_FILE_HEADER;
|
||||||
_data[3] == 0x04) {
|
if(_data[0] == OOXML_FILE_HEADER[0] &&
|
||||||
|
_data[1] == OOXML_FILE_HEADER[1] &&
|
||||||
|
_data[2] == OOXML_FILE_HEADER[2] &&
|
||||||
|
_data[3] == OOXML_FILE_HEADER[3]) {
|
||||||
throw new OfficeXmlFileException("The supplied data appears to be in the Office 2007+ XML. POI only supports OLE2 Office documents");
|
throw new OfficeXmlFileException("The supplied data appears to be in the Office 2007+ XML. POI only supports OLE2 Office documents");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,9 +18,15 @@ package org.apache.poi.hxf;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.PushbackInputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import org.apache.poi.POIXMLDocument;
|
import org.apache.poi.POIXMLDocument;
|
||||||
|
import org.apache.poi.poifs.common.POIFSConstants;
|
||||||
|
import org.apache.poi.poifs.storage.HeaderBlockConstants;
|
||||||
|
import org.apache.poi.util.IOUtils;
|
||||||
|
import org.apache.poi.util.LongField;
|
||||||
import org.apache.xmlbeans.XmlException;
|
import org.apache.xmlbeans.XmlException;
|
||||||
import org.dom4j.Document;
|
import org.dom4j.Document;
|
||||||
import org.dom4j.DocumentException;
|
import org.dom4j.DocumentException;
|
||||||
@ -87,6 +93,39 @@ public abstract class HXFDocument {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks that the supplied InputStream (which MUST
|
||||||
|
* support mark and reset, or be a PushbackInputStream)
|
||||||
|
* has a OOXML (zip) header at the start of it.
|
||||||
|
* If your InputStream does not support mark / reset,
|
||||||
|
* then wrap it in a PushBackInputStream, then be
|
||||||
|
* sure to always use that, and not the original!
|
||||||
|
* @param inp An InputStream which supports either mark/reset, or is a PushbackInputStream
|
||||||
|
*/
|
||||||
|
public static boolean hasOOXMLHeader(InputStream inp) throws IOException {
|
||||||
|
// We want to peek at the first 4 bytes
|
||||||
|
inp.mark(4);
|
||||||
|
|
||||||
|
byte[] header = new byte[4];
|
||||||
|
IOUtils.readFully(inp, header);
|
||||||
|
|
||||||
|
// Wind back those 4 bytes
|
||||||
|
if(inp instanceof PushbackInputStream) {
|
||||||
|
PushbackInputStream pin = (PushbackInputStream)inp;
|
||||||
|
pin.unread(header);
|
||||||
|
} else {
|
||||||
|
inp.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Did it match the ooxml zip signature?
|
||||||
|
return (
|
||||||
|
header[0] == POIFSConstants.OOXML_FILE_HEADER[0] &&
|
||||||
|
header[1] == POIFSConstants.OOXML_FILE_HEADER[1] &&
|
||||||
|
header[2] == POIFSConstants.OOXML_FILE_HEADER[2] &&
|
||||||
|
header[3] == POIFSConstants.OOXML_FILE_HEADER[3]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches the (single) PackagePart with the supplied
|
* Fetches the (single) PackagePart with the supplied
|
||||||
* content type.
|
* content type.
|
||||||
|
@ -0,0 +1,65 @@
|
|||||||
|
|
||||||
|
/* ====================================================================
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
==================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
package org.apache.poi.hxf;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to test that HXF correctly detects OOXML
|
||||||
|
* documents
|
||||||
|
*/
|
||||||
|
public class TestDetectAsOOXML extends TestCase
|
||||||
|
{
|
||||||
|
public String dirname;
|
||||||
|
|
||||||
|
public void setUp() {
|
||||||
|
dirname = System.getProperty("HSSF.testdata.path");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testOpensProperly() throws Exception
|
||||||
|
{
|
||||||
|
File f = new File(dirname + "/sample.xlsx");
|
||||||
|
|
||||||
|
HXFDocument.openPackage(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDetectAsPOIFS() throws Exception {
|
||||||
|
InputStream in;
|
||||||
|
|
||||||
|
// ooxml file is
|
||||||
|
in = new PushbackInputStream(
|
||||||
|
new FileInputStream(dirname + "/SampleSS.xlsx"), 10
|
||||||
|
);
|
||||||
|
assertTrue(HXFDocument.hasOOXMLHeader(in));
|
||||||
|
|
||||||
|
// xls file isn't
|
||||||
|
in = new PushbackInputStream(
|
||||||
|
new FileInputStream(dirname + "/SampleSS.xls"), 10
|
||||||
|
);
|
||||||
|
assertFalse(HXFDocument.hasOOXMLHeader(in));
|
||||||
|
|
||||||
|
// text file isn't
|
||||||
|
in = new PushbackInputStream(
|
||||||
|
new FileInputStream(dirname + "/SampleSS.txt"), 10
|
||||||
|
);
|
||||||
|
assertFalse(HXFDocument.hasOOXMLHeader(in));
|
||||||
|
}
|
||||||
|
}
|
@ -47,4 +47,26 @@ public class TestOffice2007XMLException extends TestCase
|
|||||||
// Good
|
// Good
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testDetectAsPOIFS() throws IOException {
|
||||||
|
InputStream in;
|
||||||
|
|
||||||
|
// ooxml file isn't
|
||||||
|
in = new PushbackInputStream(
|
||||||
|
new FileInputStream(dirname + "/SampleSS.xlsx"), 10
|
||||||
|
);
|
||||||
|
assertFalse(POIFSFileSystem.hasPOIFSHeader(in));
|
||||||
|
|
||||||
|
// xls file is
|
||||||
|
in = new PushbackInputStream(
|
||||||
|
new FileInputStream(dirname + "/SampleSS.xls"), 10
|
||||||
|
);
|
||||||
|
assertTrue(POIFSFileSystem.hasPOIFSHeader(in));
|
||||||
|
|
||||||
|
// text file isn't
|
||||||
|
in = new PushbackInputStream(
|
||||||
|
new FileInputStream(dirname + "/SampleSS.txt"), 10
|
||||||
|
);
|
||||||
|
assertFalse(POIFSFileSystem.hasPOIFSHeader(in));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user