mirror of https://github.com/apache/poi.git
bug 59893: commit the changes from attachment 34068 that were unrelated to available()
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1783347 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
3aae3f0a5f
commit
9330f2ac74
|
@ -126,9 +126,10 @@ public class TreeReaderListener implements POIFSReaderListener
|
|||
{
|
||||
DocumentDescriptor d;
|
||||
final DocumentInputStream is = event.getStream();
|
||||
if (!is.markSupported())
|
||||
if (!is.markSupported()) {
|
||||
throw new UnsupportedOperationException(is.getClass().getName() +
|
||||
" does not support mark().");
|
||||
}
|
||||
|
||||
/* Try do handle this document as a property set. We receive
|
||||
* an exception if is no property set and handle it as a
|
||||
|
@ -146,11 +147,7 @@ public class TreeReaderListener implements POIFSReaderListener
|
|||
}
|
||||
catch (Exception t)
|
||||
{
|
||||
System.err.println
|
||||
("Unexpected exception while processing " +
|
||||
event.getName() + " in " + event.getPath().toString());
|
||||
t.printStackTrace(System.err);
|
||||
throw new RuntimeException(t.getMessage());
|
||||
throw new RuntimeException("Unexpected exception while processing " + event.getName() + " in " + event.getPath(), t);
|
||||
}
|
||||
|
||||
is.close();
|
||||
|
@ -181,9 +178,10 @@ public class TreeReaderListener implements POIFSReaderListener
|
|||
final MutableTreeNode root)
|
||||
{
|
||||
MutableTreeNode n = pathToNode.get(path);
|
||||
if (n != null)
|
||||
if (n != null) {
|
||||
/* Node found in map, just return it. */
|
||||
return n;
|
||||
}
|
||||
if (path.length() == 0)
|
||||
{
|
||||
/* This is the root path of the POI filesystem. Its tree
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.apache.poi.poifs.filesystem.Entry;
|
|||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.LittleEndianConsts;
|
||||
import org.apache.poi.util.NotImplemented;
|
||||
|
||||
/**
|
||||
* Represents a property set in the Horrible Property Set Format
|
||||
|
@ -419,17 +420,17 @@ public class PropertySet {
|
|||
*/
|
||||
int o = offset;
|
||||
final int byteOrder = LittleEndian.getUShort(src, o);
|
||||
o += LittleEndian.SHORT_SIZE;
|
||||
o += LittleEndianConsts.SHORT_SIZE;
|
||||
if (byteOrder != BYTE_ORDER_ASSERTION) {
|
||||
return false;
|
||||
}
|
||||
final int format = LittleEndian.getUShort(src, o);
|
||||
o += LittleEndian.SHORT_SIZE;
|
||||
o += LittleEndianConsts.SHORT_SIZE;
|
||||
if (format != FORMAT_ASSERTION) {
|
||||
return false;
|
||||
}
|
||||
// final long osVersion = LittleEndian.getUInt(src, offset);
|
||||
o += LittleEndian.INT_SIZE;
|
||||
o += LittleEndianConsts.INT_SIZE;
|
||||
// final ClassID classID = new ClassID(src, offset);
|
||||
o += ClassID.LENGTH;
|
||||
final long sectionCount = LittleEndian.getUInt(src, o);
|
||||
|
@ -460,15 +461,15 @@ public class PropertySet {
|
|||
*/
|
||||
int o = offset;
|
||||
byteOrder = LittleEndian.getUShort(src, o);
|
||||
o += LittleEndian.SHORT_SIZE;
|
||||
o += LittleEndianConsts.SHORT_SIZE;
|
||||
format = LittleEndian.getUShort(src, o);
|
||||
o += LittleEndian.SHORT_SIZE;
|
||||
o += LittleEndianConsts.SHORT_SIZE;
|
||||
osVersion = (int) LittleEndian.getUInt(src, o);
|
||||
o += LittleEndian.INT_SIZE;
|
||||
o += LittleEndianConsts.INT_SIZE;
|
||||
classID = new ClassID(src, o);
|
||||
o += ClassID.LENGTH;
|
||||
final int sectionCount = LittleEndian.getInt(src, o);
|
||||
o += LittleEndian.INT_SIZE;
|
||||
o += LittleEndianConsts.INT_SIZE;
|
||||
if (sectionCount < 0) {
|
||||
throw new HPSFRuntimeException("Section count " + sectionCount + " is negative.");
|
||||
}
|
||||
|
@ -492,7 +493,7 @@ public class PropertySet {
|
|||
*/
|
||||
for (int i = 0; i < sectionCount; i++) {
|
||||
final Section s = new MutableSection(src, o);
|
||||
o += ClassID.LENGTH + LittleEndian.INT_SIZE;
|
||||
o += ClassID.LENGTH + LittleEndianConsts.INT_SIZE;
|
||||
sections.add(s);
|
||||
}
|
||||
}
|
||||
|
@ -835,6 +836,8 @@ public class PropertySet {
|
|||
/**
|
||||
* @see Object#hashCode()
|
||||
*/
|
||||
@NotImplemented
|
||||
@Override
|
||||
public int hashCode() {
|
||||
throw new UnsupportedOperationException("FIXME: Not yet implemented.");
|
||||
}
|
||||
|
@ -844,6 +847,7 @@ public class PropertySet {
|
|||
/**
|
||||
* @see Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder b = new StringBuilder();
|
||||
final int sectionCount = getSectionCount();
|
||||
|
|
|
@ -199,6 +199,7 @@ import org.apache.poi.util.LittleEndian;
|
|||
import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
import org.apache.poi.util.StringUtil;
|
||||
import org.apache.poi.util.SuppressForbidden;
|
||||
|
||||
/**
|
||||
* Utility for reading in BIFF8 records and displaying data from them.
|
||||
|
@ -612,7 +613,9 @@ public final class BiffViewer {
|
|||
public void processRecord(int globalOffset, int recordCounter, int sid, int dataSize,
|
||||
byte[] data) {
|
||||
String header = formatRecordDetails(globalOffset, sid, dataSize, recordCounter);
|
||||
if(!_noHeader) _headers.add(header);
|
||||
if(!_noHeader) {
|
||||
_headers.add(header);
|
||||
}
|
||||
Writer w = _hexDumpWriter;
|
||||
if (w != null) {
|
||||
try {
|
||||
|
@ -708,6 +711,7 @@ public final class BiffViewer {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressForbidden("just delegating the call")
|
||||
public int available() throws IOException {
|
||||
return _currentSize - _currentPos + _is.available();
|
||||
}
|
||||
|
|
|
@ -58,12 +58,10 @@ public final class ObjRecord extends Record implements Cloneable {
|
|||
public ObjRecord(RecordInputStream in) {
|
||||
// TODO - problems with OBJ sub-records stream
|
||||
// MS spec says first sub-record is always CommonObjectDataSubRecord,
|
||||
// and last is
|
||||
// always EndSubRecord. OOO spec does not mention ObjRecord(0x005D).
|
||||
// and last is always EndSubRecord. OOO spec does not mention ObjRecord(0x005D).
|
||||
// Existing POI test data seems to violate that rule. Some test data
|
||||
// seems to contain
|
||||
// garbage, and a crash is only averted by stopping at what looks like
|
||||
// the 'EndSubRecord'
|
||||
// seems to contain garbage, and a crash is only averted by stopping at
|
||||
// what looks like the 'EndSubRecord'
|
||||
|
||||
// Check if this can be continued, if so then the
|
||||
// following wont work properly
|
||||
|
@ -141,10 +139,9 @@ public final class ObjRecord extends Record implements Cloneable {
|
|||
|
||||
sb.append("[OBJ]\n");
|
||||
if(subrecords != null) { // there are special cases where this can be, see comments in constructor above
|
||||
for (int i = 0; i < subrecords.size(); i++) {
|
||||
SubRecord record = subrecords.get(i);
|
||||
sb.append("SUBRECORD: ").append(record.toString());
|
||||
}
|
||||
for (final SubRecord record : subrecords) {
|
||||
sb.append("SUBRECORD: ").append(record.toString());
|
||||
}
|
||||
}
|
||||
sb.append("[/OBJ]\n");
|
||||
return sb.toString();
|
||||
|
@ -156,8 +153,7 @@ public final class ObjRecord extends Record implements Cloneable {
|
|||
return _uninterpretedData.length + 4;
|
||||
}
|
||||
int size = 0;
|
||||
for (int i=subrecords.size()-1; i>=0; i--) {
|
||||
SubRecord record = subrecords.get(i);
|
||||
for (SubRecord record : subrecords) {
|
||||
size += record.getDataSize()+4;
|
||||
}
|
||||
if (_isPaddedToQuadByteMultiple) {
|
||||
|
@ -203,6 +199,7 @@ public final class ObjRecord extends Record implements Cloneable {
|
|||
return sid;
|
||||
}
|
||||
|
||||
// FIXME: return Collections.unmodifiableList?
|
||||
public List<SubRecord> getSubRecords() {
|
||||
return subrecords;
|
||||
}
|
||||
|
@ -223,9 +220,8 @@ public final class ObjRecord extends Record implements Cloneable {
|
|||
public ObjRecord clone() {
|
||||
ObjRecord rec = new ObjRecord();
|
||||
|
||||
for (int i = 0; i < subrecords.size(); i++) {
|
||||
SubRecord record = subrecords.get(i);
|
||||
rec.addSubRecord((SubRecord) record.clone());
|
||||
for (SubRecord record : subrecords) {
|
||||
rec.addSubRecord(record.clone());
|
||||
}
|
||||
return rec;
|
||||
}
|
||||
|
|
|
@ -84,10 +84,12 @@ public abstract class SubRecord {
|
|||
}
|
||||
|
||||
public abstract void serialize(LittleEndianOutput out);
|
||||
public abstract Object clone();
|
||||
|
||||
@Override
|
||||
public abstract SubRecord clone();
|
||||
|
||||
/**
|
||||
* Wether this record terminates the sub-record stream.
|
||||
* Whether this record terminates the sub-record stream.
|
||||
* There are two cases when this method must be overridden and return <code>true</code>
|
||||
* - EndSubRecord (sid = 0x00)
|
||||
* - LbsDataSubRecord (sid = 0x12)
|
||||
|
@ -109,19 +111,23 @@ public abstract class SubRecord {
|
|||
in.readFully(buf);
|
||||
_data = buf;
|
||||
}
|
||||
@Override
|
||||
protected int getDataSize() {
|
||||
return _data.length;
|
||||
}
|
||||
@Override
|
||||
public void serialize(LittleEndianOutput out) {
|
||||
out.writeShort(_sid);
|
||||
out.writeShort(_data.length);
|
||||
out.write(_data);
|
||||
}
|
||||
public Object clone() {
|
||||
@Override
|
||||
public UnknownSubRecord clone() {
|
||||
return this;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuffer sb = new StringBuffer(64);
|
||||
StringBuilder sb = new StringBuilder(64);
|
||||
sb.append(getClass().getName()).append(" [");
|
||||
sb.append("sid=").append(HexDump.shortToHex(_sid));
|
||||
sb.append(" size=").append(_data.length);
|
||||
|
|
|
@ -76,11 +76,9 @@ public abstract class ChunkedCipherInputStream extends LittleEndianInputStream {
|
|||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
byte[] b = new byte[1];
|
||||
if (read(b) == 1) {
|
||||
return b[0];
|
||||
}
|
||||
return -1;
|
||||
byte[] b = { 0 };
|
||||
// FIXME: compare against -1 or 1?
|
||||
return (read(b) == -1) ? -1 : b[0];
|
||||
}
|
||||
|
||||
// do not implement! -> recursion
|
||||
|
|
|
@ -64,6 +64,7 @@ public abstract class ChunkedCipherOutputStream extends FilterOutputStream {
|
|||
// the cipher can't be final, because for the last chunk we change the padding
|
||||
// and therefore need to change the cipher too
|
||||
private Cipher cipher;
|
||||
private boolean isClosed = false;
|
||||
|
||||
public ChunkedCipherOutputStream(DirectoryNode dir, int chunkSize) throws IOException, GeneralSecurityException {
|
||||
super(null);
|
||||
|
@ -224,6 +225,13 @@ public abstract class ChunkedCipherOutputStream extends FilterOutputStream {
|
|||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (isClosed) {
|
||||
LOG.log(POILogger.DEBUG, "ChunkedCipherOutputStream was already closed - ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
isClosed = true;
|
||||
|
||||
try {
|
||||
writeChunk(false);
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.apache.poi.poifs.filesystem.POIFSDocumentPath;
|
|||
import org.apache.poi.poifs.property.DirectoryProperty;
|
||||
import org.apache.poi.poifs.property.Property;
|
||||
import org.apache.poi.poifs.property.PropertyTable;
|
||||
import org.apache.poi.poifs.property.RootProperty;
|
||||
import org.apache.poi.poifs.storage.BlockAllocationTableReader;
|
||||
import org.apache.poi.poifs.storage.BlockList;
|
||||
import org.apache.poi.poifs.storage.HeaderBlock;
|
||||
|
@ -94,13 +95,15 @@ public class POIFSReader
|
|||
new PropertyTable(header_block, data_blocks);
|
||||
|
||||
// process documents
|
||||
RootProperty root = properties.getRoot();
|
||||
processProperties(SmallBlockTableReader
|
||||
.getSmallDocumentBlocks(
|
||||
header_block.getBigBlockSize(),
|
||||
data_blocks, properties.getRoot(),
|
||||
header_block.getSBATStart()),
|
||||
data_blocks, properties.getRoot()
|
||||
.getChildren(), new POIFSDocumentPath());
|
||||
data_blocks, root,
|
||||
header_block.getSBATStart()
|
||||
),
|
||||
data_blocks, root.getChildren(), new POIFSDocumentPath()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,6 +21,7 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
|
||||
import org.apache.poi.util.LittleEndianInput;
|
||||
import org.apache.poi.util.SuppressForbidden;
|
||||
|
||||
/**
|
||||
* This class provides methods to read a DocumentEntry managed by a
|
||||
|
@ -86,6 +87,7 @@ public class DocumentInputStream extends InputStream implements LittleEndianInpu
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressForbidden("just delegating")
|
||||
public int available() {
|
||||
return delegate.available();
|
||||
}
|
||||
|
|
|
@ -40,13 +40,13 @@ public final class NDocumentInputStream extends DocumentInputStream {
|
|||
private int _marked_offset_count;
|
||||
|
||||
/** the Document's size */
|
||||
private int _document_size;
|
||||
private final int _document_size;
|
||||
|
||||
/** have we been closed? */
|
||||
private boolean _closed;
|
||||
|
||||
/** the actual Document */
|
||||
private NPOIFSDocument _document;
|
||||
private final NPOIFSDocument _document;
|
||||
|
||||
private Iterator<ByteBuffer> _data;
|
||||
private ByteBuffer _buffer;
|
||||
|
@ -97,6 +97,15 @@ public final class NDocumentInputStream extends DocumentInputStream {
|
|||
|
||||
@Override
|
||||
public int available() {
|
||||
return remainingBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper methods for forbidden api calls
|
||||
*
|
||||
* @return the bytes remaining until the end of the stream
|
||||
*/
|
||||
private int remainingBytes() {
|
||||
if (_closed) {
|
||||
throw new IllegalStateException("cannot perform requested operation on a closed stream");
|
||||
}
|
||||
|
@ -146,7 +155,7 @@ public final class NDocumentInputStream extends DocumentInputStream {
|
|||
if (atEOD()) {
|
||||
return EOF;
|
||||
}
|
||||
int limit = Math.min(available(), len);
|
||||
int limit = Math.min(remainingBytes(), len);
|
||||
readFully(b, off, limit);
|
||||
return limit;
|
||||
}
|
||||
|
@ -297,13 +306,13 @@ public final class NDocumentInputStream extends DocumentInputStream {
|
|||
return LittleEndian.getUShort(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readUByte() {
|
||||
checkAvaliable(1);
|
||||
byte[] data = new byte[1];
|
||||
readFully(data, 0, 1);
|
||||
if(data[0] >= 0)
|
||||
return data[0];
|
||||
return data[0] + 256;
|
||||
}
|
||||
@Override
|
||||
public int readUByte() {
|
||||
checkAvaliable(1);
|
||||
byte[] data = new byte[1];
|
||||
readFully(data, 0, 1);
|
||||
if (data[0] >= 0)
|
||||
return data[0];
|
||||
return data[0] + 256;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,13 +33,13 @@ public final class ODocumentInputStream extends DocumentInputStream {
|
|||
private int _marked_offset;
|
||||
|
||||
/** the Document's size */
|
||||
private int _document_size;
|
||||
private final int _document_size;
|
||||
|
||||
/** have we been closed? */
|
||||
private boolean _closed;
|
||||
|
||||
/** the actual Document */
|
||||
private OPOIFSDocument _document;
|
||||
private final OPOIFSDocument _document;
|
||||
|
||||
/** the data block containing the current stream pointer */
|
||||
private DataInputBlock _currentBlock;
|
||||
|
|
|
@ -26,8 +26,6 @@ import java.io.InputStream;
|
|||
*
|
||||
* This class does not buffer any input, so the stream read position maintained
|
||||
* by this class is consistent with that of the inner stream.
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public class LittleEndianInputStream extends FilterInputStream implements LittleEndianInput {
|
||||
public LittleEndianInputStream(InputStream is) {
|
||||
|
@ -35,7 +33,8 @@ public class LittleEndianInputStream extends FilterInputStream implements Little
|
|||
}
|
||||
|
||||
@Override
|
||||
public int available() {
|
||||
@SuppressForbidden("just delegating")
|
||||
public int available() {
|
||||
try {
|
||||
return super.available();
|
||||
} catch (IOException e) {
|
||||
|
@ -44,12 +43,12 @@ public class LittleEndianInputStream extends FilterInputStream implements Little
|
|||
}
|
||||
|
||||
@Override
|
||||
public byte readByte() {
|
||||
public byte readByte() {
|
||||
return (byte)readUByte();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readUByte() {
|
||||
public int readUByte() {
|
||||
byte buf[] = new byte[1];
|
||||
try {
|
||||
checkEOF(read(buf), 1);
|
||||
|
@ -60,15 +59,15 @@ public class LittleEndianInputStream extends FilterInputStream implements Little
|
|||
}
|
||||
|
||||
@Override
|
||||
public double readDouble() {
|
||||
public double readDouble() {
|
||||
return Double.longBitsToDouble(readLong());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readInt() {
|
||||
byte buf[] = new byte[LittleEndianConsts.INT_SIZE];
|
||||
public int readInt() {
|
||||
byte buf[] = new byte[LittleEndianConsts.INT_SIZE];
|
||||
try {
|
||||
checkEOF(read(buf), buf.length);
|
||||
checkEOF(read(buf), buf.length);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -82,13 +81,14 @@ public class LittleEndianInputStream extends FilterInputStream implements Little
|
|||
* @exception RuntimeException
|
||||
* wraps any IOException thrown from reading the stream.
|
||||
*/
|
||||
//@Override
|
||||
public long readUInt() {
|
||||
long retNum = readInt();
|
||||
return retNum & 0x00FFFFFFFFL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long readLong() {
|
||||
public long readLong() {
|
||||
byte buf[] = new byte[LittleEndianConsts.LONG_SIZE];
|
||||
try {
|
||||
checkEOF(read(buf), LittleEndianConsts.LONG_SIZE);
|
||||
|
@ -99,12 +99,12 @@ public class LittleEndianInputStream extends FilterInputStream implements Little
|
|||
}
|
||||
|
||||
@Override
|
||||
public short readShort() {
|
||||
public short readShort() {
|
||||
return (short)readUShort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readUShort() {
|
||||
public int readUShort() {
|
||||
byte buf[] = new byte[LittleEndianConsts.SHORT_SIZE];
|
||||
try {
|
||||
checkEOF(read(buf), LittleEndianConsts.SHORT_SIZE);
|
||||
|
@ -120,19 +120,19 @@ public class LittleEndianInputStream extends FilterInputStream implements Little
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public void readFully(byte[] buf) {
|
||||
readFully(buf, 0, buf.length);
|
||||
}
|
||||
readFully(buf, 0, buf.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public void readFully(byte[] buf, int off, int len) {
|
||||
try {
|
||||
checkEOF(read(buf, off, len), len);
|
||||
} catch (IOException e) {
|
||||
try {
|
||||
checkEOF(read(buf, off, len), len);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readPlain(byte[] buf, int off, int len) {
|
||||
|
|
|
@ -42,6 +42,7 @@ import org.apache.poi.poifs.common.POIFSConstants;
|
|||
import org.apache.poi.poifs.storage.HeaderBlockConstants;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.Removal;
|
||||
|
||||
public final class ZipHelper {
|
||||
/**
|
||||
|
@ -54,7 +55,11 @@ public final class ZipHelper {
|
|||
* Buffer to read data from file. Use big buffer to improve performaces. the
|
||||
* InputStream class is reading only 8192 bytes per read call (default value
|
||||
* set by sun)
|
||||
*
|
||||
* @deprecated in POI 3.16-beta3, not used anymore
|
||||
*/
|
||||
@Deprecated
|
||||
@Removal(version="3.18")
|
||||
public static final int READ_WRITE_FILE_BUFFER_SIZE = 8192;
|
||||
|
||||
/**
|
||||
|
@ -74,8 +79,9 @@ public final class ZipHelper {
|
|||
PackageRelationship corePropsRel = pkg.getRelationshipsByType(
|
||||
PackageRelationshipTypes.CORE_PROPERTIES).getRelationship(0);
|
||||
|
||||
if (corePropsRel == null)
|
||||
if (corePropsRel == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ZipEntry(corePropsRel.getTargetURI().getPath());
|
||||
}
|
||||
|
@ -91,8 +97,9 @@ public final class ZipHelper {
|
|||
while (entries.hasMoreElements()) {
|
||||
ZipEntry entry = entries.nextElement();
|
||||
if (entry.getName().equals(
|
||||
ContentTypeManager.CONTENT_TYPES_PART_NAME))
|
||||
ContentTypeManager.CONTENT_TYPES_PART_NAME)) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -106,8 +113,9 @@ public final class ZipHelper {
|
|||
* @return An OPC compliant name.
|
||||
*/
|
||||
public static String getOPCNameFromZipItemName(String zipItemName) {
|
||||
if (zipItemName == null)
|
||||
throw new IllegalArgumentException("zipItemName");
|
||||
if (zipItemName == null) {
|
||||
throw new IllegalArgumentException("zipItemName cannot be null");
|
||||
}
|
||||
if (zipItemName.startsWith(FORWARD_SLASH)) {
|
||||
return zipItemName;
|
||||
}
|
||||
|
@ -123,12 +131,14 @@ public final class ZipHelper {
|
|||
* @return A zip item name without any leading slashes.
|
||||
*/
|
||||
public static String getZipItemNameFromOPCName(String opcItemName) {
|
||||
if (opcItemName == null)
|
||||
throw new IllegalArgumentException("opcItemName");
|
||||
if (opcItemName == null) {
|
||||
throw new IllegalArgumentException("opcItemName cannot be null");
|
||||
}
|
||||
|
||||
String retVal = opcItemName;
|
||||
while (retVal.startsWith(FORWARD_SLASH))
|
||||
while (retVal.startsWith(FORWARD_SLASH)) {
|
||||
retVal = retVal.substring(1);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
@ -141,12 +151,14 @@ public final class ZipHelper {
|
|||
* @return A zip URI without any leading slashes.
|
||||
*/
|
||||
public static URI getZipURIFromOPCName(String opcItemName) {
|
||||
if (opcItemName == null)
|
||||
if (opcItemName == null) {
|
||||
throw new IllegalArgumentException("opcItemName");
|
||||
}
|
||||
|
||||
String retVal = opcItemName;
|
||||
while (retVal.startsWith(FORWARD_SLASH))
|
||||
while (retVal.startsWith(FORWARD_SLASH)) {
|
||||
retVal = retVal.substring(1);
|
||||
}
|
||||
try {
|
||||
return new URI(retVal);
|
||||
} catch (URISyntaxException e) {
|
||||
|
|
|
@ -44,8 +44,6 @@ import org.w3c.dom.Element;
|
|||
|
||||
/**
|
||||
* Zip part marshaller. This marshaller is use to save any part in a zip stream.
|
||||
*
|
||||
* @author Julien Chable
|
||||
*/
|
||||
public final class ZipPartMarshaller implements PartMarshaller {
|
||||
private final static POILogger logger = POILogFactory.getLogger(ZipPartMarshaller.class);
|
||||
|
@ -56,6 +54,7 @@ public final class ZipPartMarshaller implements PartMarshaller {
|
|||
* @throws OpenXML4JException
|
||||
* Throws if an internal exception is thrown.
|
||||
*/
|
||||
@Override
|
||||
public boolean marshall(PackagePart part, OutputStream os)
|
||||
throws OpenXML4JException {
|
||||
if (!(os instanceof ZipOutputStream)) {
|
||||
|
|
|
@ -160,6 +160,7 @@ public class ZipSecureFile extends ZipFile {
|
|||
* @throws IOException if an I/O error has occurred
|
||||
* @throws IllegalStateException if the zip file has been closed
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("resource")
|
||||
public InputStream getInputStream(ZipEntry entry) throws IOException {
|
||||
InputStream zipIS = super.getInputStream(entry);
|
||||
|
@ -170,6 +171,7 @@ public class ZipSecureFile extends ZipFile {
|
|||
ThresholdInputStream newInner;
|
||||
if (zipIS instanceof InflaterInputStream) {
|
||||
newInner = AccessController.doPrivileged(new PrivilegedAction<ThresholdInputStream>() { // NOSONAR
|
||||
@Override
|
||||
@SuppressForbidden("TODO: Fix this to not use reflection (it will break in Java 9)! " +
|
||||
"Better would be to wrap *before* instead of trying to insert wrapper afterwards.")
|
||||
public ThresholdInputStream run() {
|
||||
|
@ -177,9 +179,9 @@ public class ZipSecureFile extends ZipFile {
|
|||
Field f = FilterInputStream.class.getDeclaredField("in");
|
||||
f.setAccessible(true);
|
||||
InputStream oldInner = (InputStream)f.get(zipIS);
|
||||
ThresholdInputStream newInner = new ThresholdInputStream(oldInner, null);
|
||||
f.set(zipIS, newInner);
|
||||
return newInner;
|
||||
ThresholdInputStream newInner2 = new ThresholdInputStream(oldInner, null);
|
||||
f.set(zipIS, newInner2);
|
||||
return newInner2;
|
||||
} catch (Exception ex) {
|
||||
LOG.log(POILogger.WARN, "SecurityManager doesn't allow manipulation via reflection for zipbomb detection - continue with original input stream", ex);
|
||||
}
|
||||
|
@ -203,24 +205,31 @@ public class ZipSecureFile extends ZipFile {
|
|||
this.cis = cis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
int b = in.read();
|
||||
if (b > -1) advance(1);
|
||||
if (b > -1) {
|
||||
advance(1);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte b[], int off, int len) throws IOException {
|
||||
int cnt = in.read(b, off, len);
|
||||
if (cnt > -1) advance(cnt);
|
||||
if (cnt > -1) {
|
||||
advance(cnt);
|
||||
}
|
||||
return cnt;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public long skip(long n) throws IOException {
|
||||
counter = 0;
|
||||
return in.skip(n);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void reset() throws IOException {
|
||||
counter = 0;
|
||||
in.reset();
|
||||
|
@ -277,31 +286,41 @@ public class ZipSecureFile extends ZipFile {
|
|||
((ZipInputStream)in).closeEntry();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unread(int b) throws IOException {
|
||||
if (!(in instanceof PushbackInputStream)) {
|
||||
throw new UnsupportedOperationException("underlying stream is not a PushbackInputStream");
|
||||
}
|
||||
if (--counter < 0) counter = 0;
|
||||
if (--counter < 0) {
|
||||
counter = 0;
|
||||
}
|
||||
((PushbackInputStream)in).unread(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unread(byte[] b, int off, int len) throws IOException {
|
||||
if (!(in instanceof PushbackInputStream)) {
|
||||
throw new UnsupportedOperationException("underlying stream is not a PushbackInputStream");
|
||||
}
|
||||
counter -= len;
|
||||
if (--counter < 0) counter = 0;
|
||||
if (--counter < 0) {
|
||||
counter = 0;
|
||||
}
|
||||
((PushbackInputStream)in).unread(b, off, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressForbidden("just delegating")
|
||||
public int available() throws IOException {
|
||||
return in.available();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean markSupported() {
|
||||
return in.markSupported();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void mark(int readlimit) {
|
||||
in.mark(readlimit);
|
||||
}
|
||||
|
|
|
@ -50,6 +50,8 @@ public class TestDecryptor {
|
|||
Decryptor d = Decryptor.getInstance(info);
|
||||
|
||||
assertTrue(d.verifyPassword(Decryptor.DEFAULT_PASSWORD));
|
||||
|
||||
fs.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -63,6 +65,8 @@ public class TestDecryptor {
|
|||
d.verifyPassword(Decryptor.DEFAULT_PASSWORD);
|
||||
|
||||
zipOk(fs.getRoot(), d);
|
||||
|
||||
fs.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -78,6 +82,8 @@ public class TestDecryptor {
|
|||
assertTrue(d.verifyPassword(Decryptor.DEFAULT_PASSWORD));
|
||||
|
||||
zipOk(fs.getRoot(), d);
|
||||
|
||||
fs.close();
|
||||
}
|
||||
|
||||
private void zipOk(DirectoryNode root, Decryptor d) throws IOException, GeneralSecurityException {
|
||||
|
@ -85,9 +91,13 @@ public class TestDecryptor {
|
|||
|
||||
while (true) {
|
||||
ZipEntry entry = zin.getNextEntry();
|
||||
if (entry==null) break;
|
||||
if (entry==null) {
|
||||
break;
|
||||
}
|
||||
// crc32 is checked within zip-stream
|
||||
if (entry.isDirectory()) continue;
|
||||
if (entry.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
zin.skip(entry.getSize());
|
||||
byte buf[] = new byte[10];
|
||||
int readBytes = zin.read(buf);
|
||||
|
@ -182,4 +192,4 @@ public class TestDecryptor {
|
|||
|
||||
fs.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue