#59893 - Forbid calls to InputStream.available
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1830400 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
2574fd2d3d
commit
e0f7014503
@ -17,15 +17,17 @@
|
|||||||
|
|
||||||
package org.apache.poi.poifs.poibrowser;
|
package org.apache.poi.poifs.poibrowser;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.IOException;
|
||||||
import org.apache.poi.poifs.filesystem.*;
|
|
||||||
|
import org.apache.poi.poifs.filesystem.DocumentInputStream;
|
||||||
|
import org.apache.poi.poifs.filesystem.POIFSDocumentPath;
|
||||||
import org.apache.poi.util.IOUtils;
|
import org.apache.poi.util.IOUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Describes the most important (whatever that is) features of a
|
* <p>Describes the most important (whatever that is) features of a
|
||||||
* {@link POIFSDocumentPath}.</p>
|
* {@link POIFSDocumentPath}.</p>
|
||||||
*/
|
*/
|
||||||
public class DocumentDescriptor
|
class DocumentDescriptor
|
||||||
{
|
{
|
||||||
|
|
||||||
//arbitrarily selected; may need to increase
|
//arbitrarily selected; may need to increase
|
||||||
@ -54,26 +56,20 @@ public class DocumentDescriptor
|
|||||||
public DocumentDescriptor(final String name,
|
public DocumentDescriptor(final String name,
|
||||||
final POIFSDocumentPath path,
|
final POIFSDocumentPath path,
|
||||||
final DocumentInputStream stream,
|
final DocumentInputStream stream,
|
||||||
final int nrOfBytes)
|
final int nrOfBytes) {
|
||||||
{
|
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.stream = stream;
|
this.stream = stream;
|
||||||
try
|
try {
|
||||||
{
|
if (stream.markSupported()) {
|
||||||
size = stream.available();
|
|
||||||
if (stream.markSupported())
|
|
||||||
{
|
|
||||||
stream.mark(nrOfBytes);
|
stream.mark(nrOfBytes);
|
||||||
final byte[] b = IOUtils.safelyAllocate(nrOfBytes, MAX_RECORD_LENGTH);
|
bytes = IOUtils.toByteArray(stream, nrOfBytes, MAX_RECORD_LENGTH);
|
||||||
final int read = stream.read(b, 0, Math.min(size, b.length));
|
|
||||||
bytes = new byte[read];
|
|
||||||
System.arraycopy(b, 0, bytes, 0, read);
|
|
||||||
stream.reset();
|
stream.reset();
|
||||||
|
} else {
|
||||||
|
bytes = new byte[0];
|
||||||
}
|
}
|
||||||
}
|
size = bytes.length + stream.available();
|
||||||
catch (IOException ex)
|
} catch (IOException ex) {
|
||||||
{
|
|
||||||
System.out.println(ex);
|
System.out.println(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -175,10 +175,12 @@ public class VariantSupport extends Variant {
|
|||||||
try {
|
try {
|
||||||
typedPropertyValue.readValue(lei);
|
typedPropertyValue.readValue(lei);
|
||||||
} catch ( UnsupportedOperationException exc ) {
|
} catch ( UnsupportedOperationException exc ) {
|
||||||
int propLength = Math.min( length, lei.available() );
|
try {
|
||||||
final byte[] v = IOUtils.safelyAllocate(propLength, MAX_RECORD_LENGTH);
|
final byte[] v = IOUtils.toByteArray(lei, length, MAX_RECORD_LENGTH);
|
||||||
lei.readFully(v, 0, propLength);
|
throw new ReadingNotSupportedException( type, v );
|
||||||
throw new ReadingNotSupportedException( type, v );
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ( (int) type ) {
|
switch ( (int) type ) {
|
||||||
|
@ -17,14 +17,13 @@
|
|||||||
|
|
||||||
package org.apache.poi.hssf.record;
|
package org.apache.poi.hssf.record;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.poi.util.HexDump;
|
import org.apache.poi.util.HexDump;
|
||||||
import org.apache.poi.util.LittleEndian;
|
import org.apache.poi.util.LittleEndian;
|
||||||
|
import org.apache.poi.util.LittleEndianByteArrayInputStream;
|
||||||
import org.apache.poi.util.LittleEndianByteArrayOutputStream;
|
import org.apache.poi.util.LittleEndianByteArrayOutputStream;
|
||||||
import org.apache.poi.util.LittleEndianInputStream;
|
|
||||||
import org.apache.poi.util.RecordFormatException;
|
import org.apache.poi.util.RecordFormatException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -85,8 +84,7 @@ public final class ObjRecord extends Record implements Cloneable {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
subrecords = new ArrayList<>();
|
subrecords = new ArrayList<>();
|
||||||
ByteArrayInputStream bais = new ByteArrayInputStream(subRecordData);
|
LittleEndianByteArrayInputStream subRecStream = new LittleEndianByteArrayInputStream(subRecordData);
|
||||||
LittleEndianInputStream subRecStream = new LittleEndianInputStream(bais);
|
|
||||||
CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord)SubRecord.createSubRecord(subRecStream, 0);
|
CommonObjectDataSubRecord cmo = (CommonObjectDataSubRecord)SubRecord.createSubRecord(subRecStream, 0);
|
||||||
subrecords.add(cmo);
|
subrecords.add(cmo);
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -96,7 +94,7 @@ public final class ObjRecord extends Record implements Cloneable {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int nRemainingBytes = bais.available();
|
final int nRemainingBytes = subRecordData.length-subRecStream.getReadIndex();
|
||||||
if (nRemainingBytes > 0) {
|
if (nRemainingBytes > 0) {
|
||||||
// At present (Oct-2008), most unit test samples have (subRecordData.length % 2 == 0)
|
// At present (Oct-2008), most unit test samples have (subRecordData.length % 2 == 0)
|
||||||
_isPaddedToQuadByteMultiple = subRecordData.length % MAX_PAD_ALIGNMENT == 0;
|
_isPaddedToQuadByteMultiple = subRecordData.length % MAX_PAD_ALIGNMENT == 0;
|
||||||
|
@ -32,6 +32,7 @@ import org.apache.poi.util.LittleEndian;
|
|||||||
import org.apache.poi.util.LittleEndianConsts;
|
import org.apache.poi.util.LittleEndianConsts;
|
||||||
import org.apache.poi.util.LittleEndianInput;
|
import org.apache.poi.util.LittleEndianInput;
|
||||||
import org.apache.poi.util.RecordFormatException;
|
import org.apache.poi.util.RecordFormatException;
|
||||||
|
import org.apache.poi.util.SuppressForbidden;
|
||||||
|
|
||||||
public final class Biff8DecryptingStream implements BiffHeaderInput, LittleEndianInput {
|
public final class Biff8DecryptingStream implements BiffHeaderInput, LittleEndianInput {
|
||||||
|
|
||||||
@ -39,7 +40,6 @@ public final class Biff8DecryptingStream implements BiffHeaderInput, LittleEndia
|
|||||||
//arbitrarily selected; may need to increase
|
//arbitrarily selected; may need to increase
|
||||||
private static final int MAX_RECORD_LENGTH = 100_000;
|
private static final int MAX_RECORD_LENGTH = 100_000;
|
||||||
|
|
||||||
private final EncryptionInfo info;
|
|
||||||
private ChunkedCipherInputStream ccis;
|
private ChunkedCipherInputStream ccis;
|
||||||
private final byte buffer[] = new byte[LittleEndianConsts.LONG_SIZE];
|
private final byte buffer[] = new byte[LittleEndianConsts.LONG_SIZE];
|
||||||
private boolean shouldSkipEncryptionOnCurrentRecord;
|
private boolean shouldSkipEncryptionOnCurrentRecord;
|
||||||
@ -55,8 +55,7 @@ public final class Biff8DecryptingStream implements BiffHeaderInput, LittleEndia
|
|||||||
((PushbackInputStream)stream).unread(initialBuf);
|
((PushbackInputStream)stream).unread(initialBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.info = info;
|
Decryptor dec = info.getDecryptor();
|
||||||
Decryptor dec = this.info.getDecryptor();
|
|
||||||
dec.setChunkSize(RC4_REKEYING_INTERVAL);
|
dec.setChunkSize(RC4_REKEYING_INTERVAL);
|
||||||
ccis = (ChunkedCipherInputStream)dec.getDataStream(stream, Integer.MAX_VALUE, 0);
|
ccis = (ChunkedCipherInputStream)dec.getDataStream(stream, Integer.MAX_VALUE, 0);
|
||||||
|
|
||||||
@ -69,6 +68,7 @@ public final class Biff8DecryptingStream implements BiffHeaderInput, LittleEndia
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressForbidden("just delegating")
|
||||||
public int available() {
|
public int available() {
|
||||||
return ccis.available();
|
return ccis.available();
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ public abstract class ChunkedCipherInputStream extends LittleEndianInputStream {
|
|||||||
private int read(byte[] b, int off, int len, boolean readPlain) throws IOException {
|
private int read(byte[] b, int off, int len, boolean readPlain) throws IOException {
|
||||||
int total = 0;
|
int total = 0;
|
||||||
|
|
||||||
if (available() <= 0) {
|
if (remainingBytes() <= 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ public abstract class ChunkedCipherInputStream extends LittleEndianInputStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
int count = (int)(chunk.length - (pos & chunkMask));
|
int count = (int)(chunk.length - (pos & chunkMask));
|
||||||
int avail = available();
|
int avail = remainingBytes();
|
||||||
if (avail == 0) {
|
if (avail == 0) {
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
@ -133,7 +133,7 @@ public abstract class ChunkedCipherInputStream extends LittleEndianInputStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long skip(final long n) throws IOException {
|
public long skip(final long n) {
|
||||||
long start = pos;
|
long start = pos;
|
||||||
long skip = Math.min(remainingBytes(), n);
|
long skip = Math.min(remainingBytes(), n);
|
||||||
|
|
||||||
@ -169,7 +169,7 @@ public abstract class ChunkedCipherInputStream extends LittleEndianInputStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void reset() throws IOException {
|
public synchronized void reset() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,7 +193,7 @@ public abstract class ChunkedCipherInputStream extends LittleEndianInputStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final int todo = (int)Math.min(size, chunk.length);
|
final int todo = (int)Math.min(size, chunk.length);
|
||||||
int readBytes = 0, totalBytes = 0;
|
int readBytes, totalBytes = 0;
|
||||||
do {
|
do {
|
||||||
readBytes = super.read(plain, totalBytes, todo-totalBytes);
|
readBytes = super.read(plain, totalBytes, todo-totalBytes);
|
||||||
totalBytes += Math.max(0, readBytes);
|
totalBytes += Math.max(0, readBytes);
|
||||||
@ -211,10 +211,6 @@ public abstract class ChunkedCipherInputStream extends LittleEndianInputStream {
|
|||||||
/**
|
/**
|
||||||
* Helper function for overriding the cipher invocation, i.e. XOR doesn't use a cipher
|
* Helper function for overriding the cipher invocation, i.e. XOR doesn't use a cipher
|
||||||
* and uses it's own implementation
|
* and uses it's own implementation
|
||||||
*
|
|
||||||
* @throws BadPaddingException
|
|
||||||
* @throws IllegalBlockSizeException
|
|
||||||
* @throws ShortBufferException
|
|
||||||
*/
|
*/
|
||||||
protected int invokeCipher(int totalBytes, boolean doFinal) throws GeneralSecurityException {
|
protected int invokeCipher(int totalBytes, boolean doFinal) throws GeneralSecurityException {
|
||||||
if (doFinal) {
|
if (doFinal) {
|
||||||
|
@ -273,11 +273,9 @@ public class POIFSReader
|
|||||||
while (listeners.hasNext())
|
while (listeners.hasNext())
|
||||||
{
|
{
|
||||||
POIFSReaderListener listener = listeners.next();
|
POIFSReaderListener listener = listeners.next();
|
||||||
|
try (DocumentInputStream dis = new DocumentInputStream(document)) {
|
||||||
listener.processPOIFSReaderEvent(
|
listener.processPOIFSReaderEvent(new POIFSReaderEvent(dis, path, name));
|
||||||
new POIFSReaderEvent(
|
}
|
||||||
new DocumentInputStream(document), path,
|
|
||||||
name));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -138,7 +138,7 @@ public final class ODocumentInputStream extends DocumentInputStream {
|
|||||||
if (atEOD()) {
|
if (atEOD()) {
|
||||||
return EOF;
|
return EOF;
|
||||||
}
|
}
|
||||||
int limit = Math.min(available(), len);
|
int limit = Math.min(_document_size - _current_offset, len);
|
||||||
readFully(b, off, limit);
|
readFully(b, off, limit);
|
||||||
return limit;
|
return limit;
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ import java.awt.image.AffineTransformOp;
|
|||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.awt.image.RescaleOp;
|
import java.awt.image.RescaleOp;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@ -39,6 +40,7 @@ import javax.imageio.ImageTypeSpecifier;
|
|||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
import javax.imageio.stream.MemoryCacheImageInputStream;
|
import javax.imageio.stream.MemoryCacheImageInputStream;
|
||||||
|
|
||||||
|
import org.apache.poi.util.IOUtils;
|
||||||
import org.apache.poi.util.POILogFactory;
|
import org.apache.poi.util.POILogFactory;
|
||||||
import org.apache.poi.util.POILogger;
|
import org.apache.poi.util.POILogger;
|
||||||
|
|
||||||
@ -69,20 +71,24 @@ public class BitmapImageRenderer implements ImageRenderer {
|
|||||||
* @return the bufferedImage or null, if there was no image reader for this content type
|
* @return the bufferedImage or null, if there was no image reader for this content type
|
||||||
* @throws IOException thrown if there was an error while processing the image
|
* @throws IOException thrown if there was an error while processing the image
|
||||||
*/
|
*/
|
||||||
private static BufferedImage readImage(InputStream data, String contentType) throws IOException {
|
private static BufferedImage readImage(final InputStream data, final String contentType) throws IOException {
|
||||||
IOException lastException = null;
|
IOException lastException = null;
|
||||||
BufferedImage img = null;
|
BufferedImage img = null;
|
||||||
if (data.markSupported()) {
|
|
||||||
data.mark(data.available());
|
final ByteArrayInputStream bis;
|
||||||
|
if (data instanceof ByteArrayInputStream) {
|
||||||
|
bis = (ByteArrayInputStream)data;
|
||||||
|
} else {
|
||||||
|
ByteArrayOutputStream bos = new ByteArrayOutputStream(0x3FFFF);
|
||||||
|
IOUtils.copy(data, bos);
|
||||||
|
bis = new ByteArrayInputStream(bos.toByteArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// currently don't use FileCacheImageInputStream,
|
// currently don't use FileCacheImageInputStream,
|
||||||
// because of the risk of filling the file handles (see #59166)
|
// because of the risk of filling the file handles (see #59166)
|
||||||
ImageInputStream iis = new MemoryCacheImageInputStream(data);
|
ImageInputStream iis = new MemoryCacheImageInputStream(bis);
|
||||||
try {
|
try {
|
||||||
iis = new MemoryCacheImageInputStream(data);
|
|
||||||
iis.mark();
|
|
||||||
|
|
||||||
Iterator<ImageReader> iter = ImageIO.getImageReaders(iis);
|
Iterator<ImageReader> iter = ImageIO.getImageReaders(iis);
|
||||||
while (img==null && iter.hasNext()) {
|
while (img==null && iter.hasNext()) {
|
||||||
ImageReader reader = iter.next();
|
ImageReader reader = iter.next();
|
||||||
@ -90,21 +96,11 @@ public class BitmapImageRenderer implements ImageRenderer {
|
|||||||
// 0:default mode, 1:fallback mode
|
// 0:default mode, 1:fallback mode
|
||||||
for (int mode=0; img==null && mode<3; mode++) {
|
for (int mode=0; img==null && mode<3; mode++) {
|
||||||
lastException = null;
|
lastException = null;
|
||||||
try {
|
if (mode > 0) {
|
||||||
iis.reset();
|
bis.reset();
|
||||||
} catch (IOException e) {
|
iis.close();
|
||||||
if (data.markSupported()) {
|
iis = new MemoryCacheImageInputStream(bis);
|
||||||
data.reset();
|
|
||||||
data.mark(data.available());
|
|
||||||
iis.close();
|
|
||||||
iis = new MemoryCacheImageInputStream(data);
|
|
||||||
} else {
|
|
||||||
// can't restore the input stream, so we need to stop processing here
|
|
||||||
lastException = e;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
iis.mark();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
@ -116,21 +116,57 @@ public final class IOUtils {
|
|||||||
* @return A byte array with the read bytes.
|
* @return A byte array with the read bytes.
|
||||||
* @throws IOException If reading data fails or EOF is encountered too early for the given length.
|
* @throws IOException If reading data fails or EOF is encountered too early for the given length.
|
||||||
*/
|
*/
|
||||||
public static byte[] toByteArray(InputStream stream, int length) throws IOException {
|
public static byte[] toByteArray(InputStream stream, final int length) throws IOException {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(length == Integer.MAX_VALUE ? 4096 : length);
|
return toByteArray(stream, length, Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads up to {@code length} bytes from the input stream, and returns the bytes read.
|
||||||
|
*
|
||||||
|
* @param stream The byte stream of data to read.
|
||||||
|
* @param length The maximum length to read, use {@link Integer#MAX_VALUE} to read the stream
|
||||||
|
* until EOF
|
||||||
|
* @param maxLength if the input is equal to/longer than {@code maxLength} bytes,
|
||||||
|
* then throw an {@link IOException} complaining about the length.
|
||||||
|
* use {@link Integer#MAX_VALUE} to disable the check
|
||||||
|
* @return A byte array with the read bytes.
|
||||||
|
* @throws IOException If reading data fails or EOF is encountered too early for the given length.
|
||||||
|
*/
|
||||||
|
public static byte[] toByteArray(InputStream stream, final long length, final int maxLength) throws IOException {
|
||||||
|
if (length < 0L || maxLength < 0L) {
|
||||||
|
throw new RecordFormatException("Can't allocate an array of length < 0");
|
||||||
|
}
|
||||||
|
if (length > (long)Integer.MAX_VALUE) {
|
||||||
|
throw new RecordFormatException("Can't allocate an array > "+Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
if (BYTE_ARRAY_MAX_OVERRIDE > 0) {
|
||||||
|
if (length > BYTE_ARRAY_MAX_OVERRIDE) {
|
||||||
|
throwRFE(length, BYTE_ARRAY_MAX_OVERRIDE);
|
||||||
|
}
|
||||||
|
} else if (length > maxLength) {
|
||||||
|
throwRFE(length, maxLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
final int len = Math.min((int)length, maxLength);
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream(len == Integer.MAX_VALUE ? 4096 : len);
|
||||||
|
|
||||||
byte[] buffer = new byte[4096];
|
byte[] buffer = new byte[4096];
|
||||||
int totalBytes = 0, readBytes;
|
int totalBytes = 0, readBytes;
|
||||||
do {
|
do {
|
||||||
readBytes = stream.read(buffer, 0, Math.min(buffer.length, length-totalBytes));
|
readBytes = stream.read(buffer, 0, Math.min(buffer.length, len-totalBytes));
|
||||||
totalBytes += Math.max(readBytes,0);
|
totalBytes += Math.max(readBytes,0);
|
||||||
if (readBytes > 0) {
|
if (readBytes > 0) {
|
||||||
baos.write(buffer, 0, readBytes);
|
baos.write(buffer, 0, readBytes);
|
||||||
}
|
}
|
||||||
} while (totalBytes < length && readBytes > -1);
|
} while (totalBytes < len && readBytes > -1);
|
||||||
|
|
||||||
if (length != Integer.MAX_VALUE && totalBytes < length) {
|
if (maxLength != Integer.MAX_VALUE && totalBytes == maxLength) {
|
||||||
throw new IOException("unexpected EOF");
|
throw new IOException("MaxLength ("+maxLength+") reached - stream seems to be invalid.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len != Integer.MAX_VALUE && totalBytes < len) {
|
||||||
|
throw new EOFException("unexpected EOF");
|
||||||
}
|
}
|
||||||
|
|
||||||
return baos.toByteArray();
|
return baos.toByteArray();
|
||||||
@ -350,19 +386,19 @@ public final class IOUtils {
|
|||||||
*
|
*
|
||||||
* @param inp The {@link InputStream} which provides the data
|
* @param inp The {@link InputStream} which provides the data
|
||||||
* @param out The {@link OutputStream} to write the data to
|
* @param out The {@link OutputStream} to write the data to
|
||||||
|
* @return the amount of bytes copied
|
||||||
|
*
|
||||||
* @throws IOException If copying the data fails.
|
* @throws IOException If copying the data fails.
|
||||||
*/
|
*/
|
||||||
public static void copy(InputStream inp, OutputStream out) throws IOException {
|
public static long copy(InputStream inp, OutputStream out) throws IOException {
|
||||||
byte[] buff = new byte[4096];
|
final byte[] buff = new byte[4096];
|
||||||
int count;
|
long totalCount = 0;
|
||||||
while ((count = inp.read(buff)) != -1) {
|
for (int count; (count = inp.read(buff)) != -1; totalCount += count) {
|
||||||
if (count < -1) {
|
|
||||||
throw new RecordFormatException("Can't have read < -1 bytes");
|
|
||||||
}
|
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
out.write(buff, 0, count);
|
out.write(buff, 0, count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return totalCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -370,16 +406,18 @@ public final class IOUtils {
|
|||||||
*
|
*
|
||||||
* @param srcStream The {@link InputStream} which provides the data
|
* @param srcStream The {@link InputStream} which provides the data
|
||||||
* @param destFile The file where the data should be stored
|
* @param destFile The file where the data should be stored
|
||||||
|
* @return the amount of bytes copied
|
||||||
|
*
|
||||||
* @throws IOException If the target directory does not exist and cannot be created
|
* @throws IOException If the target directory does not exist and cannot be created
|
||||||
* or if copying the data fails.
|
* or if copying the data fails.
|
||||||
*/
|
*/
|
||||||
public static void copy(InputStream srcStream, File destFile) throws IOException {
|
public static long copy(InputStream srcStream, File destFile) throws IOException {
|
||||||
File destDirectory = destFile.getParentFile();
|
File destDirectory = destFile.getParentFile();
|
||||||
if (!(destDirectory.exists() || destDirectory.mkdirs())) {
|
if (!(destDirectory.exists() || destDirectory.mkdirs())) {
|
||||||
throw new RuntimeException("Can't create destination directory: "+destDirectory);
|
throw new RuntimeException("Can't create destination directory: "+destDirectory);
|
||||||
}
|
}
|
||||||
try (OutputStream destStream = new FileOutputStream(destFile)) {
|
try (OutputStream destStream = new FileOutputStream(destFile)) {
|
||||||
IOUtils.copy(srcStream, destStream);
|
return IOUtils.copy(srcStream, destStream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ import java.util.Date;
|
|||||||
|
|
||||||
import org.apache.poi.POIXMLProperties.CoreProperties;
|
import org.apache.poi.POIXMLProperties.CoreProperties;
|
||||||
import org.apache.poi.openxml4j.util.Nullable;
|
import org.apache.poi.openxml4j.util.Nullable;
|
||||||
|
import org.apache.poi.util.IOUtils;
|
||||||
import org.apache.poi.util.LocaleUtil;
|
import org.apache.poi.util.LocaleUtil;
|
||||||
import org.apache.poi.xssf.XSSFTestDataSamples;
|
import org.apache.poi.xssf.XSSFTestDataSamples;
|
||||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||||
@ -249,20 +250,18 @@ public final class TestPOIXMLProperties {
|
|||||||
|
|
||||||
// Adding / changing
|
// Adding / changing
|
||||||
ByteArrayInputStream imageData = new ByteArrayInputStream(new byte[1]);
|
ByteArrayInputStream imageData = new ByteArrayInputStream(new byte[1]);
|
||||||
assertEquals(1, imageData.available());
|
|
||||||
noThumbProps.setThumbnail("Testing.png", imageData);
|
noThumbProps.setThumbnail("Testing.png", imageData);
|
||||||
assertNotNull(noThumbProps.getThumbnailPart());
|
assertNotNull(noThumbProps.getThumbnailPart());
|
||||||
assertEquals("/Testing.png", noThumbProps.getThumbnailFilename());
|
assertEquals("/Testing.png", noThumbProps.getThumbnailFilename());
|
||||||
assertNotNull(noThumbProps.getThumbnailImage());
|
assertNotNull(noThumbProps.getThumbnailImage());
|
||||||
assertEquals(1, noThumbProps.getThumbnailImage().available());
|
assertEquals(1, IOUtils.toByteArray(noThumbProps.getThumbnailImage()).length);
|
||||||
|
|
||||||
imageData = new ByteArrayInputStream(new byte[2]);
|
imageData = new ByteArrayInputStream(new byte[2]);
|
||||||
assertEquals(2, imageData.available());
|
|
||||||
noThumbProps.setThumbnail("Testing2.png", imageData);
|
noThumbProps.setThumbnail("Testing2.png", imageData);
|
||||||
assertNotNull(noThumbProps.getThumbnailPart());
|
assertNotNull(noThumbProps.getThumbnailPart());
|
||||||
assertEquals("/Testing.png", noThumbProps.getThumbnailFilename());
|
assertEquals("/Testing.png", noThumbProps.getThumbnailFilename());
|
||||||
assertNotNull(noThumbProps.getThumbnailImage());
|
assertNotNull(noThumbProps.getThumbnailImage());
|
||||||
assertEquals(2, noThumbProps.getThumbnailImage().available());
|
assertEquals(2, IOUtils.toByteArray(noThumbProps.getThumbnailImage()).length);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String zeroPad(long i) {
|
private static String zeroPad(long i) {
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
==================================================================== */
|
==================================================================== */
|
||||||
package org.apache.poi.openxml4j.util;
|
package org.apache.poi.openxml4j.util;
|
||||||
|
|
||||||
|
import org.apache.poi.util.IOUtils;
|
||||||
import org.apache.poi.xssf.XSSFTestDataSamples;
|
import org.apache.poi.xssf.XSSFTestDataSamples;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@ -39,8 +40,9 @@ public class TestZipSecureFile {
|
|||||||
while (entries.hasMoreElements()) {
|
while (entries.hasMoreElements()) {
|
||||||
ZipEntry entry = entries.nextElement();
|
ZipEntry entry = entries.nextElement();
|
||||||
|
|
||||||
InputStream inputStream = secureFile.getInputStream(entry);
|
try (InputStream inputStream = secureFile.getInputStream(entry)) {
|
||||||
assertTrue(inputStream.available() > 0);
|
assertTrue(IOUtils.toByteArray(inputStream).length > 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,6 @@ import static org.junit.Assert.fail;
|
|||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
@ -39,107 +38,92 @@ import org.apache.poi.poifs.filesystem.DirectoryNode;
|
|||||||
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
||||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||||
import org.apache.poi.util.IOUtils;
|
import org.apache.poi.util.IOUtils;
|
||||||
import org.apache.poi.xssf.XSSFTestDataSamples;
|
|
||||||
import org.junit.Assume;
|
import org.junit.Assume;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class TestDecryptor {
|
public class TestDecryptor {
|
||||||
|
private static final POIDataSamples samples = POIDataSamples.getPOIFSInstance();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void passwordVerification() throws IOException, GeneralSecurityException {
|
public void passwordVerification() throws IOException, GeneralSecurityException {
|
||||||
POIFSFileSystem fs = new POIFSFileSystem(POIDataSamples.getPOIFSInstance().openResourceAsStream("protect.xlsx"));
|
try (InputStream is = samples.openResourceAsStream("protect.xlsx");
|
||||||
|
POIFSFileSystem fs = new POIFSFileSystem(is)) {
|
||||||
EncryptionInfo info = new EncryptionInfo(fs);
|
EncryptionInfo info = new EncryptionInfo(fs);
|
||||||
|
Decryptor d = Decryptor.getInstance(info);
|
||||||
Decryptor d = Decryptor.getInstance(info);
|
assertTrue(d.verifyPassword(Decryptor.DEFAULT_PASSWORD));
|
||||||
|
}
|
||||||
assertTrue(d.verifyPassword(Decryptor.DEFAULT_PASSWORD));
|
|
||||||
|
|
||||||
fs.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void decrypt() throws IOException, GeneralSecurityException {
|
public void decrypt() throws IOException, GeneralSecurityException {
|
||||||
POIFSFileSystem fs = new POIFSFileSystem(POIDataSamples.getPOIFSInstance().openResourceAsStream("protect.xlsx"));
|
try (InputStream is = samples.openResourceAsStream("protect.xlsx");
|
||||||
|
POIFSFileSystem fs = new POIFSFileSystem(is)) {
|
||||||
EncryptionInfo info = new EncryptionInfo(fs);
|
EncryptionInfo info = new EncryptionInfo(fs);
|
||||||
|
Decryptor d = Decryptor.getInstance(info);
|
||||||
Decryptor d = Decryptor.getInstance(info);
|
d.verifyPassword(Decryptor.DEFAULT_PASSWORD);
|
||||||
|
zipOk(fs.getRoot(), d);
|
||||||
d.verifyPassword(Decryptor.DEFAULT_PASSWORD);
|
}
|
||||||
|
|
||||||
zipOk(fs.getRoot(), d);
|
|
||||||
|
|
||||||
fs.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void agile() throws IOException, GeneralSecurityException {
|
public void agile() throws IOException, GeneralSecurityException {
|
||||||
POIFSFileSystem fs = new POIFSFileSystem(POIDataSamples.getPOIFSInstance().openResourceAsStream("protected_agile.docx"));
|
try (InputStream is = samples.openResourceAsStream("protected_agile.docx");
|
||||||
|
POIFSFileSystem fs = new POIFSFileSystem(is)) {
|
||||||
EncryptionInfo info = new EncryptionInfo(fs);
|
EncryptionInfo info = new EncryptionInfo(fs);
|
||||||
|
assertTrue(info.getVersionMajor() == 4 && info.getVersionMinor() == 4);
|
||||||
assertTrue(info.getVersionMajor() == 4 && info.getVersionMinor() == 4);
|
Decryptor d = Decryptor.getInstance(info);
|
||||||
|
assertTrue(d.verifyPassword(Decryptor.DEFAULT_PASSWORD));
|
||||||
Decryptor d = Decryptor.getInstance(info);
|
zipOk(fs.getRoot(), d);
|
||||||
|
}
|
||||||
assertTrue(d.verifyPassword(Decryptor.DEFAULT_PASSWORD));
|
|
||||||
|
|
||||||
zipOk(fs.getRoot(), d);
|
|
||||||
|
|
||||||
fs.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void zipOk(DirectoryNode root, Decryptor d) throws IOException, GeneralSecurityException {
|
private void zipOk(DirectoryNode root, Decryptor d) throws IOException, GeneralSecurityException {
|
||||||
ZipInputStream zin = new ZipInputStream(d.getDataStream(root));
|
try (ZipInputStream zin = new ZipInputStream(d.getDataStream(root))) {
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
ZipEntry entry = zin.getNextEntry();
|
ZipEntry entry = zin.getNextEntry();
|
||||||
if (entry==null) {
|
if (entry == null) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
// crc32 is checked within zip-stream
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
assertEquals(entry.getSize() - 1, zin.skip(entry.getSize() - 1));
|
||||||
|
byte buf[] = new byte[10];
|
||||||
|
int readBytes = zin.read(buf);
|
||||||
|
// zin.available() doesn't work for entries
|
||||||
|
assertEquals("size failed for " + entry.getName(), 1, readBytes);
|
||||||
}
|
}
|
||||||
// crc32 is checked within zip-stream
|
|
||||||
if (entry.isDirectory()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
zin.skip(entry.getSize());
|
|
||||||
byte buf[] = new byte[10];
|
|
||||||
int readBytes = zin.read(buf);
|
|
||||||
// zin.available() doesn't work for entries
|
|
||||||
assertEquals("size failed for "+entry.getName(), -1, readBytes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
zin.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void dataLength() throws Exception {
|
public void dataLength() throws Exception {
|
||||||
POIFSFileSystem fs = new POIFSFileSystem(POIDataSamples.getPOIFSInstance().openResourceAsStream("protected_agile.docx"));
|
try (InputStream fsIs = samples.openResourceAsStream("protected_agile.docx");
|
||||||
|
POIFSFileSystem fs = new POIFSFileSystem(fsIs)) {
|
||||||
|
EncryptionInfo info = new EncryptionInfo(fs);
|
||||||
|
Decryptor d = Decryptor.getInstance(info);
|
||||||
|
d.verifyPassword(Decryptor.DEFAULT_PASSWORD);
|
||||||
|
|
||||||
EncryptionInfo info = new EncryptionInfo(fs);
|
try (InputStream is = d.getDataStream(fs)) {
|
||||||
|
|
||||||
Decryptor d = Decryptor.getInstance(info);
|
long len = d.getLength();
|
||||||
|
assertEquals(12810, len);
|
||||||
|
|
||||||
d.verifyPassword(Decryptor.DEFAULT_PASSWORD);
|
byte[] buf = new byte[(int) len];
|
||||||
|
assertEquals(12810, is.read(buf));
|
||||||
|
|
||||||
InputStream is = d.getDataStream(fs);
|
ZipInputStream zin = new ZipInputStream(new ByteArrayInputStream(buf));
|
||||||
|
|
||||||
long len = d.getLength();
|
while (true) {
|
||||||
assertEquals(12810, len);
|
ZipEntry entry = zin.getNextEntry();
|
||||||
|
if (entry == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
byte[] buf = new byte[(int)len];
|
IOUtils.toByteArray(zin);
|
||||||
|
}
|
||||||
is.read(buf);
|
|
||||||
|
|
||||||
ZipInputStream zin = new ZipInputStream(new ByteArrayInputStream(buf));
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
ZipEntry entry = zin.getNextEntry();
|
|
||||||
if (entry==null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (zin.available()>0) {
|
|
||||||
zin.skip(zin.available());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -148,7 +132,7 @@ public class TestDecryptor {
|
|||||||
public void bug57080() throws Exception {
|
public void bug57080() throws Exception {
|
||||||
// the test file contains a wrong ole entry size, produced by extenxls
|
// the test file contains a wrong ole entry size, produced by extenxls
|
||||||
// the fix limits the available size and tries to read all entries
|
// the fix limits the available size and tries to read all entries
|
||||||
File f = POIDataSamples.getPOIFSInstance().getFile("extenxls_pwd123.xlsx");
|
File f = samples.getFile("extenxls_pwd123.xlsx");
|
||||||
|
|
||||||
try (NPOIFSFileSystem fs = new NPOIFSFileSystem(f, true)) {
|
try (NPOIFSFileSystem fs = new NPOIFSFileSystem(f, true)) {
|
||||||
EncryptionInfo info = new EncryptionInfo(fs);
|
EncryptionInfo info = new EncryptionInfo(fs);
|
||||||
@ -174,14 +158,12 @@ public class TestDecryptor {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test58616() throws IOException, GeneralSecurityException {
|
public void test58616() throws IOException, GeneralSecurityException {
|
||||||
FileInputStream fis = new FileInputStream(XSSFTestDataSamples.getSampleFile("58616.xlsx"));
|
try (InputStream is = POIDataSamples.getSpreadSheetInstance().openResourceAsStream("58616.xlsx");
|
||||||
POIFSFileSystem pfs = new POIFSFileSystem(fis);
|
POIFSFileSystem pfs = new POIFSFileSystem(is)) {
|
||||||
EncryptionInfo info = new EncryptionInfo(pfs);
|
EncryptionInfo info = new EncryptionInfo(pfs);
|
||||||
Decryptor dec = Decryptor.getInstance(info);
|
Decryptor dec = Decryptor.getInstance(info);
|
||||||
//dec.verifyPassword(null);
|
dec.getDataStream(pfs).close();
|
||||||
dec.getDataStream(pfs);
|
}
|
||||||
pfs.close();
|
|
||||||
fis.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -189,19 +171,12 @@ public class TestDecryptor {
|
|||||||
int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES");
|
int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES");
|
||||||
Assume.assumeTrue("Please install JCE Unlimited Strength Jurisdiction Policy files for AES 256", maxKeyLen == 2147483647);
|
Assume.assumeTrue("Please install JCE Unlimited Strength Jurisdiction Policy files for AES 256", maxKeyLen == 2147483647);
|
||||||
|
|
||||||
InputStream is = POIDataSamples.getPOIFSInstance().openResourceAsStream("60320-protected.xlsx");
|
try (InputStream is = samples.openResourceAsStream("60320-protected.xlsx");
|
||||||
POIFSFileSystem fs = new POIFSFileSystem(is);
|
POIFSFileSystem fs = new POIFSFileSystem(is)) {
|
||||||
is.close();
|
EncryptionInfo info = new EncryptionInfo(fs);
|
||||||
|
Decryptor d = Decryptor.getInstance(info);
|
||||||
EncryptionInfo info = new EncryptionInfo(fs);
|
assertTrue(d.verifyPassword("Test001!!"));
|
||||||
|
zipOk(fs.getRoot(), d);
|
||||||
Decryptor d = Decryptor.getInstance(info);
|
}
|
||||||
|
|
||||||
boolean b = d.verifyPassword("Test001!!");
|
|
||||||
assertTrue(b);
|
|
||||||
|
|
||||||
zipOk(fs.getRoot(), d);
|
|
||||||
|
|
||||||
fs.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,18 +36,20 @@ import javax.crypto.Cipher;
|
|||||||
import org.apache.poi.POIDataSamples;
|
import org.apache.poi.POIDataSamples;
|
||||||
import org.apache.poi.openxml4j.opc.ContentTypes;
|
import org.apache.poi.openxml4j.opc.ContentTypes;
|
||||||
import org.apache.poi.openxml4j.opc.OPCPackage;
|
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||||
|
import org.apache.poi.openxml4j.opc.PackageAccess;
|
||||||
import org.apache.poi.poifs.crypt.agile.AgileDecryptor;
|
import org.apache.poi.poifs.crypt.agile.AgileDecryptor;
|
||||||
import org.apache.poi.poifs.crypt.agile.AgileEncryptionHeader;
|
import org.apache.poi.poifs.crypt.agile.AgileEncryptionHeader;
|
||||||
import org.apache.poi.poifs.crypt.agile.AgileEncryptionVerifier;
|
import org.apache.poi.poifs.crypt.agile.AgileEncryptionVerifier;
|
||||||
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
||||||
|
import org.apache.poi.poifs.filesystem.DocumentEntry;
|
||||||
import org.apache.poi.poifs.filesystem.DocumentNode;
|
import org.apache.poi.poifs.filesystem.DocumentNode;
|
||||||
import org.apache.poi.poifs.filesystem.Entry;
|
import org.apache.poi.poifs.filesystem.Entry;
|
||||||
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
||||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||||
import org.apache.poi.util.BoundedInputStream;
|
|
||||||
import org.apache.poi.util.IOUtils;
|
import org.apache.poi.util.IOUtils;
|
||||||
import org.apache.poi.util.TempFile;
|
import org.apache.poi.util.TempFile;
|
||||||
import org.apache.poi.xwpf.usermodel.XWPFDocument;
|
import org.apache.poi.xwpf.usermodel.XWPFDocument;
|
||||||
|
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
|
||||||
import org.junit.Assume;
|
import org.junit.Assume;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@ -59,35 +61,37 @@ public class TestEncryptor {
|
|||||||
// ... at least the output can be opened in Excel Viewer
|
// ... at least the output can be opened in Excel Viewer
|
||||||
String password = "pass";
|
String password = "pass";
|
||||||
|
|
||||||
InputStream is = POIDataSamples.getSpreadSheetInstance().openResourceAsStream("SimpleMultiCell.xlsx");
|
final byte[] payloadExpected;
|
||||||
ByteArrayOutputStream payloadExpected = new ByteArrayOutputStream();
|
try (InputStream is = POIDataSamples.getSpreadSheetInstance().openResourceAsStream("SimpleMultiCell.xlsx")) {
|
||||||
IOUtils.copy(is, payloadExpected);
|
payloadExpected = IOUtils.toByteArray(is);
|
||||||
is.close();
|
}
|
||||||
|
|
||||||
POIFSFileSystem fs = new POIFSFileSystem();
|
|
||||||
EncryptionInfo ei = new EncryptionInfo(EncryptionMode.binaryRC4);
|
|
||||||
Encryptor enc = ei.getEncryptor();
|
|
||||||
enc.confirmPassword(password);
|
|
||||||
|
|
||||||
OutputStream os = enc.getDataStream(fs.getRoot());
|
|
||||||
payloadExpected.writeTo(os);
|
|
||||||
os.close();
|
|
||||||
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
fs.writeFilesystem(bos);
|
try (POIFSFileSystem fs = new POIFSFileSystem()) {
|
||||||
|
EncryptionInfo ei = new EncryptionInfo(EncryptionMode.binaryRC4);
|
||||||
|
Encryptor enc = ei.getEncryptor();
|
||||||
|
enc.confirmPassword(password);
|
||||||
|
|
||||||
fs = new POIFSFileSystem(new ByteArrayInputStream(bos.toByteArray()));
|
try (OutputStream os = enc.getDataStream(fs.getRoot())) {
|
||||||
ei = new EncryptionInfo(fs);
|
os.write(payloadExpected);
|
||||||
Decryptor dec = ei.getDecryptor();
|
}
|
||||||
boolean b = dec.verifyPassword(password);
|
|
||||||
assertTrue(b);
|
|
||||||
|
|
||||||
ByteArrayOutputStream payloadActual = new ByteArrayOutputStream();
|
fs.writeFilesystem(bos);
|
||||||
is = dec.getDataStream(fs.getRoot());
|
}
|
||||||
IOUtils.copy(is,payloadActual);
|
|
||||||
is.close();
|
|
||||||
|
|
||||||
assertArrayEquals(payloadExpected.toByteArray(), payloadActual.toByteArray());
|
final byte[] payloadActual;
|
||||||
|
try (POIFSFileSystem fs = new POIFSFileSystem(new ByteArrayInputStream(bos.toByteArray()))) {
|
||||||
|
EncryptionInfo ei = new EncryptionInfo(fs);
|
||||||
|
Decryptor dec = ei.getDecryptor();
|
||||||
|
boolean b = dec.verifyPassword(password);
|
||||||
|
assertTrue(b);
|
||||||
|
|
||||||
|
try (InputStream is = dec.getDataStream(fs.getRoot())) {
|
||||||
|
payloadActual = IOUtils.toByteArray(is);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertArrayEquals(payloadExpected, payloadActual);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -97,43 +101,47 @@ public class TestEncryptor {
|
|||||||
|
|
||||||
File file = POIDataSamples.getDocumentInstance().getFile("bug53475-password-is-pass.docx");
|
File file = POIDataSamples.getDocumentInstance().getFile("bug53475-password-is-pass.docx");
|
||||||
String pass = "pass";
|
String pass = "pass";
|
||||||
NPOIFSFileSystem nfs = new NPOIFSFileSystem(file);
|
|
||||||
|
|
||||||
// Check the encryption details
|
final byte[] payloadExpected, encPackExpected;
|
||||||
EncryptionInfo infoExpected = new EncryptionInfo(nfs);
|
final long decPackLenExpected;
|
||||||
Decryptor decExpected = Decryptor.getInstance(infoExpected);
|
final EncryptionInfo infoExpected;
|
||||||
boolean passed = decExpected.verifyPassword(pass);
|
final Decryptor decExpected;
|
||||||
assertTrue("Unable to process: document is encrypted", passed);
|
|
||||||
|
|
||||||
// extract the payload
|
try (NPOIFSFileSystem nfs = new NPOIFSFileSystem(file, true)) {
|
||||||
InputStream is = decExpected.getDataStream(nfs);
|
|
||||||
byte payloadExpected[] = IOUtils.toByteArray(is);
|
|
||||||
is.close();
|
|
||||||
|
|
||||||
long decPackLenExpected = decExpected.getLength();
|
// Check the encryption details
|
||||||
assertEquals(decPackLenExpected, payloadExpected.length);
|
infoExpected = new EncryptionInfo(nfs);
|
||||||
|
decExpected = Decryptor.getInstance(infoExpected);
|
||||||
|
boolean passed = decExpected.verifyPassword(pass);
|
||||||
|
assertTrue("Unable to process: document is encrypted", passed);
|
||||||
|
|
||||||
is = nfs.getRoot().createDocumentInputStream(Decryptor.DEFAULT_POIFS_ENTRY);
|
// extract the payload
|
||||||
is = new BoundedInputStream(is, is.available()-16); // ignore padding block
|
try (InputStream is = decExpected.getDataStream(nfs)) {
|
||||||
byte encPackExpected[] = IOUtils.toByteArray(is);
|
payloadExpected = IOUtils.toByteArray(is);
|
||||||
is.close();
|
}
|
||||||
|
|
||||||
// listDir(nfs.getRoot(), "orig", "");
|
decPackLenExpected = decExpected.getLength();
|
||||||
|
assertEquals(decPackLenExpected, payloadExpected.length);
|
||||||
|
|
||||||
nfs.close();
|
final DirectoryNode root = nfs.getRoot();
|
||||||
|
final DocumentEntry entry = (DocumentEntry)root.getEntry(Decryptor.DEFAULT_POIFS_ENTRY);
|
||||||
|
try (InputStream is = root.createDocumentInputStream(entry)) {
|
||||||
|
// ignore padding block
|
||||||
|
encPackExpected = IOUtils.toByteArray(is, entry.getSize()-16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// check that same verifier/salt lead to same hashes
|
// check that same verifier/salt lead to same hashes
|
||||||
byte verifierSaltExpected[] = infoExpected.getVerifier().getSalt();
|
final byte verifierSaltExpected[] = infoExpected.getVerifier().getSalt();
|
||||||
byte verifierExpected[] = decExpected.getVerifier();
|
final byte verifierExpected[] = decExpected.getVerifier();
|
||||||
byte keySalt[] = infoExpected.getHeader().getKeySalt();
|
final byte keySalt[] = infoExpected.getHeader().getKeySalt();
|
||||||
byte keySpec[] = decExpected.getSecretKey().getEncoded();
|
final byte keySpec[] = decExpected.getSecretKey().getEncoded();
|
||||||
byte integritySalt[] = decExpected.getIntegrityHmacKey();
|
final byte integritySalt[] = decExpected.getIntegrityHmacKey();
|
||||||
// the hmacs of the file always differ, as we use PKCS5-padding to pad the bytes
|
// the hmacs of the file always differ, as we use PKCS5-padding to pad the bytes
|
||||||
// whereas office just uses random bytes
|
// whereas office just uses random bytes
|
||||||
// byte integrityHash[] = d.getIntegrityHmacValue();
|
// byte integrityHash[] = d.getIntegrityHmacValue();
|
||||||
|
|
||||||
POIFSFileSystem fs = new POIFSFileSystem();
|
final EncryptionInfo infoActual = new EncryptionInfo(
|
||||||
EncryptionInfo infoActual = new EncryptionInfo(
|
|
||||||
EncryptionMode.agile
|
EncryptionMode.agile
|
||||||
, infoExpected.getVerifier().getCipherAlgorithm()
|
, infoExpected.getVerifier().getCipherAlgorithm()
|
||||||
, infoExpected.getVerifier().getHashAlgorithm()
|
, infoExpected.getVerifier().getHashAlgorithm()
|
||||||
@ -145,35 +153,37 @@ public class TestEncryptor {
|
|||||||
Encryptor e = Encryptor.getInstance(infoActual);
|
Encryptor e = Encryptor.getInstance(infoActual);
|
||||||
e.confirmPassword(pass, keySpec, keySalt, verifierExpected, verifierSaltExpected, integritySalt);
|
e.confirmPassword(pass, keySpec, keySalt, verifierExpected, verifierSaltExpected, integritySalt);
|
||||||
|
|
||||||
OutputStream os = e.getDataStream(fs);
|
|
||||||
IOUtils.copy(new ByteArrayInputStream(payloadExpected), os);
|
|
||||||
os.close();
|
|
||||||
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
fs.writeFilesystem(bos);
|
try (POIFSFileSystem fs = new POIFSFileSystem()) {
|
||||||
fs.close();
|
try (OutputStream os = e.getDataStream(fs)) {
|
||||||
|
os.write(payloadExpected);
|
||||||
|
}
|
||||||
|
fs.writeFilesystem(bos);
|
||||||
|
}
|
||||||
|
|
||||||
nfs = new NPOIFSFileSystem(new ByteArrayInputStream(bos.toByteArray()));
|
final EncryptionInfo infoActual2;
|
||||||
infoActual = new EncryptionInfo(nfs.getRoot());
|
final byte[] payloadActual, encPackActual;
|
||||||
Decryptor decActual = Decryptor.getInstance(infoActual);
|
final long decPackLenActual;
|
||||||
passed = decActual.verifyPassword(pass);
|
try (NPOIFSFileSystem nfs = new NPOIFSFileSystem(new ByteArrayInputStream(bos.toByteArray()))) {
|
||||||
assertTrue("Unable to process: document is encrypted", passed);
|
infoActual2 = new EncryptionInfo(nfs.getRoot());
|
||||||
|
Decryptor decActual = Decryptor.getInstance(infoActual2);
|
||||||
|
boolean passed = decActual.verifyPassword(pass);
|
||||||
|
assertTrue("Unable to process: document is encrypted", passed);
|
||||||
|
|
||||||
// extract the payload
|
// extract the payload
|
||||||
is = decActual.getDataStream(nfs);
|
try (InputStream is = decActual.getDataStream(nfs)) {
|
||||||
byte payloadActual[] = IOUtils.toByteArray(is);
|
payloadActual = IOUtils.toByteArray(is);
|
||||||
is.close();
|
}
|
||||||
|
|
||||||
long decPackLenActual = decActual.getLength();
|
decPackLenActual = decActual.getLength();
|
||||||
|
|
||||||
is = nfs.getRoot().createDocumentInputStream(Decryptor.DEFAULT_POIFS_ENTRY);
|
final DirectoryNode root = nfs.getRoot();
|
||||||
is = new BoundedInputStream(is, is.available()-16); // ignore padding block
|
final DocumentEntry entry = (DocumentEntry)root.getEntry(Decryptor.DEFAULT_POIFS_ENTRY);
|
||||||
byte encPackActual[] = IOUtils.toByteArray(is);
|
try (InputStream is = root.createDocumentInputStream(entry)) {
|
||||||
is.close();
|
// ignore padding block
|
||||||
|
encPackActual = IOUtils.toByteArray(is, entry.getSize()-16);
|
||||||
// listDir(nfs.getRoot(), "copy", "");
|
}
|
||||||
|
}
|
||||||
nfs.close();
|
|
||||||
|
|
||||||
AgileEncryptionHeader aehExpected = (AgileEncryptionHeader)infoExpected.getHeader();
|
AgileEncryptionHeader aehExpected = (AgileEncryptionHeader)infoExpected.getHeader();
|
||||||
AgileEncryptionHeader aehActual = (AgileEncryptionHeader)infoActual.getHeader();
|
AgileEncryptionHeader aehActual = (AgileEncryptionHeader)infoActual.getHeader();
|
||||||
@ -186,32 +196,33 @@ public class TestEncryptor {
|
|||||||
@Test
|
@Test
|
||||||
public void standardEncryption() throws Exception {
|
public void standardEncryption() throws Exception {
|
||||||
File file = POIDataSamples.getDocumentInstance().getFile("bug53475-password-is-solrcell.docx");
|
File file = POIDataSamples.getDocumentInstance().getFile("bug53475-password-is-solrcell.docx");
|
||||||
String pass = "solrcell";
|
final String pass = "solrcell";
|
||||||
|
|
||||||
NPOIFSFileSystem nfs = new NPOIFSFileSystem(file);
|
final byte[] payloadExpected;
|
||||||
|
final EncryptionInfo infoExpected;
|
||||||
|
final Decryptor d;
|
||||||
|
try (NPOIFSFileSystem nfs = new NPOIFSFileSystem(file, true)) {
|
||||||
|
|
||||||
// Check the encryption details
|
// Check the encryption details
|
||||||
EncryptionInfo infoExpected = new EncryptionInfo(nfs);
|
infoExpected = new EncryptionInfo(nfs);
|
||||||
Decryptor d = Decryptor.getInstance(infoExpected);
|
d = Decryptor.getInstance(infoExpected);
|
||||||
boolean passed = d.verifyPassword(pass);
|
boolean passed = d.verifyPassword(pass);
|
||||||
assertTrue("Unable to process: document is encrypted", passed);
|
assertTrue("Unable to process: document is encrypted", passed);
|
||||||
|
|
||||||
// extract the payload
|
// extract the payload
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
try (InputStream is = d.getDataStream(nfs)) {
|
||||||
InputStream is = d.getDataStream(nfs);
|
payloadExpected = IOUtils.toByteArray(is);
|
||||||
IOUtils.copy(is, bos);
|
}
|
||||||
is.close();
|
}
|
||||||
nfs.close();
|
|
||||||
byte payloadExpected[] = bos.toByteArray();
|
|
||||||
|
|
||||||
// check that same verifier/salt lead to same hashes
|
// check that same verifier/salt lead to same hashes
|
||||||
byte verifierSaltExpected[] = infoExpected.getVerifier().getSalt();
|
final byte verifierSaltExpected[] = infoExpected.getVerifier().getSalt();
|
||||||
byte verifierExpected[] = d.getVerifier();
|
final byte verifierExpected[] = d.getVerifier();
|
||||||
byte keySpec[] = d.getSecretKey().getEncoded();
|
final byte keySpec[] = d.getSecretKey().getEncoded();
|
||||||
byte keySalt[] = infoExpected.getHeader().getKeySalt();
|
final byte keySalt[] = infoExpected.getHeader().getKeySalt();
|
||||||
|
|
||||||
|
|
||||||
EncryptionInfo infoActual = new EncryptionInfo(
|
final EncryptionInfo infoActual = new EncryptionInfo(
|
||||||
EncryptionMode.standard
|
EncryptionMode.standard
|
||||||
, infoExpected.getVerifier().getCipherAlgorithm()
|
, infoExpected.getVerifier().getCipherAlgorithm()
|
||||||
, infoExpected.getVerifier().getHashAlgorithm()
|
, infoExpected.getVerifier().getHashAlgorithm()
|
||||||
@ -220,7 +231,7 @@ public class TestEncryptor {
|
|||||||
, infoExpected.getVerifier().getChainingMode()
|
, infoExpected.getVerifier().getChainingMode()
|
||||||
);
|
);
|
||||||
|
|
||||||
Encryptor e = Encryptor.getInstance(infoActual);
|
final Encryptor e = Encryptor.getInstance(infoActual);
|
||||||
e.confirmPassword(pass, keySpec, keySalt, verifierExpected, verifierSaltExpected, null);
|
e.confirmPassword(pass, keySpec, keySalt, verifierExpected, verifierSaltExpected, null);
|
||||||
|
|
||||||
assertArrayEquals(infoExpected.getVerifier().getEncryptedVerifier(), infoActual.getVerifier().getEncryptedVerifier());
|
assertArrayEquals(infoExpected.getVerifier().getEncryptedVerifier(), infoActual.getVerifier().getEncryptedVerifier());
|
||||||
@ -229,45 +240,40 @@ public class TestEncryptor {
|
|||||||
// now we use a newly generated salt/verifier and check
|
// now we use a newly generated salt/verifier and check
|
||||||
// if the file content is still the same
|
// if the file content is still the same
|
||||||
|
|
||||||
infoActual = new EncryptionInfo(
|
final byte[] encBytes;
|
||||||
EncryptionMode.standard
|
try (POIFSFileSystem fs = new POIFSFileSystem()) {
|
||||||
, infoExpected.getVerifier().getCipherAlgorithm()
|
|
||||||
, infoExpected.getVerifier().getHashAlgorithm()
|
|
||||||
, infoExpected.getHeader().getKeySize()
|
|
||||||
, infoExpected.getHeader().getBlockSize()
|
|
||||||
, infoExpected.getVerifier().getChainingMode()
|
|
||||||
);
|
|
||||||
|
|
||||||
e = Encryptor.getInstance(infoActual);
|
final EncryptionInfo infoActual2 = new EncryptionInfo(
|
||||||
e.confirmPassword(pass);
|
EncryptionMode.standard
|
||||||
|
, infoExpected.getVerifier().getCipherAlgorithm()
|
||||||
|
, infoExpected.getVerifier().getHashAlgorithm()
|
||||||
|
, infoExpected.getHeader().getKeySize()
|
||||||
|
, infoExpected.getHeader().getBlockSize()
|
||||||
|
, infoExpected.getVerifier().getChainingMode()
|
||||||
|
);
|
||||||
|
|
||||||
POIFSFileSystem fs = new POIFSFileSystem();
|
final Encryptor e2 = Encryptor.getInstance(infoActual2);
|
||||||
OutputStream os = e.getDataStream(fs);
|
e2.confirmPassword(pass);
|
||||||
IOUtils.copy(new ByteArrayInputStream(payloadExpected), os);
|
|
||||||
os.close();
|
|
||||||
|
|
||||||
bos.reset();
|
try (OutputStream os = e2.getDataStream(fs)) {
|
||||||
fs.writeFilesystem(bos);
|
os.write(payloadExpected);
|
||||||
|
}
|
||||||
|
|
||||||
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
|
final ByteArrayOutputStream bos = new ByteArrayOutputStream(50000);
|
||||||
|
fs.writeFilesystem(bos);
|
||||||
|
encBytes = bos.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
// FileOutputStream fos = new FileOutputStream("encrypted.docx");
|
final byte[] payloadActual;
|
||||||
// IOUtils.copy(bis, fos);
|
try (NPOIFSFileSystem nfs = new NPOIFSFileSystem(new ByteArrayInputStream(encBytes))) {
|
||||||
// fos.close();
|
final EncryptionInfo ei = new EncryptionInfo(nfs);
|
||||||
// bis.reset();
|
Decryptor d2 = Decryptor.getInstance(ei);
|
||||||
|
assertTrue("Unable to process: document is encrypted", d2.verifyPassword(pass));
|
||||||
|
|
||||||
nfs = new NPOIFSFileSystem(bis);
|
try (InputStream is = d2.getDataStream(nfs)) {
|
||||||
infoExpected = new EncryptionInfo(nfs);
|
payloadActual = IOUtils.toByteArray(is);
|
||||||
d = Decryptor.getInstance(infoExpected);
|
}
|
||||||
passed = d.verifyPassword(pass);
|
}
|
||||||
assertTrue("Unable to process: document is encrypted", passed);
|
|
||||||
|
|
||||||
bos.reset();
|
|
||||||
is = d.getDataStream(nfs);
|
|
||||||
IOUtils.copy(is, bos);
|
|
||||||
is.close();
|
|
||||||
nfs.close();
|
|
||||||
byte payloadActual[] = bos.toByteArray();
|
|
||||||
|
|
||||||
assertArrayEquals(payloadExpected, payloadActual);
|
assertArrayEquals(payloadExpected, payloadActual);
|
||||||
}
|
}
|
||||||
@ -281,85 +287,87 @@ public class TestEncryptor {
|
|||||||
@Test
|
@Test
|
||||||
public void encryptPackageWithoutCoreProperties() throws Exception {
|
public void encryptPackageWithoutCoreProperties() throws Exception {
|
||||||
// Open our file without core properties
|
// Open our file without core properties
|
||||||
File inp = POIDataSamples.getOpenXML4JInstance().getFile("OPCCompliance_NoCoreProperties.xlsx");
|
final byte[] encBytes;
|
||||||
OPCPackage pkg = OPCPackage.open(inp.getPath());
|
try (InputStream is = POIDataSamples.getOpenXML4JInstance().openResourceAsStream("OPCCompliance_NoCoreProperties.xlsx");
|
||||||
|
OPCPackage pkg = OPCPackage.open(is)) {
|
||||||
|
|
||||||
// It doesn't have any core properties yet
|
// It doesn't have any core properties yet
|
||||||
assertEquals(0, pkg.getPartsByContentType(ContentTypes.CORE_PROPERTIES_PART).size());
|
assertEquals(0, pkg.getPartsByContentType(ContentTypes.CORE_PROPERTIES_PART).size());
|
||||||
assertNotNull(pkg.getPackageProperties());
|
assertNotNull(pkg.getPackageProperties());
|
||||||
assertNotNull(pkg.getPackageProperties().getLanguageProperty());
|
assertNotNull(pkg.getPackageProperties().getLanguageProperty());
|
||||||
assertNull(pkg.getPackageProperties().getLanguageProperty().getValue());
|
assertNull(pkg.getPackageProperties().getLanguageProperty().getValue());
|
||||||
|
|
||||||
// Encrypt it
|
// Encrypt it
|
||||||
EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile);
|
EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile);
|
||||||
NPOIFSFileSystem fs = new NPOIFSFileSystem();
|
Encryptor enc = info.getEncryptor();
|
||||||
|
enc.confirmPassword("password");
|
||||||
|
|
||||||
Encryptor enc = info.getEncryptor();
|
try (NPOIFSFileSystem fs = new NPOIFSFileSystem()) {
|
||||||
enc.confirmPassword("password");
|
|
||||||
OutputStream os = enc.getDataStream(fs);
|
|
||||||
pkg.save(os);
|
|
||||||
os.close();
|
|
||||||
pkg.revert();
|
|
||||||
|
|
||||||
// Save the resulting OLE2 document, and re-open it
|
try (OutputStream os = enc.getDataStream(fs)) {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
pkg.save(os);
|
||||||
fs.writeFilesystem(baos);
|
}
|
||||||
fs.close();
|
|
||||||
|
|
||||||
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
|
// Save the resulting OLE2 document, and re-open it
|
||||||
NPOIFSFileSystem inpFS = new NPOIFSFileSystem(bais);
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
fs.writeFilesystem(baos);
|
||||||
|
encBytes = baos.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check we can decrypt it
|
|
||||||
info = new EncryptionInfo(inpFS);
|
|
||||||
Decryptor d = Decryptor.getInstance(info);
|
|
||||||
assertEquals(true, d.verifyPassword("password"));
|
|
||||||
|
|
||||||
OPCPackage inpPkg = OPCPackage.open(d.getDataStream(inpFS));
|
try (NPOIFSFileSystem inpFS = new NPOIFSFileSystem(new ByteArrayInputStream(encBytes))) {
|
||||||
|
// Check we can decrypt it
|
||||||
|
EncryptionInfo info = new EncryptionInfo(inpFS);
|
||||||
|
Decryptor d = Decryptor.getInstance(info);
|
||||||
|
assertEquals(true, d.verifyPassword("password"));
|
||||||
|
|
||||||
// Check it now has empty core properties
|
try (OPCPackage inpPkg = OPCPackage.open(d.getDataStream(inpFS))) {
|
||||||
assertEquals(1, inpPkg.getPartsByContentType(ContentTypes.CORE_PROPERTIES_PART).size());
|
// Check it now has empty core properties
|
||||||
assertNotNull(inpPkg.getPackageProperties());
|
assertEquals(1, inpPkg.getPartsByContentType(ContentTypes.CORE_PROPERTIES_PART).size());
|
||||||
assertNotNull(inpPkg.getPackageProperties().getLanguageProperty());
|
assertNotNull(inpPkg.getPackageProperties());
|
||||||
assertNull(inpPkg.getPackageProperties().getLanguageProperty().getValue());
|
assertNotNull(inpPkg.getPackageProperties().getLanguageProperty());
|
||||||
|
assertNull(inpPkg.getPackageProperties().getLanguageProperty().getValue());
|
||||||
|
|
||||||
inpPkg.close();
|
}
|
||||||
inpFS.close();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore
|
@Ignore
|
||||||
public void inPlaceRewrite() throws Exception {
|
public void inPlaceRewrite() throws Exception {
|
||||||
File f = TempFile.createTempFile("protected_agile", ".docx");
|
File f = TempFile.createTempFile("protected_agile", ".docx");
|
||||||
// File f = new File("protected_agile.docx");
|
|
||||||
FileOutputStream fos = new FileOutputStream(f);
|
|
||||||
InputStream fis = POIDataSamples.getPOIFSInstance().openResourceAsStream("protected_agile.docx");
|
|
||||||
IOUtils.copy(fis, fos);
|
|
||||||
fis.close();
|
|
||||||
fos.close();
|
|
||||||
|
|
||||||
NPOIFSFileSystem fs = new NPOIFSFileSystem(f, false);
|
try (FileOutputStream fos = new FileOutputStream(f);
|
||||||
|
InputStream fis = POIDataSamples.getPOIFSInstance().openResourceAsStream("protected_agile.docx")) {
|
||||||
|
IOUtils.copy(fis, fos);
|
||||||
|
}
|
||||||
|
|
||||||
// decrypt the protected file - in this case it was encrypted with the default password
|
try (NPOIFSFileSystem fs = new NPOIFSFileSystem(f, false)) {
|
||||||
EncryptionInfo encInfo = new EncryptionInfo(fs);
|
|
||||||
Decryptor d = encInfo.getDecryptor();
|
|
||||||
boolean b = d.verifyPassword(Decryptor.DEFAULT_PASSWORD);
|
|
||||||
assertTrue(b);
|
|
||||||
|
|
||||||
// do some strange things with it ;)
|
// decrypt the protected file - in this case it was encrypted with the default password
|
||||||
InputStream docIS = d.getDataStream(fs);
|
EncryptionInfo encInfo = new EncryptionInfo(fs);
|
||||||
XWPFDocument docx = new XWPFDocument(docIS);
|
Decryptor d = encInfo.getDecryptor();
|
||||||
docx.getParagraphArray(0).insertNewRun(0).setText("POI was here! All your base are belong to us!");
|
boolean b = d.verifyPassword(Decryptor.DEFAULT_PASSWORD);
|
||||||
docx.getParagraphArray(0).insertNewRun(1).addBreak();
|
assertTrue(b);
|
||||||
|
|
||||||
// and encrypt it again
|
try (InputStream docIS = d.getDataStream(fs);
|
||||||
Encryptor e = encInfo.getEncryptor();
|
XWPFDocument docx = new XWPFDocument(docIS)) {
|
||||||
e.confirmPassword("AYBABTU");
|
|
||||||
docx.write(e.getDataStream(fs));
|
|
||||||
docx.close();
|
|
||||||
docIS.close();
|
|
||||||
|
|
||||||
docx.close();
|
// do some strange things with it ;)
|
||||||
fs.close();
|
XWPFParagraph p = docx.getParagraphArray(0);
|
||||||
|
p.insertNewRun(0).setText("POI was here! All your base are belong to us!");
|
||||||
|
p.insertNewRun(1).addBreak();
|
||||||
|
|
||||||
|
// and encrypt it again
|
||||||
|
Encryptor e = encInfo.getEncryptor();
|
||||||
|
e.confirmPassword("AYBABTU");
|
||||||
|
|
||||||
|
try (OutputStream os = e.getDataStream(fs)) {
|
||||||
|
docx.write(os);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -437,21 +445,23 @@ public class TestEncryptor {
|
|||||||
// existing = getCipher(skey, header.getCipherAlgorithm(), header.getChainingMode(), header.getKeySalt(), encryptionMode, padding);
|
// existing = getCipher(skey, header.getCipherAlgorithm(), header.getChainingMode(), header.getKeySalt(), encryptionMode, padding);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
InputStream is = POIDataSamples.getPOIFSInstance().openResourceAsStream("60320-protected.xlsx");
|
final EncryptionInfo infoOrig;
|
||||||
POIFSFileSystem fsOrig = new POIFSFileSystem(is);
|
final byte[] zipInput, epOrigBytes;
|
||||||
is.close();
|
try (InputStream is = POIDataSamples.getPOIFSInstance().openResourceAsStream("60320-protected.xlsx");
|
||||||
EncryptionInfo infoOrig = new EncryptionInfo(fsOrig);
|
POIFSFileSystem fsOrig = new POIFSFileSystem(is)) {
|
||||||
Decryptor decOrig = infoOrig.getDecryptor();
|
infoOrig = new EncryptionInfo(fsOrig);
|
||||||
boolean b = decOrig.verifyPassword("Test001!!");
|
Decryptor decOrig = infoOrig.getDecryptor();
|
||||||
assertTrue(b);
|
boolean b = decOrig.verifyPassword("Test001!!");
|
||||||
InputStream decIn = decOrig.getDataStream(fsOrig);
|
assertTrue(b);
|
||||||
byte[] zipInput = IOUtils.toByteArray(decIn);
|
try (InputStream decIn = decOrig.getDataStream(fsOrig)) {
|
||||||
decIn.close();
|
zipInput = IOUtils.toByteArray(decIn);
|
||||||
|
}
|
||||||
|
|
||||||
InputStream epOrig = fsOrig.getRoot().createDocumentInputStream("EncryptedPackage");
|
try (InputStream epOrig = fsOrig.getRoot().createDocumentInputStream("EncryptedPackage")) {
|
||||||
// ignore the 16 padding bytes
|
// ignore the 16 padding bytes
|
||||||
byte[] epOrigBytes = IOUtils.toByteArray(epOrig, 9400);
|
epOrigBytes = IOUtils.toByteArray(epOrig, 9400);
|
||||||
epOrig.close();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
EncryptionInfo eiNew = new EncryptionInfo(EncryptionMode.agile);
|
EncryptionInfo eiNew = new EncryptionInfo(EncryptionMode.agile);
|
||||||
AgileEncryptionHeader aehHeader = (AgileEncryptionHeader)eiNew.getHeader();
|
AgileEncryptionHeader aehHeader = (AgileEncryptionHeader)eiNew.getHeader();
|
||||||
@ -472,26 +482,29 @@ public class TestEncryptor {
|
|||||||
infoOrig.getVerifier().getSalt(),
|
infoOrig.getVerifier().getSalt(),
|
||||||
infoOrig.getDecryptor().getIntegrityHmacKey()
|
infoOrig.getDecryptor().getIntegrityHmacKey()
|
||||||
);
|
);
|
||||||
NPOIFSFileSystem fsNew = new NPOIFSFileSystem();
|
|
||||||
OutputStream os = enc.getDataStream(fsNew);
|
|
||||||
os.write(zipInput);
|
|
||||||
os.close();
|
|
||||||
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
final byte[] epNewBytes;
|
||||||
fsNew.writeFilesystem(bos);
|
final EncryptionInfo infoReload;
|
||||||
fsNew.close();
|
try (NPOIFSFileSystem fsNew = new NPOIFSFileSystem()) {
|
||||||
|
try (OutputStream os = enc.getDataStream(fsNew)) {
|
||||||
|
os.write(zipInput);
|
||||||
|
}
|
||||||
|
|
||||||
NPOIFSFileSystem fsReload = new NPOIFSFileSystem(new ByteArrayInputStream(bos.toByteArray()));
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
InputStream epReload = fsReload.getRoot().createDocumentInputStream("EncryptedPackage");
|
fsNew.writeFilesystem(bos);
|
||||||
byte[] epNewBytes = IOUtils.toByteArray(epReload, 9400);
|
|
||||||
epReload.close();
|
try (NPOIFSFileSystem fsReload = new NPOIFSFileSystem(new ByteArrayInputStream(bos.toByteArray()))) {
|
||||||
|
infoReload = new EncryptionInfo(fsReload);
|
||||||
|
try (InputStream epReload = fsReload.getRoot().createDocumentInputStream("EncryptedPackage")) {
|
||||||
|
epNewBytes = IOUtils.toByteArray(epReload, 9400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
assertArrayEquals(epOrigBytes, epNewBytes);
|
assertArrayEquals(epOrigBytes, epNewBytes);
|
||||||
|
|
||||||
EncryptionInfo infoReload = new EncryptionInfo(fsOrig);
|
|
||||||
Decryptor decReload = infoReload.getDecryptor();
|
Decryptor decReload = infoReload.getDecryptor();
|
||||||
b = decReload.verifyPassword("Test001!!");
|
assertTrue(decReload.verifyPassword("Test001!!"));
|
||||||
assertTrue(b);
|
|
||||||
|
|
||||||
AgileEncryptionHeader aehOrig = (AgileEncryptionHeader)infoOrig.getHeader();
|
AgileEncryptionHeader aehOrig = (AgileEncryptionHeader)infoOrig.getHeader();
|
||||||
AgileEncryptionHeader aehReload = (AgileEncryptionHeader)infoReload.getHeader();
|
AgileEncryptionHeader aehReload = (AgileEncryptionHeader)infoReload.getHeader();
|
||||||
@ -529,7 +542,5 @@ public class TestEncryptor {
|
|||||||
// assertArrayEquals(adOrig.getIntegrityHmacValue(), adReload.getIntegrityHmacValue());
|
// assertArrayEquals(adOrig.getIntegrityHmacValue(), adReload.getIntegrityHmacValue());
|
||||||
assertArrayEquals(adOrig.getSecretKey().getEncoded(), adReload.getSecretKey().getEncoded());
|
assertArrayEquals(adOrig.getSecretKey().getEncoded(), adReload.getSecretKey().getEncoded());
|
||||||
assertArrayEquals(adOrig.getVerifier(), adReload.getVerifier());
|
assertArrayEquals(adOrig.getVerifier(), adReload.getVerifier());
|
||||||
|
|
||||||
fsReload.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,6 +119,9 @@ java.lang.Object#notifyAll()
|
|||||||
@defaultMessage Don't interrupt threads use FutureUtils#cancel(Future<T>) instead
|
@defaultMessage Don't interrupt threads use FutureUtils#cancel(Future<T>) instead
|
||||||
java.util.concurrent.Future#cancel(boolean)
|
java.util.concurrent.Future#cancel(boolean)
|
||||||
|
|
||||||
|
@defaultMessage Don't use ...InputStream.available() as it gives wrong result for certain streams - use IOUtils.toByteArray to read the stream fully and then count the available bytes
|
||||||
|
java.io.InputStream#available()
|
||||||
|
|
||||||
@defaultMessage Unnecessary, inefficient, and confusing conversion of String.toString
|
@defaultMessage Unnecessary, inefficient, and confusing conversion of String.toString
|
||||||
java.lang.String#toString()
|
java.lang.String#toString()
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ public final class TextSpecInfoAtom extends RecordAtom {
|
|||||||
public TextSpecInfoRun[] getTextSpecInfoRuns(){
|
public TextSpecInfoRun[] getTextSpecInfoRuns(){
|
||||||
LittleEndianByteArrayInputStream bis = new LittleEndianByteArrayInputStream(_data); // NOSONAR
|
LittleEndianByteArrayInputStream bis = new LittleEndianByteArrayInputStream(_data); // NOSONAR
|
||||||
List<TextSpecInfoRun> lst = new ArrayList<>();
|
List<TextSpecInfoRun> lst = new ArrayList<>();
|
||||||
while (bis.available() > 0) {
|
while (bis.getReadIndex() < _data.length) {
|
||||||
lst.add(new TextSpecInfoRun(bis));
|
lst.add(new TextSpecInfoRun(bis));
|
||||||
}
|
}
|
||||||
return lst.toArray(new TextSpecInfoRun[lst.size()]);
|
return lst.toArray(new TextSpecInfoRun[lst.size()]);
|
||||||
|
@ -50,52 +50,59 @@ public class HwmfPicture {
|
|||||||
final HwmfHeader header;
|
final HwmfHeader header;
|
||||||
|
|
||||||
public HwmfPicture(InputStream inputStream) throws IOException {
|
public HwmfPicture(InputStream inputStream) throws IOException {
|
||||||
BufferedInputStream bis = new BufferedInputStream(inputStream, 10000);
|
|
||||||
LittleEndianInputStream leis = new LittleEndianInputStream(bis);
|
|
||||||
placeableHeader = HwmfPlaceableHeader.readHeader(leis);
|
|
||||||
header = new HwmfHeader(leis);
|
|
||||||
|
|
||||||
for (;;) {
|
try (BufferedInputStream bis = new BufferedInputStream(inputStream, 10000);
|
||||||
if (leis.available() < 6) {
|
LittleEndianInputStream leis = new LittleEndianInputStream(bis)) {
|
||||||
logger.log(POILogger.ERROR, "unexpected eof - wmf file was truncated");
|
placeableHeader = HwmfPlaceableHeader.readHeader(leis);
|
||||||
break;
|
header = new HwmfHeader(leis);
|
||||||
}
|
|
||||||
// recordSize in DWORDs
|
|
||||||
long recordSizeLong = leis.readUInt()*2;
|
|
||||||
if (recordSizeLong > Integer.MAX_VALUE) {
|
|
||||||
throw new RecordFormatException("record size can't be > "+Integer.MAX_VALUE);
|
|
||||||
} else if (recordSizeLong < 0L) {
|
|
||||||
throw new RecordFormatException("record size can't be < 0");
|
|
||||||
}
|
|
||||||
int recordSize = (int)recordSizeLong;
|
|
||||||
int recordFunction = leis.readShort();
|
|
||||||
// 4 bytes (recordSize) + 2 bytes (recordFunction)
|
|
||||||
int consumedSize = 6;
|
|
||||||
HwmfRecordType wrt = HwmfRecordType.getById(recordFunction);
|
|
||||||
if (wrt == null) {
|
|
||||||
throw new IOException("unexpected record type: "+recordFunction);
|
|
||||||
}
|
|
||||||
if (wrt == HwmfRecordType.eof) break;
|
|
||||||
if (wrt.clazz == null) {
|
|
||||||
throw new IOException("unsupported record type: "+recordFunction);
|
|
||||||
}
|
|
||||||
|
|
||||||
HwmfRecord wr;
|
for (;;) {
|
||||||
try {
|
long recordSize;
|
||||||
wr = wrt.clazz.newInstance();
|
int recordFunction;
|
||||||
records.add(wr);
|
try {
|
||||||
} catch (Exception e) {
|
// recordSize in DWORDs
|
||||||
throw (IOException)new IOException("can't create wmf record").initCause(e);
|
long recordSizeLong = leis.readUInt()*2;
|
||||||
}
|
if (recordSizeLong > Integer.MAX_VALUE) {
|
||||||
|
throw new RecordFormatException("record size can't be > "+Integer.MAX_VALUE);
|
||||||
|
} else if (recordSizeLong < 0L) {
|
||||||
|
throw new RecordFormatException("record size can't be < 0");
|
||||||
|
}
|
||||||
|
recordSize = (int)recordSizeLong;
|
||||||
|
recordFunction = leis.readShort();
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.log(POILogger.ERROR, "unexpected eof - wmf file was truncated");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// 4 bytes (recordSize) + 2 bytes (recordFunction)
|
||||||
|
int consumedSize = 6;
|
||||||
|
HwmfRecordType wrt = HwmfRecordType.getById(recordFunction);
|
||||||
|
if (wrt == null) {
|
||||||
|
throw new IOException("unexpected record type: "+recordFunction);
|
||||||
|
}
|
||||||
|
if (wrt == HwmfRecordType.eof) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (wrt.clazz == null) {
|
||||||
|
throw new IOException("unsupported record type: "+recordFunction);
|
||||||
|
}
|
||||||
|
|
||||||
consumedSize += wr.init(leis, recordSize, recordFunction);
|
HwmfRecord wr;
|
||||||
int remainingSize = recordSize - consumedSize;
|
try {
|
||||||
if (remainingSize < 0) {
|
wr = wrt.clazz.newInstance();
|
||||||
throw new RecordFormatException("read too many bytes. record size: "+recordSize + "; comsumed size: "+consumedSize);
|
records.add(wr);
|
||||||
} else if(remainingSize > 0) {
|
} catch (Exception e) {
|
||||||
long skipped = IOUtils.skipFully(leis, remainingSize);
|
throw (IOException)new IOException("can't create wmf record").initCause(e);
|
||||||
if (skipped != (long)remainingSize) {
|
}
|
||||||
throw new RecordFormatException("Tried to skip "+remainingSize + " but skipped: "+skipped);
|
|
||||||
|
consumedSize += wr.init(leis, recordSize, recordFunction);
|
||||||
|
int remainingSize = (int)(recordSize - consumedSize);
|
||||||
|
if (remainingSize < 0) {
|
||||||
|
throw new RecordFormatException("read too many bytes. record size: "+recordSize + "; comsumed size: "+consumedSize);
|
||||||
|
} else if(remainingSize > 0) {
|
||||||
|
long skipped = IOUtils.skipFully(leis, remainingSize);
|
||||||
|
if (skipped != (long)remainingSize) {
|
||||||
|
throw new RecordFormatException("Tried to skip "+remainingSize + " but skipped: "+skipped);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@ import java.io.FileInputStream;
|
|||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.FilterInputStream;
|
import java.io.FilterInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -57,32 +58,30 @@ import org.junit.Ignore;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class TestHwmfParsing {
|
public class TestHwmfParsing {
|
||||||
|
|
||||||
|
private static final POIDataSamples samples = POIDataSamples.getSlideShowInstance();
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parse() throws IOException {
|
public void parse() throws IOException {
|
||||||
File f = POIDataSamples.getSlideShowInstance().getFile("santa.wmf");
|
try (InputStream fis = samples.openResourceAsStream("santa.wmf")) {
|
||||||
FileInputStream fis = new FileInputStream(f);
|
HwmfPicture wmf = new HwmfPicture(fis);
|
||||||
HwmfPicture wmf = new HwmfPicture(fis);
|
List<HwmfRecord> records = wmf.getRecords();
|
||||||
fis.close();
|
assertEquals(581, records.size());
|
||||||
List<HwmfRecord> records = wmf.getRecords();
|
}
|
||||||
assertEquals(581, records.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = RecordFormatException.class)
|
@Test(expected = RecordFormatException.class)
|
||||||
public void testInfiniteLoop() throws Exception {
|
public void testInfiniteLoop() throws Exception {
|
||||||
File f = POIDataSamples.getSlideShowInstance().getFile("61338.wmf");
|
try (InputStream is = samples.openResourceAsStream("61338.wmf")) {
|
||||||
FileInputStream fis = null;
|
new HwmfPicture(is);
|
||||||
try {
|
|
||||||
fis = new FileInputStream(f);
|
|
||||||
HwmfPicture wmf = new HwmfPicture(fis);
|
|
||||||
} finally {
|
|
||||||
fis.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore("This is work-in-progress and not a real unit test ...")
|
@Ignore("This is work-in-progress and not a real unit test ...")
|
||||||
public void paint() throws IOException {
|
public void paint() throws IOException {
|
||||||
File f = POIDataSamples.getSlideShowInstance().getFile("santa.wmf");
|
File f = samples.getFile("santa.wmf");
|
||||||
// File f = new File("bla.wmf");
|
// File f = new File("bla.wmf");
|
||||||
FileInputStream fis = new FileInputStream(f);
|
FileInputStream fis = new FileInputStream(f);
|
||||||
HwmfPicture wmf = new HwmfPicture(fis);
|
HwmfPicture wmf = new HwmfPicture(fis);
|
||||||
|
@ -29,6 +29,7 @@ import java.util.Map;
|
|||||||
import org.apache.poi.poifs.eventfilesystem.POIFSReader;
|
import org.apache.poi.poifs.eventfilesystem.POIFSReader;
|
||||||
import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
|
import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
|
||||||
import org.apache.poi.poifs.eventfilesystem.POIFSReaderListener;
|
import org.apache.poi.poifs.eventfilesystem.POIFSReaderListener;
|
||||||
|
import org.apache.poi.util.IOUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test (Proof of concept) program that employs the
|
* Test (Proof of concept) program that employs the
|
||||||
@ -110,16 +111,15 @@ public class ReaderWriter
|
|||||||
@Override
|
@Override
|
||||||
public void processPOIFSReaderEvent(final POIFSReaderEvent event)
|
public void processPOIFSReaderEvent(final POIFSReaderEvent event)
|
||||||
{
|
{
|
||||||
|
@SuppressWarnings("resource")
|
||||||
DocumentInputStream istream = event.getStream();
|
DocumentInputStream istream = event.getStream();
|
||||||
POIFSDocumentPath path = event.getPath();
|
POIFSDocumentPath path = event.getPath();
|
||||||
String name = event.getName();
|
String name = event.getName();
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
byte[] data = IOUtils.toByteArray(istream);
|
||||||
int size = istream.available();
|
int size = data.length;
|
||||||
byte[] data = new byte[ istream.available() ];
|
|
||||||
|
|
||||||
istream.read(data);
|
|
||||||
DocumentDescriptor descriptor = new DocumentDescriptor(path,
|
DocumentDescriptor descriptor = new DocumentDescriptor(path,
|
||||||
name);
|
name);
|
||||||
|
|
||||||
|
@ -17,22 +17,28 @@
|
|||||||
|
|
||||||
package org.apache.poi.poifs.filesystem;
|
package org.apache.poi.poifs.filesystem;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
import org.apache.poi.POIDataSamples;
|
import org.apache.poi.POIDataSamples;
|
||||||
import org.apache.poi.poifs.property.DirectoryProperty;
|
import org.apache.poi.poifs.property.DirectoryProperty;
|
||||||
import org.apache.poi.poifs.storage.RawDataBlock;
|
import org.apache.poi.poifs.storage.RawDataBlock;
|
||||||
|
import org.apache.poi.util.SuppressForbidden;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to test DocumentInputStream functionality
|
* Class to test DocumentInputStream functionality
|
||||||
*/
|
*/
|
||||||
public final class TestDocumentInputStream extends TestCase {
|
public final class TestDocumentInputStream {
|
||||||
private DocumentNode _workbook_n;
|
private DocumentNode _workbook_n;
|
||||||
private DocumentNode _workbook_o;
|
private DocumentNode _workbook_o;
|
||||||
private byte[] _workbook_data;
|
private byte[] _workbook_data;
|
||||||
@ -42,8 +48,8 @@ public final class TestDocumentInputStream extends TestCase {
|
|||||||
// any block size
|
// any block size
|
||||||
private static final int _buffer_size = 6;
|
private static final int _buffer_size = 6;
|
||||||
|
|
||||||
@Override
|
@Before
|
||||||
protected void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
int blocks = (_workbook_size + 511) / 512;
|
int blocks = (_workbook_size + 511) / 512;
|
||||||
|
|
||||||
_workbook_data = new byte[ 512 * blocks ];
|
_workbook_data = new byte[ 512 * blocks ];
|
||||||
@ -92,6 +98,7 @@ public final class TestDocumentInputStream extends TestCase {
|
|||||||
/**
|
/**
|
||||||
* test constructor
|
* test constructor
|
||||||
*/
|
*/
|
||||||
|
@Test
|
||||||
public void testConstructor() throws IOException {
|
public void testConstructor() throws IOException {
|
||||||
DocumentInputStream ostream = new ODocumentInputStream(_workbook_o);
|
DocumentInputStream ostream = new ODocumentInputStream(_workbook_o);
|
||||||
DocumentInputStream nstream = new NDocumentInputStream(_workbook_n);
|
DocumentInputStream nstream = new NDocumentInputStream(_workbook_n);
|
||||||
@ -99,8 +106,8 @@ public final class TestDocumentInputStream extends TestCase {
|
|||||||
assertEquals(_workbook_size, _workbook_o.getSize());
|
assertEquals(_workbook_size, _workbook_o.getSize());
|
||||||
assertEquals(_workbook_size, _workbook_n.getSize());
|
assertEquals(_workbook_size, _workbook_n.getSize());
|
||||||
|
|
||||||
assertEquals(_workbook_size, ostream.available());
|
assertEquals(_workbook_size, available(ostream));
|
||||||
assertEquals(_workbook_size, nstream.available());
|
assertEquals(_workbook_size, available(nstream));
|
||||||
|
|
||||||
ostream.close();
|
ostream.close();
|
||||||
nstream.close();
|
nstream.close();
|
||||||
@ -109,23 +116,24 @@ public final class TestDocumentInputStream extends TestCase {
|
|||||||
/**
|
/**
|
||||||
* test available() behavior
|
* test available() behavior
|
||||||
*/
|
*/
|
||||||
|
@Test
|
||||||
public void testAvailable() throws IOException {
|
public void testAvailable() throws IOException {
|
||||||
DocumentInputStream ostream = new DocumentInputStream(_workbook_o);
|
DocumentInputStream ostream = new DocumentInputStream(_workbook_o);
|
||||||
DocumentInputStream nstream = new NDocumentInputStream(_workbook_n);
|
DocumentInputStream nstream = new NDocumentInputStream(_workbook_n);
|
||||||
|
|
||||||
assertEquals(_workbook_size, ostream.available());
|
assertEquals(_workbook_size, available(ostream));
|
||||||
assertEquals(_workbook_size, nstream.available());
|
assertEquals(_workbook_size, available(nstream));
|
||||||
ostream.close();
|
ostream.close();
|
||||||
nstream.close();
|
nstream.close();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ostream.available();
|
available(ostream);
|
||||||
fail("Should have caught IOException");
|
fail("Should have caught IOException");
|
||||||
} catch (IllegalStateException ignored) {
|
} catch (IllegalStateException ignored) {
|
||||||
// as expected
|
// as expected
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
nstream.available();
|
available(nstream);
|
||||||
fail("Should have caught IOException");
|
fail("Should have caught IOException");
|
||||||
} catch (IllegalStateException ignored) {
|
} catch (IllegalStateException ignored) {
|
||||||
// as expected
|
// as expected
|
||||||
@ -135,6 +143,7 @@ public final class TestDocumentInputStream extends TestCase {
|
|||||||
/**
|
/**
|
||||||
* test mark/reset/markSupported.
|
* test mark/reset/markSupported.
|
||||||
*/
|
*/
|
||||||
|
@Test
|
||||||
public void testMarkFunctions() throws IOException {
|
public void testMarkFunctions() throws IOException {
|
||||||
byte[] buffer = new byte[ _workbook_size / 5 ];
|
byte[] buffer = new byte[ _workbook_size / 5 ];
|
||||||
byte[] small_buffer = new byte[212];
|
byte[] small_buffer = new byte[212];
|
||||||
@ -152,12 +161,12 @@ public final class TestDocumentInputStream extends TestCase {
|
|||||||
_workbook_data[ j ], buffer[ j ]
|
_workbook_data[ j ], buffer[ j ]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
assertEquals(_workbook_size - buffer.length, stream.available());
|
assertEquals(_workbook_size - buffer.length, available(stream));
|
||||||
|
|
||||||
// Reset, and check the available goes back to being the
|
// Reset, and check the available goes back to being the
|
||||||
// whole of the stream
|
// whole of the stream
|
||||||
stream.reset();
|
stream.reset();
|
||||||
assertEquals(_workbook_size, stream.available());
|
assertEquals(_workbook_size, available(stream));
|
||||||
|
|
||||||
|
|
||||||
// Read part of a block
|
// Read part of a block
|
||||||
@ -168,7 +177,7 @@ public final class TestDocumentInputStream extends TestCase {
|
|||||||
_workbook_data[ j ], small_buffer[ j ]
|
_workbook_data[ j ], small_buffer[ j ]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
assertEquals(_workbook_size - small_buffer.length, stream.available());
|
assertEquals(_workbook_size - small_buffer.length, available(stream));
|
||||||
stream.mark(0);
|
stream.mark(0);
|
||||||
|
|
||||||
// Read the next part
|
// Read the next part
|
||||||
@ -179,11 +188,11 @@ public final class TestDocumentInputStream extends TestCase {
|
|||||||
_workbook_data[ j+small_buffer.length ], small_buffer[ j ]
|
_workbook_data[ j+small_buffer.length ], small_buffer[ j ]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
assertEquals(_workbook_size - 2*small_buffer.length, stream.available());
|
assertEquals(_workbook_size - 2*small_buffer.length, available(stream));
|
||||||
|
|
||||||
// Reset, check it goes back to where it was
|
// Reset, check it goes back to where it was
|
||||||
stream.reset();
|
stream.reset();
|
||||||
assertEquals(_workbook_size - small_buffer.length, stream.available());
|
assertEquals(_workbook_size - small_buffer.length, available(stream));
|
||||||
|
|
||||||
// Read
|
// Read
|
||||||
stream.read(small_buffer);
|
stream.read(small_buffer);
|
||||||
@ -193,7 +202,7 @@ public final class TestDocumentInputStream extends TestCase {
|
|||||||
_workbook_data[ j+small_buffer.length ], small_buffer[ j ]
|
_workbook_data[ j+small_buffer.length ], small_buffer[ j ]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
assertEquals(_workbook_size - 2*small_buffer.length, stream.available());
|
assertEquals(_workbook_size - 2*small_buffer.length, available(stream));
|
||||||
|
|
||||||
|
|
||||||
// Now read at various points
|
// Now read at various points
|
||||||
@ -236,11 +245,11 @@ public final class TestDocumentInputStream extends TestCase {
|
|||||||
_workbook_data[ j ], buffer[ j ]
|
_workbook_data[ j ], buffer[ j ]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
assertEquals(_workbook_size - buffer.length, stream.available());
|
assertEquals(_workbook_size - buffer.length, available(stream));
|
||||||
|
|
||||||
// Read all of it again, check it began at the start again
|
// Read all of it again, check it began at the start again
|
||||||
stream.reset();
|
stream.reset();
|
||||||
assertEquals(_workbook_size, stream.available());
|
assertEquals(_workbook_size, available(stream));
|
||||||
|
|
||||||
stream.read(buffer);
|
stream.read(buffer);
|
||||||
for (int j = 0; j < buffer.length; j++) {
|
for (int j = 0; j < buffer.length; j++) {
|
||||||
@ -254,7 +263,7 @@ public final class TestDocumentInputStream extends TestCase {
|
|||||||
stream.mark(12);
|
stream.mark(12);
|
||||||
stream.read(buffer);
|
stream.read(buffer);
|
||||||
assertEquals(_workbook_size - (2 * buffer.length),
|
assertEquals(_workbook_size - (2 * buffer.length),
|
||||||
stream.available());
|
available(stream));
|
||||||
for (int j = buffer.length; j < (2 * buffer.length); j++)
|
for (int j = buffer.length; j < (2 * buffer.length); j++)
|
||||||
{
|
{
|
||||||
assertEquals("checking byte " + j, _workbook_data[ j ],
|
assertEquals("checking byte " + j, _workbook_data[ j ],
|
||||||
@ -263,12 +272,12 @@ public final class TestDocumentInputStream extends TestCase {
|
|||||||
|
|
||||||
// Reset, should go back to only one buffer full read
|
// Reset, should go back to only one buffer full read
|
||||||
stream.reset();
|
stream.reset();
|
||||||
assertEquals(_workbook_size - buffer.length, stream.available());
|
assertEquals(_workbook_size - buffer.length, available(stream));
|
||||||
|
|
||||||
// Read the buffer again
|
// Read the buffer again
|
||||||
stream.read(buffer);
|
stream.read(buffer);
|
||||||
assertEquals(_workbook_size - (2 * buffer.length),
|
assertEquals(_workbook_size - (2 * buffer.length),
|
||||||
stream.available());
|
available(stream));
|
||||||
for (int j = buffer.length; j < (2 * buffer.length); j++)
|
for (int j = buffer.length; j < (2 * buffer.length); j++)
|
||||||
{
|
{
|
||||||
assertEquals("checking byte " + j, _workbook_data[ j ],
|
assertEquals("checking byte " + j, _workbook_data[ j ],
|
||||||
@ -281,6 +290,7 @@ public final class TestDocumentInputStream extends TestCase {
|
|||||||
/**
|
/**
|
||||||
* test simple read method
|
* test simple read method
|
||||||
*/
|
*/
|
||||||
|
@Test
|
||||||
public void testReadSingleByte() throws IOException {
|
public void testReadSingleByte() throws IOException {
|
||||||
DocumentInputStream[] streams = new DocumentInputStream[] {
|
DocumentInputStream[] streams = new DocumentInputStream[] {
|
||||||
new DocumentInputStream(_workbook_o),
|
new DocumentInputStream(_workbook_o),
|
||||||
@ -297,7 +307,7 @@ public final class TestDocumentInputStream extends TestCase {
|
|||||||
( byte ) b);
|
( byte ) b);
|
||||||
remaining--;
|
remaining--;
|
||||||
assertEquals("checking remaining after reading byte " + j,
|
assertEquals("checking remaining after reading byte " + j,
|
||||||
remaining, stream.available());
|
remaining, available(stream));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure we fell off the end
|
// Ensure we fell off the end
|
||||||
@ -317,6 +327,7 @@ public final class TestDocumentInputStream extends TestCase {
|
|||||||
/**
|
/**
|
||||||
* Test buffered read
|
* Test buffered read
|
||||||
*/
|
*/
|
||||||
|
@Test
|
||||||
public void testBufferRead() throws IOException {
|
public void testBufferRead() throws IOException {
|
||||||
DocumentInputStream[] streams = new DocumentInputStream[] {
|
DocumentInputStream[] streams = new DocumentInputStream[] {
|
||||||
new DocumentInputStream(_workbook_o),
|
new DocumentInputStream(_workbook_o),
|
||||||
@ -333,22 +344,22 @@ public final class TestDocumentInputStream extends TestCase {
|
|||||||
|
|
||||||
// test reading zero length buffer
|
// test reading zero length buffer
|
||||||
assertEquals(0, stream.read(new byte[ 0 ]));
|
assertEquals(0, stream.read(new byte[ 0 ]));
|
||||||
assertEquals(_workbook_size, stream.available());
|
assertEquals(_workbook_size, available(stream));
|
||||||
byte[] buffer = new byte[ _buffer_size ];
|
byte[] buffer = new byte[ _buffer_size ];
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
|
||||||
while (stream.available() >= buffer.length)
|
while (available(stream) >= buffer.length)
|
||||||
{
|
{
|
||||||
assertEquals(_buffer_size, stream.read(buffer));
|
assertEquals(_buffer_size, stream.read(buffer));
|
||||||
for (byte data : buffer) {
|
for (byte element : buffer) {
|
||||||
assertEquals("in main loop, byte " + offset,
|
assertEquals("in main loop, byte " + offset,
|
||||||
_workbook_data[ offset ], data);
|
_workbook_data[ offset ], element);
|
||||||
offset++;
|
offset++;
|
||||||
}
|
}
|
||||||
assertEquals("offset " + offset, _workbook_size - offset,
|
assertEquals("offset " + offset, _workbook_size - offset,
|
||||||
stream.available());
|
available(stream));
|
||||||
}
|
}
|
||||||
assertEquals(_workbook_size % _buffer_size, stream.available());
|
assertEquals(_workbook_size % _buffer_size, available(stream));
|
||||||
Arrays.fill(buffer, ( byte ) 0);
|
Arrays.fill(buffer, ( byte ) 0);
|
||||||
int count = stream.read(buffer);
|
int count = stream.read(buffer);
|
||||||
|
|
||||||
@ -378,6 +389,7 @@ public final class TestDocumentInputStream extends TestCase {
|
|||||||
/**
|
/**
|
||||||
* Test complex buffered read
|
* Test complex buffered read
|
||||||
*/
|
*/
|
||||||
|
@Test
|
||||||
public void testComplexBufferRead() throws IOException {
|
public void testComplexBufferRead() throws IOException {
|
||||||
DocumentInputStream[] streams = new DocumentInputStream[] {
|
DocumentInputStream[] streams = new DocumentInputStream[] {
|
||||||
new DocumentInputStream(_workbook_o),
|
new DocumentInputStream(_workbook_o),
|
||||||
@ -413,11 +425,11 @@ public final class TestDocumentInputStream extends TestCase {
|
|||||||
|
|
||||||
// test reading zero
|
// test reading zero
|
||||||
assertEquals(0, stream.read(new byte[ 5 ], 0, 0));
|
assertEquals(0, stream.read(new byte[ 5 ], 0, 0));
|
||||||
assertEquals(_workbook_size, stream.available());
|
assertEquals(_workbook_size, available(stream));
|
||||||
byte[] buffer = new byte[ _workbook_size ];
|
byte[] buffer = new byte[ _workbook_size ];
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
|
||||||
while (stream.available() >= _buffer_size)
|
while (available(stream) >= _buffer_size)
|
||||||
{
|
{
|
||||||
Arrays.fill(buffer, ( byte ) 0);
|
Arrays.fill(buffer, ( byte ) 0);
|
||||||
assertEquals(_buffer_size,
|
assertEquals(_buffer_size,
|
||||||
@ -437,9 +449,9 @@ public final class TestDocumentInputStream extends TestCase {
|
|||||||
}
|
}
|
||||||
offset += _buffer_size;
|
offset += _buffer_size;
|
||||||
assertEquals("offset " + offset, _workbook_size - offset,
|
assertEquals("offset " + offset, _workbook_size - offset,
|
||||||
stream.available());
|
available(stream));
|
||||||
}
|
}
|
||||||
assertEquals(_workbook_size % _buffer_size, stream.available());
|
assertEquals(_workbook_size % _buffer_size, available(stream));
|
||||||
Arrays.fill(buffer, ( byte ) 0);
|
Arrays.fill(buffer, ( byte ) 0);
|
||||||
int count = stream.read(buffer, offset,
|
int count = stream.read(buffer, offset,
|
||||||
_workbook_size % _buffer_size);
|
_workbook_size % _buffer_size);
|
||||||
@ -474,38 +486,40 @@ public final class TestDocumentInputStream extends TestCase {
|
|||||||
/**
|
/**
|
||||||
* Tests that we can skip within the stream
|
* Tests that we can skip within the stream
|
||||||
*/
|
*/
|
||||||
|
@Test
|
||||||
public void testSkip() throws IOException {
|
public void testSkip() throws IOException {
|
||||||
DocumentInputStream[] streams = new DocumentInputStream[] {
|
DocumentInputStream[] streams = new DocumentInputStream[] {
|
||||||
new DocumentInputStream(_workbook_o),
|
new DocumentInputStream(_workbook_o),
|
||||||
new NDocumentInputStream(_workbook_n)
|
new NDocumentInputStream(_workbook_n)
|
||||||
};
|
};
|
||||||
for(DocumentInputStream stream : streams) {
|
for(DocumentInputStream stream : streams) {
|
||||||
assertEquals(_workbook_size, stream.available());
|
assertEquals(_workbook_size, available(stream));
|
||||||
int count = stream.available();
|
int count = available(stream);
|
||||||
|
|
||||||
while (stream.available() >= _buffer_size) {
|
while (available(stream) >= _buffer_size) {
|
||||||
assertEquals(_buffer_size, stream.skip(_buffer_size));
|
assertEquals(_buffer_size, stream.skip(_buffer_size));
|
||||||
count -= _buffer_size;
|
count -= _buffer_size;
|
||||||
assertEquals(count, stream.available());
|
assertEquals(count, available(stream));
|
||||||
}
|
}
|
||||||
assertEquals(_workbook_size % _buffer_size,
|
assertEquals(_workbook_size % _buffer_size,
|
||||||
stream.skip(_buffer_size));
|
stream.skip(_buffer_size));
|
||||||
assertEquals(0, stream.available());
|
assertEquals(0, available(stream));
|
||||||
stream.reset();
|
stream.reset();
|
||||||
assertEquals(_workbook_size, stream.available());
|
assertEquals(_workbook_size, available(stream));
|
||||||
assertEquals(_workbook_size, stream.skip(_workbook_size * 2));
|
assertEquals(_workbook_size, stream.skip(_workbook_size * 2));
|
||||||
assertEquals(0, stream.available());
|
assertEquals(0, available(stream));
|
||||||
stream.reset();
|
stream.reset();
|
||||||
assertEquals(_workbook_size, stream.available());
|
assertEquals(_workbook_size, available(stream));
|
||||||
assertEquals(_workbook_size,
|
assertEquals(_workbook_size,
|
||||||
stream.skip(2 + ( long ) Integer.MAX_VALUE));
|
stream.skip(2 + ( long ) Integer.MAX_VALUE));
|
||||||
assertEquals(0, stream.available());
|
assertEquals(0, available(stream));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that we can read files at multiple levels down the tree
|
* Test that we can read files at multiple levels down the tree
|
||||||
*/
|
*/
|
||||||
|
@Test
|
||||||
public void testReadMultipleTreeLevels() throws Exception {
|
public void testReadMultipleTreeLevels() throws Exception {
|
||||||
final POIDataSamples _samples = POIDataSamples.getPublisherInstance();
|
final POIDataSamples _samples = POIDataSamples.getPublisherInstance();
|
||||||
File sample = _samples.getFile("Sample.pub");
|
File sample = _samples.getFile("Sample.pub");
|
||||||
@ -551,4 +565,9 @@ public final class TestDocumentInputStream extends TestCase {
|
|||||||
npoifs.close();
|
npoifs.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressForbidden("just for testing")
|
||||||
|
private static int available(InputStream is) throws IOException {
|
||||||
|
return is.available();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ import org.apache.poi.poifs.storage.BATBlock;
|
|||||||
import org.apache.poi.poifs.storage.BlockAllocationTableReader;
|
import org.apache.poi.poifs.storage.BlockAllocationTableReader;
|
||||||
import org.apache.poi.poifs.storage.HeaderBlock;
|
import org.apache.poi.poifs.storage.HeaderBlock;
|
||||||
import org.apache.poi.poifs.storage.RawDataBlockList;
|
import org.apache.poi.poifs.storage.RawDataBlockList;
|
||||||
|
import org.apache.poi.util.IOUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for the older OPOIFS-based POIFSFileSystem
|
* Tests for the older OPOIFS-based POIFSFileSystem
|
||||||
@ -285,13 +286,8 @@ public final class TestPOIFSFileSystem extends TestCase {
|
|||||||
checkAllDirectoryContents((DirectoryEntry)entry);
|
checkAllDirectoryContents((DirectoryEntry)entry);
|
||||||
} else {
|
} else {
|
||||||
DocumentNode doc = (DocumentNode) entry;
|
DocumentNode doc = (DocumentNode) entry;
|
||||||
DocumentInputStream dis = new DocumentInputStream(doc);
|
try (DocumentInputStream dis = new DocumentInputStream(doc)) {
|
||||||
try {
|
IOUtils.toByteArray(dis);
|
||||||
int numBytes = dis.available();
|
|
||||||
byte[] data = new byte [numBytes];
|
|
||||||
dis.read(data);
|
|
||||||
} finally {
|
|
||||||
dis.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,6 +172,29 @@ public final class TestIOUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = RecordFormatException.class)
|
||||||
|
public void testMaxLengthTooLong() throws IOException {
|
||||||
|
try (InputStream is = new FileInputStream(TMP)) {
|
||||||
|
IOUtils.toByteArray(is, Integer.MAX_VALUE, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMaxLengthIgnored() throws IOException {
|
||||||
|
try (InputStream is = new FileInputStream(TMP)) {
|
||||||
|
IOUtils.toByteArray(is, 90, Integer.MAX_VALUE);
|
||||||
|
IOUtils.toByteArray(is, 90, 100);
|
||||||
|
IOUtils.toByteArray(is, Integer.MAX_VALUE, Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = RecordFormatException.class)
|
||||||
|
public void testMaxLengthInvalid() throws IOException {
|
||||||
|
try (InputStream is = new FileInputStream(TMP)) {
|
||||||
|
IOUtils.toByteArray(is, 90, 80);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWonkyInputStream() throws IOException {
|
public void testWonkyInputStream() throws IOException {
|
||||||
long skipped = IOUtils.skipFully(new WonkyInputStream(), 10000);
|
long skipped = IOUtils.skipFully(new WonkyInputStream(), 10000);
|
||||||
|
@ -258,10 +258,14 @@ public final class TestLittleEndian {
|
|||||||
InputStream stream = new ByteArrayInputStream(_good_array);
|
InputStream stream = new ByteArrayInputStream(_good_array);
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
while (stream.available() > 0) {
|
while (true) {
|
||||||
short value = LittleEndian.readShort(stream);
|
try {
|
||||||
assertEquals(value, expected_value);
|
short value = LittleEndian.readShort(stream);
|
||||||
count++;
|
assertEquals(value, expected_value);
|
||||||
|
count++;
|
||||||
|
} catch (BufferUnderrunException e) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
assertEquals(count,
|
assertEquals(count,
|
||||||
_good_array.length / LittleEndianConsts.SHORT_SIZE);
|
_good_array.length / LittleEndianConsts.SHORT_SIZE);
|
||||||
@ -283,10 +287,14 @@ public final class TestLittleEndian {
|
|||||||
InputStream stream = new ByteArrayInputStream(_good_array);
|
InputStream stream = new ByteArrayInputStream(_good_array);
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
while (stream.available() > 0) {
|
while (true) {
|
||||||
int value = LittleEndian.readInt(stream);
|
try {
|
||||||
assertEquals(value, expected_value);
|
int value = LittleEndian.readInt(stream);
|
||||||
count++;
|
assertEquals(value, expected_value);
|
||||||
|
count++;
|
||||||
|
} catch (BufferUnderrunException e) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
assertEquals(count, _good_array.length / LittleEndianConsts.INT_SIZE);
|
assertEquals(count, _good_array.length / LittleEndianConsts.INT_SIZE);
|
||||||
stream = new ByteArrayInputStream(_bad_array);
|
stream = new ByteArrayInputStream(_bad_array);
|
||||||
@ -308,10 +316,14 @@ public final class TestLittleEndian {
|
|||||||
InputStream stream = new ByteArrayInputStream(_good_array);
|
InputStream stream = new ByteArrayInputStream(_good_array);
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
while (stream.available() > 0) {
|
while (true) {
|
||||||
long value = LittleEndian.readLong(stream);
|
try {
|
||||||
assertEquals(value, expected_value);
|
long value = LittleEndian.readLong(stream);
|
||||||
count++;
|
assertEquals(value, expected_value);
|
||||||
|
count++;
|
||||||
|
} catch (BufferUnderrunException e) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
assertEquals(count,
|
assertEquals(count,
|
||||||
_good_array.length / LittleEndianConsts.LONG_SIZE);
|
_good_array.length / LittleEndianConsts.LONG_SIZE);
|
||||||
@ -324,21 +336,17 @@ public final class TestLittleEndian {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// public void testReadFromStream() throws IOException {
|
@Test(expected = BufferUnderrunException.class)
|
||||||
// int actual;
|
public void testReadFromStream() throws IOException {
|
||||||
// actual = LittleEndian.readUShort(new ByteArrayInputStream(new byte[] { 5, -128, }));
|
int actual;
|
||||||
// assertEquals(32773, actual);
|
actual = LittleEndian.readUShort(new ByteArrayInputStream(new byte[] { 5, -128, }));
|
||||||
//
|
assertEquals(32773, actual);
|
||||||
// actual = LittleEndian.readUShort(new ByteArrayInputStream(new byte[] { 1, 2, 3, 4, }));
|
|
||||||
// assertEquals(513, actual);
|
actual = LittleEndian.readUShort(new ByteArrayInputStream(new byte[] { 1, 2, 3, 4, }));
|
||||||
//
|
assertEquals(513, actual);
|
||||||
// try {
|
|
||||||
// LittleEndian.readInt(new ByteArrayInputStream(new byte[] { 1, 2, 3, }));
|
LittleEndian.readInt(new ByteArrayInputStream(new byte[] { 1, 2, 3, }));
|
||||||
// fail("Should have caught BufferUnderrunException");
|
}
|
||||||
// } catch (BufferUnderrunException ignored) {
|
|
||||||
// // as expected
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUnsignedByteToInt() {
|
public void testUnsignedByteToInt() {
|
||||||
|
Loading…
Reference in New Issue
Block a user