SafePNGInputStream extends InputStream { @Override public int read() throws IOException { if (_firstRun) { _detectPNGSignature(); _firstRun = false; _readForwardByteCount = _PNG_SIGNATURE.length; } if (!_png) { return _bufferedInputStream.read(); } if (_readForwardByteCount > 0) { _readForwardByteCount--; return _bufferedInputStream.read(); } _bufferedInputStream.mark(_CHUNK_LENGTH_SIZE + _CHUNK_ID_SIZE); long chunkLength = _readChunkLength(); if (chunkLength == -1) { _bufferedInputStream.reset(); return _bufferedInputStream.read(); } PNGChunkType pngChunkType = _getPNGChunkType(); if (pngChunkType == PNGChunkType.OTHER) { return _readPreservedChunk(chunkLength); } if (pngChunkType == PNGChunkType.ITXT) { byte[] data = new byte[3]; int count = _bufferedInputStream.read(data); if ((count != 3) || (data[2] == 0)) { return _readPreservedChunk(chunkLength); } chunkLength -= 3; } long bytesToSkip = chunkLength + _CRC_SIZE; while (bytesToSkip > 0) { long skipped = _bufferedInputStream.skip(bytesToSkip); if (skipped <= 0) { break; } bytesToSkip -= skipped; } return read(); } SafePNGInputStream(BufferedInputStream bufferedInputStream); @Override int read();  }
@Test public void testChunksOtherThanZTXTArePreserved() throws Exception { InputStream inputStream = _createInputStream( _PNG_SIGNATURE, _MISC_CHUNK1); byte[] bytes = new byte[_PNG_SIGNATURE.length + _MISC_CHUNK1.length]; inputStream.read(bytes); Assert.assertArrayEquals( ArrayUtil.append(_PNG_SIGNATURE, _MISC_CHUNK1), bytes); Assert.assertEquals(-1, inputStream.read()); }
@Test public void testCompressedITXTChunksAreFilteredOut() throws Exception { InputStream inputStream = _createInputStream( _PNG_SIGNATURE, _COMPRESSED_ITXT_CHUNK); byte[] bytes = new byte[_PNG_SIGNATURE.length]; inputStream.read(bytes); Assert.assertArrayEquals(_PNG_SIGNATURE, bytes); Assert.assertEquals(-1, inputStream.read()); }
@Test public void testEmptyInputStreamReturnsNoData() throws Exception { InputStream inputStream = _createInputStream(new byte[0]); Assert.assertEquals(-1, inputStream.read()); }
@Test public void testICCPChunksAreFilteredOut() throws Exception { InputStream inputStream = _createInputStream( _PNG_SIGNATURE, _ICCP_CHUNK); byte[] bytes = new byte[_PNG_SIGNATURE.length]; inputStream.read(bytes); Assert.assertArrayEquals(_PNG_SIGNATURE, bytes); Assert.assertEquals(-1, inputStream.read()); }
@Test public void testPNGSignatureIsPreserved() throws Exception { InputStream inputStream = _createInputStream(_PNG_SIGNATURE); byte[] bytes = new byte[_PNG_SIGNATURE.length]; inputStream.read(bytes); Assert.assertArrayEquals(_PNG_SIGNATURE, bytes); Assert.assertEquals(-1, inputStream.read()); }
@Test public void testRemainingChunksOrderIsPreserved() throws Exception { InputStream inputStream = _createInputStream( _PNG_SIGNATURE, _MISC_CHUNK1, _ZTXT_CHUNK, _COMPRESSED_ITXT_CHUNK, _MISC_CHUNK2, _ICCP_CHUNK); byte[] bytes = new byte [_PNG_SIGNATURE.length + _MISC_CHUNK1.length + _MISC_CHUNK2.length]; inputStream.read(bytes); Assert.assertArrayEquals( ArrayUtil.append(_PNG_SIGNATURE, _MISC_CHUNK1, _MISC_CHUNK2), bytes); Assert.assertEquals(-1, inputStream.read()); }
@Test public void testStreamNotModifiedWhenNotAPNG() throws Exception { InputStream inputStream = _createInputStream(_NOT_PNG_CONTENT_BYTES); byte[] bytes = new byte[_NOT_PNG_CONTENT_BYTES.length]; inputStream.read(bytes); Assert.assertArrayEquals(_NOT_PNG_CONTENT_BYTES, bytes); }
@Test public void testUncompressedITXTChunksArePreserved() throws Exception { InputStream inputStream = _createInputStream( _PNG_SIGNATURE, _UNCOMPRESSED_ITXT_CHUNK); byte[] bytes = new byte[_PNG_SIGNATURE.length + _UNCOMPRESSED_ITXT_CHUNK.length]; inputStream.read(bytes); Assert.assertArrayEquals( ArrayUtil.append(_PNG_SIGNATURE, _UNCOMPRESSED_ITXT_CHUNK), bytes); Assert.assertEquals(-1, inputStream.read()); }
@Test public void testZTXTChunksAreFilteredOut() throws Exception { InputStream inputStream = _createInputStream( _PNG_SIGNATURE, _ZTXT_CHUNK); byte[] bytes = new byte[_PNG_SIGNATURE.length]; inputStream.read(bytes); Assert.assertArrayEquals(_PNG_SIGNATURE, bytes); Assert.assertEquals(-1, inputStream.read()); }