Repository: commons-compress Updated Branches: refs/heads/master 06c4b62ca -> ffb618d50
COMPRESS-445 provide statistics for 7z as well Project: http://git-wip-us.apache.org/repos/asf/commons-compress/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-compress/commit/ffb618d5 Tree: http://git-wip-us.apache.org/repos/asf/commons-compress/tree/ffb618d5 Diff: http://git-wip-us.apache.org/repos/asf/commons-compress/diff/ffb618d5 Branch: refs/heads/master Commit: ffb618d50a74e316aef01ffa2e381d4617900f3f Parents: 06c4b62 Author: Stefan Bodewig <bode...@apache.org> Authored: Mon Apr 30 18:13:46 2018 +0200 Committer: Stefan Bodewig <bode...@apache.org> Committed: Mon Apr 30 18:13:46 2018 +0200 ---------------------------------------------------------------------- src/changes/changes.xml | 2 + .../compress/archivers/sevenz/SevenZFile.java | 67 ++++++++++++++++++-- 2 files changed, 64 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-compress/blob/ffb618d5/src/changes/changes.xml ---------------------------------------------------------------------- diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 7341f10..11f0193 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -67,6 +67,8 @@ The <action> type attribute can be add,update,fix,remove. and uncompressed bytes read so far. This may be used to detect a ZipBomb if the compression ratio exceeds a certain threshold, for example. + For SevenZFile a new method returns the statistics for the + current entry. </action> <action issue="COMPRESS-443" type="add" date="2018-04-25"> Added a unit test that is supposed to fail if we break the http://git-wip-us.apache.org/repos/asf/commons-compress/blob/ffb618d5/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java b/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java index ecee9a9..14d33d4 100644 --- a/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java +++ b/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java @@ -22,6 +22,7 @@ import java.io.ByteArrayInputStream; import java.io.Closeable; import java.io.DataInputStream; import java.io.File; +import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; @@ -40,6 +41,7 @@ import org.apache.commons.compress.utils.BoundedInputStream; import org.apache.commons.compress.utils.CRC32VerifyingInputStream; import org.apache.commons.compress.utils.CharsetNames; import org.apache.commons.compress.utils.IOUtils; +import org.apache.commons.compress.utils.InputStreamStatistics; /** * Reads a 7z file, using SeekableByteChannel under @@ -81,6 +83,9 @@ public class SevenZFile implements Closeable { private InputStream currentFolderInputStream = null; private byte[] password; + private long compressedBytesReadFromCurrentEntry; + private long uncompressedBytesReadFromCurrentEntry; + private final ArrayList<InputStream> deferredBlockStreams = new ArrayList<>(); // shared with SevenZOutputFile and tests, neither mutates it @@ -220,6 +225,7 @@ public class SevenZFile implements Closeable { ++currentEntryIndex; final SevenZArchiveEntry entry = archive.files[currentEntryIndex]; buildDecodingStream(); + uncompressedBytesReadFromCurrentEntry = compressedBytesReadFromCurrentEntry = 0; return entry; } @@ -920,10 +926,33 @@ public class SevenZFile implements Closeable { private InputStream buildDecoderStack(final Folder folder, final long folderOffset, final int firstPackStreamIndex, final SevenZArchiveEntry entry) throws IOException { channel.position(folderOffset); - InputStream inputStreamStack = - new BufferedInputStream( + InputStream inputStreamStack = new FilterInputStream(new BufferedInputStream( new BoundedSeekableByteChannelInputStream(channel, - archive.packSizes[firstPackStreamIndex])); + archive.packSizes[firstPackStreamIndex]))) { + @Override + public int read() throws IOException { + final int r = in.read(); + if (r >= 0) { + count(1); + } + return r; + } + @Override + public int read(final byte[] b) throws IOException { + return read(b, 0, b.length); + } + @Override + public int read(final byte[] b, final int off, final int len) throws IOException { + final int r = in.read(b, off, len); + if (r >= 0) { + count(r); + } + return r; + } + private void count(int c) { + compressedBytesReadFromCurrentEntry += c; + } + }; final LinkedList<SevenZMethodConfiguration> methods = new LinkedList<>(); for (final Coder coder : folder.getOrderedCoders()) { if (coder.numInStreams != 1 || coder.numOutStreams != 1) { @@ -951,7 +980,11 @@ public class SevenZFile implements Closeable { * if an I/O error has occurred */ public int read() throws IOException { - return getCurrentStream().read(); + int b = getCurrentStream().read(); + if (b >= 0) { + uncompressedBytesReadFromCurrentEntry++; + } + return b; } private InputStream getCurrentStream() throws IOException { @@ -969,6 +1002,7 @@ public class SevenZFile implements Closeable { try (final InputStream stream = deferredBlockStreams.remove(0)) { IOUtils.skip(stream, Long.MAX_VALUE); } + compressedBytesReadFromCurrentEntry = 0; } return deferredBlockStreams.get(0); @@ -997,7 +1031,30 @@ public class SevenZFile implements Closeable { * if an I/O error has occurred */ public int read(final byte[] b, final int off, final int len) throws IOException { - return getCurrentStream().read(b, off, len); + int cnt = getCurrentStream().read(b, off, len); + if (cnt > 0) { + uncompressedBytesReadFromCurrentEntry += cnt; + } + return cnt; + } + + /** + * Provides statistics for bytes read from the current entry. + * + * @return statistics for bytes read from the current entry + * @since 1.17 + */ + public InputStreamStatistics getStatisticsForCurrentEntry() { + return new InputStreamStatistics() { + @Override + public long getCompressedCount() { + return compressedBytesReadFromCurrentEntry; + } + @Override + public long getUncompressedCount() { + return uncompressedBytesReadFromCurrentEntry; + } + }; } private static long readUint64(final ByteBuffer in) throws IOException {