diff options
author | PJ Fanning <fanningpj@apache.org> | 2022-02-19 12:08:48 +0000 |
---|---|---|
committer | PJ Fanning <fanningpj@apache.org> | 2022-02-19 12:08:48 +0000 |
commit | 788dd3f03ced7fad0649160d74fd92e9915a0bd1 (patch) | |
tree | cb6c0aaa0bb2b3e0de295479b9d88319a913f35a /poi-scratchpad | |
parent | 4998436a00da6816d76ca31862ff2274ee9f53ce (diff) | |
download | poi-788dd3f03ced7fad0649160d74fd92e9915a0bd1.tar.gz poi-788dd3f03ced7fad0649160d74fd92e9915a0bd1.zip |
refactor some stream code
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1898213 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'poi-scratchpad')
8 files changed, 142 insertions, 132 deletions
diff --git a/poi-scratchpad/src/main/java/org/apache/poi/extractor/ole2/OLE2ScratchpadExtractorFactory.java b/poi-scratchpad/src/main/java/org/apache/poi/extractor/ole2/OLE2ScratchpadExtractorFactory.java index 3c4ab886f4..2485589e31 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/extractor/ole2/OLE2ScratchpadExtractorFactory.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/extractor/ole2/OLE2ScratchpadExtractorFactory.java @@ -16,7 +16,6 @@ ==================================================================== */ package org.apache.poi.extractor.ole2; -import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; @@ -24,6 +23,7 @@ import java.io.InputStream; import java.util.List; import java.util.stream.StreamSupport; +import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.poi.extractor.ExtractorFactory; @@ -185,7 +185,7 @@ public class OLE2ScratchpadExtractorFactory implements ExtractorProvider { for (AttachmentChunks attachment : msg.getAttachmentFiles()) { if (attachment.getAttachData() != null) { byte[] data = attachment.getAttachData().getValue(); - nonPOIFS.add( new ByteArrayInputStream(data) ); + nonPOIFS.add( new UnsynchronizedByteArrayInputStream(data) ); } else if (attachment.getAttachmentDirectory() != null) { dirs.add(attachment.getAttachmentDirectory().getDirectory()); } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/CompressedStreamStore.java b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/CompressedStreamStore.java index fc1057f839..0009a3d511 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/CompressedStreamStore.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hdgf/streams/CompressedStreamStore.java @@ -17,9 +17,9 @@ package org.apache.poi.hdgf.streams; -import java.io.ByteArrayInputStream; import java.io.IOException; +import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream; import org.apache.poi.hdgf.HDGFLZW; import org.apache.poi.util.IOUtils; @@ -92,25 +92,26 @@ public final class CompressedStreamStore extends StreamStore { * Decompresses the given data, returning it as header + contents */ public static byte[][] decompress(byte[] data, int offset, int length) throws IOException { - ByteArrayInputStream bais = new ByteArrayInputStream(data, offset, length); + try (UnsynchronizedByteArrayInputStream bais = new UnsynchronizedByteArrayInputStream(data, offset, length)) { + // Decompress + HDGFLZW lzw = new HDGFLZW(); + byte[] decompressed = lzw.decompress(bais); - // Decompress - HDGFLZW lzw = new HDGFLZW(); - byte[] decompressed = lzw.decompress(bais); + if (decompressed.length < 4) { + throw new IllegalArgumentException("Could not read enough data to decompress: " + decompressed.length); + } - if (decompressed.length < 4) { - throw new IllegalArgumentException("Could not read enough data to decompress: " + decompressed.length); - } + // Split into header and contents + byte[][] ret = new byte[2][]; + ret[0] = new byte[4]; + ret[1] = new byte[decompressed.length - 4]; - // Split into header and contents - byte[][] ret = new byte[2][]; - ret[0] = new byte[4]; - ret[1] = new byte[decompressed.length - 4]; + System.arraycopy(decompressed, 0, ret[0], 0, 4); + System.arraycopy(decompressed, 4, ret[1], 0, ret[1].length); - System.arraycopy(decompressed, 0, ret[0], 0, 4); - System.arraycopy(decompressed, 4, ret[1], 0, ret[1].length); + // All done + return ret; + } - // All done - return ret; } } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hemf/draw/HemfImageRenderer.java b/poi-scratchpad/src/main/java/org/apache/poi/hemf/draw/HemfImageRenderer.java index 95d3b7e70a..221c9d5a5a 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hemf/draw/HemfImageRenderer.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hemf/draw/HemfImageRenderer.java @@ -25,11 +25,11 @@ import java.awt.RenderingHints; import java.awt.geom.Dimension2D; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; +import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream; import org.apache.poi.common.usermodel.GenericRecord; import org.apache.poi.hemf.usermodel.HemfPicture; import org.apache.poi.hwmf.draw.HwmfGraphicsState; @@ -65,7 +65,7 @@ public class HemfImageRenderer implements ImageRenderer, EmbeddedExtractor { if (!PictureData.PictureType.EMF.contentType.equals(contentType)) { throw new IOException("Invalid picture type"); } - image = new HemfPicture(new ByteArrayInputStream(data)); + image = new HemfPicture(new UnsynchronizedByteArrayInputStream(data)); } @Override diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hemf/record/emfplus/HemfPlusBrush.java b/poi-scratchpad/src/main/java/org/apache/poi/hemf/record/emfplus/HemfPlusBrush.java index e713254e9e..ec0ac8e465 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hemf/record/emfplus/HemfPlusBrush.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hemf/record/emfplus/HemfPlusBrush.java @@ -26,7 +26,6 @@ import java.awt.Color; import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; -import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.AbstractMap; import java.util.Arrays; @@ -40,6 +39,7 @@ import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.IntStream; +import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream; import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream; import org.apache.poi.common.usermodel.GenericRecord; import org.apache.poi.hemf.draw.HemfDrawProperties; @@ -391,7 +391,7 @@ public class HemfPlusBrush { EmfPlusBrushData brushData = brushType.constructor.get(); byte[] buf = getRawData(continuedObjectData); try { - brushData.init(new LittleEndianInputStream(new ByteArrayInputStream(buf)), buf.length); + brushData.init(new LittleEndianInputStream(new UnsynchronizedByteArrayInputStream(buf)), buf.length); } catch (IOException e) { throw new RuntimeException(e); } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hemf/record/emfplus/HemfPlusImage.java b/poi-scratchpad/src/main/java/org/apache/poi/hemf/record/emfplus/HemfPlusImage.java index 4b0a402e13..e764e78a1e 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hemf/record/emfplus/HemfPlusImage.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hemf/record/emfplus/HemfPlusImage.java @@ -22,7 +22,6 @@ import static org.apache.poi.hemf.record.emfplus.HemfPlusDraw.readARGB; import java.awt.Color; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.Collections; import java.util.LinkedHashMap; @@ -32,6 +31,7 @@ import java.util.function.Supplier; import javax.imageio.ImageIO; +import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream; import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream; import org.apache.poi.hemf.draw.HemfDrawProperties; import org.apache.poi.hemf.draw.HemfGraphics; @@ -419,21 +419,24 @@ public class HemfPlusImage { if (getBitmapType() == EmfPlusBitmapDataType.PIXEL) { return new Rectangle2D.Double(0, 0, bitmapWidth, bitmapHeight); } else { - BufferedImage bi = ImageIO.read(new ByteArrayInputStream(getRawData(continuedObjectData))); - return new Rectangle2D.Double(bi.getMinX(), bi.getMinY(), bi.getWidth(), bi.getHeight()); + try(UnsynchronizedByteArrayInputStream is = new UnsynchronizedByteArrayInputStream(getRawData(continuedObjectData))) { + BufferedImage bi = ImageIO.read(is); + return new Rectangle2D.Double(bi.getMinX(), bi.getMinY(), bi.getWidth(), bi.getHeight()); + } } case METAFILE: - ByteArrayInputStream bis = new ByteArrayInputStream(getRawData(continuedObjectData)); - switch (getMetafileType()) { - case Wmf: - case WmfPlaceable: - HwmfPicture wmf = new HwmfPicture(bis); - return wmf.getBounds(); - case Emf: - case EmfPlusDual: - case EmfPlusOnly: - HemfPicture emf = new HemfPicture(bis); - return emf.getBounds(); + try(UnsynchronizedByteArrayInputStream bis = new UnsynchronizedByteArrayInputStream(getRawData(continuedObjectData))) { + switch (getMetafileType()) { + case Wmf: + case WmfPlaceable: + HwmfPicture wmf = new HwmfPicture(bis); + return wmf.getBounds(); + case Emf: + case EmfPlusDual: + case EmfPlusOnly: + HemfPicture emf = new HemfPicture(bis); + return emf.getBounds(); + } } break; default: diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hmef/attribute/MAPIAttribute.java b/poi-scratchpad/src/main/java/org/apache/poi/hmef/attribute/MAPIAttribute.java index 0338ed62dc..a5f797220e 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hmef/attribute/MAPIAttribute.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hmef/attribute/MAPIAttribute.java @@ -17,13 +17,13 @@ package org.apache.poi.hmef.attribute; -import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream; import org.apache.poi.hmef.Attachment; import org.apache.poi.hmef.HMEFMessage; import org.apache.poi.hsmf.datatypes.MAPIProperty; @@ -115,107 +115,108 @@ public class MAPIAttribute { "instead received a " + parent.getProperty() + " one" ); } - ByteArrayInputStream inp = new ByteArrayInputStream(parent.getData()); - - // First up, get the number of attributes - int count = LittleEndian.readInt(inp); - List<MAPIAttribute> attrs = new ArrayList<>(); - - // Now, read each one in in turn - for(int i=0; i<count; i++) { - int typeAndMV = LittleEndian.readUShort(inp); - int id = LittleEndian.readUShort(inp); - - // Is it either Multi-Valued or Variable-Length? - boolean isMV = false; - boolean isVL = false; - int typeId = typeAndMV; - if( (typeAndMV & Types.MULTIVALUED_FLAG) != 0 ) { - isMV = true; - typeId -= Types.MULTIVALUED_FLAG; - } - if(typeId == Types.ASCII_STRING.getId() || typeId == Types.UNICODE_STRING.getId() || - typeId == Types.BINARY.getId() || typeId == Types.DIRECTORY.getId()) { - isVL = true; - } - - // Turn the type ID into a strongly typed thing - MAPIType type = Types.getById(typeId); - if (type == null) { - type = Types.createCustom(typeId); - } - - // If it's a named property, rather than a standard - // MAPI property, grab the details of it - MAPIProperty prop = MAPIProperty.get(id); - if(id >= 0x8000 && id <= 0xFFFF) { - byte[] guid = new byte[16]; - if (IOUtils.readFully(inp, guid) < 0) { - throw new IOException("Not enough data to read guid"); + try(UnsynchronizedByteArrayInputStream inp = new UnsynchronizedByteArrayInputStream(parent.getData())) { + // First up, get the number of attributes + int count = LittleEndian.readInt(inp); + List<MAPIAttribute> attrs = new ArrayList<>(); + + // Now, read each one in in turn + for(int i=0; i<count; i++) { + int typeAndMV = LittleEndian.readUShort(inp); + int id = LittleEndian.readUShort(inp); + + // Is it either Multi-Valued or Variable-Length? + boolean isMV = false; + boolean isVL = false; + int typeId = typeAndMV; + if( (typeAndMV & Types.MULTIVALUED_FLAG) != 0 ) { + isMV = true; + typeId -= Types.MULTIVALUED_FLAG; } - int mptype = LittleEndian.readInt(inp); - - // Get the name of it - String name; - if(mptype == 0) { - // It's based on a normal one - int mpid = LittleEndian.readInt(inp); - MAPIProperty base = MAPIProperty.get(mpid); - name = base.name; - } else { - // Custom name was stored - int mplen = LittleEndian.readInt(inp); - byte[] mpdata = IOUtils.safelyAllocate(mplen, MAX_RECORD_LENGTH); - if (IOUtils.readFully(inp, mpdata) < 0) { - throw new IOException("Not enough data to read " + mplen + " bytes for attribute name"); - } - name = StringUtil.getFromUnicodeLE(mpdata, 0, (mplen/2)-1); - skipToBoundary(mplen, inp); + if(typeId == Types.ASCII_STRING.getId() || typeId == Types.UNICODE_STRING.getId() || + typeId == Types.BINARY.getId() || typeId == Types.DIRECTORY.getId()) { + isVL = true; } - // Now create - prop = MAPIProperty.createCustom(id, type, name); - } - if(prop == MAPIProperty.UNKNOWN) { - prop = MAPIProperty.createCustom(id, type, "(unknown " + Integer.toHexString(id) + ")"); - } + // Turn the type ID into a strongly typed thing + MAPIType type = Types.getById(typeId); + if (type == null) { + type = Types.createCustom(typeId); + } - // Now read in the value(s) - int values = 1; - if(isMV || isVL) { - values = LittleEndian.readInt(inp); - } + // If it's a named property, rather than a standard + // MAPI property, grab the details of it + MAPIProperty prop = MAPIProperty.get(id); + if(id >= 0x8000 && id <= 0xFFFF) { + byte[] guid = new byte[16]; + if (IOUtils.readFully(inp, guid) < 0) { + throw new IOException("Not enough data to read guid"); + } + int mptype = LittleEndian.readInt(inp); + + // Get the name of it + String name; + if(mptype == 0) { + // It's based on a normal one + int mpid = LittleEndian.readInt(inp); + MAPIProperty base = MAPIProperty.get(mpid); + name = base.name; + } else { + // Custom name was stored + int mplen = LittleEndian.readInt(inp); + byte[] mpdata = IOUtils.safelyAllocate(mplen, MAX_RECORD_LENGTH); + if (IOUtils.readFully(inp, mpdata) < 0) { + throw new IOException("Not enough data to read " + mplen + " bytes for attribute name"); + } + name = StringUtil.getFromUnicodeLE(mpdata, 0, (mplen/2)-1); + skipToBoundary(mplen, inp); + } - if (type == Types.NULL && values > 1) { - throw new IOException("Placeholder/NULL arrays aren't supported."); - } + // Now create + prop = MAPIProperty.createCustom(id, type, name); + } + if(prop == MAPIProperty.UNKNOWN) { + prop = MAPIProperty.createCustom(id, type, "(unknown " + Integer.toHexString(id) + ")"); + } - for(int j=0; j<values; j++) { - int len = getLength(type, inp); - byte[] data = IOUtils.safelyAllocate(len, MAX_RECORD_LENGTH); - if (IOUtils.readFully(inp, data) < 0) { - throw new IOException("Not enough data to read " + len + " bytes of attribute value"); + // Now read in the value(s) + int values = 1; + if(isMV || isVL) { + values = LittleEndian.readInt(inp); } - skipToBoundary(len, inp); - - // Create - MAPIAttribute attr; - if(type == Types.UNICODE_STRING || type == Types.ASCII_STRING) { - attr = new MAPIStringAttribute(prop, typeId, data); - } else if(type == Types.APP_TIME || type == Types.TIME) { - attr = new MAPIDateAttribute(prop, typeId, data); - } else if(id == MAPIProperty.RTF_COMPRESSED.id) { - attr = new MAPIRtfAttribute(prop, typeId, data); - } else { - attr = new MAPIAttribute(prop, typeId, data); + + if (type == Types.NULL && values > 1) { + throw new IOException("Placeholder/NULL arrays aren't supported."); + } + + for(int j=0; j<values; j++) { + int len = getLength(type, inp); + byte[] data = IOUtils.safelyAllocate(len, MAX_RECORD_LENGTH); + if (IOUtils.readFully(inp, data) < 0) { + throw new IOException("Not enough data to read " + len + " bytes of attribute value"); + } + skipToBoundary(len, inp); + + // Create + MAPIAttribute attr; + if(type == Types.UNICODE_STRING || type == Types.ASCII_STRING) { + attr = new MAPIStringAttribute(prop, typeId, data); + } else if(type == Types.APP_TIME || type == Types.TIME) { + attr = new MAPIDateAttribute(prop, typeId, data); + } else if(id == MAPIProperty.RTF_COMPRESSED.id) { + attr = new MAPIRtfAttribute(prop, typeId, data); + } else { + attr = new MAPIAttribute(prop, typeId, data); + } + attrs.add(attr); } - attrs.add(attr); } - } - // All done - return attrs; + // All done + return attrs; + } } + private static int getLength(MAPIType type, InputStream inp) throws IOException { if (type.isFixedLength()) { return type.getLength(); diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hmef/attribute/MAPIRtfAttribute.java b/poi-scratchpad/src/main/java/org/apache/poi/hmef/attribute/MAPIRtfAttribute.java index 295a022db8..f8b2d19522 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hmef/attribute/MAPIRtfAttribute.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hmef/attribute/MAPIRtfAttribute.java @@ -17,9 +17,10 @@ package org.apache.poi.hmef.attribute; -import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; +import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream; import org.apache.poi.hmef.Attachment; import org.apache.poi.hmef.CompressedRTF; import org.apache.poi.hmef.HMEFMessage; @@ -44,7 +45,11 @@ public final class MAPIRtfAttribute extends MAPIAttribute { // Decompress it, removing any trailing padding as needed CompressedRTF rtf = new CompressedRTF(); - byte[] tmp = rtf.decompress(new ByteArrayInputStream(data)); + byte[] tmp; + try (InputStream is = new UnsynchronizedByteArrayInputStream(data)) { + tmp = rtf.decompress(is); + } + if(tmp.length > rtf.getDeCompressedSize()) { this.decompressed = IOUtils.safelyClone(tmp, 0, rtf.getDeCompressedSize(), MAX_RECORD_LENGTH); } else { diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/usermodel/Picture.java b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/usermodel/Picture.java index 26bfc0546a..05b22ccd00 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/usermodel/Picture.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/usermodel/Picture.java @@ -17,13 +17,13 @@ package org.apache.poi.hwpf.usermodel; -import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Collections; import java.util.List; import java.util.zip.InflaterInputStream; +import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream; import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -140,8 +140,8 @@ public final class Picture { */ if ( matchSignature( rawContent, COMPRESSED1, 32 ) || matchSignature( rawContent, COMPRESSED2, 32 ) ) { - try (ByteArrayInputStream bis = new ByteArrayInputStream( rawContent, 33, rawContent.length - 33 ); - InflaterInputStream in = new InflaterInputStream(bis); + try (UnsynchronizedByteArrayInputStream bis = new UnsynchronizedByteArrayInputStream( rawContent, 33, rawContent.length - 33 ); + InflaterInputStream in = new InflaterInputStream(bis); UnsynchronizedByteArrayOutputStream out = new UnsynchronizedByteArrayOutputStream()) { IOUtils.copy(in, out); |