mirror of
https://github.com/apache/poi.git
synced 2026-02-27 20:40:08 +08:00
make max record sizes configurable
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1894453 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
dbc6576da4
commit
04c130b8d5
@ -64,7 +64,7 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideSize;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.PresentationDocument;
|
||||
|
||||
/**
|
||||
* High level representation of a ooxml slideshow.
|
||||
* High level representation of an ooxml slideshow.
|
||||
* This is the first object most users will construct whether
|
||||
* they are reading or writing a slideshow. It is also the
|
||||
* top level object for creating new slides/etc.
|
||||
@ -75,7 +75,8 @@ public class XMLSlideShow extends POIXMLDocument
|
||||
implements SlideShow<XSLFShape, XSLFTextParagraph> {
|
||||
private static final Logger LOG = LogManager.getLogger(XMLSlideShow.class);
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 1_000_000;
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 1_000_000;
|
||||
private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
|
||||
private CTPresentation _presentation;
|
||||
private final List<XSLFSlide> _slides = new ArrayList<>();
|
||||
@ -86,6 +87,20 @@ public class XMLSlideShow extends POIXMLDocument
|
||||
private XSLFNotesMaster _notesMaster;
|
||||
private XSLFCommentAuthors _commentAuthors;
|
||||
|
||||
/**
|
||||
* @param length the max record length allowed for XMLSlideShow
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max record length allowed for XMLSlideShow
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
public XMLSlideShow() {
|
||||
this(empty());
|
||||
}
|
||||
|
||||
@ -36,11 +36,26 @@ import org.apache.poi.util.LittleEndianInputStream;
|
||||
public abstract class XSSFBParser {
|
||||
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 1_000_000;
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 1_000_000;
|
||||
private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
|
||||
private final LittleEndianInputStream is;
|
||||
private final SparseBitSet records;
|
||||
|
||||
/**
|
||||
* @param length the max record length allowed for XSSFBParser
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max record length allowed for XSSFBParser
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
public XSSFBParser(InputStream is) {
|
||||
this.is = new LittleEndianInputStream(is);
|
||||
records = null;
|
||||
|
||||
@ -43,8 +43,8 @@ import static org.apache.logging.log4j.util.Unbox.box;
|
||||
public final class ChunkFactory {
|
||||
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 1_000_000;
|
||||
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 1_000_000;
|
||||
private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
|
||||
/** The version of the currently open document */
|
||||
private int version;
|
||||
@ -63,6 +63,20 @@ public final class ChunkFactory {
|
||||
/** For logging problems we spot with the file */
|
||||
private static final Logger LOG = LogManager.getLogger(ChunkFactory.class);
|
||||
|
||||
/**
|
||||
* @param length the max record length allowed for ChunkFactory
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max record length allowed for ChunkFactory
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
public ChunkFactory(int version) throws IOException {
|
||||
this.version = version;
|
||||
|
||||
|
||||
@ -30,7 +30,8 @@ import org.apache.poi.util.IOUtils;
|
||||
public final class CompressedStreamStore extends StreamStore {
|
||||
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 64_000_000;
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 64_000_000;
|
||||
private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
|
||||
/** The raw, compressed contents */
|
||||
private byte[] compressedContents;
|
||||
@ -44,6 +45,20 @@ public final class CompressedStreamStore extends StreamStore {
|
||||
byte[] _getCompressedContents() { return compressedContents; }
|
||||
byte[] _getBlockHeader() { return blockHeader; }
|
||||
|
||||
/**
|
||||
* @param length the max record length allowed for CompressedStreamStore
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max record length allowed for CompressedStreamStore
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new compressed StreamStore, which will handle
|
||||
* the decompression.
|
||||
|
||||
@ -26,10 +26,25 @@ import org.apache.poi.util.IOUtils;
|
||||
*/
|
||||
public class StreamStore { // TODO - instantiable superclass
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 10_000_000;
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 10_000_000;
|
||||
private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
|
||||
private byte[] contents;
|
||||
|
||||
/**
|
||||
* @param length the max record length allowed for StreamStore
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max record length allowed for StreamStore
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new, non compressed Stream Store
|
||||
*/
|
||||
|
||||
@ -41,12 +41,27 @@ import org.apache.poi.util.StringUtil;
|
||||
public class MAPIAttribute {
|
||||
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 1_000_000;
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 1_000_000;
|
||||
private static int MAX_RECORD_LENGTH = 1_000_000;
|
||||
|
||||
private final MAPIProperty property;
|
||||
private final int type;
|
||||
private final byte[] data;
|
||||
|
||||
/**
|
||||
* @param length the max record length allowed for MAPIAttribute
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max record length allowed for MAPIAttribute
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a single new attribute from
|
||||
* the contents of the stream
|
||||
|
||||
@ -35,12 +35,27 @@ import org.apache.poi.util.LittleEndian;
|
||||
public class TNEFAttribute {
|
||||
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 20_000_000;
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 20_000_000;
|
||||
private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
|
||||
private final TNEFProperty property;
|
||||
private final int type;
|
||||
private final byte[] data;
|
||||
private final int checksum;
|
||||
|
||||
/**
|
||||
* @param length the max record length allowed for TNEFAttribute
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max record length allowed for TNEFAttribute
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a single new attribute from the id, type,
|
||||
|
||||
@ -26,7 +26,22 @@ import org.apache.poi.util.StringUtil;
|
||||
public final class QCTextBit extends QCBit {
|
||||
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 1_000_000;
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 1_000_000;
|
||||
private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
|
||||
/**
|
||||
* @param length the max record length allowed for QCTextBit
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max record length allowed for QCTextBit
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
public QCTextBit(String thingType, String bitType, byte[] data) {
|
||||
super(thingType, bitType, data);
|
||||
|
||||
@ -37,288 +37,310 @@ import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
* This class provides a way to "peek" inside a powerpoint file. It
|
||||
* will print out all the types it find, and for those it know aren't
|
||||
* atoms, what they contain
|
||||
*
|
||||
* will print out all the types it finds, and for those it knows aren't
|
||||
* atoms, what they contain
|
||||
* <p>
|
||||
* To figure out what things are, and if they are atoms or not, used the
|
||||
* list in hslf.record.RecordTypes
|
||||
*
|
||||
* list in hslf.record.RecordTypes
|
||||
* <p>
|
||||
* To peek inside PPDrawings, which hold Escher drawings, we use the
|
||||
* DDF package from POI (but we can fake it by using the Escher listings
|
||||
* from hslf.record.RecordTypes also)
|
||||
* DDF package from POI (but we can fake it by using the Escher listings
|
||||
* from hslf.record.RecordTypes also)
|
||||
*/
|
||||
public final class SlideShowDumper {
|
||||
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 100_000;
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 100_000;
|
||||
private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
|
||||
private byte[] docstream;
|
||||
|
||||
/** Do we try to use DDF to understand the escher objects? */
|
||||
private boolean ddfEscher;
|
||||
/** Do we use our own built-in basic escher groker to understand the escher objects? */
|
||||
private boolean basicEscher;
|
||||
/**
|
||||
* Do we try to use DDF to understand the escher objects?
|
||||
*/
|
||||
private boolean ddfEscher;
|
||||
/**
|
||||
* Do we use our own built-in basic escher groker to understand the escher objects?
|
||||
*/
|
||||
private boolean basicEscher;
|
||||
|
||||
private PrintStream out;
|
||||
private PrintStream out;
|
||||
|
||||
/**
|
||||
* right now this function takes one parameter: a ppt file, and outputs
|
||||
* a dump of what it contains
|
||||
*/
|
||||
public static void main(String[] args) throws IOException
|
||||
{
|
||||
if(args.length == 0) {
|
||||
System.err.println("Usage: SlideShowDumper [-escher|-basicescher] <filename>");
|
||||
return;
|
||||
/**
|
||||
* @param length the max record length allowed for SlideShowDumper
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
String filename = args[0];
|
||||
if(args.length > 1) {
|
||||
filename = args[1];
|
||||
/**
|
||||
* @return the max record length allowed for SlideShowDumper
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
try (POIFSFileSystem poifs = new POIFSFileSystem(new File(filename))) {
|
||||
SlideShowDumper foo = new SlideShowDumper(poifs, System.out);
|
||||
|
||||
if(args.length > 1) {
|
||||
if(args[0].equalsIgnoreCase("-escher")) {
|
||||
foo.setDDFEscher(true);
|
||||
} else {
|
||||
foo.setBasicEscher(true);
|
||||
}
|
||||
/**
|
||||
* right now this function takes one parameter: a ppt file, and outputs
|
||||
* a dump of what it contains
|
||||
*/
|
||||
public static void main(String[] args) throws IOException {
|
||||
if (args.length == 0) {
|
||||
System.err.println("Usage: SlideShowDumper [-escher|-basicescher] <filename>");
|
||||
return;
|
||||
}
|
||||
|
||||
foo.printDump();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a Powerpoint dump from a POIFS Filesystem. Parses the
|
||||
* document and dumps out the contents
|
||||
*
|
||||
* @param filesystem the POIFS FileSystem to read from
|
||||
* @throws IOException if there is a problem while parsing the document.
|
||||
*/
|
||||
public SlideShowDumper(POIFSFileSystem filesystem, PrintStream out) throws IOException {
|
||||
// Grab the document stream
|
||||
InputStream is = filesystem.createDocumentInputStream(HSLFSlideShow.POWERPOINT_DOCUMENT);
|
||||
docstream = IOUtils.toByteArray(is);
|
||||
is.close();
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Control dumping of any Escher records found - should DDF be used?
|
||||
*/
|
||||
public void setDDFEscher(boolean grok) {
|
||||
ddfEscher = grok;
|
||||
basicEscher = !(grok);
|
||||
}
|
||||
|
||||
/**
|
||||
* Control dumping of any Escher records found - should our built in
|
||||
* basic groker be used?
|
||||
*/
|
||||
public void setBasicEscher(boolean grok) {
|
||||
basicEscher = grok;
|
||||
ddfEscher = !(grok);
|
||||
}
|
||||
|
||||
public void printDump() throws IOException {
|
||||
// The format of records in a powerpoint file are:
|
||||
// <little endian 2 byte "info">
|
||||
// <little endian 2 byte "type">
|
||||
// <little endian 4 byte "length">
|
||||
// If it has a zero length, following it will be another record
|
||||
// <xx xx yy yy 00 00 00 00> <xx xx yy yy zz zz zz zz>
|
||||
// If it has a length, depending on its type it may have children or data
|
||||
// If it has children, these will follow straight away
|
||||
// <xx xx yy yy zz zz zz zz <xx xx yy yy zz zz zz zz>>
|
||||
// If it has data, this will come straigh after, and run for the length
|
||||
// <xx xx yy yy zz zz zz zz dd dd dd dd dd dd dd>
|
||||
// All lengths given exclude the 8 byte record header
|
||||
// (Data records are known as Atoms)
|
||||
|
||||
// Document should start with:
|
||||
// 0F 00 E8 03 ## ## ## ##
|
||||
// (type 1000 = document, info 00 0f is normal, rest is document length)
|
||||
// 01 00 E9 03 28 00 00 00
|
||||
// (type 1001 = document atom, info 00 01 normal, 28 bytes long)
|
||||
|
||||
// When parsing a document, look to see if you know about that type
|
||||
// of the current record. If you know it's a type that has children,
|
||||
// process the record's data area looking for more records
|
||||
// If you know about the type and it doesn't have children, either do
|
||||
// something with the data (eg TextRun) or skip over it
|
||||
// Otherwise, check the first byte. If you do a BINARY_AND on it with
|
||||
// 0x0f (15) and get back 0x0f, you know it has children. Otherwise
|
||||
// it doesn't
|
||||
|
||||
walkTree(0,0,docstream.length);
|
||||
}
|
||||
|
||||
public void walkTree(int depth, int startPos, int maxLen) throws IOException {
|
||||
int pos = startPos;
|
||||
int endPos = startPos + maxLen;
|
||||
final String ind = (depth == 0) ? "%1$s" : "%1$"+depth+"s";
|
||||
while(pos <= endPos - 8) {
|
||||
long type = LittleEndian.getUShort(docstream,pos+2);
|
||||
long len = LittleEndian.getUInt(docstream,pos+4);
|
||||
byte opt = docstream[pos];
|
||||
|
||||
String fmt = ind+"At position %2$d (%2$04x): type is %3$d (%3$04x), len is %4$d (%4$04x)";
|
||||
out.println(String.format(Locale.ROOT, fmt, "", pos, type, len));
|
||||
|
||||
// See if we know about the type of it
|
||||
String recordName = RecordTypes.forTypeID((short)type).name();
|
||||
|
||||
// Jump over header, and think about going on more
|
||||
pos += 8;
|
||||
out.println(String.format(Locale.ROOT, ind+"That's a %2$s", "", recordName));
|
||||
|
||||
// Now check if it's a container or not
|
||||
int container = opt & 0x0f;
|
||||
|
||||
// BinaryTagData seems to contain records, but it
|
||||
// isn't tagged as doing so. Try stepping in anyway
|
||||
if(type == 5003L && opt == 0L) {
|
||||
container = 0x0f;
|
||||
String filename = args[0];
|
||||
if (args.length > 1) {
|
||||
filename = args[1];
|
||||
}
|
||||
|
||||
out.println();
|
||||
if (type != 0L && container == 0x0f) {
|
||||
if (type == 1035L || type == 1036L) {
|
||||
// Special Handling of 1035=PPDrawingGroup and 1036=PPDrawing
|
||||
if(ddfEscher) {
|
||||
// Seems to be:
|
||||
walkEscherDDF((depth+3),pos+8,(int)len-8);
|
||||
} else if(basicEscher) {
|
||||
walkEscherBasic((depth+3),pos+8,(int)len-8);
|
||||
try (POIFSFileSystem poifs = new POIFSFileSystem(new File(filename))) {
|
||||
SlideShowDumper foo = new SlideShowDumper(poifs, System.out);
|
||||
|
||||
if (args.length > 1) {
|
||||
if (args[0].equalsIgnoreCase("-escher")) {
|
||||
foo.setDDFEscher(true);
|
||||
} else {
|
||||
foo.setBasicEscher(true);
|
||||
}
|
||||
} else {
|
||||
// General container record handling code
|
||||
walkTree((depth+2),pos,(int)len);
|
||||
}
|
||||
|
||||
foo.printDump();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a Powerpoint dump from a POIFS Filesystem. Parses the
|
||||
* document and dumps out the contents
|
||||
*
|
||||
* @param filesystem the POIFS FileSystem to read from
|
||||
* @throws IOException if there is a problem while parsing the document.
|
||||
*/
|
||||
public SlideShowDumper(POIFSFileSystem filesystem, PrintStream out) throws IOException {
|
||||
// Grab the document stream
|
||||
InputStream is = filesystem.createDocumentInputStream(HSLFSlideShow.POWERPOINT_DOCUMENT);
|
||||
docstream = IOUtils.toByteArray(is);
|
||||
is.close();
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Control dumping of any Escher records found - should DDF be used?
|
||||
*/
|
||||
public void setDDFEscher(boolean grok) {
|
||||
ddfEscher = grok;
|
||||
basicEscher = !(grok);
|
||||
}
|
||||
|
||||
/**
|
||||
* Control dumping of any Escher records found - should our built in
|
||||
* basic groker be used?
|
||||
*/
|
||||
public void setBasicEscher(boolean grok) {
|
||||
basicEscher = grok;
|
||||
ddfEscher = !(grok);
|
||||
}
|
||||
|
||||
public void printDump() throws IOException {
|
||||
// The format of records in a powerpoint file are:
|
||||
// <little endian 2 byte "info">
|
||||
// <little endian 2 byte "type">
|
||||
// <little endian 4 byte "length">
|
||||
// If it has a zero length, following it will be another record
|
||||
// <xx xx yy yy 00 00 00 00> <xx xx yy yy zz zz zz zz>
|
||||
// If it has a length, depending on its type it may have children or data
|
||||
// If it has children, these will follow straight away
|
||||
// <xx xx yy yy zz zz zz zz <xx xx yy yy zz zz zz zz>>
|
||||
// If it has data, this will come straigh after, and run for the length
|
||||
// <xx xx yy yy zz zz zz zz dd dd dd dd dd dd dd>
|
||||
// All lengths given exclude the 8 byte record header
|
||||
// (Data records are known as Atoms)
|
||||
|
||||
// Document should start with:
|
||||
// 0F 00 E8 03 ## ## ## ##
|
||||
// (type 1000 = document, info 00 0f is normal, rest is document length)
|
||||
// 01 00 E9 03 28 00 00 00
|
||||
// (type 1001 = document atom, info 00 01 normal, 28 bytes long)
|
||||
|
||||
// When parsing a document, look to see if you know about that type
|
||||
// of the current record. If you know it's a type that has children,
|
||||
// process the record's data area looking for more records
|
||||
// If you know about the type and it doesn't have children, either do
|
||||
// something with the data (eg TextRun) or skip over it
|
||||
// Otherwise, check the first byte. If you do a BINARY_AND on it with
|
||||
// 0x0f (15) and get back 0x0f, you know it has children. Otherwise
|
||||
// it doesn't
|
||||
|
||||
walkTree(0, 0, docstream.length);
|
||||
}
|
||||
|
||||
public void walkTree(int depth, int startPos, int maxLen) throws IOException {
|
||||
int pos = startPos;
|
||||
int endPos = startPos + maxLen;
|
||||
final String ind = (depth == 0) ? "%1$s" : "%1$" + depth + "s";
|
||||
while (pos <= endPos - 8) {
|
||||
long type = LittleEndian.getUShort(docstream, pos + 2);
|
||||
long len = LittleEndian.getUInt(docstream, pos + 4);
|
||||
byte opt = docstream[pos];
|
||||
|
||||
String fmt = ind + "At position %2$d (%2$04x): type is %3$d (%3$04x), len is %4$d (%4$04x)";
|
||||
out.println(String.format(Locale.ROOT, fmt, "", pos, type, len));
|
||||
|
||||
// See if we know about the type of it
|
||||
String recordName = RecordTypes.forTypeID((short) type).name();
|
||||
|
||||
// Jump over header, and think about going on more
|
||||
pos += 8;
|
||||
out.println(String.format(Locale.ROOT, ind + "That's a %2$s", "", recordName));
|
||||
|
||||
// Now check if it's a container or not
|
||||
int container = opt & 0x0f;
|
||||
|
||||
// BinaryTagData seems to contain records, but it
|
||||
// isn't tagged as doing so. Try stepping in anyway
|
||||
if (type == 5003L && opt == 0L) {
|
||||
container = 0x0f;
|
||||
}
|
||||
|
||||
out.println();
|
||||
if (type != 0L && container == 0x0f) {
|
||||
if (type == 1035L || type == 1036L) {
|
||||
// Special Handling of 1035=PPDrawingGroup and 1036=PPDrawing
|
||||
if (ddfEscher) {
|
||||
// Seems to be:
|
||||
walkEscherDDF((depth + 3), pos + 8, (int) len - 8);
|
||||
} else if (basicEscher) {
|
||||
walkEscherBasic((depth + 3), pos + 8, (int) len - 8);
|
||||
}
|
||||
} else {
|
||||
// General container record handling code
|
||||
walkTree((depth + 2), pos, (int) len);
|
||||
}
|
||||
}
|
||||
|
||||
pos += (int) len;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the DDF code to walk the Escher records
|
||||
*/
|
||||
public void walkEscherDDF(int indent, int pos, int len) {
|
||||
if (len < 8) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String ind = (indent == 0) ? "%1$s" : "%1$" + indent + "s";
|
||||
|
||||
byte[] contents = IOUtils.safelyClone(docstream, pos, len, MAX_RECORD_LENGTH);
|
||||
DefaultEscherRecordFactory erf = new HSLFEscherRecordFactory();
|
||||
EscherRecord record = erf.createRecord(contents, 0);
|
||||
|
||||
// For now, try filling in the fields
|
||||
record.fillFields(contents, 0, erf);
|
||||
|
||||
long atomType = LittleEndian.getUShort(contents, 2);
|
||||
// This lacks the 8 byte header size
|
||||
long atomLen = LittleEndian.getUShort(contents, 4);
|
||||
// This (should) include the 8 byte header size
|
||||
int recordLen = record.getRecordSize();
|
||||
|
||||
String fmt = ind + "At position %2$d (%2$04x): type is %3$d (%3$04x), len is %4$d (%4$04x) (%5$d) - record claims %6$d";
|
||||
out.println(String.format(Locale.ROOT, fmt, "", pos, atomType, atomLen, atomLen + 8, recordLen));
|
||||
|
||||
|
||||
// Check for corrupt / lying ones
|
||||
if (recordLen != 8 && (recordLen != (atomLen + 8))) {
|
||||
out.println(String.format(Locale.ROOT, ind + "** Atom length of $2d ($3d) doesn't match record length of %4d", "", atomLen, atomLen + 8, recordLen));
|
||||
}
|
||||
|
||||
// Print the record's details
|
||||
String recordStr = record.toString().replace("\n", String.format(Locale.ROOT, "\n" + ind, ""));
|
||||
out.println(String.format(Locale.ROOT, ind + "%2$s", "", recordStr));
|
||||
|
||||
if (record instanceof EscherContainerRecord) {
|
||||
walkEscherDDF((indent + 3), pos + 8, (int) atomLen);
|
||||
}
|
||||
|
||||
// Handle records that seem to lie
|
||||
if (atomType == 61451L) {
|
||||
// Normally claims a size of 8
|
||||
recordLen = (int) atomLen + 8;
|
||||
}
|
||||
if (atomType == 61453L) {
|
||||
// Returns EscherContainerRecord, but really msofbtClientTextbox
|
||||
recordLen = (int) atomLen + 8;
|
||||
record.fillFields(contents, 0, erf);
|
||||
if (!(record instanceof EscherTextboxRecord)) {
|
||||
out.println(String.format(Locale.ROOT, ind + "%2$s", "", "** Really a msofbtClientTextbox !"));
|
||||
}
|
||||
}
|
||||
|
||||
pos += (int)len;
|
||||
}
|
||||
}
|
||||
// Decide on what to do, based on how the lengths match up
|
||||
if (recordLen == 8 && atomLen > 8) {
|
||||
// Assume it has children, rather than being corrupted
|
||||
walkEscherDDF((indent + 3), pos + 8, (int) atomLen);
|
||||
|
||||
/**
|
||||
* Use the DDF code to walk the Escher records
|
||||
*/
|
||||
public void walkEscherDDF(int indent, int pos, int len) {
|
||||
if(len < 8) { return; }
|
||||
// Wind on our length + our header
|
||||
pos += atomLen;
|
||||
pos += 8;
|
||||
len -= atomLen;
|
||||
len -= 8;
|
||||
} else {
|
||||
// No children, wind on our real length
|
||||
pos += atomLen;
|
||||
pos += 8;
|
||||
len -= atomLen;
|
||||
len -= 8;
|
||||
}
|
||||
|
||||
final String ind = (indent == 0) ? "%1$s" : "%1$"+indent+"s";
|
||||
|
||||
byte[] contents = IOUtils.safelyClone(docstream, pos, len, MAX_RECORD_LENGTH);
|
||||
DefaultEscherRecordFactory erf = new HSLFEscherRecordFactory();
|
||||
EscherRecord record = erf.createRecord(contents,0);
|
||||
|
||||
// For now, try filling in the fields
|
||||
record.fillFields(contents,0,erf);
|
||||
|
||||
long atomType = LittleEndian.getUShort(contents,2);
|
||||
// This lacks the 8 byte header size
|
||||
long atomLen = LittleEndian.getUShort(contents,4);
|
||||
// This (should) include the 8 byte header size
|
||||
int recordLen = record.getRecordSize();
|
||||
|
||||
String fmt = ind+"At position %2$d (%2$04x): type is %3$d (%3$04x), len is %4$d (%4$04x) (%5$d) - record claims %6$d";
|
||||
out.println(String.format(Locale.ROOT, fmt, "", pos, atomType, atomLen, atomLen+8, recordLen));
|
||||
|
||||
|
||||
// Check for corrupt / lying ones
|
||||
if(recordLen != 8 && (recordLen != (atomLen+8))) {
|
||||
out.println(String.format(Locale.ROOT, ind+"** Atom length of $2d ($3d) doesn't match record length of %4d", "", atomLen, atomLen+8, recordLen));
|
||||
}
|
||||
|
||||
// Print the record's details
|
||||
String recordStr = record.toString().replace("\n", String.format(Locale.ROOT, "\n"+ind, ""));
|
||||
out.println(String.format(Locale.ROOT, ind+"%2$s", "", recordStr));
|
||||
|
||||
if(record instanceof EscherContainerRecord) {
|
||||
walkEscherDDF((indent+3), pos + 8, (int)atomLen );
|
||||
}
|
||||
|
||||
// Handle records that seem to lie
|
||||
if(atomType == 61451L) {
|
||||
// Normally claims a size of 8
|
||||
recordLen = (int)atomLen + 8;
|
||||
}
|
||||
if(atomType == 61453L) {
|
||||
// Returns EscherContainerRecord, but really msofbtClientTextbox
|
||||
recordLen = (int)atomLen + 8;
|
||||
record.fillFields( contents, 0, erf );
|
||||
if(! (record instanceof EscherTextboxRecord)) {
|
||||
out.println(String.format(Locale.ROOT, ind+"%2$s", "", "** Really a msofbtClientTextbox !"));
|
||||
// Move on to the next one, if we're not at the end yet
|
||||
if (len >= 8) {
|
||||
walkEscherDDF(indent, pos, len);
|
||||
}
|
||||
}
|
||||
|
||||
// Decide on what to do, based on how the lengths match up
|
||||
if(recordLen == 8 && atomLen > 8 ) {
|
||||
// Assume it has children, rather than being corrupted
|
||||
walkEscherDDF((indent+3), pos + 8, (int)atomLen );
|
||||
/**
|
||||
* Use the basic record format groking code to walk the Escher records
|
||||
*/
|
||||
public void walkEscherBasic(int indent, int pos, int len) throws IOException {
|
||||
if (len < 8) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Wind on our length + our header
|
||||
pos += atomLen;
|
||||
pos += 8;
|
||||
len -= atomLen;
|
||||
len -= 8;
|
||||
} else {
|
||||
// No children, wind on our real length
|
||||
pos += atomLen;
|
||||
pos += 8;
|
||||
len -= atomLen;
|
||||
len -= 8;
|
||||
}
|
||||
final String ind = (indent == 0) ? "%1$s" : "%1$" + indent + "s";
|
||||
|
||||
// Move on to the next one, if we're not at the end yet
|
||||
if(len >= 8) {
|
||||
walkEscherDDF(indent, pos, len );
|
||||
}
|
||||
}
|
||||
long type = LittleEndian.getUShort(docstream, pos + 2);
|
||||
long atomlen = LittleEndian.getUInt(docstream, pos + 4);
|
||||
|
||||
/**
|
||||
* Use the basic record format groking code to walk the Escher records
|
||||
*/
|
||||
public void walkEscherBasic(int indent, int pos, int len) throws IOException {
|
||||
if(len < 8) { return; }
|
||||
String fmt = ind + "At position %2$d ($2$04x): type is %3$d (%3$04x), len is %4$d (%4$04x)";
|
||||
out.println(String.format(Locale.ROOT, fmt, "", pos, type, atomlen));
|
||||
|
||||
final String ind = (indent == 0) ? "%1$s" : "%1$"+indent+"s";
|
||||
String typeName = RecordTypes.forTypeID((short) type).name();
|
||||
out.println(String.format(Locale.ROOT, ind + "%2$s", "That's an Escher Record: ", typeName));
|
||||
|
||||
long type = LittleEndian.getUShort(docstream,pos+2);
|
||||
long atomlen = LittleEndian.getUInt(docstream,pos+4);
|
||||
// Record specific dumps
|
||||
if (type == 61453L) {
|
||||
// Text Box. Print out first 8 bytes of data, then 8 4 later
|
||||
HexDump.dump(docstream, 0, out, pos + 8, 8);
|
||||
HexDump.dump(docstream, 0, out, pos + 20, 8);
|
||||
out.println();
|
||||
}
|
||||
|
||||
String fmt = ind+"At position %2$d ($2$04x): type is %3$d (%3$04x), len is %4$d (%4$04x)";
|
||||
out.println(String.format(Locale.ROOT, fmt, "", pos, type, atomlen));
|
||||
|
||||
String typeName = RecordTypes.forTypeID((short)type).name();
|
||||
out.println(String.format(Locale.ROOT, ind+"%2$s", "That's an Escher Record: ", typeName));
|
||||
|
||||
// Record specific dumps
|
||||
if(type == 61453L) {
|
||||
// Text Box. Print out first 8 bytes of data, then 8 4 later
|
||||
HexDump.dump(docstream, 0, out, pos+8, 8);
|
||||
HexDump.dump(docstream, 0, out, pos+20, 8);
|
||||
// Blank line before next entry
|
||||
out.println();
|
||||
|
||||
// Look in children if we are a container
|
||||
if (type == 61443L || type == 61444L) {
|
||||
walkEscherBasic((indent + 3), pos + 8, (int) atomlen);
|
||||
}
|
||||
|
||||
// Keep going if not yet at end
|
||||
if (atomlen < len) {
|
||||
int atomleni = (int) atomlen;
|
||||
walkEscherBasic(indent, pos + atomleni + 8, len - atomleni - 8);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Blank line before next entry
|
||||
out.println();
|
||||
|
||||
// Look in children if we are a container
|
||||
if(type == 61443L || type == 61444L) {
|
||||
walkEscherBasic((indent+3), pos+8, (int)atomlen);
|
||||
}
|
||||
|
||||
// Keep going if not yet at end
|
||||
if(atomlen < len) {
|
||||
int atomleni = (int)atomlen;
|
||||
walkEscherBasic(indent, pos+atomleni+8, len-atomleni-8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,13 +31,14 @@ import org.apache.poi.util.StringUtil;
|
||||
/**
|
||||
* A CString (type 4026). Holds a unicode string, and the first two bytes
|
||||
* of the record header normally encode the count. Typically attached to
|
||||
* some complex sequence of records, eg Commetns.
|
||||
* some complex sequence of records, eg Comments.
|
||||
*/
|
||||
|
||||
public final class CString extends RecordAtom {
|
||||
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 1_000_000;
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 1_000_000;
|
||||
private static int MAX_RECORD_LENGTH = 1_000_000;
|
||||
|
||||
private byte[] _header;
|
||||
|
||||
@ -49,6 +50,20 @@ public final class CString extends RecordAtom {
|
||||
return StringUtil.getFromUnicodeLE(_text);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param length the max record length allowed for CString
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max record length allowed for CString
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
/** Updates the text in the Atom. */
|
||||
public void setText(String text) {
|
||||
// Convert to little endian unicode
|
||||
|
||||
@ -36,7 +36,8 @@ public class ExObjListAtom extends RecordAtom
|
||||
{
|
||||
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 1_000_000;
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 1_000_000;
|
||||
private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
|
||||
/**
|
||||
* Record header.
|
||||
@ -48,6 +49,20 @@ public class ExObjListAtom extends RecordAtom
|
||||
*/
|
||||
private byte[] _data;
|
||||
|
||||
/**
|
||||
* @param length the max record length allowed for MasterTextPropAtom
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max record length allowed for MasterTextPropAtom
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a brand new link related atom record.
|
||||
*/
|
||||
|
||||
@ -51,14 +51,14 @@ public class FontEmbeddedData extends RecordAtom implements FontFacet {
|
||||
private FontHeader fontHeader;
|
||||
|
||||
/**
|
||||
* @param length the max length allowed for FontEmbeddedData
|
||||
* @param length the max record length allowed for FontEmbeddedData
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max length allowed for FontEmbeddedData
|
||||
* @return the max record length allowed for FontEmbeddedData
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
|
||||
@ -38,7 +38,8 @@ import org.apache.poi.util.LittleEndian;
|
||||
public final class MasterTextPropAtom extends RecordAtom {
|
||||
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 100_000;
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 100_000;
|
||||
private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
|
||||
/**
|
||||
* Record header.
|
||||
@ -53,6 +54,20 @@ public final class MasterTextPropAtom extends RecordAtom {
|
||||
// indent details
|
||||
private List<IndentProp> indents;
|
||||
|
||||
/**
|
||||
* @param length the max record length allowed for MasterTextPropAtom
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max record length allowed for MasterTextPropAtom
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new empty master text prop atom.
|
||||
*/
|
||||
|
||||
@ -36,7 +36,8 @@ import org.apache.poi.util.LittleEndian;
|
||||
public final class StyleTextProp9Atom extends RecordAtom {
|
||||
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 100_000;
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 100_000;
|
||||
private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
|
||||
private final TextPFException9[] autoNumberSchemes;
|
||||
/** Record header. */
|
||||
@ -47,6 +48,20 @@ public final class StyleTextProp9Atom extends RecordAtom {
|
||||
private short recordId;
|
||||
private int length;
|
||||
|
||||
/**
|
||||
* @param length the max record length allowed for StyleTextProp9Atom
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max record length allowed for StyleTextProp9Atom
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the link related atom record from its
|
||||
* source data.
|
||||
|
||||
@ -85,7 +85,8 @@ public final class HSLFSlideShow extends POIDocument implements SlideShow<HSLFSh
|
||||
private static final Logger LOG = LogManager.getLogger(HSLFSlideShow.class);
|
||||
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 10_000_000;
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 10_000_000;
|
||||
private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
|
||||
enum LoadSavePhase {
|
||||
INIT, LOADED
|
||||
@ -112,6 +113,19 @@ public final class HSLFSlideShow extends POIDocument implements SlideShow<HSLFSh
|
||||
private final List<HSLFNotes> _notes = new ArrayList<>();
|
||||
private FontCollection _fonts;
|
||||
|
||||
/**
|
||||
* @param length the max record length allowed for HSLFSlideShow
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max record length allowed for HSLFSlideShow
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a Powerpoint document from the underlying
|
||||
|
||||
@ -60,7 +60,8 @@ public abstract class PropertiesChunk extends Chunk {
|
||||
public static final String NAME = "__properties_version1.0";
|
||||
|
||||
// arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 1_000_000;
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 1_000_000;
|
||||
private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
|
||||
// standard prefix, defined in the spec
|
||||
public static final String VARIABLE_LENGTH_PROPERTY_PREFIX = "__substg1.0_";
|
||||
@ -84,6 +85,20 @@ public abstract class PropertiesChunk extends Chunk {
|
||||
*/
|
||||
private final ChunkGroup parentGroup;
|
||||
|
||||
/**
|
||||
* @param length the max record length allowed for PropertiesChunk
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max record length allowed for PropertiesChunk
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Properties Chunk.
|
||||
*/
|
||||
|
||||
@ -29,10 +29,25 @@ public final class DocumentProperties extends DOPAbstractType
|
||||
{
|
||||
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 100_000;
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 100_000;
|
||||
private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
|
||||
private byte[] _preserved;
|
||||
|
||||
/**
|
||||
* @param length the max record length allowed for DocumentProperties
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max record length allowed for DocumentProperties
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #DocumentProperties(byte[],int,int)} instead
|
||||
*/
|
||||
|
||||
@ -32,175 +32,172 @@ import org.apache.poi.util.LittleEndianConsts;
|
||||
* that stores info about the whole structure and the fonts
|
||||
*/
|
||||
@Internal
|
||||
public final class Ffn
|
||||
{
|
||||
public final class Ffn {
|
||||
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 100_000;
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 100_000;
|
||||
private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
|
||||
private int _cbFfnM1;//total length of FFN - 1.
|
||||
private byte _info;
|
||||
private int _cbFfnM1;//total length of FFN - 1.
|
||||
private byte _info;
|
||||
private static BitField _prq = BitFieldFactory.getInstance(0x0003);// pitch request
|
||||
private static BitField _fTrueType = BitFieldFactory.getInstance(0x0004);// when 1, font is a TrueType font
|
||||
private static BitField _ff = BitFieldFactory.getInstance(0x0070);
|
||||
private short _wWeight;// base weight of font
|
||||
private byte _chs;// character set identifier
|
||||
private byte _ixchSzAlt; // index into ffn.szFfn to the name of
|
||||
// the alternate font
|
||||
private byte [] _panose = new byte[10];//????
|
||||
private byte [] _fontSig = new byte[24];//????
|
||||
private short _wWeight;// base weight of font
|
||||
private byte _chs;// character set identifier
|
||||
private byte _ixchSzAlt; // index into ffn.szFfn to the name of
|
||||
// the alternate font
|
||||
private byte[] _panose = new byte[10];//????
|
||||
private byte[] _fontSig = new byte[24];//????
|
||||
|
||||
// zero terminated string that records name of font, cuurently not
|
||||
// supporting Extended chars
|
||||
private char [] _xszFfn;
|
||||
// zero terminated string that records name of font, cuurently not
|
||||
// supporting Extended chars
|
||||
private char[] _xszFfn;
|
||||
|
||||
// extra facilitator members
|
||||
private int _xszFfnLength;
|
||||
// extra facilitator members
|
||||
private int _xszFfnLength;
|
||||
|
||||
public Ffn(byte[] buf, int offset)
|
||||
{
|
||||
int offsetTmp = offset;
|
||||
|
||||
_cbFfnM1 = LittleEndian.getUByte(buf,offset);
|
||||
offset += LittleEndianConsts.BYTE_SIZE;
|
||||
_info = buf[offset];
|
||||
offset += LittleEndianConsts.BYTE_SIZE;
|
||||
_wWeight = LittleEndian.getShort(buf, offset);
|
||||
offset += LittleEndianConsts.SHORT_SIZE;
|
||||
_chs = buf[offset];
|
||||
offset += LittleEndianConsts.BYTE_SIZE;
|
||||
_ixchSzAlt = buf[offset];
|
||||
offset += LittleEndianConsts.BYTE_SIZE;
|
||||
|
||||
// read panose and fs so we can write them back out.
|
||||
System.arraycopy(buf, offset, _panose, 0, _panose.length);
|
||||
offset += _panose.length;
|
||||
System.arraycopy(buf, offset, _fontSig, 0, _fontSig.length);
|
||||
offset += _fontSig.length;
|
||||
|
||||
offsetTmp = offset - offsetTmp;
|
||||
_xszFfnLength = (this.getSize() - offsetTmp)/2;
|
||||
_xszFfn = new char[_xszFfnLength];
|
||||
|
||||
for(int i = 0; i < _xszFfnLength; i++)
|
||||
{
|
||||
_xszFfn[i] = (char)LittleEndian.getShort(buf, offset);
|
||||
offset += LittleEndianConsts.SHORT_SIZE;
|
||||
/**
|
||||
* @param length the max record length allowed for Ffn
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max record length allowed for Ffn
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
public Ffn(byte[] buf, int offset) {
|
||||
int offsetTmp = offset;
|
||||
|
||||
}
|
||||
_cbFfnM1 = LittleEndian.getUByte(buf, offset);
|
||||
offset += LittleEndianConsts.BYTE_SIZE;
|
||||
_info = buf[offset];
|
||||
offset += LittleEndianConsts.BYTE_SIZE;
|
||||
_wWeight = LittleEndian.getShort(buf, offset);
|
||||
offset += LittleEndianConsts.SHORT_SIZE;
|
||||
_chs = buf[offset];
|
||||
offset += LittleEndianConsts.BYTE_SIZE;
|
||||
_ixchSzAlt = buf[offset];
|
||||
offset += LittleEndianConsts.BYTE_SIZE;
|
||||
|
||||
public int get_cbFfnM1()
|
||||
{
|
||||
return _cbFfnM1;
|
||||
}
|
||||
// read panose and fs so we can write them back out.
|
||||
System.arraycopy(buf, offset, _panose, 0, _panose.length);
|
||||
offset += _panose.length;
|
||||
System.arraycopy(buf, offset, _fontSig, 0, _fontSig.length);
|
||||
offset += _fontSig.length;
|
||||
|
||||
public short getWeight()
|
||||
{
|
||||
return _wWeight;
|
||||
}
|
||||
offsetTmp = offset - offsetTmp;
|
||||
_xszFfnLength = (this.getSize() - offsetTmp) / 2;
|
||||
_xszFfn = new char[_xszFfnLength];
|
||||
|
||||
public byte getChs()
|
||||
{
|
||||
return _chs;
|
||||
}
|
||||
for (int i = 0; i < _xszFfnLength; i++) {
|
||||
_xszFfn[i] = (char) LittleEndian.getShort(buf, offset);
|
||||
offset += LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
public byte [] getPanose()
|
||||
{
|
||||
return _panose;
|
||||
}
|
||||
|
||||
public byte [] getFontSig()
|
||||
{
|
||||
return _fontSig;
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return (_cbFfnM1 + 1);
|
||||
}
|
||||
|
||||
public String getMainFontName()
|
||||
{
|
||||
int index = 0;
|
||||
for (;index < _xszFfnLength; index++)
|
||||
{
|
||||
if (_xszFfn[index] == '\0')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new String(_xszFfn, 0, index);
|
||||
}
|
||||
|
||||
public String getAltFontName()
|
||||
{
|
||||
int index = _ixchSzAlt;
|
||||
for (;index < _xszFfnLength; index++)
|
||||
{
|
||||
if (_xszFfn[index] == '\0')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new String(_xszFfn, _ixchSzAlt, index);
|
||||
|
||||
}
|
||||
|
||||
public void set_cbFfnM1(int _cbFfnM1)
|
||||
{
|
||||
this._cbFfnM1 = _cbFfnM1;
|
||||
}
|
||||
|
||||
// changed protected to public
|
||||
public byte[] toByteArray()
|
||||
{
|
||||
int offset = 0;
|
||||
byte[] buf = IOUtils.safelyAllocate(this.getSize(), MAX_RECORD_LENGTH);
|
||||
|
||||
buf[offset] = (byte)_cbFfnM1;
|
||||
offset += LittleEndianConsts.BYTE_SIZE;
|
||||
buf[offset] = _info;
|
||||
offset += LittleEndianConsts.BYTE_SIZE;
|
||||
LittleEndian.putShort(buf, offset, _wWeight);
|
||||
offset += LittleEndianConsts.SHORT_SIZE;
|
||||
buf[offset] = _chs;
|
||||
offset += LittleEndianConsts.BYTE_SIZE;
|
||||
buf[offset] = _ixchSzAlt;
|
||||
offset += LittleEndianConsts.BYTE_SIZE;
|
||||
|
||||
System.arraycopy(_panose,0,buf, offset,_panose.length);
|
||||
offset += _panose.length;
|
||||
System.arraycopy(_fontSig,0,buf, offset, _fontSig.length);
|
||||
offset += _fontSig.length;
|
||||
|
||||
for(int i = 0; i < _xszFfn.length; i++)
|
||||
{
|
||||
LittleEndian.putShort(buf, offset, (short)_xszFfn[i]);
|
||||
offset += LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
return buf;
|
||||
public int get_cbFfnM1() {
|
||||
return _cbFfnM1;
|
||||
}
|
||||
|
||||
}
|
||||
public short getWeight() {
|
||||
return _wWeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof Ffn)) return false;
|
||||
Ffn o = (Ffn)other;
|
||||
public byte getChs() {
|
||||
return _chs;
|
||||
}
|
||||
|
||||
return (
|
||||
o._cbFfnM1 == this._cbFfnM1
|
||||
&& o._info == this._info
|
||||
&& o._wWeight == _wWeight
|
||||
&& o._chs == _chs
|
||||
&& o._ixchSzAlt == _ixchSzAlt
|
||||
&& Arrays.equals(o._panose,_panose)
|
||||
&& Arrays.equals(o._fontSig,_fontSig)
|
||||
&& Arrays.equals(o._xszFfn,_xszFfn)
|
||||
);
|
||||
}
|
||||
public byte[] getPanose() {
|
||||
return _panose;
|
||||
}
|
||||
|
||||
public byte[] getFontSig() {
|
||||
return _fontSig;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return (_cbFfnM1 + 1);
|
||||
}
|
||||
|
||||
public String getMainFontName() {
|
||||
int index = 0;
|
||||
for (; index < _xszFfnLength; index++) {
|
||||
if (_xszFfn[index] == '\0') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new String(_xszFfn, 0, index);
|
||||
}
|
||||
|
||||
public String getAltFontName() {
|
||||
int index = _ixchSzAlt;
|
||||
for (; index < _xszFfnLength; index++) {
|
||||
if (_xszFfn[index] == '\0') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new String(_xszFfn, _ixchSzAlt, index);
|
||||
|
||||
}
|
||||
|
||||
public void set_cbFfnM1(int _cbFfnM1) {
|
||||
this._cbFfnM1 = _cbFfnM1;
|
||||
}
|
||||
|
||||
// changed protected to public
|
||||
public byte[] toByteArray() {
|
||||
int offset = 0;
|
||||
byte[] buf = IOUtils.safelyAllocate(this.getSize(), MAX_RECORD_LENGTH);
|
||||
|
||||
buf[offset] = (byte) _cbFfnM1;
|
||||
offset += LittleEndianConsts.BYTE_SIZE;
|
||||
buf[offset] = _info;
|
||||
offset += LittleEndianConsts.BYTE_SIZE;
|
||||
LittleEndian.putShort(buf, offset, _wWeight);
|
||||
offset += LittleEndianConsts.SHORT_SIZE;
|
||||
buf[offset] = _chs;
|
||||
offset += LittleEndianConsts.BYTE_SIZE;
|
||||
buf[offset] = _ixchSzAlt;
|
||||
offset += LittleEndianConsts.BYTE_SIZE;
|
||||
|
||||
System.arraycopy(_panose, 0, buf, offset, _panose.length);
|
||||
offset += _panose.length;
|
||||
System.arraycopy(_fontSig, 0, buf, offset, _fontSig.length);
|
||||
offset += _fontSig.length;
|
||||
|
||||
for (int i = 0; i < _xszFfn.length; i++) {
|
||||
LittleEndian.putShort(buf, offset, (short) _xszFfn[i]);
|
||||
offset += LittleEndianConsts.SHORT_SIZE;
|
||||
}
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof Ffn)) return false;
|
||||
Ffn o = (Ffn) other;
|
||||
|
||||
return (
|
||||
o._cbFfnM1 == this._cbFfnM1
|
||||
&& o._info == this._info
|
||||
&& o._wWeight == _wWeight
|
||||
&& o._chs == _chs
|
||||
&& o._ixchSzAlt == _ixchSzAlt
|
||||
&& Arrays.equals(o._panose, _panose)
|
||||
&& Arrays.equals(o._fontSig, _fontSig)
|
||||
&& Arrays.equals(o._xszFfn, _xszFfn)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
|
||||
@ -28,9 +28,6 @@ import org.apache.poi.util.LittleEndianConsts;
|
||||
@Internal
|
||||
public final class SprmBuffer implements Duplicatable {
|
||||
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 100_000;
|
||||
|
||||
byte[] _buf;
|
||||
boolean _istd;
|
||||
int _offset;
|
||||
@ -56,7 +53,7 @@ public final class SprmBuffer implements Duplicatable {
|
||||
}
|
||||
|
||||
public SprmBuffer(int sprmsStartOffset) {
|
||||
_buf = IOUtils.safelyAllocate(sprmsStartOffset + 4L, MAX_RECORD_LENGTH);
|
||||
_buf = IOUtils.safelyAllocate(sprmsStartOffset + 4L, SprmUtils.MAX_RECORD_LENGTH);
|
||||
_offset = sprmsStartOffset;
|
||||
_sprmsStartOffset = sprmsStartOffset;
|
||||
}
|
||||
@ -118,7 +115,7 @@ public final class SprmBuffer implements Duplicatable {
|
||||
// commented - buffer shall not contain any additional bytes --
|
||||
// sergey
|
||||
// byte[] newBuf = new byte[_offset + addition + 6];
|
||||
IOUtils.safelyAllocateCheck(_offset + (long)addition, MAX_RECORD_LENGTH);
|
||||
IOUtils.safelyAllocateCheck(_offset + (long)addition, SprmUtils.MAX_RECORD_LENGTH);
|
||||
_buf = Arrays.copyOf(_buf, _offset + addition);
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,14 +30,14 @@ public final class SprmUtils {
|
||||
static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
|
||||
/**
|
||||
* @param length the max length allowed for SPRM data
|
||||
* @param length the max record length allowed for SPRM data
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max length allowed for SPRM data
|
||||
* @return the max record length allowed for SPRM data
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
|
||||
@ -37,7 +37,8 @@ import org.apache.poi.util.Removal;
|
||||
public final class EscherArrayProperty extends EscherComplexProperty implements Iterable<byte[]> {
|
||||
|
||||
// arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 100_000;
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 100_000;
|
||||
private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
|
||||
/**
|
||||
* The size of the header that goes at the start of the array, before the data
|
||||
@ -54,6 +55,20 @@ public final class EscherArrayProperty extends EscherComplexProperty implements
|
||||
*/
|
||||
private final boolean emptyComplexPart;
|
||||
|
||||
/**
|
||||
* @param length the max record length allowed for EscherArrayProperty
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max record length allowed for EscherArrayProperty
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of an escher array property.
|
||||
* This constructor can be used to create emptyComplexParts with a complexSize = 0.
|
||||
|
||||
@ -57,14 +57,14 @@ public final class EscherBSERecord extends EscherRecord {
|
||||
private byte[] _remainingData = new byte[0];
|
||||
|
||||
/**
|
||||
* @param length the max length allowed for EscherBSERecord
|
||||
* @param length the max record length allowed for EscherBSERecord
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max length allowed for EscherBSERecord
|
||||
* @return the max record length allowed for EscherBSERecord
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
|
||||
@ -38,14 +38,14 @@ public class EscherBlipRecord extends EscherRecord {
|
||||
private byte[] field_pictureData;
|
||||
|
||||
/**
|
||||
* @param length the max length allowed for EscherBlipRecord
|
||||
* @param length the max record length allowed for EscherBlipRecord
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max length allowed for EscherBlipRecord
|
||||
* @return the max record length allowed for EscherBlipRecord
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
|
||||
@ -62,14 +62,14 @@ public class EscherClientAnchorRecord extends EscherRecord {
|
||||
private boolean shortRecord;
|
||||
|
||||
/**
|
||||
* @param length the max length allowed for EscherClientAnchorRecord
|
||||
* @param length the max record length allowed for EscherClientAnchorRecord
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max length allowed for EscherClientAnchorRecord
|
||||
* @return the max record length allowed for EscherClientAnchorRecord
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
|
||||
@ -41,14 +41,14 @@ public class EscherClientDataRecord extends EscherRecord {
|
||||
private byte[] remainingData;
|
||||
|
||||
/**
|
||||
* @param length the max length allowed for EscherClientDataRecord
|
||||
* @param length the max record length allowed for EscherClientDataRecord
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max length allowed for EscherClientDataRecord
|
||||
* @return the max record length allowed for EscherClientDataRecord
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
|
||||
@ -79,14 +79,14 @@ public final class EscherMetafileBlip extends EscherBlipRecord {
|
||||
private byte[] remainingData;
|
||||
|
||||
/**
|
||||
* @param length the max length allowed for EscherMetafileBlip
|
||||
* @param length the max record length allowed for EscherMetafileBlip
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max length allowed for EscherMetafileBlip
|
||||
* @return the max record length allowed for EscherMetafileBlip
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
|
||||
@ -45,14 +45,14 @@ public final class EscherTextboxRecord extends EscherRecord {
|
||||
private byte[] thedata = NO_BYTES;
|
||||
|
||||
/**
|
||||
* @param length the max length allowed for EscherTextboxRecord
|
||||
* @param length the max record length allowed for EscherTextboxRecord
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max length allowed for EscherTextboxRecord
|
||||
* @return the max record length allowed for EscherTextboxRecord
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
|
||||
@ -34,7 +34,8 @@ import org.apache.poi.util.LittleEndian;
|
||||
public final class UnknownEscherRecord extends EscherRecord {
|
||||
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 100_000_000;
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 100_000_000;
|
||||
private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
|
||||
private static final byte[] NO_BYTES = new byte[0];
|
||||
|
||||
@ -42,6 +43,20 @@ public final class UnknownEscherRecord extends EscherRecord {
|
||||
private byte[] thedata = NO_BYTES;
|
||||
private final List<EscherRecord> _childRecords = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* @param length the max record length allowed for UnknownEscherRecord
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max record length allowed for UnknownEscherRecord
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
public UnknownEscherRecord() {}
|
||||
|
||||
public UnknownEscherRecord(UnknownEscherRecord other) {
|
||||
|
||||
@ -30,14 +30,14 @@ public class Blob {
|
||||
private byte[] _value;
|
||||
|
||||
/**
|
||||
* @param length the max length allowed for Blob
|
||||
* @param length the max record length allowed for Blob
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max length allowed for Blob
|
||||
* @return the max record length allowed for Blob
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
|
||||
@ -38,14 +38,14 @@ public class ClipboardData {
|
||||
private byte[] _value;
|
||||
|
||||
/**
|
||||
* @param length the max length allowed for ClipboardData
|
||||
* @param length the max record length allowed for ClipboardData
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max length allowed for ClipboardData
|
||||
* @return the max record length allowed for ClipboardData
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
|
||||
@ -42,14 +42,14 @@ public class CodePageString {
|
||||
private byte[] _value;
|
||||
|
||||
/**
|
||||
* @param length the max length allowed for CodePageString
|
||||
* @param length the max record length allowed for CodePageString
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max length allowed for CodePageString
|
||||
* @return the max record length allowed for CodePageString
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
|
||||
@ -63,8 +63,8 @@ public class OldExcelExtractor implements POITextExtractor {
|
||||
|
||||
private static final int FILE_PASS_RECORD_SID = 0x2f;
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 100_000;
|
||||
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 100_000;
|
||||
private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
|
||||
private RecordInputStream ris;
|
||||
|
||||
@ -74,6 +74,20 @@ public class OldExcelExtractor implements POITextExtractor {
|
||||
private int biffVersion;
|
||||
private int fileType;
|
||||
|
||||
/**
|
||||
* @param length the max record length allowed for OldExcelExtractor
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max record length allowed for OldExcelExtractor
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
public OldExcelExtractor(InputStream input) throws IOException {
|
||||
open(input);
|
||||
}
|
||||
|
||||
@ -38,12 +38,27 @@ public final class Biff8DecryptingStream implements BiffHeaderInput, LittleEndia
|
||||
|
||||
public static final int RC4_REKEYING_INTERVAL = 1024;
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 100_000;
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 100_000;
|
||||
private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
|
||||
private final ChunkedCipherInputStream ccis;
|
||||
private final byte[] buffer = new byte[LittleEndianConsts.LONG_SIZE];
|
||||
private boolean shouldSkipEncryptionOnCurrentRecord;
|
||||
|
||||
/**
|
||||
* @param length the max record length allowed for Biff8DecryptingStream
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max record length allowed for Biff8DecryptingStream
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
public Biff8DecryptingStream(InputStream in, int initialOffset, EncryptionInfo info) throws RecordFormatException {
|
||||
try {
|
||||
byte[] initialBuf = IOUtils.safelyAllocate(initialOffset, MAX_RECORD_LENGTH);
|
||||
|
||||
@ -138,8 +138,10 @@ import org.apache.poi.util.Removal;
|
||||
public final class HSSFWorkbook extends POIDocument implements Workbook {
|
||||
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 100_000;
|
||||
private static final int MAX_IMAGE_LENGTH = 50_000_000;
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 100_000;
|
||||
private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
private static final int DEFAULT_MAX_IMAGE_LENGTH = 50_000_000;
|
||||
private static int MAX_IMAGE_LENGTH = DEFAULT_MAX_IMAGE_LENGTH;
|
||||
|
||||
private static final Pattern COMMA_PATTERN = Pattern.compile(",");
|
||||
|
||||
@ -218,6 +220,34 @@ public final class HSSFWorkbook extends POIDocument implements Workbook {
|
||||
return new HSSFWorkbook(book);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param length the max record length allowed for HSSFWorkbook
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max record length allowed for HSSFWorkbook
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param length the max image length allowed for HSSFWorkbook
|
||||
*/
|
||||
public static void setMaxImageLength(int length) {
|
||||
MAX_IMAGE_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max image length allowed for HSSFWorkbook
|
||||
*/
|
||||
public static int getMaxImageLength() {
|
||||
return MAX_IMAGE_LENGTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new HSSFWorkbook from scratch (start here!)
|
||||
*/
|
||||
|
||||
@ -31,10 +31,6 @@ import org.apache.poi.util.LittleEndianInputStream;
|
||||
@Internal
|
||||
public abstract class ChunkedCipherInputStream extends LittleEndianInputStream {
|
||||
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 100_000;
|
||||
private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
|
||||
private final int chunkSize;
|
||||
private final int chunkBits;
|
||||
|
||||
@ -46,20 +42,6 @@ public abstract class ChunkedCipherInputStream extends LittleEndianInputStream {
|
||||
private long pos;
|
||||
private boolean chunkIsValid;
|
||||
|
||||
/**
|
||||
* @param length the max length allowed for ChunkedCipherInputStream
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max length allowed for ChunkedCipherInputStream
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
public ChunkedCipherInputStream(InputStream stream, long size, int chunkSize)
|
||||
throws GeneralSecurityException {
|
||||
this(stream, size, chunkSize, 0);
|
||||
@ -72,8 +54,8 @@ public abstract class ChunkedCipherInputStream extends LittleEndianInputStream {
|
||||
this.pos = initialPos;
|
||||
this.chunkSize = chunkSize;
|
||||
int cs = chunkSize == -1 ? 4096 : chunkSize;
|
||||
this.chunk = IOUtils.safelyAllocate(cs, MAX_RECORD_LENGTH);
|
||||
this.plain = IOUtils.safelyAllocate(cs, MAX_RECORD_LENGTH);
|
||||
this.chunk = IOUtils.safelyAllocate(cs, CryptoFunctions.MAX_RECORD_LENGTH);
|
||||
this.plain = IOUtils.safelyAllocate(cs, CryptoFunctions.MAX_RECORD_LENGTH);
|
||||
this.chunkBits = Integer.bitCount(chunk.length-1);
|
||||
this.lastIndex = (int)(pos >> chunkBits);
|
||||
this.cipher = initCipherForBlock(null, lastIndex);
|
||||
|
||||
@ -43,9 +43,6 @@ import org.apache.poi.util.TempFile;
|
||||
@Internal
|
||||
public abstract class ChunkedCipherOutputStream extends FilterOutputStream {
|
||||
private static final Logger LOG = LogManager.getLogger(ChunkedCipherOutputStream.class);
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 100_000;
|
||||
private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
|
||||
private static final int STREAMING = -1;
|
||||
|
||||
@ -66,25 +63,11 @@ public abstract class ChunkedCipherOutputStream extends FilterOutputStream {
|
||||
private Cipher cipher;
|
||||
private boolean isClosed;
|
||||
|
||||
/**
|
||||
* @param length the max length allowed for ChunkedCipherOutputStream
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max length allowed for ChunkedCipherOutputStream
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
public ChunkedCipherOutputStream(DirectoryNode dir, int chunkSize) throws IOException, GeneralSecurityException {
|
||||
super(null);
|
||||
this.chunkSize = chunkSize;
|
||||
int cs = chunkSize == STREAMING ? 4096 : chunkSize;
|
||||
this.chunk = IOUtils.safelyAllocate(cs, MAX_RECORD_LENGTH);
|
||||
this.chunk = IOUtils.safelyAllocate(cs, CryptoFunctions.MAX_RECORD_LENGTH);
|
||||
this.plainByteFlags = new SparseBitSet(cs);
|
||||
this.chunkBits = Integer.bitCount(cs-1);
|
||||
this.fileOut = TempFile.createTempFile("encrypted_package", "crypt");
|
||||
@ -98,7 +81,7 @@ public abstract class ChunkedCipherOutputStream extends FilterOutputStream {
|
||||
super(stream);
|
||||
this.chunkSize = chunkSize;
|
||||
int cs = chunkSize == STREAMING ? 4096 : chunkSize;
|
||||
this.chunk = IOUtils.safelyAllocate(cs, MAX_RECORD_LENGTH);
|
||||
this.chunk = IOUtils.safelyAllocate(cs, CryptoFunctions.MAX_RECORD_LENGTH);
|
||||
this.plainByteFlags = new SparseBitSet(cs);
|
||||
this.chunkBits = Integer.bitCount(cs-1);
|
||||
this.fileOut = null;
|
||||
|
||||
@ -47,7 +47,22 @@ import org.apache.poi.util.StringUtil;
|
||||
public final class CryptoFunctions {
|
||||
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 100_000;
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 100_000;
|
||||
static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
|
||||
/**
|
||||
* @param length the max record length allowed for CryptoFunctions
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max record length allowed for CryptoFunctions
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
private CryptoFunctions() {
|
||||
}
|
||||
|
||||
@ -35,24 +35,6 @@ import org.apache.poi.util.StringUtil;
|
||||
|
||||
public class DataSpaceMapUtils {
|
||||
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 100_000;
|
||||
private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
|
||||
/**
|
||||
* @param length the max length allowed for EscherTextboxRecord
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max length allowed for EscherTextboxRecord
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
public static void addDefaultDataSpace(DirectoryEntry dir) throws IOException {
|
||||
DataSpaceMapEntry dsme = new DataSpaceMapEntry(
|
||||
new int[]{ 0 }
|
||||
@ -352,7 +334,7 @@ public class DataSpaceMapUtils {
|
||||
return length == 0 ? null : "";
|
||||
}
|
||||
|
||||
byte[] data = IOUtils.safelyAllocate(length, MAX_RECORD_LENGTH);
|
||||
byte[] data = IOUtils.safelyAllocate(length, CryptoFunctions.MAX_RECORD_LENGTH);
|
||||
is.readFully(data);
|
||||
|
||||
// Padding (variable): A set of bytes that MUST be of correct size such that the size of the UTF-8-LP-P4
|
||||
|
||||
@ -68,11 +68,26 @@ import org.w3c.dom.Document;
|
||||
public class AgileEncryptor extends Encryptor {
|
||||
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 1_000_000;
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 1_000_000;
|
||||
private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
|
||||
private byte[] integritySalt;
|
||||
private byte[] pwHash;
|
||||
|
||||
/**
|
||||
* @param length the max record length allowed for AgileEncryptor
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max record length allowed for AgileEncryptor
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
protected AgileEncryptor() {}
|
||||
|
||||
protected AgileEncryptor(AgileEncryptor other) {
|
||||
|
||||
@ -50,9 +50,11 @@ public class Ole10Native {
|
||||
public static final String OLE10_NATIVE = "\u0001Ole10Native";
|
||||
private static final Charset ISO1 = StandardCharsets.ISO_8859_1;
|
||||
// arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 100_000_000;
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 100_000_000;
|
||||
private static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
// arbitrarily selected; may need to increase
|
||||
private static final int MAX_STRING_LENGTH = 1024;
|
||||
private static final int DEFAULT_MAX_STRING_LENGTH = 1024;
|
||||
private static int MAX_STRING_LENGTH = DEFAULT_MAX_STRING_LENGTH;
|
||||
|
||||
/**
|
||||
* Default content of the \u0001Ole entry
|
||||
@ -138,6 +140,34 @@ public class Ole10Native {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param length the max record length allowed for Ole10Native
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max record length allowed for Ole10Native
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param length the max string length allowed for Ole10Native
|
||||
*/
|
||||
public static void setMaxStringLength(int length) {
|
||||
MAX_STRING_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max string length allowed for Ole10Native
|
||||
*/
|
||||
public static int getMaxStringLength() {
|
||||
return MAX_STRING_LENGTH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance and fills the fields based on ... the fields
|
||||
*/
|
||||
|
||||
@ -40,139 +40,133 @@ import org.apache.poi.util.IOUtils;
|
||||
*/
|
||||
public final class POIFSDocument implements POIFSViewable, Iterable<ByteBuffer> {
|
||||
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 100_000;
|
||||
|
||||
private DocumentProperty _property;
|
||||
|
||||
private POIFSFileSystem _filesystem;
|
||||
private POIFSStream _stream;
|
||||
private int _block_size;
|
||||
|
||||
/**
|
||||
* Constructor for an existing Document
|
||||
*/
|
||||
public POIFSDocument(DocumentNode document) {
|
||||
this((DocumentProperty)document.getProperty(),
|
||||
((DirectoryNode)document.getParent()).getFileSystem());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for an existing Document
|
||||
*/
|
||||
public POIFSDocument(DocumentProperty property, POIFSFileSystem filesystem) {
|
||||
this._property = property;
|
||||
this._filesystem = filesystem;
|
||||
private POIFSFileSystem _filesystem;
|
||||
private POIFSStream _stream;
|
||||
private int _block_size;
|
||||
|
||||
if(property.getSize() < POIFSConstants.BIG_BLOCK_MINIMUM_DOCUMENT_SIZE) {
|
||||
_stream = new POIFSStream(_filesystem.getMiniStore(), property.getStartBlock());
|
||||
_block_size = _filesystem.getMiniStore().getBlockStoreBlockSize();
|
||||
} else {
|
||||
_stream = new POIFSStream(_filesystem, property.getStartBlock());
|
||||
_block_size = _filesystem.getBlockStoreBlockSize();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Constructor for an existing Document
|
||||
*/
|
||||
public POIFSDocument(DocumentNode document) {
|
||||
this((DocumentProperty) document.getProperty(),
|
||||
((DirectoryNode) document.getParent()).getFileSystem());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for a new Document
|
||||
*
|
||||
* @param name the name of the POIFSDocument
|
||||
* @param stream the InputStream we read data from
|
||||
*/
|
||||
public POIFSDocument(String name, POIFSFileSystem filesystem, InputStream stream)
|
||||
throws IOException
|
||||
{
|
||||
this._filesystem = filesystem;
|
||||
/**
|
||||
* Constructor for an existing Document
|
||||
*/
|
||||
public POIFSDocument(DocumentProperty property, POIFSFileSystem filesystem) {
|
||||
this._property = property;
|
||||
this._filesystem = filesystem;
|
||||
|
||||
// Store it
|
||||
int length = store(stream);
|
||||
if (property.getSize() < POIFSConstants.BIG_BLOCK_MINIMUM_DOCUMENT_SIZE) {
|
||||
_stream = new POIFSStream(_filesystem.getMiniStore(), property.getStartBlock());
|
||||
_block_size = _filesystem.getMiniStore().getBlockStoreBlockSize();
|
||||
} else {
|
||||
_stream = new POIFSStream(_filesystem, property.getStartBlock());
|
||||
_block_size = _filesystem.getBlockStoreBlockSize();
|
||||
}
|
||||
}
|
||||
|
||||
// Build the property for it
|
||||
this._property = new DocumentProperty(name, length);
|
||||
_property.setStartBlock(_stream.getStartBlock());
|
||||
_property.setDocument(this);
|
||||
}
|
||||
|
||||
public POIFSDocument(String name, final int size, POIFSFileSystem filesystem, POIFSWriterListener writer)
|
||||
throws IOException
|
||||
{
|
||||
this._filesystem = filesystem;
|
||||
/**
|
||||
* Constructor for a new Document
|
||||
*
|
||||
* @param name the name of the POIFSDocument
|
||||
* @param stream the InputStream we read data from
|
||||
*/
|
||||
public POIFSDocument(String name, POIFSFileSystem filesystem, InputStream stream)
|
||||
throws IOException {
|
||||
this._filesystem = filesystem;
|
||||
|
||||
if (size < POIFSConstants.BIG_BLOCK_MINIMUM_DOCUMENT_SIZE) {
|
||||
_stream = new POIFSStream(filesystem.getMiniStore());
|
||||
_block_size = _filesystem.getMiniStore().getBlockStoreBlockSize();
|
||||
} else {
|
||||
_stream = new POIFSStream(filesystem);
|
||||
_block_size = _filesystem.getBlockStoreBlockSize();
|
||||
}
|
||||
|
||||
this._property = new DocumentProperty(name, size);
|
||||
_property.setStartBlock(_stream.getStartBlock());
|
||||
_property.setDocument(this);
|
||||
// Store it
|
||||
int length = store(stream);
|
||||
|
||||
try (DocumentOutputStream os = new DocumentOutputStream(this, size)) {
|
||||
POIFSDocumentPath path = new POIFSDocumentPath(name.split("\\\\"));
|
||||
String docName = path.getComponent(path.length() - 1);
|
||||
POIFSWriterEvent event = new POIFSWriterEvent(os, path, docName, size);
|
||||
writer.processPOIFSWriterEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the given data for this Document
|
||||
*/
|
||||
private int store(InputStream stream) throws IOException {
|
||||
final int bigBlockSize = POIFSConstants.BIG_BLOCK_MINIMUM_DOCUMENT_SIZE;
|
||||
BufferedInputStream bis = new BufferedInputStream(stream, bigBlockSize+1);
|
||||
bis.mark(bigBlockSize);
|
||||
// Build the property for it
|
||||
this._property = new DocumentProperty(name, length);
|
||||
_property.setStartBlock(_stream.getStartBlock());
|
||||
_property.setDocument(this);
|
||||
}
|
||||
|
||||
// Do we need to store as a mini stream or a full one?
|
||||
long streamBlockSize = IOUtils.skipFully(bis, bigBlockSize);
|
||||
if (streamBlockSize < bigBlockSize) {
|
||||
_stream = new POIFSStream(_filesystem.getMiniStore());
|
||||
_block_size = _filesystem.getMiniStore().getBlockStoreBlockSize();
|
||||
} else {
|
||||
_stream = new POIFSStream(_filesystem);
|
||||
_block_size = _filesystem.getBlockStoreBlockSize();
|
||||
}
|
||||
public POIFSDocument(String name, final int size, POIFSFileSystem filesystem, POIFSWriterListener writer)
|
||||
throws IOException {
|
||||
this._filesystem = filesystem;
|
||||
|
||||
// start from the beginning
|
||||
bis.reset();
|
||||
|
||||
// Store it
|
||||
final long length;
|
||||
try (OutputStream os = _stream.getOutputStream()) {
|
||||
length = IOUtils.copy(bis, os);
|
||||
if (size < POIFSConstants.BIG_BLOCK_MINIMUM_DOCUMENT_SIZE) {
|
||||
_stream = new POIFSStream(filesystem.getMiniStore());
|
||||
_block_size = _filesystem.getMiniStore().getBlockStoreBlockSize();
|
||||
} else {
|
||||
_stream = new POIFSStream(filesystem);
|
||||
_block_size = _filesystem.getBlockStoreBlockSize();
|
||||
}
|
||||
|
||||
// Pad to the end of the block with -1s
|
||||
int usedInBlock = (int) (length % _block_size);
|
||||
if (usedInBlock != 0 && usedInBlock != _block_size) {
|
||||
int toBlockEnd = _block_size - usedInBlock;
|
||||
byte[] padding = IOUtils.safelyAllocate(toBlockEnd, MAX_RECORD_LENGTH);
|
||||
Arrays.fill(padding, (byte) 0xFF);
|
||||
os.write(padding);
|
||||
}
|
||||
}
|
||||
this._property = new DocumentProperty(name, size);
|
||||
_property.setStartBlock(_stream.getStartBlock());
|
||||
_property.setDocument(this);
|
||||
|
||||
return Math.toIntExact(length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the underlying stream and property
|
||||
*/
|
||||
void free() throws IOException {
|
||||
_stream.free();
|
||||
_property.setStartBlock(POIFSConstants.END_OF_CHAIN);
|
||||
}
|
||||
|
||||
POIFSFileSystem getFileSystem()
|
||||
{
|
||||
return _filesystem;
|
||||
}
|
||||
|
||||
int getDocumentBlockSize() {
|
||||
return _block_size;
|
||||
}
|
||||
try (DocumentOutputStream os = new DocumentOutputStream(this, size)) {
|
||||
POIFSDocumentPath path = new POIFSDocumentPath(name.split("\\\\"));
|
||||
String docName = path.getComponent(path.length() - 1);
|
||||
POIFSWriterEvent event = new POIFSWriterEvent(os, path, docName, size);
|
||||
writer.processPOIFSWriterEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the given data for this Document
|
||||
*/
|
||||
private int store(InputStream stream) throws IOException {
|
||||
final int bigBlockSize = POIFSConstants.BIG_BLOCK_MINIMUM_DOCUMENT_SIZE;
|
||||
BufferedInputStream bis = new BufferedInputStream(stream, bigBlockSize + 1);
|
||||
bis.mark(bigBlockSize);
|
||||
|
||||
// Do we need to store as a mini stream or a full one?
|
||||
long streamBlockSize = IOUtils.skipFully(bis, bigBlockSize);
|
||||
if (streamBlockSize < bigBlockSize) {
|
||||
_stream = new POIFSStream(_filesystem.getMiniStore());
|
||||
_block_size = _filesystem.getMiniStore().getBlockStoreBlockSize();
|
||||
} else {
|
||||
_stream = new POIFSStream(_filesystem);
|
||||
_block_size = _filesystem.getBlockStoreBlockSize();
|
||||
}
|
||||
|
||||
// start from the beginning
|
||||
bis.reset();
|
||||
|
||||
// Store it
|
||||
final long length;
|
||||
try (OutputStream os = _stream.getOutputStream()) {
|
||||
length = IOUtils.copy(bis, os);
|
||||
|
||||
// Pad to the end of the block with -1s
|
||||
int usedInBlock = (int) (length % _block_size);
|
||||
if (usedInBlock != 0 && usedInBlock != _block_size) {
|
||||
int toBlockEnd = _block_size - usedInBlock;
|
||||
byte[] padding = IOUtils.safelyAllocate(toBlockEnd, POIFSFileSystem.MAX_RECORD_LENGTH);
|
||||
Arrays.fill(padding, (byte) 0xFF);
|
||||
os.write(padding);
|
||||
}
|
||||
}
|
||||
|
||||
return Math.toIntExact(length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the underlying stream and property
|
||||
*/
|
||||
void free() throws IOException {
|
||||
_stream.free();
|
||||
_property.setStartBlock(POIFSConstants.END_OF_CHAIN);
|
||||
}
|
||||
|
||||
POIFSFileSystem getFileSystem() {
|
||||
return _filesystem;
|
||||
}
|
||||
|
||||
int getDocumentBlockSize() {
|
||||
return _block_size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<ByteBuffer> iterator() {
|
||||
@ -180,83 +174,83 @@ public final class POIFSDocument implements POIFSViewable, Iterable<ByteBuffer>
|
||||
}
|
||||
|
||||
Iterator<ByteBuffer> getBlockIterator() {
|
||||
return (getSize() > 0 ? _stream : Collections.<ByteBuffer>emptyList()).iterator();
|
||||
return (getSize() > 0 ? _stream : Collections.<ByteBuffer>emptyList()).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return size of the document
|
||||
*/
|
||||
public int getSize() {
|
||||
return _property.getSize();
|
||||
}
|
||||
|
||||
public void replaceContents(InputStream stream) throws IOException {
|
||||
free();
|
||||
int size = store(stream);
|
||||
_property.setStartBlock(_stream.getStartBlock());
|
||||
_property.updateSize(size);
|
||||
}
|
||||
/**
|
||||
* @return size of the document
|
||||
*/
|
||||
public int getSize() {
|
||||
return _property.getSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the instance's DocumentProperty
|
||||
*/
|
||||
DocumentProperty getDocumentProperty() {
|
||||
return _property;
|
||||
}
|
||||
public void replaceContents(InputStream stream) throws IOException {
|
||||
free();
|
||||
int size = store(stream);
|
||||
_property.setStartBlock(_stream.getStartBlock());
|
||||
_property.updateSize(size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of objects, some of which may implement POIFSViewable
|
||||
*
|
||||
* @return an array of Object; may not be null, but may be empty
|
||||
*/
|
||||
public Object[] getViewableArray() {
|
||||
String result = "<NO DATA>";
|
||||
/**
|
||||
* @return the instance's DocumentProperty
|
||||
*/
|
||||
DocumentProperty getDocumentProperty() {
|
||||
return _property;
|
||||
}
|
||||
|
||||
if(getSize() > 0) {
|
||||
// Get all the data into a single array
|
||||
byte[] data = IOUtils.safelyAllocate(getSize(), MAX_RECORD_LENGTH);
|
||||
int offset = 0;
|
||||
for(ByteBuffer buffer : _stream) {
|
||||
int length = Math.min(_block_size, data.length-offset);
|
||||
buffer.get(data, offset, length);
|
||||
offset += length;
|
||||
}
|
||||
|
||||
result = HexDump.dump(data, 0, 0);
|
||||
}
|
||||
|
||||
return new String[]{ result };
|
||||
}
|
||||
/**
|
||||
* Get an array of objects, some of which may implement POIFSViewable
|
||||
*
|
||||
* @return an array of Object; may not be null, but may be empty
|
||||
*/
|
||||
public Object[] getViewableArray() {
|
||||
String result = "<NO DATA>";
|
||||
|
||||
/**
|
||||
* Get an Iterator of objects, some of which may implement POIFSViewable
|
||||
*
|
||||
* @return an Iterator; may not be null, but may have an empty back end
|
||||
* store
|
||||
*/
|
||||
public Iterator<Object> getViewableIterator() {
|
||||
return emptyIterator();
|
||||
}
|
||||
if (getSize() > 0) {
|
||||
// Get all the data into a single array
|
||||
byte[] data = IOUtils.safelyAllocate(getSize(), POIFSFileSystem.MAX_RECORD_LENGTH);
|
||||
int offset = 0;
|
||||
for (ByteBuffer buffer : _stream) {
|
||||
int length = Math.min(_block_size, data.length - offset);
|
||||
buffer.get(data, offset, length);
|
||||
offset += length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Give viewers a hint as to whether to call getViewableArray or
|
||||
* getViewableIterator
|
||||
*
|
||||
* @return <code>true</code> if a viewer should call getViewableArray,
|
||||
* <code>false</code> if a viewer should call getViewableIterator
|
||||
*/
|
||||
public boolean preferArray() {
|
||||
return true;
|
||||
}
|
||||
result = HexDump.dump(data, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a short description of the object, to be used when a
|
||||
* POIFSViewable object has not provided its contents.
|
||||
*
|
||||
* @return short description
|
||||
*/
|
||||
public String getShortDescription() {
|
||||
return new String[]{result};
|
||||
}
|
||||
|
||||
return "Document: \"" + _property.getName() + "\" size = " + getSize();
|
||||
}
|
||||
/**
|
||||
* Get an Iterator of objects, some of which may implement POIFSViewable
|
||||
*
|
||||
* @return an Iterator; may not be null, but may have an empty back end
|
||||
* store
|
||||
*/
|
||||
public Iterator<Object> getViewableIterator() {
|
||||
return emptyIterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Give viewers a hint as to whether to call getViewableArray or
|
||||
* getViewableIterator
|
||||
*
|
||||
* @return <code>true</code> if a viewer should call getViewableArray,
|
||||
* <code>false</code> if a viewer should call getViewableIterator
|
||||
*/
|
||||
public boolean preferArray() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a short description of the object, to be used when a
|
||||
* POIFSViewable object has not provided its contents.
|
||||
*
|
||||
* @return short description
|
||||
*/
|
||||
public String getShortDescription() {
|
||||
|
||||
return "Document: \"" + _property.getName() + "\" size = " + getSize();
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,7 +61,8 @@ import org.apache.poi.util.Internal;
|
||||
public class POIFSFileSystem extends BlockStore
|
||||
implements POIFSViewable, Closeable {
|
||||
//arbitrarily selected; may need to increase
|
||||
private static final int MAX_RECORD_LENGTH = 100_000;
|
||||
private static final int DEFAULT_MAX_RECORD_LENGTH = 100_000;
|
||||
static int MAX_RECORD_LENGTH = DEFAULT_MAX_RECORD_LENGTH;
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(POIFSFileSystem.class);
|
||||
|
||||
@ -94,6 +95,20 @@ public class POIFSFileSystem extends BlockStore
|
||||
private POIFSBigBlockSize bigBlockSize =
|
||||
POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS;
|
||||
|
||||
/**
|
||||
* @param length the max record length allowed for POIFSFileSystem
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max record length allowed for POIFSFileSystem
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
}
|
||||
|
||||
private POIFSFileSystem(boolean newFS) {
|
||||
_header = new HeaderBlock(bigBlockSize);
|
||||
_property_table = new PropertyTable(_header);
|
||||
|
||||
@ -68,14 +68,14 @@ public class EmbeddedExtractor implements Iterable<EmbeddedExtractor> {
|
||||
private static final String CONTENT_TYPE_XLS = "application/vnd.ms-excel";
|
||||
|
||||
/**
|
||||
* @param length the max length allowed for EmbeddedExtractor
|
||||
* @param length the max record length allowed for EmbeddedExtractor
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max length allowed for EmbeddedExtractor
|
||||
* @return the max record length allowed for EmbeddedExtractor
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
|
||||
@ -57,14 +57,14 @@ final class FunctionMetadataReader {
|
||||
private static final Set<String> DIGIT_ENDING_FUNCTION_NAMES_SET = new HashSet<>(Arrays.asList(DIGIT_ENDING_FUNCTION_NAMES));
|
||||
|
||||
/**
|
||||
* @param length the max length allowed for FunctionMetadataReader
|
||||
* @param length the max record length allowed for FunctionMetadataReader
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max length allowed for FunctionMetadataReader
|
||||
* @return the max record length allowed for FunctionMetadataReader
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
|
||||
@ -61,14 +61,14 @@ public abstract class LZWDecompresser {
|
||||
private final boolean positionIsBigEndian;
|
||||
|
||||
/**
|
||||
* @param length the max length allowed for LZWDecompresser
|
||||
* @param length the max record length allowed for LZWDecompresser
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max length allowed for LZWDecompresser
|
||||
* @return the max record length allowed for LZWDecompresser
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
|
||||
@ -37,14 +37,14 @@ public final class StringUtil {
|
||||
public static final Charset WIN_1252 = Charset.forName("cp1252");
|
||||
|
||||
/**
|
||||
* @param length the max length allowed for StringUtil
|
||||
* @param length the max record length allowed for StringUtil
|
||||
*/
|
||||
public static void setMaxRecordLength(int length) {
|
||||
MAX_RECORD_LENGTH = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the max length allowed for StringUtil
|
||||
* @return the max record length allowed for StringUtil
|
||||
*/
|
||||
public static int getMaxRecordLength() {
|
||||
return MAX_RECORD_LENGTH;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user