Repository navigation
Releases
Release v5.1.0
Changelog
🚀 Features
- 31d28eb harden extraction against tar metadata, symlink and permission abuse (#342), closes #342
- ab1fbb8 support Java 17 as the minimum runtime (#340), closes #340
🧰 Tasks
- 199c49f deps: update dependency com.github.luben:zstd-jni to v1.5.7-22 (#341), closes #341
- d8c034a deps: update dependency org.ow2.asm:asm to v9.11 (#338), closes #338
- 8186dcc deps: update dependency com.github.luben:zstd-jni to v1.5.7-21 (#337), closes #337
- d1ba8ff deps: update hominux/.github digest to bb78570 (#336), closes #336
- cd493eb deps: update build and test dependencies to v1.6.5 (#335), closes #335
- d119e00 deps: update hominux/.github digest to d59901b (#332), closes #332
🛠 Build
- 4bd5f70 add a manual workflow to announce an existing release (#333), closes #333
- 5052aba update the announcement workflow to skip patch releases (#331), closes #331
📝 Documentation
Contributors
We'd like to thank the following people for their contributions:
Ali Ustek, GitHub, renovate[bot]
Release v5.0.0
Changelog
🚀 Features
- 7219e59 🚨 archivers: build entries with EntrySource factories and move the entry types to the top level (#306) - ArchiveExtractor.Entry, ArchiveExtractor.ErrorHandlerChoice and ArchiveExtractor.EscapingSymlinkPolicy move to com.hominux.compress4j.archivers.Entry, ErrorHandlerChoice and EscapingSymlinkPolicy; filter, errorHandler, postProcessor, escapingSymlinkPolicy and ArchiveItem.entry() use the top-level types. ArchiveCreator loses addFile(String, Path), addFile(String, Path, FileTime), addFile(String, byte[]), addFile(String, byte[], FileTime), addFile(String, InputStream, long), addFile(String, InputStream, long, FileTime), addDirectory(String), addDirectory(String, FileTime) and addDirectoryRecursively(Path, FileTime). Use add(EntrySource.file(...)), add(EntrySource.directory(...)), withLastModified and addDirectoryRecursively("", dir, time). EntrySource gains file(String, Path), file(String, InputStream, long), directory(String) and withLastModified(FileTime). EntrySource.file(String, Path) accepts regular files only and throws IllegalArgumentException for a directory or symlink; use EntrySource.of(base, path), or new EntrySource.Symlink(...) and new EntrySource.Directory(...) to add one under a chosen name., closes #306
- 9402ebc 🚨 compressors: compress and decompress any codec through one Compressor and Decompressor (#303) - compressors.Compressor and compressors.Decompressor are now final classes built with builder(target, Compression) and builder(source[, Compression]); Compressor.write(File) is removed; Decompressor.write refuses an existing target unless overwrite is set and enforces ExtractionLimits.defaults() (maxRatio 100) by default. The old abstract bases are renamed CodecCompressor and CodecDecompressor, their nested builders become CodecCompressor.CompressorBuilder and CodecDecompressor.DecompressorBuilder, and every per-codec class now extends them. Reading xz and lzma (Decompressor and TarArchiveExtractor) without an explicit memoryLimitKiB is now capped at 256 MiB; Integer.MAX_VALUE lifts the cap. ExtractionLimits.maxRatio is now enforced by Decompressor., closes #303
- 039e6fb 🚨 tar: read and write every tar compression through one reader and writer (#302) - TarGzArchiveExtractor/Creator, TarBZip2ArchiveExtractor/Creator, TarXzArchiveExtractor/Creator, TarLz4ArchiveExtractor/Creator, TarLzmaArchiveExtractor/Creator, TarZstdArchiveExtractor/Creator and TarZArchiveExtractor, with their nested builders and their codec accessors (compressorOutputStreamBuilder, xzInputStream, lz4InputStream, lzmaInputStream, zstdInputStream, zInputStream), are removed, as are BaseTarArchiveExtractor, BaseTarArchiveCreator and their nested builders and protected members. Use TarArchiveCreator.builder(...).compression(Compression.gzip()) and TarArchiveExtractor.builder(...), which detects the compression. TarArchiveExtractor and TarArchiveCreator are final, their public constructors are removed, and their builders are the nested Builder classes. encoding takes a Charset, longFileMode takes TarLongFileMode and bigNumberMode takes TarBigNumberMode (defaults POSIX and STAR instead of the commons ERROR defaults); blockSize throws IllegalArgumentException unless it is -511 or a positive multiple of 512. Reading fails with IOException on a bad header checksum or on 1 to 511 bytes of input, and .tar.lzma needs compression(Compression.lzma()). Streams without mark support are buffered., closes #302
- 1024944 🚨 exceptions: report which limit an input exceeded and enforce default extraction limits (#299) - *ArchiveSecurityException is renamed UnsafeInputException. ArchiveLimitExceededException is removed; limit breaches throw LimitExceededException(Limit, long, Optional) and the message text changed. ArchiveExtractor.UNLIMITED is removed; use ExtractionLimits.UNLIMITED. Every extractor, including the public stream-taking constructors, now enforces ExtractionLimits.defaults(): an archive with more than 1,000,000 entries, counted after strip-components and the filter, throws LimitExceededException. Opt out with limits(ExtractionLimits.unlimited()) or maxEntries(ExtractionLimits.UNLIMITED); the stream-taking constructors have no opt-out. maxEntries, maxEntrySize and maxTotalSize throw IllegalArgumentException for negative values other than -1; previously any negative value meant unlimited. The new maxRatio rejects 0 and negative values other than -1.
- fix(exceptions): resolve Sonar issues on extraction limits
Signed-off-by: austek 13117393+austek@users.noreply.github.com
---------*, closes #299
- 3baa3e6 🚨 archivers: write archives from a stream of entry sources (#288) - the creator filter is a Predicate, addFile(String, InputStream) requires a size, unsafe names throw UnsafeEntryException and withFilter is removed. ArchiveCreator subclasses implement writeDirectory, writeFile, writeSymlink and requiresSize instead of writeDirectoryEntry and writeFileEntry., closes #288
- f7bb3ac 🚨 archivers: read and write every format through channels and streams (#287) - ZipArchiveExtractor(ZipFileArchiveInputStream) is removed, ZipArchiveExtractor(ZipArchiveExtractorBuilder) is private, ZipArchiveExtractorBuilder(Path) is package-private and buildArchiveInputStream() returns ArchiveInputStream. SevenZArchiveExtractorBuilder(Path) is removed and the SevenZArchiveExtractor(SevenZFileArchiveInputStream) constructor is protected. setSeekableByteChannel on both builders is replaced by ZipArchiveExtractor.builder(SeekableByteChannel) and SevenZArchiveExtractor.builder(SeekableByteChannel). ArjArchiveExtractor and DumpArchiveExtractor constructors taking a prebuilt archive stream are protected; use the builders., closes #287
- 1362139 🚨 archivers: stream archive entries through one guarded pipeline (#286) - ArchiveExtractor.stream() returns Stream, honours strip, filter and limits, and is single-use; ArchiveExtractor is no longer Iterable. Setters are removed and nextEntry/openEntryStream are protected. Entry.linkTarget is Optional and Entry gains lastModified and size components. The entry filter sees names after strip-components. RELATIVIZE_ABSOLUTE rejects targets that resolve outside the output directory, and DISALLOW re-checks every created symlink after extraction., closes #286
- 8338d87 🚨 security: reject unsafe archive entries with a sealed security exception hierarchy (#285) - *ArchiveLimitExceededException is final and extends ArchiveSecurityException.
-
feat(security): reject traversal and escaping symlinks with UnsafeEntryException
-
feat(security)!: never let the error handler suppress a security exception
BREAKING CHANGE: errorHandler choices no longer apply to path traversal or escaping symlinks.
- feat(security)!: reject escaping symlinks by default
BREAKING CHANGE: escapingSymlinkPolicy defaults to DISALLOW; pass ALLOW to keep the 4.x behaviour.
-
docs(security): state that escaping symlinks are rejected by default
-
docs(security): name UnsafeEntryException wherever traversal failures are described
-
fix(security): accept symlinks that resolve to the output directory*, closes #285
🐛 Fixes
- 0ff41ac archivers: skip a file entry that already exists as a dangling symlink (#328), closes #328
- 745b7b7 archivers: run the JDK 25 CI legs' tests on JDK 25 (#325), closes #298 #325
- 04f2f9c archivers: report cpio newc hard links that carry no data (#324), closes #296 #324
- ebccc7d archivers: report the expanded size of sparse tar entries (#323), closes #301 #323
- 0f88a0a archivers: extract a ./ entry into the output directory (#322), closes #300 #322
- 3591e9f 🚨 archivers: surface parser runtime failures as IOException (#313) - *runtime exceptions thrown by format parsers and codecs on malformed input now reach callers as IOException with the original as its cause. Invalid entry names and link targets now fail as IOException (handled by the error handler) instead of InvalidPathException. The error handler is now consulted for parser runtime failures while reading entry content; before, extraction aborted. stream() surfaces these failures as UncheckedIOException wrapping the IOException. A Runti ...
Release v4.0.2
Changelog
🐛 Fixes
- 3f6c290 deps: update dependency org.apache.commons:commons-lang3 to v3.21.0 (#277), closes #277
- 3cf4f6f point the POM homepage and SCM url at the docs site and repo (#275), closes #224 #275
🧰 Tasks
- b46a137 add the repository social preview image (#278), closes #224 #278
- 033d684 deps: update dependency com.diffplug.spotless to v8.10.3 (#276), closes #276
🛠 Build
📝 Documentation
- bd9eaf7 refresh the JReleaser deployment guide (#273), closes #273
- 1c1f5ce restore the Antora component version from the site playbook (#272), closes #272
Contributors
We'd like to thank the following people for their contributions:
Ali Ustek, GitHub, renovate[bot]
Release v4.0.1
Release v3.1.1
Changelog
🔀 Merge
🐛 Fixes
🧰 Tasks
- 297bcb4 deps: update gradle and github actions (#189), closes #189
- 6a6bfed deps: update actions/setup-java action to v6 (#188), closes #188
- 7ab6168 deps: update gradle and github actions (#187), closes #187
- 248aba8 deps: update gradle and github actions (#186), closes #186
- ec867a7 deps: update build and test dependencies (#184), closes #184
- 63473e4 deps: update gradle and github actions (#185), closes #185
- a0cbc97 deps: update gradle and github actions (#183), closes #183
🛠 Build
- d22d3cb analyse GitHub Actions workflows with sonar
- 2e23feb audit workflows with zizmor
- c0ab305 analyse fork pull requests on maintainer request (#178), closes #178
- c5b4c32 fall back to the newest published release for the API baseline (#182), closes #182
Contributors
We'd like to thank the following people for their contributions:
Ali Ustek, GitHub, austek, renovate[bot]
Release v3.1.0
Changelog
🚀 Features
🧰 Tasks
- 91a4e53 deps: update gradle and github actions (#177), closes #177
- 5d4c1a6 deps: update build and test dependencies to v1.6.1 (#176), closes #176
- 94661fe deps: update dependency com.autonomousapps.build-health to v3.17.0 (#174), closes #174
- 48b6975 deps: update build and test dependencies (#173), closes #173
- a94e479 deps: pin dependencies (#172), closes #172
- e67e154 harden renovate configuration (#170), closes #169 #170
🛠 Build
- 9bf473e publish the version the release plan asked for (#181), closes #181
- a5a6f17 automate semver releases with api compatibility validation (#169), closes #169
- eecfc89 Update Non-major dependency updates (#167), closes #167
- e78d3d5 Update gradle and github actions (#168), closes #168
- 770e9a4 Update Non-major dependency updates (#166), closes #166
- 9a16f91 Update gradle and github actions (#165), closes #165
- 11425aa Update Non-major dependency updates (#164), closes #164
- 74b8e3d Update gradle and github actions (#163), closes #163
- 44383d3 Update gradle and github actions (#161), closes #161
- aba47b0 Update Non-major dependency updates (#162), closes #162
- a7cdcba Update Non-major dependency updates (#159), closes #159
- c5d711d Update gradle and github actions (#160), closes #160
Contributors
We'd like to thank the following people for their contributions:
Ali Ustek, GitHub, renovate[bot]
v3.0.0
What's Changed
- Update gradle and github actions by @renovate[bot] in #151
- Update Non-major dependency updates by @renovate[bot] in #150
- handle test file creation by @austek in #153
- Update Gradle to v9.3.1 by @renovate[bot] in #152
- Add streaming by @austek in #154
- Update Non-major dependency updates by @renovate[bot] in #155
- Remove deprecated classes by @austek in #136
- Update dependency com.fasterxml.jackson.core:jackson-databind to v2.21.0 by @renovate[bot] in #156
- Handle compiler warnings by @austek in #157
- Add documentation by @austek in #158
Full Changelog: v2.2.1...v3.0.0
v2.2.1
What's Changed
- Fix Path traversal on extraction by @austek in #149
- add xz support by @renasustek in #146
Full Changelog: v2.2.0...v2.2.1
v2.2.0
What's Changed
- add more tests by @austek in #138
- Correct the packages for the compressor by @austek in #139
- Update Tests by @austek in #140
- Implement CPIO support by @renasustek in #141
- Update tests to use the same archives as the existing tests by @austek in #142
- Change minimum JDK to 21 by @austek in #143
- Add Zip Support by @renasustek in #144
- Move examples to the src folder by @austek in #145
- Add Pack200 support by @austek in #147
- Fix Pack200 docs by @austek in #148
Full Changelog: v2.1.14...v2.2.0
v2.1.14
What's Changed
- Update dependency org.apache.commons:commons-compress to v1.28.0 by @renovate[bot] in #123
- Upgrade to gradle 9 by @austek in #124
- Add documentation by @austek in #126
- JDK 17 codebase by @austek in #127
- Use Configurations for examples by @austek in #128
- Refactor/use feature variants by @austek in #129
- Refactor/add gzip decompressor options by @renasustek in #130
- Add docs by @renasustek in #132
- Update dependency org.junit:junit-bom to v6 by @renovate[bot] in #134
- Update Non-major dependency updates by @renovate[bot] in #133
- Add JDK 25 to pipeline by @austek in #135
- add AR support by @renasustek in #137
Full Changelog: v2.1.3...v2.1.14